commit f9100f0f0a998dad5056a03109a991a569de96b1 Author: Ondřej Hruška Date: Sat May 24 21:05:31 2014 +0200 Initial commit. diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..2003e78 --- /dev/null +++ b/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..509450b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/bin/ +/target/ +*.log +.attach_pid* +*~ diff --git a/.project b/.project new file mode 100644 index 0000000..1c8998e --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + SpriteGen + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..8000cd6 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/lib/OpenAL32.dll b/lib/OpenAL32.dll new file mode 100644 index 0000000..6dd2600 Binary files /dev/null and b/lib/OpenAL32.dll differ diff --git a/lib/OpenAL64.dll b/lib/OpenAL64.dll new file mode 100644 index 0000000..00c98c0 Binary files /dev/null and b/lib/OpenAL64.dll differ diff --git a/lib/jinput-dx8.dll b/lib/jinput-dx8.dll new file mode 100644 index 0000000..6d27ad5 Binary files /dev/null and b/lib/jinput-dx8.dll differ diff --git a/lib/jinput-dx8_64.dll b/lib/jinput-dx8_64.dll new file mode 100644 index 0000000..6730589 Binary files /dev/null and b/lib/jinput-dx8_64.dll differ diff --git a/lib/jinput-raw.dll b/lib/jinput-raw.dll new file mode 100644 index 0000000..ce1d162 Binary files /dev/null and b/lib/jinput-raw.dll differ diff --git a/lib/jinput-raw_64.dll b/lib/jinput-raw_64.dll new file mode 100644 index 0000000..3d2b3ad Binary files /dev/null and b/lib/jinput-raw_64.dll differ diff --git a/lib/jinput.jar b/lib/jinput.jar new file mode 100644 index 0000000..7c2b6b0 Binary files /dev/null and b/lib/jinput.jar differ diff --git a/lib/jogg-0.0.7.jar b/lib/jogg-0.0.7.jar new file mode 100644 index 0000000..ecb0260 Binary files /dev/null and b/lib/jogg-0.0.7.jar differ diff --git a/lib/jorbis-0.0.15.jar b/lib/jorbis-0.0.15.jar new file mode 100644 index 0000000..4cf51f9 Binary files /dev/null and b/lib/jorbis-0.0.15.jar differ diff --git a/lib/libjinput-linux.so b/lib/libjinput-linux.so new file mode 100644 index 0000000..3cdc439 Binary files /dev/null and b/lib/libjinput-linux.so differ diff --git a/lib/libjinput-linux64.so b/lib/libjinput-linux64.so new file mode 100644 index 0000000..de1ee5f Binary files /dev/null and b/lib/libjinput-linux64.so differ diff --git a/lib/libjinput-osx.jnilib b/lib/libjinput-osx.jnilib new file mode 100644 index 0000000..59a3eab Binary files /dev/null and b/lib/libjinput-osx.jnilib differ diff --git a/lib/liblwjgl.jnilib b/lib/liblwjgl.jnilib new file mode 100644 index 0000000..cbb5b4c Binary files /dev/null and b/lib/liblwjgl.jnilib differ diff --git a/lib/liblwjgl.so b/lib/liblwjgl.so new file mode 100644 index 0000000..5a02874 Binary files /dev/null and b/lib/liblwjgl.so differ diff --git a/lib/liblwjgl64.so b/lib/liblwjgl64.so new file mode 100644 index 0000000..4572589 Binary files /dev/null and b/lib/liblwjgl64.so differ diff --git a/lib/libopenal.so b/lib/libopenal.so new file mode 100644 index 0000000..7742faf Binary files /dev/null and b/lib/libopenal.so differ diff --git a/lib/libopenal64.so b/lib/libopenal64.so new file mode 100644 index 0000000..d1e45e5 Binary files /dev/null and b/lib/libopenal64.so differ diff --git a/lib/lwjgl-source-2.8.4.zip b/lib/lwjgl-source-2.8.4.zip new file mode 100644 index 0000000..f48fd31 Binary files /dev/null and b/lib/lwjgl-source-2.8.4.zip differ diff --git a/lib/lwjgl.dll b/lib/lwjgl.dll new file mode 100644 index 0000000..6819404 Binary files /dev/null and b/lib/lwjgl.dll differ diff --git a/lib/lwjgl.jar b/lib/lwjgl.jar new file mode 100644 index 0000000..a0fb56d Binary files /dev/null and b/lib/lwjgl.jar differ diff --git a/lib/lwjgl64.dll b/lib/lwjgl64.dll new file mode 100644 index 0000000..e66ab2a Binary files /dev/null and b/lib/lwjgl64.dll differ diff --git a/lib/lwjgl_util.jar b/lib/lwjgl_util.jar new file mode 100644 index 0000000..9973b24 Binary files /dev/null and b/lib/lwjgl_util.jar differ diff --git a/lib/slick-util-src.zip b/lib/slick-util-src.zip new file mode 100644 index 0000000..7ca6790 Binary files /dev/null and b/lib/slick-util-src.zip differ diff --git a/lib/slick-util.jar b/lib/slick-util.jar new file mode 100644 index 0000000..86a64a7 Binary files /dev/null and b/lib/slick-util.jar differ diff --git a/res/models/turtle.mtl b/res/models/turtle.mtl new file mode 100644 index 0000000..7c02a3b --- /dev/null +++ b/res/models/turtle.mtl @@ -0,0 +1,11 @@ +# Exported from Wings 3D 1.4.1 +newmtl turtle_auv +Ns 100.0 +d 1.0 +illum 2 +Kd 1.0 1.0 1.0 +Ka 1.0 1.0 1.0 +Ks 1.0 1.0 1.0 +Ke 0.0 0.0 0.0 +map_Kd turtle.png + diff --git a/res/models/turtle.obj b/res/models/turtle.obj new file mode 100644 index 0000000..d002649 --- /dev/null +++ b/res/models/turtle.obj @@ -0,0 +1,3558 @@ +# Exported from Wings 3D 1.4.1 +mtllib turtle.mtl +o Turtle +#828 vertices, 846 faces +v -0.80266960 -2.3711919e-18 0.0000000e+0 +v -0.89373423 -0.13818402 3.4694470e-18 +v -0.76473622 -2.3711919e-18 -0.30650816 +v -0.76473622 -2.3711919e-18 0.30650816 +v -0.77137495 0.19353122 0.0000000e+0 +v -0.85570047 -0.13748246 -0.34371029 +v -0.85570047 -0.13748246 0.34371029 +v -0.73547665 0.18452479 -0.30151110 +v -0.73547665 0.18452479 0.30151110 +v -0.65583095 -0.32794273 -2.3420988e-4 +v -0.68992247 -2.3711919e-18 -0.54394207 +v -0.68984847 -2.3711919e-18 0.54394207 +v -0.67653894 0.33947664 0.0000000e+0 +v -0.63487086 -0.32642164 -0.25935297 +v -0.63480519 -0.32664160 0.25879310 +v -0.78443975 -0.13572993 -0.61636166 +v -0.78435189 -0.13572993 0.61636166 +v -0.66570188 0.16356370 -0.53452271 +v -0.66563183 0.16356370 0.53452271 +v -0.65192885 0.32712790 -0.26726096 +v -0.65192885 0.32712790 0.26726096 +v -0.59059614 -0.32087042 -0.48796757 +v -0.59039985 -0.32114834 0.48711031 +v -0.59694733 0.29686368 -0.48507138 +v -0.59694893 0.29686368 0.48507138 +v -0.55282078 -0.36031684 -4.3697178e-4 +v -0.58504202 -2.3711919e-18 -0.70367391 +v -0.58496276 -2.3711919e-18 0.70367391 +v -0.57494583 0.43274935 0.0000000e+0 +v -0.53353921 -0.35802794 -0.23850900 +v -0.53345788 -0.35827080 0.23749835 +v -0.68379928 -0.13413026 -0.80360558 +v -0.68375568 -0.13413026 0.80360558 +v -0.57221820 0.14040230 -0.68824724 +v -0.57214240 0.14040230 0.68824724 +v -0.55961089 0.42120731 -0.22941552 +v -0.55961089 0.42120731 0.22941552 +v -0.50325882 -0.35002931 -0.46052243 +v -0.50304376 -0.35024151 0.45918357 +v -0.53070168 -0.31603941 -0.63955028 +v -0.53022751 -0.31572573 0.63823730 +v -0.53120778 0.26095778 -0.63960209 +v -0.53114126 0.26095778 0.63960209 +v -0.52440120 0.39143648 -0.42640161 +v -0.52440246 0.39143648 0.42640161 +v -0.48628425 -0.34028422 -0.58741622 +v -0.48587067 -0.34013634 0.58585914 +v -0.47882987 0.35333836 -0.57735027 +v -0.47877452 0.35333836 0.57735027 +v -0.45420638 -0.37525634 -6.4057739e-4 +v -0.46063589 -2.3711919e-18 -0.83101140 +v -0.46066594 3.6779217e-2 0.83101140 +v -0.45102219 0.50921470 0.0000000e+0 +v -0.42638293 -0.37280554 -0.26839761 +v -0.42627477 -0.37294684 0.26685021 +v -0.52496939 -0.13572993 -0.94023237 +v -0.52438873 -0.10452247 0.94027627 +v -0.44488678 0.16356370 -0.80178367 +v -0.45266466 0.18840532 0.80178367 +v -0.43461545 0.49069161 -0.26726096 +v -0.43461545 0.49069161 0.26726096 +v -0.40748810 -0.36089455 -0.49806387 +v -0.40721296 -0.36052097 0.49598776 +v -0.40483831 -0.32105387 -0.72038531 +v -0.40393160 -0.31794242 0.71726602 +v -0.40308467 0.29686368 -0.72760670 +v -0.40307279 0.30369518 0.72760670 +v -0.39764046 0.44529530 -0.48507138 +v -0.39764155 0.44529530 0.48507138 +v -0.38067158 -0.35009394 -0.61468662 +v -0.38010824 -0.34782606 0.61186658 +v -0.35366948 0.39143648 -0.63960209 +v -0.35362412 0.39143648 0.63960209 +v -0.22458689 -0.39465664 -1.0344999e-3 +v -0.25983938 2.3929590e-2 -0.94051882 +v -0.26023289 0.14180636 0.94056829 +v -0.25711673 0.58059424 0.0000000e+0 +v -0.21864651 -0.38934671 -0.26949339 +v -0.21855633 -0.38939845 0.26705660 +v -0.29294316 -0.10838493 -1.05239040 +v -0.29295311 -8.5717680e-3 1.04910175 +v -0.25553267 0.19498172 -0.90453420 +v -0.24691814 0.26132422 0.88774269 +v -0.24515065 0.55357493 -0.30151110 +v -0.24515065 0.55357493 0.30151110 +v -0.22029869 -0.36647773 -0.52256027 +v -0.21888953 -0.37191998 0.52103678 +v -0.21712386 -0.33634976 -0.77764372 +v -0.21749588 -0.32957697 0.77410172 +v -0.22221407 0.32712790 -0.80178367 +v -0.22612258 0.36496987 0.80178367 +v -0.21905060 0.49069161 -0.53452271 +v -0.21905127 0.49069161 0.53452271 +v -0.19784352 -0.35454618 -0.65153785 +v -0.19626953 -0.35699175 0.65057667 +v -0.19030970 0.42120731 -0.68824724 +v -0.19031415 0.42833915 0.68824724 +v 2.1672994e-5 -0.40094728 -1.1698653e-3 +v 1.7637519e-5 -0.39463068 -0.27690119 +v 2.6867344e-5 -0.39495090 0.27414217 +v 9.5406669e-6 -0.37319326 -0.55656899 +v 3.3845069e-5 -0.37573790 0.55470973 +v 8.8699207e-6 -0.37329842 -0.67278896 +v -1.8814271e-6 -0.36411920 0.67313975 +v 1.0667420e-5 -0.34680098 -0.80932385 +v 6.1685684e-5 -0.34258285 0.79738986 +v 3.4512266e-6 -2.8182097e-2 -1.09916587 +v 4.2063421e-6 0.11901938 1.09334767 +v 1.5667753e-5 6.8506767e-2 -0.98717085 +v 1.2067871e-5 0.25843062 0.98496826 +v 1.6421028e-5 0.22410500 -0.94868339 +v 1.6657167e-5 0.31094545 0.92017767 +v 2.2670137e-5 0.33947664 -0.83205017 +v 2.2658843e-5 0.38919556 0.81975546 +v -4.4623133e-5 0.43274935 -0.70710678 +v -4.4910660e-5 0.44845894 0.70710678 +v 1.1969840e-5 0.50921470 -0.55470039 +v 1.1969833e-5 0.50921470 0.55470039 +v 1.1987512e-5 0.58059424 -0.31622748 +v 1.1987512e-5 0.58059424 0.31622748 +v 1.1987512e-5 0.61200000 0.0000000e+0 +v 0.19784225 -0.35427671 -0.65153571 +v 0.19626045 -0.35697343 0.65085149 +v 0.19021065 0.42120731 -0.68824724 +v 0.19021565 0.42833915 0.68824724 +v 0.22031095 -0.36637239 -0.52255624 +v 0.21895482 -0.37206752 0.52122212 +v 0.21712261 -0.33609297 -0.77764254 +v 0.21759455 -0.32947447 0.77423486 +v 0.22600679 0.32712790 -0.80178367 +v 0.22615601 0.36496987 0.80178367 +v 0.21907454 0.49069161 -0.53452271 +v 0.21907521 0.49069161 0.53452271 +v 0.21868148 -0.38935047 -0.26948323 +v 0.21861051 -0.38944170 0.26712387 +v 0.29293447 -0.10837915 -1.05239040 +v 0.29294793 -8.5717680e-3 1.04910175 +v 0.25555336 0.19498014 -0.90453420 +v 0.24694129 0.26132422 0.88774269 +v 0.24517462 0.55357493 -0.30151110 +v 0.24517462 0.55357493 0.30151110 +v 0.22463017 -0.39466904 -1.0086887e-3 +v 0.25985828 2.3927912e-2 -0.94051882 +v 0.26025045 0.14180636 0.94056829 +v 0.25714071 0.58059424 0.0000000e+0 +v 0.38056145 -0.35009444 -0.61468346 +v 0.38006989 -0.34780448 0.61212563 +v 0.35354628 0.39143648 -0.63960209 +v 0.35350220 0.39143648 0.63960209 +v 0.40751611 -0.36089550 -0.49805856 +v 0.40729541 -0.36054740 0.49614419 +v 0.40470349 -0.32105411 -0.72038346 +v 0.40386201 -0.31791293 0.71745516 +v 0.40294176 0.29686368 -0.72760670 +v 0.40293067 0.30369518 0.72760670 +v 0.39766438 0.44529530 -0.48507138 +v 0.39766548 0.44529530 0.48507138 +v 0.42641625 -0.37280834 -0.26838444 +v 0.42633511 -0.37296425 0.26692847 +v 0.52492539 -0.13572993 -0.94023237 +v 0.52434715 -0.10452247 0.94027627 +v 0.45256500 0.16356370 -0.80178367 +v 0.45265944 0.18840532 0.80178367 +v 0.43463943 0.49069161 -0.26726096 +v 0.43463943 0.49069161 0.26726096 +v 0.45424898 -0.37526336 -6.0858738e-4 +v 0.46062732 -2.3711919e-18 -0.83101140 +v 0.46065887 3.6779217e-2 0.83101140 +v 0.45104616 0.50921470 0.0000000e+0 +v 0.48614066 -0.34028460 -0.58741309 +v 0.48581291 -0.34013783 0.58602377 +v 0.47867826 0.35333836 -0.57735027 +v 0.47862396 0.35333836 0.57735027 +v 0.50328622 -0.35003011 -0.46051704 +v 0.50313470 -0.35025252 0.45932384 +v 0.53053363 -0.31603965 -0.63954802 +v 0.53017662 -0.31572320 0.63842754 +v 0.53103519 0.26095778 -0.63960209 +v 0.53096976 0.26095778 0.63960209 +v 0.52442511 0.39143648 -0.42640161 +v 0.52442637 0.39143648 0.42640161 +v 0.53357111 -0.35802998 -0.23849670 +v 0.53351566 -0.35827917 0.23756254 +v 0.68371902 -0.13413026 -0.80360558 +v 0.68367682 -0.13413026 0.80360558 +v 0.57202879 0.14040230 -0.68824724 +v 0.57195411 0.14040230 0.68824724 +v 0.55963486 0.42120731 -0.22941552 +v 0.55963486 0.42120731 0.22941552 +v 0.55286040 -0.36032094 -4.1058666e-4 +v 0.58484872 -2.3711919e-18 -0.70367391 +v 0.58477058 -2.3711919e-18 0.70367391 +v 0.57496980 0.43274935 0.0000000e+0 +v 0.59062156 -0.32087091 -0.48796358 +v 0.59051650 -0.32115236 0.48729424 +v 0.59697123 0.29686368 -0.48507138 +v 0.59697283 0.29686368 0.48507138 +v 0.63489957 -0.32642280 -0.25934409 +v 0.63486337 -0.32664568 0.25885444 +v 0.78416307 -0.13572993 -0.61636166 +v 0.78407588 -0.13572993 0.61636166 +v 0.66548667 0.16356370 -0.53452271 +v 0.65819258 0.16356370 0.53452271 +v 0.65195282 0.32712790 -0.26726096 +v 0.65195282 0.32712790 0.26726096 +v 0.65586661 -0.32794496 -2.1347948e-4 +v 0.68969854 -2.3711919e-18 -0.54394207 +v 0.68216227 -2.3711919e-18 0.54394207 +v 0.67656291 0.33947664 0.0000000e+0 +v 0.85572445 -0.13748246 -0.34371029 +v 0.85572445 -0.13748246 0.34371029 +v 0.73550063 0.18452479 -0.30151110 +v 0.73550063 0.18452479 0.30151110 +v 0.89375820 -0.13818402 3.4694470e-18 +v 0.76476020 -2.3711919e-18 -0.30650816 +v 0.76476020 -2.3711919e-18 0.30650816 +v 0.77139892 0.19353122 0.0000000e+0 +v 0.80269358 -2.3711919e-18 0.0000000e+0 +v 0.90996923 -3.9762542e-2 0.0000000e+0 +v 0.86887881 -3.9762542e-2 0.34857535 +v 0.86887881 -3.9762542e-2 -0.34857535 +v 0.79144632 -3.9762542e-2 0.62146967 +v 0.79153465 -3.9762542e-2 -0.62146967 +v 0.68639663 -3.9762542e-2 0.80673422 +v 0.68643916 -3.9762542e-2 -0.80673422 +v 0.52928274 -7.6994195e-3 0.94868053 +v 0.52945203 -3.9762542e-2 -0.94882090 +v 0.29725810 9.7836223e-2 1.06699903 +v 0.29727366 -1.5652378e-2 -1.06856817 +v 4.9513295e-16 0.21674347 1.11660545 +v 1.5447771e-6 4.1510420e-2 -1.11910286 +v -0.29726956 9.7836223e-2 1.06699903 +v -0.29728575 -1.5654996e-2 -1.06856817 +v -0.52932708 -7.6994195e-3 0.94868053 +v -0.52949822 -3.9762542e-2 -0.94882090 +v -0.68647651 -3.9762542e-2 0.80673422 +v -0.68652044 -3.9762542e-2 -0.80673422 +v -0.79172607 -3.9762542e-2 0.62146967 +v -0.79181506 -3.9762542e-2 -0.62146967 +v -0.86885483 -3.9762542e-2 0.34857535 +v -0.86885483 -3.9762542e-2 -0.34857535 +v -0.90994525 -3.9762542e-2 0.0000000e+0 +v -0.86393290 -1.5045716e-2 0.0000000e+0 +v -0.79223805 -2.3711919e-18 -0.15811374 +v -0.79223805 -2.3711919e-18 0.15811374 +v -0.88336028 -0.13799570 -0.17681498 +v -0.88336028 -0.13799570 0.17681498 +v -0.76715182 -0.27960942 -1.4642137e-5 +v -0.82406064 -1.5045716e-2 -0.33045358 +v -0.73056945 -2.3711919e-18 -0.43546393 +v -0.82406064 -1.5045716e-2 0.33045358 +v -0.73057119 -2.3711919e-18 0.43546393 +v -0.74038390 -0.27898010 -0.29519076 +v -0.82335547 -0.13669601 -0.49076624 +v -0.74033654 -0.27910601 0.29510150 +v -0.82335754 -0.13669601 0.49076624 +v -0.65043927 -0.32779360 -0.12590505 +v -0.65041277 -0.32790137 0.12541520 +v -0.74755045 -1.5045716e-2 -0.58787332 +v -0.63941085 -2.3711919e-18 -0.63090358 +v -0.74746780 -1.5045716e-2 0.58787332 +v -0.63933231 -2.3711919e-18 0.63090358 +v -0.61765146 -0.32411356 -0.37746659 +v -0.61752989 -0.32440196 0.37679309 +v -0.68068572 -0.27616195 -0.54333769 +v -0.73156938 -0.13467782 -0.71887533 +v -0.68037511 -0.27632042 0.54283057 +v -0.73147587 -0.13467782 0.71887533 +v -0.56654142 -0.31799529 -0.57307144 +v -0.56617719 -0.31814639 0.57203156 +v -0.63543825 -1.5045716e-2 -0.76188897 +v -0.53398109 -2.3711919e-18 -0.76957847 +v -0.64659476 -1.5045716e-2 0.76188897 +v -0.53396716 1.2890211e-2 0.76957847 +v -0.59667303 -0.27407370 -0.71640098 +v -0.61206012 -0.13467782 -0.87585073 +v -0.59603895 -0.27372241 0.71543414 +v -0.61200796 -0.12931921 0.87585073 +v -0.47556661 -0.31811925 -0.68338619 +v -0.47491233 -0.31651964 0.68142237 +v -0.49954900 -1.5045716e-2 -0.89781076 +v -0.36898046 4.7892066e-3 -0.89036678 +v -0.49952228 2.0081503e-2 0.89778553 +v -0.36904223 6.7129497e-2 0.89053597 +v -0.46063793 -0.27656975 -0.82881924 +v -0.41814811 -0.13582125 -1.00137213 +v -0.45915997 -0.27446753 0.82531309 +v -0.41784857 -7.6814582e-2 1.00136090 +v -0.31562958 -0.32441470 -0.75187468 +v -0.31195359 -0.32232991 0.74920357 +v -0.28109853 1.0193247e-2 -1.01347842 +v -0.13407532 6.1923922e-2 -0.97434170 +v -0.28128517 0.12784613 1.01267762 +v -0.15635380 0.23457756 0.97448438 +v -0.25020853 -0.29221461 -0.91054096 +v -0.15072530 -3.6241492e-2 -1.08640756 +v -0.24780722 -0.29427595 0.89959384 +v -0.17401487 9.4375422e-2 1.08147722 +v -0.10488868 -0.34541421 -0.80354249 +v -0.10493228 -0.33867665 0.79149105 +v 1.6899028e-5 -0.32620762 -0.94135326 +v 0.10490501 -0.34532668 -0.79641534 +v 3.3179116e-5 -0.31746196 0.92669953 +v 0.10505877 -0.33872967 0.79151351 +v -2.4258934e-7 9.9423070e-3 -1.13817825 +v 0.15072822 -3.6240224e-2 -1.08640756 +v 4.7454455e-16 0.17265607 1.13437214 +v 0.17401760 9.4375422e-2 1.08147722 +v 0.13410350 6.1922292e-2 -0.97434170 +v 0.15637383 0.23457756 0.97448438 +v 0.25022831 -0.29221909 -0.91054048 +v 0.31558835 -0.32407793 -0.75187307 +v 0.24785686 -0.29424703 0.89965270 +v 0.31190519 -0.32224691 0.74948384 +v 0.30307221 -5.9205240e-2 -1.08791821 +v 0.41812301 -0.13581655 -1.00137213 +v 0.30278813 4.8063418e-2 1.08551950 +v 0.41782631 -7.6814582e-2 1.00136090 +v 0.36898648 4.7893184e-3 -0.89036678 +v 0.36904927 6.7129497e-2 0.89053597 +v 0.46062383 -0.27656985 -0.82881837 +v 0.47541352 -0.31811949 -0.68338413 +v 0.45919661 -0.27445310 0.82541722 +v 0.47484442 -0.31651127 0.68158855 +v 0.54101629 -8.3821591e-2 -0.96825261 +v 0.61199721 -0.13467782 -0.87585073 +v 0.54071820 -5.3532371e-2 0.96798942 +v 0.61194679 -0.12931921 0.87585073 +v 0.53395821 -2.3711919e-18 -0.76957847 +v 0.53394591 1.2890211e-2 0.76957847 +v 0.59646752 -0.27407382 -0.71639981 +v 0.56636696 -0.31799562 -0.57306856 +v 0.59612752 -0.27372905 0.71580644 +v 0.56612689 -0.31814206 0.57224476 +v 0.70260898 -8.3821591e-2 -0.82483987 +v 0.73130915 -0.13467782 -0.71887533 +v 0.70256536 -8.3821591e-2 0.82483987 +v 0.73121649 -0.13467782 0.71887533 +v 0.63920235 -2.3711919e-18 -0.63090358 +v 0.63912477 -2.3711919e-18 0.63090358 +v 0.61767830 -0.32411435 -0.37746057 +v 0.68070837 -0.27616217 -0.54333560 +v 0.61761516 -0.32440660 0.37690286 +v 0.68064881 -0.27632451 0.54319439 +v 0.65047086 -0.32779533 -0.12589128 +v 0.74040840 -0.27898061 -0.29518606 +v 0.65045596 -0.32790430 0.12544921 +v 0.74038906 -0.27910781 0.29515107 +v 0.80846172 -8.3821591e-2 -0.63439622 +v 0.82337934 -0.13669601 -0.49076624 +v 0.80837104 -8.3821591e-2 0.63439622 +v 0.82338140 -0.13669601 0.49076624 +v 0.76718096 -0.27961040 -2.3977774e-6 +v 0.73059333 -2.3711919e-18 -0.43546393 +v 0.73059508 -2.3711919e-18 0.43546393 +v 0.88338425 -0.13799570 -0.17681498 +v 0.88461258 -8.3821591e-2 -0.35504981 +v 0.88338425 -0.13799570 0.17681498 +v 0.88461258 -8.3821591e-2 0.35504981 +v 0.92547968 -8.3821591e-2 0.0000000e+0 +v 0.79226202 -2.3711919e-18 -0.15811374 +v 0.79226202 -2.3711919e-18 0.15811374 +v 0.86395688 -1.5045716e-2 0.0000000e+0 +v 0.82408461 -1.5045716e-2 0.33045358 +v 0.82408461 -1.5045716e-2 -0.33045358 +v 0.74721248 -1.5045716e-2 0.58787332 +v 0.74729441 -1.5045716e-2 -0.58787332 +v 0.64653435 -1.5045716e-2 0.76188897 +v 0.63521617 -1.5045716e-2 -0.76188897 +v 0.49949399 2.0081503e-2 0.89778553 +v 0.49951906 -1.5045716e-2 -0.89781076 +v 0.28128594 0.12784613 1.01267762 +v 0.28109981 1.0193890e-2 -1.01347842 +v 4.6762303e-6 0.24232796 1.06110683 +v 7.6353236e-6 6.1438091e-2 -1.06251498 +v -0.30280526 4.8063418e-2 1.08551950 +v -0.30308907 -5.9213658e-2 -1.08791821 +v -0.54076852 -5.3532371e-2 0.96798942 +v -0.54106871 -8.3821591e-2 -0.96825261 +v -0.70265306 -8.3821591e-2 0.82483987 +v -0.70269805 -8.3821591e-2 -0.82483987 +v -0.80866007 -8.3821591e-2 0.63439622 +v -0.80875138 -8.3821591e-2 -0.63439622 +v -0.88458860 -8.3821591e-2 0.35504981 +v -0.88458860 -8.3821591e-2 -0.35504981 +v -0.92545570 -8.3821591e-2 0.0000000e+0 +v -0.61528819 -3.3573060e-2 0.88095707 +v -0.42255610 2.0673441e-2 1.01313329 +v -0.17755261 0.19209394 1.10317691 +v 0.17755261 0.19209394 1.10317691 +v 0.42253014 2.0673441e-2 1.01313329 +v 0.61522556 -3.3573060e-2 0.88095707 +v 0.61526248 -3.9762542e-2 -0.88095707 +v 0.42307806 -3.7181853e-2 -1.01389050 +v 0.15321115 2.8700983e-2 -1.10525623 +v -0.15321192 2.8700024e-2 -1.10525623 +v -0.42310605 -3.7189289e-2 -1.01389050 +v -0.61532676 -3.9762542e-2 -0.88095707 +v 0.73567316 -3.9762542e-2 -0.72258756 +v 0.83381442 -3.9762542e-2 -0.49633315 +v 0.89871035 -3.9762542e-2 -0.17959365 +v 0.89871035 -3.9762542e-2 0.17959365 +v 0.83381652 -3.9762542e-2 0.49633315 +v 0.73557971 -3.9762542e-2 0.72258756 +v -0.73593545 -3.9762542e-2 -0.72258756 +v -0.83379056 -3.9762542e-2 -0.49633315 +v -0.89868638 -3.9762542e-2 -0.17959365 +v -0.89868638 -3.9762542e-2 0.17959365 +v -0.83379266 -3.9762542e-2 0.49633315 +v -0.73584115 -3.9762542e-2 0.72258756 +v -0.62947848 -7.9742110e-2 0.90009139 +v -0.54096306 -0.27353435 0.77574800 +v -0.43104220 -2.4800178e-2 1.03220399 +v -0.36000540 -0.28150986 0.86758473 +v -0.18033053 0.14781107 1.12122675 +v -0.12513974 -0.31084864 0.91969826 +v 0.18033053 0.14781107 1.12122675 +v 0.12520335 -0.31085887 0.91971620 +v 0.43101138 -2.4800178e-2 1.03220399 +v 0.36004615 -0.28148054 0.86768773 +v 0.62940875 -7.9742110e-2 0.90009139 +v 0.54103622 -0.27353076 0.77590005 +v 0.57979506 -1.5045716e-2 -0.83257877 +v 0.54176776 -0.27505637 -0.77741464 +v 0.39962580 -1.0344543e-2 -0.96058712 +v 0.36207943 -0.29443404 -0.87403921 +v 0.14496552 5.0995284e-2 -1.04905521 +v 0.12683758 -0.31224693 -0.93483099 +v -0.14495381 5.0995579e-2 -1.04905521 +v -0.12680732 -0.31228849 -0.94226214 +v -0.39963911 -1.0347937e-2 -0.96058712 +v -0.36207516 -0.29443328 -0.87403991 +v -0.57984144 -1.5045716e-2 -0.83257877 +v -0.53252709 -0.27505626 -0.77741565 +v 0.69362665 -1.5045716e-2 -0.68273916 +v 0.78920589 -1.5045716e-2 -0.47003545 +v 0.91430264 -8.3821591e-2 -0.18282320 +v 0.91430264 -8.3821591e-2 0.18282320 +v 0.85014407 -8.3821591e-2 0.50608322 +v 0.75228216 -8.3821591e-2 0.73846163 +v 0.64665763 -0.27474400 -0.63909259 +v 0.71737287 -0.27774258 -0.42712053 +v 0.76014974 -0.27968029 -0.14961969 +v 0.76014134 -0.27974503 0.14960747 +v 0.71733958 -0.27791072 0.42704705 +v 0.64646050 -0.27479582 0.63882095 +v -0.64687564 -0.27474384 -0.63909410 +v -0.71734951 -0.27774223 -0.42712364 +v -0.76012357 -0.27967956 -0.14962709 +v -0.76010565 -0.27974372 0.14958458 +v -0.71723536 -0.27790827 0.42692263 +v -0.64636021 -0.27479346 0.63840050 +v -0.69386567 -1.5045716e-2 -0.68273916 +v -0.78918202 -1.5045716e-2 -0.47003545 +v -0.85298859 -1.5045716e-2 -0.17035578 +v -0.91427867 -8.3821591e-2 0.18282320 +v -0.85012022 -8.3821591e-2 0.50608322 +v -0.76610070 -8.3821591e-2 0.73846163 +v -0.57981487 -5.0671400e-3 0.83257877 +v -0.39936928 4.9395256e-2 0.96024235 +v -0.16858367 0.21784274 1.04796338 +v 0.16858863 0.21784274 1.04796338 +v 0.39935749 4.9395256e-2 0.96024235 +v 0.57977015 -5.0671400e-3 0.83257877 +v 0.62945288 -8.3821591e-2 -0.90009139 +v 0.43180559 -8.2695247e-2 -1.03335993 +v 0.15610249 -8.8539400e-3 -1.12443227 +v -0.15610674 -8.8577778e-3 -1.12443227 +v -0.43183900 -8.2703820e-2 -1.03335993 +v -0.62952426 -8.3821591e-2 -0.90009139 +v 0.75237815 -8.3821591e-2 -0.73846163 +v 0.85014192 -8.3821591e-2 -0.50608322 +v 0.85301256 -1.5045716e-2 -0.17035578 +v 0.85301256 -1.5045716e-2 0.17035578 +v 0.78920784 -1.5045716e-2 0.47003545 +v 0.69353990 -1.5045716e-2 0.68273916 +v -0.75264960 -8.3821591e-2 -0.73846163 +v -0.85011806 -8.3821591e-2 -0.50608322 +v -0.91427867 -8.3821591e-2 -0.18282320 +v -0.85298859 -1.5045716e-2 0.17035578 +v -0.78918397 -1.5045716e-2 0.47003545 +v -0.69377802 -1.5045716e-2 0.68273916 +v -0.51729336 0.15715391 0.74501545 +v -0.43643894 -0.34540159 0.59444146 +v -0.35417948 0.22257811 0.85315893 +v -0.27657483 -0.35279846 0.63423775 +v -0.13694370 0.29012225 0.93220213 +v -7.4995958e-2 -0.36208057 0.66840652 +v 0.13697015 0.29012225 0.93220213 +v 7.4994429e-2 -0.36210575 0.66847693 +v 0.35419007 0.22257811 0.85315893 +v 0.27659262 -0.35271361 0.63481233 +v 0.51727722 0.15715391 0.74501545 +v 0.43638466 -0.34540113 0.59461668 +v 0.51728231 0.15198300 -0.74501545 +v 0.43678482 -0.34627210 -0.59648061 +v 0.35400837 0.17404425 -0.85315893 +v 0.27851460 -0.34850024 -0.63528262 +v 0.12776757 0.21398470 -0.92660880 +v 7.5676812e-2 -0.36876508 -0.67848304 +v -0.12773536 0.21398640 -0.92660880 +v -7.5663042e-2 -0.36883753 -0.68383725 +v -0.35399750 0.17404425 -0.85315893 +v -0.27854877 -0.34885912 -0.63528534 +v -0.50850200 0.15198300 -0.74501545 +v -0.43691119 -0.34627162 -0.59648393 +v 0.61867668 0.15198300 -0.61138498 +v 0.69999815 0.17404425 -0.41801691 +v 0.75344978 0.18902801 -0.15075555 +v 0.75344978 0.18902801 0.15075555 +v 0.69999976 0.17404425 0.41801691 +v 0.61860376 0.15198300 0.61138498 +v 0.49296366 -0.34623023 -0.52821551 +v 0.52242084 -0.35543175 -0.33574096 +v 0.54862719 -0.35981209 -9.2605594e-2 +v 0.54860962 -0.35991632 9.1762297e-2 +v 0.52233279 -0.35573925 0.33472342 +v 0.49270296 -0.34635829 0.52691852 +v -0.49310202 -0.34622967 -0.52821957 +v -0.52239103 -0.35543028 -0.33574985 +v -0.54859098 -0.35980868 -9.2625824e-2 +v -0.54856433 -0.35991116 9.1724933e-2 +v -0.52226050 -0.35572966 0.33463028 +v -0.49276117 -0.34635043 0.52675897 +v -0.61887742 0.15198300 -0.61138498 +v -0.69997426 0.17404425 -0.41801691 +v -0.75342580 0.18902801 -0.15075555 +v -0.75342580 0.18902801 0.15075555 +v -0.69997587 0.17404425 0.41801691 +v -0.61880355 0.15198300 0.61138498 +v -0.69416416 -0.17231662 0.68376047 +v -0.78035738 -0.17231662 0.46586538 +v -0.83633513 -0.17231662 0.16755599 +v -0.83633513 -0.17231662 -0.16755599 +v -0.78035546 -0.17231662 -0.46586538 +v -0.69456287 -0.17231662 -0.68414727 +v 0.69423604 -0.17231662 0.68414727 +v 0.78038125 -0.17231662 0.46586538 +v 0.83635911 -0.17231662 0.16755599 +v 0.83635911 -0.17231662 -0.16755599 +v 0.78037933 -0.17231662 -0.46586538 +v 0.69432265 -0.17231662 -0.68414727 +v -0.58119907 -0.17231662 -0.83318143 +v -0.39597832 -0.18629729 -0.94990970 +v -0.14246732 -0.21279229 -1.02720353 +v 0.14248253 -0.21279294 -1.02857411 +v 0.39596679 -0.18629489 -0.94990970 +v 0.58115137 -0.17231662 -0.83318143 +v 0.58001849 -0.17231662 0.83166730 +v 0.38968553 -0.18785545 0.93553998 +v 0.13725646 -0.24700578 0.97728871 +v -0.13722973 -0.24700578 0.97728871 +v -0.38969113 -0.18785545 0.93553998 +v -0.58006389 -0.17231662 0.83166730 +v 0.84591649 -0.17231662 1.7347235e-18 +v 0.81080524 -0.17231662 0.32589815 +v 0.81080524 -0.17231662 -0.32589815 +v 0.74338194 -0.17231662 0.58581363 +v 0.74346310 -0.17231662 -0.58581363 +v 0.64957532 -0.17231662 0.76515192 +v 0.64961490 -0.17231662 -0.76515192 +v 0.49342863 -0.17225596 0.88593197 +v 0.49776871 -0.17231662 -0.89316590 +v 0.26815885 -0.21120550 0.96454134 +v 0.27707577 -0.18062568 -0.99714690 +v 1.5668651e-5 -0.25999766 0.98195778 +v 9.5080309e-6 -0.22812210 -1.03370100 +v -0.26814535 -0.21120550 0.96454134 +v -0.27707162 -0.18062899 -0.99714690 +v -0.49345385 -0.17225596 0.88593197 +v -0.49779829 -0.17231662 -0.89316590 +v -0.64929165 -0.17231662 0.76476128 +v -0.64967897 -0.17231662 -0.76515192 +v -0.74335249 -0.17231662 0.58543729 +v -0.74371775 -0.17231662 -0.58581363 +v -0.81078126 -0.17231662 0.32589815 +v -0.81078126 -0.17231662 -0.32589815 +v -0.84589252 -0.17231662 1.7347235e-18 +v -0.84754178 -0.19293488 8.7365110e-5 +v -0.81296808 -0.19293488 -0.32678303 +v -0.81296808 -0.19293488 0.32695776 +v -0.74723498 -0.19293488 -0.58844697 +v -0.74676284 -0.19293488 0.58809838 +v -0.65379763 -0.19293488 -0.76962181 +v -0.65328836 -0.19293488 0.76926445 +v -0.50026865 -0.19293488 -0.89704437 +v -0.49718058 -0.19295261 0.89195908 +v -0.27796384 -0.20889164 -0.99974826 +v -0.27154225 -0.23221607 0.97788321 +v -0.58379818 -0.19293488 0.83665017 +v -0.39289460 -0.20885166 0.94271251 +v -0.13890928 -0.26800830 0.99731747 +v 0.13892974 -0.26800830 0.99731749 +v 0.39288527 -0.20885166 0.94271252 +v 0.58374927 -0.19293488 0.83665017 +v 0.58459255 -0.19293488 -0.83759333 +v 0.39756446 -0.20824464 -0.95313996 +v 0.14287195 -0.23405292 -1.03070706 +v -0.14285896 -0.23405311 -1.02915174 +v -0.39757860 -0.20824736 -0.95313996 +v -0.58464358 -0.19293488 -0.83759333 +v 0.69830098 -0.19293488 -0.68786653 +v 0.78319395 -0.19293488 -0.46753299 +v 0.83816390 -0.19293488 -0.16789330 +v 0.83816390 -0.19293488 0.16806803 +v 0.78319720 -0.19293488 0.46770772 +v 0.69821746 -0.19293488 0.68804126 +v -0.69854500 -0.19293488 -0.68786653 +v -0.78317127 -0.19293488 -0.46753299 +v -0.83814109 -0.19293488 -0.16789330 +v -0.83814109 -0.19293488 0.16806803 +v -0.78317453 -0.19293488 0.46770772 +v -0.69802955 -0.19293488 0.68750552 +v 0.84756458 -0.19293488 8.7365110e-5 +v 0.81299089 -0.19293488 0.32695776 +v 0.81299089 -0.19293488 -0.32678303 +v 0.74689863 -0.19293488 0.58862170 +v 0.74697682 -0.19293488 -0.58844697 +v 0.65369408 -0.19293488 0.76979654 +v 0.65372997 -0.19293488 -0.76962181 +v 0.49715170 -0.19295261 0.89195908 +v 0.50023611 -0.19293488 -0.89704437 +v 0.27155076 -0.23221606 0.97788323 +v 0.27796562 -0.20888705 -0.99974826 +v 1.2252562e-5 -0.28085970 1.00468640 +v 8.4288755e-6 -0.26119221 -1.01173727 +v -0.69164277 -0.21352367 0.68142482 +v -0.77525699 -0.21352367 0.46311148 +v -0.82905213 -0.21352367 0.16628513 +v -0.82905213 -0.21352367 -0.16611415 +v -0.77525381 -0.21352367 -0.46294095 +v -0.69222805 -0.21352367 -0.68187947 +v 0.69190440 -0.21352367 0.68204930 +v 0.77527942 -0.21352367 0.46311148 +v 0.82907470 -0.21352367 0.16628513 +v 0.82907470 -0.21352367 -0.16611415 +v 0.77527624 -0.21352367 -0.46294095 +v 0.69198687 -0.21352367 -0.68187947 +v -0.57939304 -0.21352367 -0.83021584 +v -0.39353920 -0.22950038 -0.94360989 +v -0.14128950 -0.26478753 -0.99165256 +v 0.14130412 -0.26478673 -1.01953081 +v 0.39352688 -0.22950184 -0.94360989 +v 0.57934402 -0.21352367 -0.83021584 +v 0.57867451 -0.21352367 0.82950712 +v 0.38979093 -0.22977266 0.93536101 +v 0.13804567 -0.28867717 0.99434247 +v -0.13802487 -0.28867692 0.99434199 +v -0.38979875 -0.22977297 0.93535992 +v -0.57872149 -0.21352367 0.82950712 +v -0.26994159 -0.25320886 0.97229897 +v -0.27499477 -0.23088992 -0.98924929 +v -0.49314271 -0.21355085 0.88480719 +v -0.49547561 -0.21352367 -0.88860830 +v -0.64751298 -0.21352367 0.76266112 +v -0.63685771 -0.21352367 -0.76310779 +v -0.73949044 -0.21352367 0.58254882 +v -0.74002672 -0.21352367 -0.58298991 +v -0.80442975 -0.21352367 0.32358291 +v -0.80442975 -0.21352367 -0.32341210 +v -0.83823766 -0.21352367 8.5522330e-5 +v 0.83826022 -0.21352367 8.5522330e-5 +v 0.80445232 -0.21352367 0.32358291 +v 0.80445232 -0.21352367 -0.32341210 +v 0.73969480 -0.21352367 0.58316011 +v 0.73977191 -0.21352367 -0.58298991 +v 0.64799508 -0.21352367 0.76327742 +v 0.64803060 -0.21352367 -0.76310779 +v 0.49311539 -0.21355085 0.88480724 +v 0.49544500 -0.21352367 -0.88860830 +v 0.26995101 -0.25320830 0.97230014 +v 0.27499827 -0.23088622 -0.98924929 +v 1.2298073e-5 -0.30136149 1.00263090 +v 9.2293870e-6 -0.28559732 -0.98538279 +v 2.1590966e-5 -0.22890059 0.93109909 +v 0.27577513 -0.17231334 0.90939033 +v 0.40317476 -0.13450178 0.96613265 +v 0.14880523 -0.21002865 0.92366263 +v -0.14876737 -0.21002865 0.92366263 +v -0.40318788 -0.13450178 0.96613265 +v -0.27575146 -0.17231334 0.90939033 +v 0.27921196 -6.4845613e-2 0.92206478 +v 2.1098247e-5 7.0258216e-2 0.94179068 +v 0.41061861 -0.10485776 0.98320800 +v 0.15231794 4.9644762e-2 0.93426273 +v -0.15228147 4.9644762e-2 0.93426273 +v -0.41063616 -0.10485776 0.98320800 +v -0.27919002 -6.4845613e-2 0.92206478 +v -0.14348375 -0.17676648 0.92601124 +v 2.1898477e-5 -0.19520041 0.93362477 +v 0.14352262 -0.17676648 0.92601124 +v 0.21344629 -0.14378025 0.91109901 +v 0.21495135 -7.8903360e-2 0.92080916 +v 0.13671166 1.7559603e-2 0.93202640 +v 2.1798434e-5 3.6080989e-2 0.93922794 +v -0.13667256 1.7559603e-2 0.93202640 +v -0.21491865 -7.8903360e-2 0.92080916 +v -0.21341218 -0.14378025 0.91109901 +v -0.14310232 -0.17912663 1.02383701 +v 1.1595038e-5 -0.19720143 1.03111939 +v 0.14312107 -0.17912663 1.02383701 +v 0.21248762 -0.14617126 1.00959003 +v 0.21375923 -8.2046970e-2 1.01887959 +v 0.13623395 1.2736009e-2 1.02974238 +v 1.1530746e-5 3.1565965e-2 1.03659851 +v -0.13621495 1.2736009e-2 1.02974238 +v -0.21374598 -8.2046970e-2 1.01887959 +v -0.21247301 -0.14617126 1.00959003 +v -0.15901485 -0.19570750 1.09652799 +v 3.4520158e-6 -0.21471657 1.10432010 +v 0.15901649 -0.19570750 1.09652799 +v 0.23658344 -0.15871741 1.08141894 +v 0.23789284 -8.7289987e-2 1.09125955 +v 0.15151222 1.6911360e-2 1.10298745 +v 3.4914142e-6 3.9020001e-2 1.11016930 +v -0.15151009 1.6911360e-2 1.10298745 +v -0.23789762 -8.7289987e-2 1.09125955 +v -0.23658688 -0.15871741 1.08141894 +v -0.17249257 -0.20494049 1.17710591 +v -5.5435911e-13 -0.23354008 1.19375880 +v 0.17249257 -0.20494049 1.17710591 +v 0.26114532 -0.16132612 1.16189030 +v 0.26156562 -7.9031692e-2 1.16442939 +v 0.16548905 3.0441506e-2 1.16820445 +v -5.4584116e-13 5.8672792e-2 1.17270115 +v -0.16548905 3.0441506e-2 1.16820445 +v -0.26156562 -7.9031692e-2 1.16442939 +v -0.26114532 -0.16132612 1.16189030 +v -0.18946243 -0.22605539 1.31516064 +v -6.1609217e-13 -0.26360473 1.33976811 +v 0.18946243 -0.22605539 1.31516064 +v 0.28783538 -0.16014565 1.28089814 +v 0.28808052 -5.9589789e-2 1.27317239 +v 0.18191747 7.2580511e-2 1.26355428 +v -5.9910625e-13 0.10610455 1.26565624 +v -0.18191747 7.2580511e-2 1.26355428 +v -0.28808052 -5.9589789e-2 1.27317239 +v -0.28783538 -0.16014565 1.28089814 +v -0.17549571 -0.21571126 1.42869863 +v -6.2801241e-13 -0.25189019 1.45066119 +v 0.17549571 -0.21571126 1.42869863 +v 0.26728462 -0.14729722 1.39478294 +v 0.26741086 -4.2923560e-2 1.38574347 +v 0.16869638 8.8267918e-2 1.37935018 +v -6.0854885e-13 0.11888628 1.38499248 +v -0.16869638 8.8267918e-2 1.37935018 +v -0.26741086 -4.2923560e-2 1.38574347 +v -0.26728462 -0.14729722 1.39478294 +v -0.13223964 -0.17854901 1.53663699 +v -6.3180637e-13 -0.19625803 1.53985795 +v 0.13223964 -0.17854901 1.53663699 +v 0.20448715 -0.11719334 1.50455398 +v 0.20464545 -3.4120639e-2 1.49678437 +v 0.12822971 6.6255239e-2 1.48977581 +v -6.1414192e-13 9.0467078e-2 1.49088483 +v -0.12822971 6.6255239e-2 1.48977581 +v -0.20464545 -3.4120639e-2 1.49678437 +v -0.20448715 -0.11719334 1.50455398 +v -9.3754471e-2 -0.13842626 1.57914566 +v -6.3091244e-13 -0.15595273 1.58677152 +v 9.3754471e-2 -0.13842626 1.57914566 +v 0.14698645 -9.6245048e-2 1.56424795 +v 0.14659759 -3.5596172e-2 1.55654746 +v 9.1467784e-2 2.7553484e-2 1.55242889 +v -6.1819833e-13 4.8827618e-2 1.55231761 +v -9.1467784e-2 2.7553484e-2 1.55242889 +v -0.14659759 -3.5596172e-2 1.55654746 +v -0.14698645 -9.6245048e-2 1.56424795 +v -7.5279503e-2 -9.6038325e-2 1.60538739 +v -6.2861478e-13 -0.10907335 1.61144226 +v 7.5279503e-2 -9.6038325e-2 1.60538739 +v 0.10544536 -7.4515356e-2 1.59599145 +v 0.10472165 -5.0508201e-2 1.59352296 +v 6.7937092e-2 -1.1263571e-2 1.59195345 +v -6.2151337e-13 4.4510697e-3 1.59210724 +v -6.7937092e-2 -1.1263571e-2 1.59195345 +v -0.10472165 -5.0508201e-2 1.59352296 +v -0.10544536 -7.4515356e-2 1.59599145 +v -0.24045346 -0.17245290 -1.01076812 +v -0.25240991 -0.11929160 -1.06127557 +v -0.13216743 -5.8414741e-2 -1.09379240 +v 3.4290518e-6 -4.6073013e-2 -1.10173312 +v 0.13217065 -5.8413622e-2 -1.09379242 +v 0.25240359 -0.11928680 -1.06127550 +v 0.24045683 -0.17245038 -1.01076800 +v 0.12631531 -0.20019429 -1.04261536 +v 8.8251224e-6 -0.20811522 -1.04356180 +v -0.12630123 -0.20019369 -1.04126067 +v -0.19646081 -0.18140706 -0.99566199 +v -0.20146716 -0.12807735 -1.06646296 +v -0.11640133 -7.6258125e-2 -1.13293878 +v 2.5966252e-6 -6.1374303e-2 -1.15931936 +v 0.11640448 -7.6256410e-2 -1.13293875 +v 0.20146704 -0.12807358 -1.06646281 +v 0.19646606 -0.18140451 -0.99566179 +v 0.11228578 -0.21607708 -1.01599771 +v 7.6365863e-6 -0.23109048 -1.02938648 +v -0.11227336 -0.21607751 -1.01395982 +v -0.16088640 -0.19289390 -1.11793082 +v -0.16498624 -0.14922070 -1.18873179 +v -9.5323449e-2 -0.10166282 -1.24303601 +v 2.9820251e-6 -7.9917923e-2 -1.24794155 +v 9.5327746e-2 -0.10166119 -1.24303543 +v 0.16498786 -0.14921762 -1.18873164 +v 0.16089242 -0.19289181 -1.11793062 +v 9.1954827e-2 -0.21100897 -1.11384293 +v 7.1093901e-6 -0.21550971 -1.11150406 +v -9.1942944e-2 -0.21100830 -1.11384054 +v -0.10232196 -0.17948849 -1.28628563 +v -0.10492946 -0.15116858 -1.34032734 +v -6.0623924e-2 -0.12300153 -1.37050718 +v 3.6862676e-6 -0.11468203 -1.37939847 +v 6.0630236e-2 -0.12300061 -1.37050637 +v 0.10493407 -0.15116654 -1.34032464 +v 0.10232937 -0.17948713 -1.28628464 +v 5.8485060e-2 -0.19665448 -1.27914466 +v 6.3112716e-6 -0.20396080 -1.27901934 +v -5.8473923e-2 -0.19665467 -1.27914372 +v -4.7006179e-2 -0.17825084 -1.46143393 +v -4.8204115e-2 -0.16789983 -1.46383111 +v -2.7849294e-2 -0.15824544 -1.46568783 +v 4.2039561e-6 -0.15420516 -1.46770553 +v 2.7857215e-2 -0.15824550 -1.46568744 +v 4.8211253e-2 -0.16789999 -1.46383023 +v 4.7014602e-2 -0.17825097 -1.46143331 +v 2.6871679e-2 -0.17343872 -1.47339416 +v 5.4099339e-6 -0.17015717 -1.47997630 +v -2.6861542e-2 -0.17343869 -1.47339427 +vt 1.4699972e-2 0.62463149 +vt 1.7568090e-2 0.57942934 +vt 1.7844723e-2 0.66969902 +vt 2.5694925e-2 0.53702042 +vt 2.5859044e-2 0.71157587 +vt 2.6439066e-2 0.62460228 +vt 2.9246019e-2 0.58114934 +vt 2.9406655e-2 0.66796562 +vt 3.5125644e-2 0.74690651 +vt 3.6123860e-2 0.50113991 +vt 3.6939827e-2 0.54033069 +vt 3.6987015e-2 0.70848435 +vt 3.9393174e-2 0.62457293 +vt 4.2164999e-2 0.58360926 +vt 4.2164999e-2 0.66550196 +vt 4.5811016e-2 0.74256240 +vt 4.6435016e-2 0.77705737 +vt 4.6754031e-2 0.50579027 +vt 4.8246356e-2 0.47159392 +vt 4.9333364e-2 0.70398272 +vt 4.9333364e-2 0.54512850 +vt 5.4976663e-2 0.62456873 +vt 5.5290194e-2 0.62710168 +vt 5.6646707e-2 0.77106817 +vt 5.6790623e-2 0.59189466 +vt 5.7219021e-2 0.66255949 +vt 5.7219021e-2 0.58655173 +vt 5.7618642e-2 0.73598386 +vt 5.8084121e-2 0.47756123 +vt 5.8271880e-2 0.66234267 +vt 5.8465836e-2 0.51267966 +vt 5.8874084e-2 8.2416183e-2 +vt 5.9550063e-2 0.13227794 +vt 6.0791752e-2 7.0983736e-2 +vt 6.0952480e-2 0.44863288 +vt 6.1179690e-2 0.80205027 +vt 6.2000367e-2 0.55879039 +vt 6.2377665e-2 0.11609845 +vt 6.2547432e-2 0.11758030 +vt 6.4033991e-2 0.69822725 +vt 6.4033991e-2 0.55088397 +vt 6.5121953e-2 0.69561902 +vt 6.6520311e-2 0.12227641 +vt 6.7216260e-2 0.13309515 +vt 6.8081900e-2 0.76250752 +vt 6.8458677e-2 7.0075410e-2 +vt 6.9266477e-2 0.48606507 +vt 6.9474486e-2 0.12054248 +vt 6.9624704e-2 0.52996482 +vt 7.0918773e-2 0.79448528 +vt 7.1753759e-2 0.72791739 +vt 7.2095842e-2 0.45523507 +vt 7.2619639e-2 0.52106883 +vt 7.4586777e-2 0.72444649 +vt 7.5975997e-2 0.82282074 +vt 7.6156736e-2 0.12382144 +vt 7.6297024e-2 0.42946160 +vt 7.6850989e-2 0.13340619 +vt 7.7795717e-2 0.11726505 +vt 7.8777082e-2 0.50519284 +vt 8.1525047e-2 0.75191609 +vt 8.1740624e-2 0.78380969 +vt 8.2420311e-2 0.46514348 +vt 8.2717418e-2 0.49650164 +vt 8.3057583e-2 0.14670897 +vt 8.3748082e-2 0.15350585 +vt 8.4489210e-2 0.43727210 +vt 8.4521992e-2 0.13802773 +vt 8.4731569e-2 0.81375749 +vt 8.5757971e-2 0.74910030 +vt 8.6675186e-2 9.4135526e-2 +vt 8.7691764e-2 8.5997943e-2 +vt 8.7930426e-2 0.11982748 +vt 8.8005178e-2 0.12091118 +vt 8.9179455e-2 0.48447456 +vt 8.9265728e-2 0.12352452 +vt 9.1063753e-2 0.12425112 +vt 9.1202181e-2 8.3114962e-2 +vt 9.2248074e-2 0.13165811 +vt 9.3680661e-2 0.41327851 +vt 9.3717334e-2 0.11846896 +vt 9.3983079e-2 0.44812667 +vt 9.4258746e-2 0.77091567 +vt 9.4418131e-2 0.17332045 +vt 9.4850057e-2 0.47721325 +vt 9.5104977e-2 0.18009216 +vt 9.5597330e-2 0.16862252 +vt 9.5923331e-2 0.62614586 +vt 9.6235236e-2 0.15273045 +vt 9.6431925e-2 0.84070733 +vt 9.6965488e-2 0.59636676 +vt 9.7296538e-2 0.80150116 +vt 9.7561553e-2 0.13606334 +vt 9.8332668e-2 0.76935604 +vt 9.8351871e-2 0.65588208 +vt 0.10028473 0.56644132 +vt 0.10046336 0.46634528 +vt 0.10149071 0.42186542 +vt 0.10279911 0.17654056 +vt 0.10319445 0.68568666 +vt 0.10380084 0.83057550 +vt 0.10389030 0.16618533 +vt 0.10511520 0.54282522 +vt 0.10514846 0.19610256 +vt 0.10583159 0.20071264 +vt 0.10605749 0.19957948 +vt 0.10746518 0.46152929 +vt 0.10868948 0.78659466 +vt 0.10899884 0.19572428 +vt 0.10944095 0.70901881 +vt 0.10968224 0.20170285 +vt 0.10986777 0.20201812 +vt 0.11012102 0.43369873 +vt 0.11131653 0.51908330 +vt 0.11210598 0.78667684 +vt 0.11242134 0.81732661 +vt 0.11426731 0.13518137 +vt 0.11426741 0.15200477 +vt 0.11426746 0.12401301 +vt 0.11426757 0.17748769 +vt 0.11426767 0.19578260 +vt 0.11451965 0.45219792 +vt 0.11494988 0.20340361 +vt 0.11495113 0.20233597 +vt 0.11495190 0.16566161 +vt 0.11495381 0.11462049 +vt 0.11495439 0.13534207 +vt 0.11495481 0.12076239 +vt 0.11495510 0.11979810 +vt 0.11495573 0.12387411 +vt 0.11620318 8.8544748e-2 +vt 0.11620320 8.5889351e-2 +vt 0.11620390 9.8521565e-2 +vt 0.11630596 0.40073373 +vt 0.11736110 0.73235951 +vt 0.11803264 0.50187438 +vt 0.11953639 0.19572421 +vt 0.11984131 0.44802724 +vt 0.12003206 0.20201814 +vt 0.12021980 0.20170293 +vt 0.12077963 0.85602075 +vt 0.12263429 0.80110010 +vt 0.12322547 0.40950869 +vt 0.12338659 0.19610242 +vt 0.12384265 0.19957959 +vt 0.12406972 0.20071281 +vt 0.12549847 0.74887033 +vt 0.12573580 0.17654035 +vt 0.12575170 0.48465685 +vt 0.12601450 0.16618515 +vt 0.12636651 0.80104557 +vt 0.12669314 0.84533807 +vt 0.12819525 0.62535684 +vt 0.13020955 0.42165384 +vt 0.13071045 0.57608225 +vt 0.13229920 0.15273023 +vt 0.13234803 0.13606296 +vt 0.13288913 0.67436004 +vt 0.13319340 0.43942982 +vt 0.13374368 0.83143999 +vt 0.13411634 0.17331983 +vt 0.13430959 0.16862260 +vt 0.13480319 0.18009250 +vt 0.13494284 0.76511652 +vt 0.13619544 0.11810973 +vt 0.13628609 0.13165798 +vt 0.13766796 0.43666887 +vt 0.13770697 0.53438304 +vt 0.13858034 0.47374829 +vt 0.13884923 0.12401238 +vt 0.13926846 0.12352444 +vt 0.14120491 8.3114779e-2 +vt 0.14190689 0.12066965 +vt 0.14197989 0.11955332 +vt 0.14216719 0.71518668 +vt 0.14219706 0.81439284 +vt 0.14295729 0.38906603 +vt 0.14418638 0.81498567 +vt 0.14471533 8.5997737e-2 +vt 0.14539033 0.13802762 +vt 0.14547616 0.14670872 +vt 0.14573332 9.4134903e-2 +vt 0.14616665 0.15350567 +vt 0.14651797 0.50240812 +vt 0.14930165 0.39805061 +vt 0.14947429 0.77555941 +vt 0.14967099 0.86946075 +vt 0.15212256 0.11726491 +vt 0.15237659 0.12382114 +vt 0.15272212 0.62476489 +vt 0.15307084 0.13340596 +vt 0.15313139 0.74574064 +vt 0.15414637 0.58409868 +vt 0.15453081 0.85847160 +vt 0.15481852 0.41101285 +vt 0.15521856 0.46467419 +vt 0.15561102 0.66521913 +vt 0.15664279 0.42745557 +vt 0.15822308 0.54789079 +vt 0.15977774 0.84418295 +vt 0.15981268 0.42681643 +vt 0.16044445 0.12054233 +vt 0.16138767 0.70066661 +vt 0.16201186 0.12227605 +vt 0.16270781 0.13309483 +vt 0.16344417 0.51869034 +vt 0.16395023 7.0074637e-2 +vt 0.16431545 0.78495276 +vt 0.16593999 0.82676375 +vt 0.16641429 0.82739926 +vt 0.16737108 0.11758007 +vt 0.16753841 0.11609813 +vt 0.16827749 0.72878395 +vt 0.17037587 0.13227754 +vt 0.17161756 7.0982796e-2 +vt 0.17353679 8.2414816e-2 +vt 0.17385959 0.48674435 +vt 0.17728897 0.45558611 +vt 0.17753789 0.38323676 +vt 0.17767158 0.62420076 +vt 0.17951562 0.57802418 +vt 0.18009537 0.75897858 +vt 0.18061457 0.67010573 +vt 0.18296178 0.87697366 +vt 0.18317087 0.79386622 +vt 0.18333565 0.53827002 +vt 0.18398425 0.39298530 +vt 0.18611418 0.70878193 +vt 0.18667255 0.86670489 +vt 0.18764865 0.40611443 +vt 0.18807873 0.42438714 +vt 0.18838554 0.50772686 +vt 0.18962184 0.42200312 +vt 0.18990407 0.85289185 +vt 0.19265076 0.73745264 +vt 0.19311298 0.83542167 +vt 0.19341629 0.83580999 +vt 0.20177435 0.44975414 +vt 0.20496162 0.80028992 +vt 0.21151878 0.47533816 +vt 0.21209563 0.62351070 +vt 0.21378289 0.38531406 +vt 0.21412752 0.57231309 +vt 0.21412752 0.67470831 +vt 0.21505996 0.77007141 +vt 0.21655289 0.53014388 +vt 0.21699095 0.39447945 +vt 0.21837276 0.71519743 +vt 0.21880257 0.40650963 +vt 0.21929229 0.87760986 +vt 0.22006863 0.49966318 +vt 0.22016891 0.42178279 +vt 0.22090758 0.42894823 +vt 0.22111859 0.86888366 +vt 0.22240454 0.74427893 +vt 0.22248586 0.85619398 +vt 0.22390276 0.83995948 +vt 0.22474335 0.83631959 +vt 0.22696098 0.44365999 +vt 0.23055022 0.80290234 +vt 0.25353668 0.87768578 +vt 0.25353794 0.87004910 +vt 0.25354088 0.85770151 +vt 0.25354507 0.84176953 +vt 0.25361414 0.42168412 +vt 0.25362852 0.40596273 +vt 0.25364975 0.39379768 +vt 0.25367098 0.38408854 +vt 0.25571426 0.77447154 +vt 0.25575697 0.56981420 +vt 0.25575697 0.62351070 +vt 0.25575697 0.67720721 +vt 0.25576388 0.74686230 +vt 0.25579586 0.83799917 +vt 0.25580793 0.71800868 +vt 0.25583306 0.52677674 +vt 0.25584173 0.80457076 +vt 0.25587403 0.49691383 +vt 0.25593752 0.47264171 +vt 0.25599829 0.44688646 +vt 0.25604879 0.42888066 +vt 0.27362782 0.13668852 +vt 0.27621400 0.12590377 +vt 0.27695518 0.10440522 +vt 0.27762891 0.11986916 +vt 0.27836412 0.10054154 +vt 0.28031121 8.9393285e-2 +vt 0.28091719 9.3577166e-2 +vt 0.28122634 0.80280382 +vt 0.28319193 0.83997462 +vt 0.28459981 0.85620829 +vt 0.28503138 0.44381578 +vt 0.28595920 0.86889830 +vt 0.28675373 0.83629424 +vt 0.28714360 0.42180578 +vt 0.28778145 0.87762421 +vt 0.28850769 0.40653765 +vt 0.28917497 0.74420513 +vt 0.29031203 0.39452568 +vt 0.29115685 0.42916273 +vt 0.29166567 0.49977378 +vt 0.29330472 0.71522446 +vt 0.29351375 0.38537788 +vt 0.29511036 0.53020395 +vt 0.29738641 0.57231309 +vt 0.29738641 0.67470831 +vt 0.29740850 0.76982390 +vt 0.29774548 0.15348957 +vt 0.29941830 0.62351070 +vt 0.29971107 0.14132996 +vt 0.30031085 0.47552117 +vt 0.30181980 0.11594471 +vt 0.30247025 9.8239759e-2 +vt 0.30252577 0.11612549 +vt 0.30326647 8.2695023e-2 +vt 0.30390904 8.7344842e-2 +vt 0.30641745 0.80044600 +vt 0.31013643 0.45003232 +vt 0.31367254 0.83582929 +vt 0.31397751 0.11359852 +vt 0.31426247 0.10306492 +vt 0.31469894 0.11433008 +vt 0.31718119 0.85291240 +vt 0.31765872 0.42203796 +vt 0.31817661 0.83569214 +vt 0.31898895 0.73754962 +vt 0.31963977 0.40616657 +vt 0.32040674 0.86672489 +vt 0.32076701 0.17101829 +vt 0.32206441 0.15876213 +vt 0.32329307 0.39305926 +vt 0.32332333 0.50791713 +vt 0.32390157 0.42480672 +vt 0.32411486 0.87699715 +vt 0.32520126 0.70844944 +vt 0.32639937 0.13206338 +vt 0.32649082 9.0619997e-2 +vt 0.32749028 9.6218087e-2 +vt 0.32799454 0.53848914 +vt 0.32815490 0.79409096 +vt 0.32835559 7.5021349e-2 +vt 0.32867330 8.0172096e-2 +vt 0.32938739 0.12784881 +vt 0.32973198 0.38331606 +vt 0.33097580 0.67027907 +vt 0.33142345 0.75903448 +vt 0.33214404 0.57793790 +vt 0.33380937 0.62420275 +vt 0.33451669 0.45594798 +vt 0.33781474 0.48702155 +vt 0.34113437 0.82678171 +vt 0.34306873 0.72875896 +vt 0.34541973 0.82765809 +vt 0.34730458 0.84420602 +vt 0.34746274 0.42686835 +vt 0.34795863 0.51888872 +vt 0.34870020 0.78436896 +vt 0.35026640 0.70057670 +vt 0.35246023 0.41107532 +vt 0.35255065 0.85849286 +vt 0.35342572 0.54793469 +vt 0.35463427 7.2236706e-2 +vt 0.35463492 7.7565880e-2 +vt 0.35463604 8.6785078e-2 +vt 0.35463610 9.2445907e-2 +vt 0.35483618 0.17623612 +vt 0.35494149 0.16376117 +vt 0.35517803 0.13590855 +vt 0.35519291 0.42800886 +vt 0.35521621 0.13136673 +vt 0.35585090 0.66520837 +vt 0.35646467 0.46508170 +vt 0.35733058 0.58418850 +vt 0.35741225 0.86947595 +vt 0.35798391 0.39808991 +vt 0.35837108 0.74553641 +vt 0.35874451 0.62481387 +vt 0.36356177 0.77490476 +vt 0.36431882 0.38908692 +vt 0.36488453 0.81438321 +vt 0.36495010 0.50268103 +vt 0.36766397 0.81507427 +vt 0.36928253 0.71530959 +vt 0.36959011 0.43668048 +vt 0.37298834 0.47415990 +vt 0.37333398 0.83144220 +vt 0.37379156 0.53453787 +vt 0.37668301 0.76500718 +vt 0.37703928 0.42167318 +vt 0.37846835 0.44002505 +vt 0.37862160 0.67426325 +vt 0.38037659 0.84534568 +vt 0.38059567 8.0172096e-2 +vt 0.38072294 0.57617432 +vt 0.38091219 7.5021347e-2 +vt 0.38109950 0.12828204 +vt 0.38178099 9.6218087e-2 +vt 0.38278026 9.0619997e-2 +vt 0.38324612 0.62535701 +vt 0.38400925 0.40951334 +vt 0.38401599 0.13254608 +vt 0.38441887 0.80110922 +vt 0.38559418 0.80090014 +vt 0.38570314 0.48502649 +vt 0.38610153 0.74870313 +vt 0.38629160 0.85603690 +vt 0.38739351 0.44802021 +vt 0.38789664 0.15931365 +vt 0.38898800 0.17158983 +vt 0.39092633 0.40073907 +vt 0.39335184 0.50217212 +vt 0.39413775 0.73236821 +vt 0.39462827 0.81734949 +vt 0.39500789 0.10306492 +vt 0.39529259 0.11359852 +vt 0.39601117 0.11501129 +vt 0.39697764 0.45277128 +vt 0.39712740 0.43369555 +vt 0.39834645 0.78656848 +vt 0.39933158 0.51890576 +vt 0.39961912 0.78638721 +vt 0.39970776 0.46149668 +vt 0.40210972 0.70899692 +vt 0.40326514 0.83057628 +vt 0.40535743 8.7344842e-2 +vt 0.40574381 0.42184197 +vt 0.40599905 8.2695023e-2 +vt 0.40623042 0.54300873 +vt 0.40679814 9.8239759e-2 +vt 0.40744826 0.11594471 +vt 0.40815052 0.11701039 +vt 0.40826313 0.68551295 +vt 0.40972865 0.80150027 +vt 0.41053741 0.14225844 +vt 0.41064702 0.84068796 +vt 0.41091052 0.46685890 +vt 0.41106666 0.56656409 +vt 0.41228675 0.47716725 +vt 0.41229674 0.15444926 +vt 0.41275249 0.77090468 +vt 0.41308918 0.65575261 +vt 0.41318988 0.76929876 +vt 0.41324082 0.44810678 +vt 0.41354836 0.41325736 +vt 0.41439735 0.59638835 +vt 0.41546859 0.62609693 +vt 0.42211353 0.48491275 +vt 0.42232130 0.81375461 +vt 0.42267373 0.49651061 +vt 0.42271226 0.43724019 +vt 0.42472333 0.46511543 +vt 0.42525873 0.78380606 +vt 0.42550476 0.75190230 +vt 0.42579992 0.74886958 +vt 0.42834567 9.3577166e-2 +vt 0.42895093 8.9393285e-2 +vt 0.43089732 0.10054154 +vt 0.43091488 0.42944615 +vt 0.43107181 0.82280928 +vt 0.43187414 0.50493790 +vt 0.43230541 0.10440522 +vt 0.43297369 0.12117061 +vt 0.43428641 0.12722806 +vt 0.43448446 0.52103547 +vt 0.43500724 0.45519006 +vt 0.43530978 0.72790997 +vt 0.43609129 0.79448163 +vt 0.43668991 0.13805462 +vt 0.43692826 0.72445578 +vt 0.43783668 0.48606602 +vt 0.43893462 0.76249905 +vt 0.44156180 0.53009793 +vt 0.44304416 0.69822725 +vt 0.44304416 0.55088397 +vt 0.44408537 0.44808772 +vt 0.44584172 0.80204048 +vt 0.44638225 0.69531703 +vt 0.44863948 0.51266513 +vt 0.44899431 0.47757768 +vt 0.44925078 0.55880527 +vt 0.44944598 0.73597447 +vt 0.44985913 0.58655173 +vt 0.44985913 0.66255949 +vt 0.45035955 0.77106211 +vt 0.45210047 0.62457296 +vt 0.45310638 0.66215679 +vt 0.45447875 0.59189142 +vt 0.45602042 0.62698867 +vt 0.45774479 0.70398272 +vt 0.45774479 0.54512850 +vt 0.45879569 0.47156363 +vt 0.46035551 0.50578501 +vt 0.46056573 0.77705152 +vt 0.46125902 0.74255596 +vt 0.46491315 0.66550196 +vt 0.46491315 0.58360926 +vt 0.46768382 0.62457606 +vt 0.47009019 0.70848313 +vt 0.47014566 0.54033924 +vt 0.47098785 0.50113520 +vt 0.47194531 0.74690820 +vt 0.47767051 0.66796969 +vt 0.47782006 0.58114870 +vt 0.48064192 0.62460323 +vt 0.48121833 0.71157566 +vt 0.48139516 0.53703506 +vt 0.48923243 0.66970525 +vt 0.48949313 0.57942836 +vt 0.49238032 0.62463023 +vt 0.51640180 0.62532389 +vt 0.51809929 0.58273135 +vt 0.51809929 0.66804072 +vt 0.52260840 0.54271404 +vt 0.52260840 0.70838817 +vt 0.52784323 0.50766791 +vt 0.52784356 0.74381759 +vt 0.53085590 0.62524131 +vt 0.53239804 0.58404698 +vt 0.53239804 0.66655278 +vt 0.53417365 0.77398618 +vt 0.53418742 0.47796331 +vt 0.53650784 0.54526468 +vt 0.53650784 0.70564754 +vt 0.54128045 0.51113846 +vt 0.54128077 0.74014090 +vt 0.54269122 0.79857761 +vt 0.54270579 0.45399554 +vt 0.54417222 0.62534471 +vt 0.54562373 0.58630517 +vt 0.54562373 0.66449052 +vt 0.54706540 0.76966635 +vt 0.54707864 0.48205879 +vt 0.54757678 0.62521695 +vt 0.54874280 0.62586617 +vt 0.54900449 0.58607746 +vt 0.54900449 0.66446097 +vt 0.54950467 0.54950426 +vt 0.54950467 0.70157558 +vt 0.55024980 0.81900732 +vt 0.55025643 0.43411895 +vt 0.55075161 0.66478094 +vt 0.55102118 0.58724200 +vt 0.55282759 0.54914668 +vt 0.55282759 0.70167167 +vt 0.55393381 0.62588386 +vt 0.55412524 0.51701750 +vt 0.55412553 0.73440065 +vt 0.55490598 0.79388279 +vt 0.55492005 0.45844011 +vt 0.55592045 0.66405697 +vt 0.55612669 0.58797392 +vt 0.55659774 0.70182385 +vt 0.55677729 0.55087633 +vt 0.55735244 0.51647379 +vt 0.55735293 0.73467586 +vt 0.55973210 0.76259116 +vt 0.55974443 0.48923795 +vt 0.56064378 0.41698810 +vt 0.56136022 0.83697107 +vt 0.56165232 0.70040559 +vt 0.56173922 0.55220462 +vt 0.56203656 0.81391850 +vt 0.56204297 0.43893852 +vt 0.56274845 0.16093661 +vt 0.56285333 0.76308780 +vt 0.56286520 0.48846503 +vt 0.56374245 0.51875226 +vt 0.56443101 0.73466567 +vt 0.56483229 0.13579041 +vt 0.56719520 0.78580670 +vt 0.56720836 0.46656886 +vt 0.56783820 0.18435295 +vt 0.56827775 0.11873201 +vt 0.56854916 0.52059364 +vt 0.56928704 0.73265990 +vt 0.56946744 0.40176469 +vt 0.57024586 0.78655411 +vt 0.57025855 0.46554000 +vt 0.57208399 0.42250465 +vt 0.57225875 0.49093023 +vt 0.57302621 0.83117025 +vt 0.57311340 0.10397345 +vt 0.57398509 0.80495455 +vt 0.57399111 0.44791788 +vt 0.57415811 0.76249331 +vt 0.57455842 8.3875358e-2 +vt 0.57479133 0.85336553 +vt 0.57595457 0.62590265 +vt 0.57685870 0.49327992 +vt 0.57701499 0.80587633 +vt 0.57702044 0.44671313 +vt 0.57759727 0.65962298 +vt 0.57760373 0.59229077 +vt 0.57870999 0.75988821 +vt 0.58099243 0.40807861 +vt 0.58103575 0.38752953 +vt 0.58112291 0.13832737 +vt 0.58148411 0.15921171 +vt 0.58196847 0.20697890 +vt 0.58201676 0.55969592 +vt 0.58224887 0.69259171 +vt 0.58248305 0.12289030 +vt 0.58317636 0.46756363 +vt 0.58438284 0.82120724 +vt 0.58455490 0.43278583 +vt 0.58637430 0.78549972 +vt 0.58637864 0.10720754 +vt 0.58639932 0.17880117 +vt 0.58643656 0.84667029 +vt 0.58732618 0.53019550 +vt 0.58751169 0.47045587 +vt 0.58751508 0.82211924 +vt 0.58764315 0.43150431 +vt 0.58770791 8.6579339e-2 +vt 0.58808631 0.72226871 +vt 0.59055973 0.78240132 +vt 0.59117781 0.86916834 +vt 0.59225846 0.39455110 +vt 0.59409209 0.22036069 +vt 0.59427047 0.44841955 +vt 0.59536912 0.50419726 +vt 0.59644076 0.19939954 +vt 0.59699873 0.74827339 +vt 0.59704640 0.83566587 +vt 0.59769479 0.42060699 +vt 0.59819562 0.80381452 +vt 0.59832414 0.39869287 +vt 0.60008971 0.45126014 +vt 0.60032653 0.83645883 +vt 0.60079811 0.41908151 +vt 0.60188933 0.80024050 +vt 0.60267229 0.86152827 +vt 0.60305026 0.48276328 +vt 0.60314327 0.62582957 +vt 0.60432511 0.59782802 +vt 0.60443761 0.65389124 +vt 0.60470946 0.40257692 +vt 0.60491715 0.21333151 +vt 0.60538190 0.76931930 +vt 0.60656499 0.88272502 +vt 0.60773138 0.56811375 +vt 0.60806428 0.68367267 +vt 0.60901373 0.13919089 +vt 0.60988252 0.15766409 +vt 0.61002027 0.43147269 +vt 0.61019533 0.12573761 +vt 0.61153572 0.54185663 +vt 0.61219695 0.17620526 +vt 0.61228089 0.71002123 +vt 0.61261637 0.11015157 +vt 0.61334383 8.9504291e-2 +vt 0.61346241 0.43550469 +vt 0.61402027 0.46532801 +vt 0.61458934 0.81930652 +vt 0.61498518 0.84940424 +vt 0.61621576 0.40953537 +vt 0.61682137 0.87425812 +vt 0.61698106 0.78613513 +vt 0.61741462 0.51725780 +vt 0.61768329 0.81523649 +vt 0.61863343 0.85004446 +vt 0.61864538 0.73447579 +vt 0.61868366 0.19525168 +vt 0.61945167 0.40774414 +vt 0.62210782 0.20945653 +vt 0.62269117 0.49835018 +vt 0.62445200 0.75317891 +vt 0.62714985 0.62572688 +vt 0.62802825 0.60528190 +vt 0.62813920 0.64617727 +vt 0.62822037 0.45123219 +vt 0.62937199 0.79920543 +vt 0.62952055 0.41646382 +vt 0.63049575 0.48347066 +vt 0.63127751 0.57295868 +vt 0.63162625 0.67851402 +vt 0.63203655 0.86111322 +vt 0.63253201 0.42093862 +vt 0.63258581 0.76764504 +vt 0.63367393 0.55138792 +vt 0.63428519 0.70004347 +vt 0.63433498 0.83231410 +vt 0.63691111 0.86158058 +vt 0.63695293 0.82799494 +vt 0.63773317 0.52369730 +vt 0.63878588 0.72755574 +vt 0.63987835 0.50868637 +vt 0.64006221 0.20842101 +vt 0.64030083 0.19475027 +vt 0.64062323 0.17628017 +vt 0.64095224 0.15743218 +vt 0.64118550 0.49552250 +vt 0.64123896 0.74242362 +vt 0.64126822 0.13933227 +vt 0.64148809 0.12670014 +vt 0.64174981 0.11162218 +vt 0.64210268 9.1300133e-2 +vt 0.64268339 0.47354578 +vt 0.64282891 0.75542566 +vt 0.64438891 0.43918979 +vt 0.64482645 0.77703941 +vt 0.64741347 0.81026691 +vt 0.64921159 0.62562071 +vt 0.65218256 0.49348752 +vt 0.65371800 0.75715028 +vt 0.65480411 0.40428213 +vt 0.65525027 0.56636738 +vt 0.65559704 0.68477911 +vt 0.65729791 0.40922817 +vt 0.65796952 0.21008251 +vt 0.65845460 0.46504339 +vt 0.65906671 0.84221866 +vt 0.65909008 0.51539580 +vt 0.66011282 0.73532221 +vt 0.66047371 0.78490828 +vt 0.66131557 0.83769491 +vt 0.66188733 0.19600580 +vt 0.66466099 0.48935377 +vt 0.66609854 0.76091413 +vt 0.66740083 0.42972230 +vt 0.66903480 0.17719737 +vt 0.66966827 0.81931980 +vt 0.67090761 9.0509824e-2 +vt 0.67091748 0.11116987 +vt 0.67199484 0.15874836 +vt 0.67279603 0.12683089 +vt 0.67350774 0.14031695 +vt 0.67501454 0.21455505 +vt 0.67849527 0.45776891 +vt 0.68086136 0.79180030 +vt 0.68279180 0.39258257 +vt 0.68397196 0.20092734 +vt 0.68461805 0.39803747 +vt 0.68558774 0.22195772 +vt 0.68734174 0.48438878 +vt 0.68742498 0.84861994 +vt 0.68891429 0.76568912 +vt 0.68917110 0.84405863 +vt 0.69252972 0.42054524 +vt 0.69472609 0.18069190 +vt 0.69498364 0.82571229 +vt 0.69663116 8.8480696e-2 +vt 0.69724258 0.10914280 +vt 0.69817098 0.20900711 +vt 0.70011258 0.62537822 +vt 0.70032182 0.16128588 +vt 0.70059076 0.12495235 +vt 0.70066683 0.50970189 +vt 0.70090761 0.45218875 +vt 0.70141138 0.14042690 +vt 0.70142156 0.56611100 +vt 0.70144628 0.68456330 +vt 0.70161005 0.74051096 +vt 0.70185324 0.79693465 +vt 0.70543478 0.48075678 +vt 0.70662758 0.76912636 +vt 0.70986695 8.6235360e-2 +vt 0.71061247 0.10637188 +vt 0.71308222 0.18688797 +vt 0.71493210 0.12129134 +vt 0.71559815 0.38808853 +vt 0.71672011 0.39938455 +vt 0.71778064 0.13845963 +vt 0.71854777 0.85048184 +vt 0.71898595 0.16366340 +vt 0.71969409 0.84602117 +vt 0.72120532 0.41469323 +vt 0.72243120 0.82901830 +vt 0.72624349 0.44668051 +vt 0.72675506 0.80026985 +vt 0.73290614 0.47384739 +vt 0.73330905 0.77283605 +vt 0.74132603 0.15539057 +vt 0.74528607 0.12194336 +vt 0.74964590 0.39372066 +vt 0.74964849 0.40208891 +vt 0.74969528 0.56447406 +vt 0.74969862 0.47637094 +vt 0.74969870 0.62534682 +vt 0.74969888 0.44544398 +vt 0.74970092 0.41562328 +vt 0.74970226 0.68612604 +vt 0.74972334 0.50219042 +vt 0.74973797 0.74775962 +vt 0.74974416 0.77378656 +vt 0.74977082 0.80135863 +vt 0.74977482 0.83010045 +vt 0.74979125 0.84692247 +vt 0.74979716 0.85141491 +vt 0.75044526 9.8826564e-2 +vt 0.75184605 0.18781835 +vt 0.75506376 5.0662344e-2 +vt 0.75541575 7.7930646e-2 +vt 0.76618303 0.77285046 +vt 0.76648140 0.47500524 +vt 0.77206139 0.12406372 +vt 0.77252760 0.15889485 +vt 0.77264878 0.21499518 +vt 0.77278501 0.80026740 +vt 0.77316794 0.44824188 +vt 0.77403105 0.10253185 +vt 0.77643305 5.4913000e-2 +vt 0.77681374 8.1976403e-2 +vt 0.77710497 0.82899934 +vt 0.77818426 0.18263615 +vt 0.77823029 0.41633388 +vt 0.77983813 0.84596416 +vt 0.78098211 0.85041530 +vt 0.78221250 0.39462255 +vt 0.78361193 0.38724929 +vt 0.78492856 0.22071243 +vt 0.78501161 0.23343727 +vt 0.78807788 0.20263711 +vt 0.79286876 0.76916919 +vt 0.79380003 0.22600311 +vt 0.79394289 0.48079294 +vt 0.79395459 0.23105238 +vt 0.79629673 0.21206463 +vt 0.79678507 0.24676949 +vt 0.79768783 0.79696059 +vt 0.79786840 0.74052354 +vt 0.79795811 0.68457424 +vt 0.79796897 0.56610933 +vt 0.79850907 0.45218379 +vt 0.79876571 0.50974134 +vt 0.79928469 0.62537989 +vt 0.80024222 0.22162862 +vt 0.80181026 0.23935874 +vt 0.80453900 0.82571414 +vt 0.80687841 0.42052259 +vt 0.81030337 0.84405642 +vt 0.81059309 0.76578504 +vt 0.81203466 0.84861880 +vt 0.81206379 0.48441501 +vt 0.81462549 0.39781329 +vt 0.81631883 0.18138671 +vt 0.81631883 0.19894216 +vt 0.81631883 0.20850188 +vt 0.81631883 0.21898700 +vt 0.81631883 0.24270142 +vt 0.81631883 0.25128796 +vt 0.81631883 0.12631828 +vt 0.81631883 0.15984931 +vt 0.81631974 0.10337673 +vt 0.81632188 8.3422966e-2 +vt 0.81632477 5.6718511e-2 +vt 0.81657060 0.39234447 +vt 0.81866790 0.79184653 +vt 0.82094658 0.45777682 +vt 0.82988809 0.81936098 +vt 0.83082740 0.23935874 +vt 0.83208091 0.42969284 +vt 0.83239543 0.22162862 +vt 0.83340403 0.76090325 +vt 0.83473167 0.48941852 +vt 0.83585259 0.24676949 +vt 0.83634093 0.21206463 +vt 0.83820799 0.83777126 +vt 0.83868307 0.23105238 +vt 0.83883762 0.22600311 +vt 0.83907217 0.78490689 +vt 0.83936978 0.73527164 +vt 0.84032375 0.51545322 +vt 0.84045270 0.84231191 +vt 0.84096947 0.46510600 +vt 0.84221525 0.40908688 +vt 0.84379651 0.68474754 +vt 0.84413575 0.56640346 +vt 0.84455978 0.20263711 +vt 0.84473107 0.40411423 +vt 0.84578281 0.75709645 +vt 0.84720308 0.49355596 +vt 0.84762605 0.23343727 +vt 0.84770909 0.22071243 +vt 0.85014450 0.62563788 +vt 0.85220501 0.81030069 +vt 0.85445339 0.18263615 +vt 0.85474383 0.77699630 +vt 0.85514967 0.43923013 +vt 0.85582902 8.1976538e-2 +vt 0.85621523 5.4913160e-2 +vt 0.85668279 0.75534099 +vt 0.85671442 0.47363784 +vt 0.85819025 0.49559937 +vt 0.85822794 0.74232971 +vt 0.85860702 0.10253179 +vt 0.85949065 0.50875820 +vt 0.85998888 0.21499518 +vt 0.86011006 0.15889484 +vt 0.86057628 0.12406368 +vt 0.86068059 0.72745237 +vt 0.86166189 0.52377250 +vt 0.86268202 0.82809361 +vt 0.86301504 0.86159484 +vt 0.86510916 0.69996195 +vt 0.86530126 0.83244004 +vt 0.86570934 0.55145009 +vt 0.86698235 0.76755067 +vt 0.86708498 0.42092733 +vt 0.86773423 0.67845125 +vt 0.86787208 0.86112761 +vt 0.86809109 0.57301735 +vt 0.86888719 0.48356916 +vt 0.87012862 0.41644284 +vt 0.87031874 0.79918515 +vt 0.87118631 0.64616822 +vt 0.87131536 0.60532820 +vt 0.87217910 0.62575614 +vt 0.87322935 0.45155820 +vt 0.87509452 0.75303554 +vt 0.87667732 0.49844404 +vt 0.87722603 7.7931117e-2 +vt 0.87758337 5.0662878e-2 +vt 0.88055629 0.40776116 +vt 0.88079161 0.18781835 +vt 0.88080295 0.73433217 +vt 0.88137766 0.85006313 +vt 0.88197974 0.51734615 +vt 0.88206185 0.81527988 +vt 0.88219164 9.8826490e-2 +vt 0.88274636 0.78606739 +vt 0.88305683 0.87427342 +vt 0.88377696 0.40955241 +vt 0.88501143 0.84942298 +vt 0.88517383 0.81938273 +vt 0.88537514 0.46544008 +vt 0.88613579 0.43564436 +vt 0.88711165 0.70983050 +vt 0.88735162 0.12194339 +vt 0.88784315 0.54195219 +vt 0.88958832 0.43161355 +vt 0.89122663 0.68358105 +vt 0.89131164 0.15539058 +vt 0.89162483 0.56821315 +vt 0.89329179 0.88274093 +vt 0.89420456 0.76918833 +vt 0.89482239 0.65384275 +vt 0.89498664 0.59791822 +vt 0.89526204 0.40259466 +vt 0.89612846 0.62587592 +vt 0.89632031 0.48287559 +vt 0.89731131 0.86154805 +vt 0.89800461 0.80026804 +vt 0.89927536 0.41910249 +vt 0.89974962 0.83648133 +vt 0.90143581 0.45188253 +vt 0.90163557 0.39871101 +vt 0.90173793 0.80384253 +vt 0.90236327 0.42062796 +vt 0.90261588 0.74799318 +vt 0.90301535 0.83568839 +vt 0.90403433 0.50430115 +vt 0.90539174 0.44848622 +vt 0.90769030 0.39456961 +vt 0.90878427 0.86918887 +vt 0.90928584 0.78217032 +vt 0.91124742 0.72203685 +vt 0.91185161 0.47057099 +vt 0.91206867 0.53031535 +vt 0.91249313 0.43152850 +vt 0.91262211 0.82214478 +vt 0.91351091 0.78524009 +vt 0.91362442 0.84669399 +vt 0.91556604 0.43281001 +vt 0.91573923 0.82123277 +vt 0.91619522 0.46770409 +vt 0.91698547 0.69233692 +vt 0.91734816 0.55984743 +vt 0.91889253 0.38754873 +vt 0.91904925 0.40810095 +vt 0.92088645 0.75961562 +vt 0.92155439 0.65958908 +vt 0.92168320 0.59244870 +vt 0.92248912 0.49336962 +vt 0.92309477 0.44686667 +vt 0.92317246 0.80590435 +vt 0.92323264 0.62598422 +vt 0.92525121 0.85339007 +vt 0.92546100 0.76214863 +vt 0.92612764 0.44803771 +vt 0.92618673 0.80498253 +vt 0.92708343 0.49101114 +vt 0.92709712 0.83119709 +vt 0.92803587 0.42253013 +vt 0.92992062 0.46569495 +vt 0.92999926 0.78658278 +vt 0.93010884 0.73213383 +vt 0.93055660 0.40178784 +vt 0.93088181 0.52072007 +vt 0.93297353 0.46668837 +vt 0.93303435 0.78583533 +vt 0.93495255 0.73410661 +vt 0.93569556 0.51887576 +vt 0.93735552 0.48861871 +vt 0.93742755 0.76311815 +vt 0.93744769 0.70012643 +vt 0.93766508 0.55239038 +vt 0.93813195 0.43896665 +vt 0.93813860 0.81394791 +vt 0.93874626 0.83699880 +vt 0.93946000 0.41701443 +vt 0.94047785 0.48935673 +vt 0.94053357 0.76262150 +vt 0.94247489 0.70150620 +vt 0.94263616 0.55107296 +vt 0.94291010 0.73470904 +vt 0.94291060 0.51650622 +vt 0.94311934 0.66396455 +vt 0.94315460 0.58820982 +vt 0.94516285 0.62602381 +vt 0.94531555 0.45846911 +vt 0.94532982 0.79391294 +vt 0.94612313 0.73443383 +vt 0.94612342 0.51704994 +vt 0.94745599 0.54918035 +vt 0.94745599 0.70170586 +vt 0.94825459 0.66469119 +vt 0.94825814 0.58750028 +vt 0.94990301 0.43414798 +vt 0.94990987 0.81903766 +vt 0.95032903 0.62602350 +vt 0.95076498 0.54953796 +vt 0.95076498 0.70160980 +vt 0.95129646 0.58611221 +vt 0.95129646 0.66449599 +vt 0.95273066 0.62525219 +vt 0.95319660 0.48208977 +vt 0.95321000 0.76969831 +vt 0.95466356 0.58633996 +vt 0.95466356 0.66452558 +vt 0.95612166 0.62538000 +vt 0.95753064 0.79860876 +vt 0.95897643 0.74017591 +vt 0.95897674 0.51117268 +vt 0.95958278 0.45395070 +vt 0.96377214 0.54530024 +vt 0.96377214 0.70568365 +vt 0.96607576 0.47799539 +vt 0.96608969 0.77401927 +vt 0.96790133 0.58408372 +vt 0.96790133 0.66658980 +vt 0.96945074 0.62527858 +vt 0.97240072 0.74385389 +vt 0.97240105 0.50770340 +vt 0.97765965 0.54275096 +vt 0.97765965 0.70842565 +vt 0.98218926 0.66807919 +vt 0.98218926 0.58276953 +vt 0.98389446 0.62536264 +vn -0.72613719 0.68754984 -2.8980470e-17 +vn -0.74030664 -0.67226935 0.0000000e+0 +vn -0.70801834 0.68852872 -0.15696568 +vn -0.70801948 0.68852857 0.15696122 +vn -0.93027984 0.36685068 0.0000000e+0 +vn -0.73268951 -0.66519230 -0.14382379 +vn -0.73269078 -0.66519196 0.14381894 +vn -0.90921573 0.35938221 -0.21016941 +vn -0.90921670 0.35938263 0.21016449 +vn -0.34846596 -0.93732138 -3.3643134e-4 +vn -0.65127804 0.69521626 -0.30415665 +vn -0.65119320 0.69520241 0.30436987 +vn -0.76997696 0.63807169 0.0000000e+0 +vn -0.33947245 -0.93878988 -5.8583382e-2 +vn -0.33970810 -0.93872884 5.8194194e-2 +vn -0.69297346 -0.66062809 -0.28871840 +vn -0.68405869 -0.67660299 0.27252910 +vn -0.84549943 0.35122239 -0.40221083 +vn -0.84541447 0.35108276 0.40251121 +vn -0.77409503 0.60984876 -0.16988636 +vn -0.77409535 0.60984901 0.16988402 +vn -0.33012671 -0.93680826 -0.11578707 +vn -0.32941211 -0.93689482 0.11711430 +vn -0.73190198 0.59310275 -0.33548267 +vn -0.73188851 0.59301836 0.33566119 +vn -0.22429462 -0.97452127 -4.7581673e-4 +vn -0.56122943 0.69919834 -0.44288059 +vn -0.59972996 0.69050883 0.40437795 +vn -0.60396200 0.79701311 0.0000000e+0 +vn -0.21671672 -0.97530266 -4.2644845e-2 +vn -0.21618947 -0.97544541 4.2051920e-2 +vn -0.59981771 -0.65993977 -0.45243588 +vn -0.57284575 -0.67486081 0.46519957 +vn -0.73597607 0.32070259 -0.59622905 +vn -0.76220508 0.31370167 0.56624612 +vn -0.59503601 0.78634501 -0.16611343 +vn -0.59503611 0.78634531 0.16611166 +vn -0.21346371 -0.97329385 -8.4453116e-2 +vn -0.21011829 -0.97391985 8.5617963e-2 +vn -0.26970341 -0.93712423 -0.22149098 +vn -0.26209227 -0.93822113 0.22593973 +vn -0.64409483 0.55620716 -0.52514326 +vn -0.66082911 0.56347667 0.49578114 +vn -0.57031322 0.75817607 -0.31608840 +vn -0.57029304 0.75815467 0.31617613 +vn -0.20727434 -0.96336740 -0.17017813 +vn -0.19769513 -0.96379553 0.17892684 +vn -0.53880619 0.72393878 -0.43081380 +vn -0.54109731 0.72704355 0.42263624 +vn -0.12406869 -0.99227357 -3.4419208e-4 +vn -0.42847901 0.71363008 -0.55420018 +vn -0.55983853 0.67577105 0.47949381 +vn -0.42871596 0.90343933 0.0000000e+0 +vn -0.11359699 -0.99251053 -4.4928460e-2 +vn -0.11490746 -0.99244478 4.3007313e-2 +vn -0.41454082 -0.67663450 -0.60854059 +vn -0.32933136 -0.60212941 0.72731082 +vn -0.55586652 0.38142442 -0.73859855 +vn -0.60944545 0.40122907 0.68380660 +vn -0.42247902 0.89012282 -0.17085911 +vn -0.42247866 0.89012319 0.17085809 +vn -0.10176383 -0.99046217 -9.2891401e-2 +vn -0.10377617 -0.98993333 9.6241911e-2 +vn -0.15748114 -0.95784089 -0.24029257 +vn -0.14710027 -0.95321010 0.26410608 +vn -0.46865756 0.63645329 -0.61260697 +vn -0.50790002 0.66774813 0.54419666 +vn -0.40437757 0.85449395 -0.32606575 +vn -0.40764802 0.85449544 0.32196371 +vn -9.0375495e-2 -0.98103274 -0.17148479 +vn -0.10094755 -0.97751910 0.18511080 +vn -0.40871747 0.78030758 -0.47336044 +vn -0.42757971 0.79534877 0.42964628 +vn -5.4315516e-2 -0.99852379 -2.4118318e-4 +vn -0.37426784 0.70960464 -0.59697977 +vn -0.61676101 0.66516229 0.42090970 +vn -0.22957539 0.97329088 0.0000000e+0 +vn -5.1033958e-2 -0.99746997 -4.9489432e-2 +vn -5.2667388e-2 -0.99767217 4.3317331e-2 +vn -0.16578596 -0.54039183 -0.82491920 +vn 0.29662251 -0.68413092 0.66631822 +vn -0.35181809 0.45113863 -0.82018167 +vn -0.48148156 0.52124345 0.70461391 +vn -0.22621860 0.95650315 -0.18419248 +vn -0.22621842 0.95650326 0.18419212 +vn -5.8211679e-2 -0.99456855 -8.6283227e-2 +vn -5.9603394e-2 -0.99329064 9.9101664e-2 +vn -0.13892216 -0.97175485 -0.19076986 +vn -0.12506958 -0.96896805 0.21321002 +vn -0.30413609 0.68640271 -0.66056988 +vn -0.31115480 0.76765246 0.56026100 +vn -0.21593547 0.91099327 -0.35137321 +vn -0.22309378 0.91619440 0.33289186 +vn -0.10619227 -0.98827327 -0.10972303 +vn -8.0056962e-2 -0.98432717 0.15713343 +vn -0.21880655 0.83112103 -0.51123530 +vn -0.24449560 0.87285784 0.42230450 +vn -4.1293731e-5 -0.99999994 -3.4010420e-4 +vn 5.4494042e-5 -0.99863214 -5.2286164e-2 +vn -1.5603243e-4 -0.99900136 4.4679428e-2 +vn 2.6635211e-4 -0.99903396 -4.3944024e-2 +vn -2.0942798e-4 -0.99581923 9.1345557e-2 +vn 3.7088592e-3 -0.99555193 -9.4141380e-2 +vn -2.3662977e-4 -0.99073887 0.13578087 +vn 6.5433368e-3 -0.98205100 -0.18850203 +vn -2.0359699e-4 -0.98263979 0.18552359 +vn 4.3770646e-6 -0.32547085 -0.94555208 +vn -1.8517792e-6 -0.81420442 0.58057830 +vn 4.3501654e-6 0.76369123 -0.64558168 +vn 2.0991639e-6 0.88186762 0.47149709 +vn 4.2181087e-6 0.50795832 -0.86138165 +vn 1.9650224e-6 0.76554698 0.64338000 +vn -4.6541778e-4 0.72809786 -0.68547304 +vn 1.8977794e-6 0.85269522 0.52240872 +vn -2.8257583e-4 0.85077247 -0.52553414 +vn 2.4087463e-6 0.90664882 0.42188613 +vn 1.6464002e-6 0.93274891 -0.36052665 +vn 1.7896393e-6 0.94331130 0.33190930 +vn 5.1852707e-10 0.98198730 -0.18894695 +vn 5.1853525e-10 0.98198731 0.18894687 +vn -1.4040489e-17 1.00000000 0.0000000e+0 +vn 0.10551605 -0.98820147 -0.11101452 +vn 8.0255593e-2 -0.98420280 0.15780964 +vn 0.21916763 0.83194069 -0.50974527 +vn 0.24455308 0.87284657 0.42229452 +vn 5.8307747e-2 -0.99447392 -8.7303094e-2 +vn 5.9721113e-2 -0.99323659 9.9571404e-2 +vn 0.13436380 -0.97229606 -0.19127661 +vn 0.12531678 -0.96890864 0.21333484 +vn 0.30350939 0.68594271 -0.66133550 +vn 0.31124459 0.76769462 0.56015336 +vn 0.21595368 0.91095888 -0.35145117 +vn 0.22311232 0.91615919 0.33297631 +vn 5.1029129e-2 -0.99746442 -4.9605987e-2 +vn 5.2616674e-2 -0.99768135 4.3167187e-2 +vn 0.16581392 -0.54036369 -0.82493202 +vn -0.29667599 -0.68414690 0.66627800 +vn 0.35160951 0.44829331 -0.82182958 +vn 0.48155733 0.52124204 0.70456318 +vn 0.22621861 0.95650314 -0.18419250 +vn 0.22621843 0.95650326 0.18419214 +vn 5.4295361e-2 -0.99852488 -2.8685217e-4 +vn 0.37429283 0.70958809 -0.59698377 +vn 0.61678368 0.66510862 0.42096129 +vn 0.22957539 0.97329088 0.0000000e+0 +vn 8.9243707e-2 -0.98103538 -0.17206144 +vn 0.10107284 -0.97741695 0.18558123 +vn 0.40935594 0.78069253 -0.47217252 +vn 0.42769420 0.79522849 0.42975495 +vn 0.10155676 -0.99044953 -9.3252098e-2 +vn 0.10401299 -0.98988263 9.6507361e-2 +vn 0.15296983 -0.95860502 -0.24015963 +vn 0.14699662 -0.95318311 0.26426113 +vn 0.46547162 0.64431906 -0.60678589 +vn 0.50798379 0.66791058 0.54391904 +vn 0.40443887 0.85439723 -0.32624312 +vn 0.40770934 0.85439851 0.32214326 +vn 0.11355747 -0.99251248 -4.4985279e-2 +vn 0.11504324 -0.99243309 4.2914065e-2 +vn 0.41461425 -0.67657676 -0.60855477 +vn 0.32940465 -0.60209080 0.72730960 +vn 0.55091708 0.37997573 -0.74304025 +vn 0.60951229 0.40146106 0.68361084 +vn 0.42247904 0.89012281 -0.17085916 +vn 0.42247868 0.89012317 0.17085814 +vn 0.12410793 -0.99226865 -3.7732756e-4 +vn 0.42722073 0.70611820 -0.56469419 +vn 0.55990931 0.67572198 0.47948032 +vn 0.42871596 0.90343933 0.0000000e+0 +vn 0.20738714 -0.96333362 -0.17023193 +vn 0.19772104 -0.96376549 0.17905998 +vn 0.53872433 0.72379802 -0.43115254 +vn 0.54101851 0.72690502 0.42297525 +vn 0.21344614 -0.97327524 -8.4711612e-2 +vn 0.21015427 -0.97389497 8.5812382e-2 +vn 0.27123751 -0.93771064 -0.21709206 +vn 0.26166332 -0.93835515 0.22588031 +vn 0.65046519 0.55966236 -0.51349107 +vn 0.66437760 0.56165071 0.49310332 +vn 0.57024740 0.75811248 -0.31635957 +vn 0.57022778 0.75809135 0.31644553 +vn 0.21673085 -0.97529898 -4.2657299e-2 +vn 0.21624788 -0.97543467 4.2000685e-2 +vn 0.60031598 -0.65980304 -0.45197418 +vn 0.59379576 -0.65776115 0.46341867 +vn 0.75517359 0.31356846 -0.57566281 +vn 0.76273794 0.31358390 0.56559347 +vn 0.59503600 0.78634500 -0.16611352 +vn 0.59503610 0.78634530 0.16611174 +vn 0.22432449 -0.97451438 -4.9471814e-4 +vn 0.57207902 0.69465909 -0.43608984 +vn 0.60010867 0.69049126 0.40384576 +vn 0.60396200 0.79701311 0.0000000e+0 +vn 0.32996914 -0.93681933 -0.11614605 +vn 0.32904676 -0.93701468 0.11718240 +vn 0.73187128 0.59282502 -0.33604006 +vn 0.73530187 0.58492993 0.34232753 +vn 0.33948589 -0.93878441 -5.8593211e-2 +vn 0.33975697 -0.93871637 5.8110098e-2 +vn 0.69270444 -0.66058966 -0.28945095 +vn 0.69260804 -0.66058442 0.28969350 +vn 0.84525885 0.35076898 -0.40311114 +vn 0.84820441 0.33859107 0.40731482 +vn 0.77409501 0.60984875 -0.16988648 +vn 0.77409534 0.60984899 0.16988413 +vn 0.34849397 -0.93731096 -3.5602565e-4 +vn 0.65103797 0.69516927 -0.30477737 +vn 0.65089115 0.69684066 0.30125373 +vn 0.76997696 0.63807169 0.0000000e+0 +vn 0.73268944 -0.66519232 -0.14382406 +vn 0.73269071 -0.66519197 0.14381920 +vn 0.90921568 0.35938218 -0.21016967 +vn 0.90921666 0.35938260 0.21016475 +vn 0.74030664 -0.67226935 0.0000000e+0 +vn 0.70801828 0.68852873 -0.15696591 +vn 0.70801942 0.68852858 0.15696146 +vn 0.93027984 0.36685068 0.0000000e+0 +vn 0.72613719 0.68754984 0.0000000e+0 +vn 0.75807099 0.65217204 0.0000000e+0 +vn 0.73009621 0.66665511 0.15010158 +vn 0.73009494 0.66665541 -0.15010640 +vn 0.64541165 0.70974314 0.28232690 +vn 0.64550542 0.70974916 -0.28209729 +vn 0.56121804 0.72875387 0.39236731 +vn 0.53005602 0.74727801 -0.40076950 +vn 0.53315868 0.69156582 0.48731769 +vn 0.39715994 0.72914452 -0.55732598 +vn 0.60957329 0.59450625 0.52438795 +vn 0.37714986 0.70161654 -0.60455953 +vn 5.9132451e-7 0.69428810 0.71969718 +vn -7.6737303e-7 0.76137202 -0.64831523 +vn -0.60954177 0.59456802 0.52435455 +vn -0.37712759 0.70163246 -0.60455494 +vn -0.53307140 0.69163793 0.48731084 +vn -0.39706959 0.72918475 -0.55733773 +vn -0.53778988 0.74565203 0.39342736 +vn -0.52974027 0.74725123 -0.40123665 +vn -0.63420815 0.72719958 0.26260387 +vn -0.64576475 0.70979017 -0.28139973 +vn -0.73009628 0.66665510 0.15010132 +vn -0.73009501 0.66665540 -0.15010614 +vn -0.75807099 0.65217204 -3.7236469e-17 +vn -0.35786746 0.93377239 -5.8154890e-17 +vn -0.72091895 0.68720379 -8.9592542e-2 +vn -0.72091895 0.68720379 8.9592542e-2 +vn -0.73728750 -0.67035452 -8.3856768e-2 +vn -0.73728750 -0.67035452 8.3856768e-2 +vn -0.54954484 -0.83546421 -1.5328256e-4 +vn -0.33997405 0.93763570 -7.2504705e-2 +vn -0.68990991 0.69049448 -0.21735151 +vn -0.33997478 0.93763560 7.2502558e-2 +vn -0.68984042 0.69050172 0.21754900 +vn -0.54655096 -0.83215483 -9.3810358e-2 +vn -0.72447883 -0.66098309 -0.19552950 +vn -0.54680220 -0.83200142 9.3706950e-2 +vn -0.72399694 -0.66141054 0.19586864 +vn -0.34458492 -0.93816348 -3.3324403e-2 +vn -0.34474120 -0.93812795 3.2702570e-2 +vn -0.28723153 0.94911102 -0.12917556 +vn -0.60395142 0.69388252 -0.39213483 +vn -0.28718989 0.94910941 0.12927994 +vn -0.60422405 0.69554266 0.38875919 +vn -0.33305290 -0.93882903 -8.7611757e-2 +vn -0.33301710 -0.93881784 8.7867321e-2 +vn -0.51787358 -0.83441638 -0.18856367 +vn -0.66402139 -0.65359108 -0.36317255 +vn -0.51780894 -0.83403234 0.19043097 +vn -0.63684655 -0.68718019 0.34958527 +vn -0.32108526 -0.93429421 -0.15491477 +vn -0.31865885 -0.93455127 0.15833655 +vn -0.22458760 0.95933325 -0.17099743 +vn -0.49694660 0.70922567 -0.50004303 +vn -0.27536414 0.94986494 0.14809180 +vn -0.60383524 0.67623574 0.42200502 +vn -0.42706314 -0.83670509 -0.34284351 +vn -0.48601900 -0.67559250 -0.55440085 +vn -0.41739192 -0.84607790 0.33156624 +vn -0.44314883 -0.64851831 0.61890477 +vn -0.20506439 -0.94374471 -0.25941186 +vn -0.18709728 -0.94550610 0.26648231 +vn -0.18608097 0.95473316 -0.23207427 +vn -0.40084597 0.70802296 -0.58140003 +vn -0.37971580 0.91352276 0.14591803 +vn -0.55888754 0.67061130 0.48777578 +vn -0.30337606 -0.86255007 -0.40493252 +vn -0.29864926 -0.65161181 -0.69728809 +vn -0.26269082 -0.86719721 0.42303963 +vn -7.6119356e-2 -0.63894216 0.76547943 +vn -0.12870378 -0.97010148 -0.20576309 +vn -0.13736762 -0.96048153 0.24208545 +vn -0.29630712 0.93138692 -0.21147221 +vn -0.23674366 0.74030297 -0.62920899 +vn -0.61438999 0.78144205 0.10896455 +vn -0.39646753 0.80389874 0.44335123 +vn -0.18869027 -0.88694819 -0.42156719 +vn -6.2445087e-2 -0.34345959 -0.93708918 +vn -0.20399566 -0.92672718 0.31553525 +vn 0.25277802 -0.75351046 0.60689806 +vn -0.10108966 -0.97680819 -0.18875019 +vn -8.1335296e-2 -0.97803405 0.19192177 +vn -3.8184439e-3 -0.90879436 -0.41722684 +vn 0.10285249 -0.97649274 -0.18942887 +vn -8.5331188e-5 -0.97584809 0.21845024 +vn 8.1451874e-2 -0.97801595 0.19196456 +vn 3.3948235e-6 -0.18002510 -0.98366202 +vn 6.2458426e-2 -0.34345477 -0.93709005 +vn -2.2740001e-7 -0.12979894 0.99154033 +vn -0.25281336 -0.75352649 0.60686344 +vn 0.23676015 0.74029101 -0.62921686 +vn 0.39647608 0.80386994 0.44339581 +vn 0.19388367 -0.89803822 -0.39488794 +vn 0.12762084 -0.97036145 -0.20521104 +vn 0.20413436 -0.92668841 0.31555942 +vn 0.13726561 -0.96043907 0.24231165 +vn 0.26509404 -0.12059587 -0.95665134 +vn 0.29869625 -0.65156161 -0.69731486 +vn 0.26311122 -0.10176579 0.95938325 +vn 7.6136031e-2 -0.63893909 0.76548033 +vn 0.39720919 0.70621567 -0.58607533 +vn 0.55894021 0.67055756 0.48778931 +vn 0.29830923 -0.86146976 -0.41095189 +vn 0.20337879 -0.94533776 -0.25489916 +vn 0.26269969 -0.86701609 0.42340521 +vn 0.18680005 -0.94554437 0.26655504 +vn 0.56209917 -4.2852682e-2 -0.82595894 +vn 0.48612195 -0.67552541 -0.55439234 +vn 0.54673008 -5.5901168e-2 0.83544077 +vn 0.44321298 -0.64800129 0.61940018 +vn 0.51080488 0.69967399 -0.49953446 +vn 0.60420644 0.67618961 0.42154739 +vn 0.42624593 -0.84335236 -0.32721737 +vn 0.32097656 -0.93427041 -0.15528310 +vn 0.41581908 -0.84683473 0.33161036 +vn 0.31810746 -0.93471416 0.15848369 +vn 0.79831968 -1.1007790e-2 -0.60213331 +vn 0.66449732 -0.65338245 -0.36267709 +vn 0.79841373 -1.5546987e-2 0.60190847 +vn 0.66461300 -0.65332870 0.36256195 +vn 0.60403562 0.69384195 -0.39207694 +vn 0.61478635 0.69713585 0.36883512 +vn 0.33306205 -0.93882510 -8.7619099e-2 +vn 0.51799624 -0.83419013 -0.18922664 +vn 0.33301678 -0.93883854 8.7647162e-2 +vn 0.51759209 -0.83426013 0.19002229 +vn 0.34460457 -0.93815580 -3.3337337e-2 +vn 0.54656205 -0.83214682 -9.3816782e-2 +vn 0.34478171 -0.93811438 3.2664746e-2 +vn 0.54700214 -0.83187880 9.3628634e-2 +vn 0.91880367 -3.8305926e-2 -0.39285172 +vn 0.72419302 -0.66106852 -0.19629793 +vn 0.91866651 -3.8304607e-2 0.39317248 +vn 0.72410860 -0.66109483 0.19652062 +vn 0.54958420 -0.83543832 -1.6786301e-4 +vn 0.68967516 0.69051895 -0.21801777 +vn 0.68148463 0.69304099 0.23510185 +vn 0.73728750 -0.67035452 -8.3856768e-2 +vn 0.97762954 -7.6000461e-2 -0.19612349 +vn 0.73728750 -0.67035452 8.3856768e-2 +vn 0.97763086 -7.6000428e-2 0.19611690 +vn 0.99573600 -9.2248680e-2 -1.9145758e-18 +vn 0.72091895 0.68720379 -8.9592542e-2 +vn 0.72091895 0.68720379 8.9592542e-2 +vn 0.35786746 0.93377239 8.7450962e-19 +vn 0.33997475 0.93763561 7.2502673e-2 +vn 0.33997401 0.93763571 -7.2504821e-2 +vn 0.28317358 0.95051776 0.12778384 +vn 0.28712778 0.94909924 -0.12949236 +vn 0.27555965 0.94984135 0.14787930 +vn 0.22467922 0.95935107 -0.17077699 +vn 0.37980610 0.91347769 0.14596522 +vn 0.18613772 0.95472056 -0.23208057 +vn 0.61443715 0.78139138 0.10906188 +vn 0.29632655 0.93137440 -0.21150013 +vn 1.8921529e-6 0.95147915 0.30771322 +vn 2.5766914e-6 0.97310417 -0.23036553 +vn -0.26310076 -0.10173838 0.95938902 +vn -0.26506066 -0.12061178 -0.95665858 +vn -0.54665816 -5.5888048e-2 0.83548871 +vn -0.56202481 -4.2858337e-2 -0.82600925 +vn -0.77846233 -1.2430645e-2 0.62756823 +vn -0.79779608 -1.1008518e-2 -0.60282686 +vn -0.92972727 -3.3793564e-2 0.36669496 +vn -0.91921365 -3.8308422e-2 -0.39189123 +vn -0.97763093 -7.6000426e-2 0.19611654 +vn -0.97762961 -7.6000459e-2 -0.19612313 +vn -0.99573600 -9.2248680e-2 0.0000000e+0 +vn -0.54617728 0.71047094 0.44375828 +vn -0.55289296 0.65139520 0.51960915 +vn -0.39827799 0.65204448 0.64514543 +vn 0.39829333 0.65201692 0.64516382 +vn 0.55295065 0.65132578 0.51963478 +vn 0.54628182 0.71039309 0.44375425 +vn 0.45074390 0.74455506 -0.49241009 +vn 0.37923638 0.71032210 -0.59297747 +vn 0.24958164 0.73520855 -0.63022012 +vn -0.24957284 0.73521678 -0.63021399 +vn -0.37917618 0.71034555 -0.59298788 +vn -0.45064903 0.74455551 -0.49249624 +vn 0.59139435 0.73100964 -0.34040803 +vn 0.70046689 0.68522513 -0.19953111 +vn 0.74954145 0.65597051 -8.8827378e-2 +vn 0.74954145 0.65597051 8.8827378e-2 +vn 0.70038471 0.68524718 0.19974374 +vn 0.59908425 0.72532855 0.33911141 +vn -0.59107291 0.73108084 -0.34081317 +vn -0.70074408 0.68515511 -0.19879693 +vn -0.74954145 0.65597051 -8.8827378e-2 +vn -0.74954145 0.65597051 8.8827378e-2 +vn -0.70066119 0.68517756 0.19901157 +vn -0.56499523 0.75982665 0.32162688 +vn -0.65996728 -3.3711231e-2 0.75053764 +vn -0.32315735 -0.85516624 0.40529005 +vn -0.41892686 -7.8061885e-2 0.90465829 +vn -0.23410190 -0.89384900 0.38240066 +vn -0.11533231 -0.12131669 0.98589082 +vn -0.13094527 -0.96023890 0.24656557 +vn 0.11533168 -0.12133064 0.98588918 +vn 0.13105658 -0.96020102 0.24665395 +vn 0.41896906 -7.8080971e-2 0.90463710 +vn 0.23404529 -0.89379590 0.38255939 +vn 0.66005077 -3.3720601e-2 0.75046379 +vn 0.32211975 -0.85521806 0.40600609 +vn 0.19885321 0.95876442 -0.20304725 +vn 0.34045820 -0.85054631 -0.40082314 +vn 0.22582733 0.94642239 -0.23083908 +vn 0.23405915 -0.88329063 -0.40621912 +vn 0.21120758 0.95316742 -0.21647915 +vn 0.14525996 -0.91551764 -0.37513596 +vn -0.21119223 0.95317648 -0.21645426 +vn -0.14493384 -0.88838691 -0.43561781 +vn -0.22579077 0.94643196 -0.23083560 +vn -0.23449212 -0.88289682 -0.40682509 +vn -0.19874818 0.95876110 -0.20316574 +vn -0.34503889 -0.84961769 -0.39887083 +vn 0.25066576 0.95545951 -0.15576841 +vn 0.31972995 0.94269354 -9.5402508e-2 +vn 0.98945499 -8.7940991e-2 -0.11508783 +vn 0.98945499 -8.7940991e-2 0.11508783 +vn 0.96197344 -5.8692134e-2 0.26676269 +vn 0.87363034 -1.8938744e-2 0.48622150 +vn 0.49004053 -0.83524233 -0.24946047 +vn 0.53505091 -0.83356647 -0.13743170 +vn 0.54773700 -0.83492834 -5.3654904e-2 +vn 0.54798987 -0.83478195 5.3349818e-2 +vn 0.53542170 -0.83330395 0.13757953 +vn 0.48710407 -0.83645313 0.25114891 +vn -0.49117756 -0.83121694 -0.26042848 +vn -0.53493034 -0.83368223 -0.13719868 +vn -0.54771654 -0.83494234 -5.3645886e-2 +vn -0.54790639 -0.83483488 5.3378864e-2 +vn -0.53502899 -0.83346532 0.13812870 +vn -0.48816554 -0.83571153 0.25155645 +vn -0.25059341 0.95546505 -0.15585086 +vn -0.31988657 0.94267179 -9.5091946e-2 +vn -0.35266424 0.93477386 -4.2728992e-2 +vn -0.98945499 -8.7940991e-2 0.11508783 +vn -0.96226426 -5.8683924e-2 0.26571356 +vn -0.87205329 -1.0834749e-2 0.48929099 +vn -0.34288479 0.92996877 0.13262013 +vn -0.47839037 0.86778769 0.13448860 +vn -0.42191712 0.87951707 0.22008106 +vn 0.42193527 0.87949235 0.22014506 +vn 0.47846345 0.86773610 0.13456145 +vn 0.34298080 0.92993899 0.13258070 +vn 0.66524274 -2.0443523e-2 -0.74634721 +vn 0.44180955 -7.2558095e-2 -0.89416981 +vn 0.11364311 -0.16633947 -0.97949805 +vn -0.11362811 -0.16635051 -0.97949791 +vn -0.44175569 -7.2573821e-2 -0.89419514 +vn -0.66515890 -2.0443292e-2 -0.74642194 +vn 0.87352985 -1.8941508e-2 -0.48640191 +vn 0.96205809 -5.8689923e-2 -0.26645775 +vn 0.35266424 0.93477386 -4.2728992e-2 +vn 0.35266424 0.93477386 4.2728992e-2 +vn 0.31661972 0.94368831 9.5939166e-2 +vn 0.25852813 0.95425991 0.15017065 +vn -0.87310930 -1.8946809e-2 -0.48715621 +vn -0.96234932 -5.8681682e-2 -0.26540582 +vn -0.98945499 -8.7940991e-2 -0.11508783 +vn -0.35266424 0.93477386 4.2728992e-2 +vn -0.31983872 0.94267883 9.5183088e-2 +vn -0.25912054 0.95372031 0.15255856 +vn -0.70652337 0.34709378 0.61672573 +vn -0.13025164 -0.97354656 0.18772750 +vn -0.51527111 0.45512263 0.72619493 +vn -9.4627829e-2 -0.98004794 0.17479019 +vn -0.30072666 0.67384350 0.67490623 +vn -5.1381528e-2 -0.98870915 0.14076274 +vn 0.30073355 0.67382747 0.67491916 +vn 5.1214549e-2 -0.98869272 0.14093894 +vn 0.51537607 0.45523970 0.72604705 +vn 9.4896427e-2 -0.97987521 0.17561105 +vn 0.70709327 0.34715300 0.61603888 +vn 0.13026934 -0.97349953 0.18795892 +vn 0.68098468 0.34040033 -0.64837296 +vn 0.14721917 -0.97334428 -0.17586193 +vn 0.47126638 0.40602464 -0.78297636 +vn 8.0551031e-2 -0.98586758 -0.14688989 +vn 0.19281431 0.48516794 -0.85289783 +vn 7.4773632e-2 -0.99263998 -9.5261645e-2 +vn -0.19325473 0.48572745 -0.85247959 +vn -7.2340145e-2 -0.99290811 -9.4341825e-2 +vn -0.47585584 0.40998264 -0.77812303 +vn -8.1135750e-2 -0.98594128 -0.14607119 +vn -0.65980004 0.34650931 -0.66677973 +vn -0.14713013 -0.97337083 -0.17578950 +vn 0.78988648 0.32734178 -0.51858144 +vn 0.88631157 0.35625576 -0.29586082 +vn 0.92470657 0.36173025 -0.11861274 +vn 0.92470657 0.36173025 0.11861274 +vn 0.88023863 0.34921280 0.32129486 +vn 0.80333127 0.32404236 0.49965531 +vn 0.21513853 -0.96998078 -0.11336973 +vn 0.21393674 -0.97473091 -6.4270729e-2 +vn 0.21974909 -0.97526240 -2.3949541e-2 +vn 0.21957578 -0.97532265 2.3069633e-2 +vn 0.21233678 -0.97506766 6.4468171e-2 +vn 0.20951391 -0.97077674 0.11703183 +vn -0.21509407 -0.97002435 -0.11308091 +vn -0.21392774 -0.97473345 -6.4262214e-2 +vn -0.21972642 -0.97526789 -2.3934223e-2 +vn -0.21953250 -0.97533160 2.3103137e-2 +vn -0.21227375 -0.97507674 6.4538383e-2 +vn -0.20947224 -0.97082298 0.11672241 +vn -0.78981857 0.32756734 -0.51854244 +vn -0.88650345 0.35648335 -0.29501060 +vn -0.92470657 0.36173025 -0.11861274 +vn -0.92470657 0.36173025 0.11861274 +vn -0.88644718 0.35641505 0.29526211 +vn -0.78981270 0.32748863 0.51860109 +vn -0.83273254 -0.33528918 0.44061058 +vn -0.89468746 -0.37971792 0.23526294 +vn -0.90497845 -0.41376822 9.9044767e-2 +vn -0.90479346 -0.41417712 -9.9025824e-2 +vn -0.89519744 -0.37943653 -0.23377224 +vn -0.83400980 -0.33128800 -0.44122093 +vn 0.83506692 -0.32941861 0.44062072 +vn 0.89523459 -0.37853237 0.23509207 +vn 0.90496695 -0.41379367 9.9043517e-2 +vn 0.90478194 -0.41420258 -9.9024572e-2 +vn 0.89492004 -0.37950679 -0.23471840 +vn 0.83441323 -0.33124561 -0.44048939 +vn -0.60924830 -0.33989013 -0.71644344 +vn -0.38756506 -0.32679736 -0.86197263 +vn -0.15366780 -0.31230385 -0.93747134 +vn 0.15338788 -0.30809230 -0.93890963 +vn 0.38761398 -0.32678733 -0.86195443 +vn 0.60932877 -0.33989132 -0.71637444 +vn 0.57242557 -0.27828506 0.77128879 +vn 0.21604845 0.15513100 0.96398000 +vn -8.9901304e-2 0.75573634 0.64867583 +vn 8.9890441e-2 0.75572605 0.64868932 +vn -0.21601187 0.15513655 0.96398731 +vn -0.57387161 -0.27994688 0.76961102 +vn 0.90794321 -0.41909322 -6.4642082e-7 +vn 0.90083221 -0.39912652 0.17087818 +vn 0.90052662 -0.39983690 -0.17082818 +vn 0.86730525 -0.35510240 0.34883218 +vn 0.86690696 -0.35655739 -0.34833769 +vn 0.74991726 -0.31544274 0.58148085 +vn 0.75542642 -0.32511714 -0.56888467 +vn 0.44099183 -0.28563009 0.85084761 +vn 0.50770795 -0.35029288 -0.78710072 +vn -7.2801647e-2 0.56787656 0.81988788 +vn 0.28196642 -0.31935555 -0.90471375 +vn -1.4192671e-6 0.78166238 0.62370178 +vn -4.5920095e-3 -0.45958511 -0.88812186 +vn 7.2788175e-2 0.56786921 0.81989417 +vn -0.27841539 -0.32318124 -0.90445495 +vn -0.44091752 -0.28563680 0.85088387 +vn -0.50763957 -0.35029880 -0.78714218 +vn -0.74949514 -0.31996761 0.57954962 +vn -0.75491269 -0.32511422 -0.56956789 +vn -0.86570863 -0.35911599 0.34868937 +vn -0.86726385 -0.35655317 -0.34745251 +vn -0.90084312 -0.39910115 0.17087989 +vn -0.90053756 -0.39981152 -0.17082990 +vn -0.90795501 -0.41906765 -6.4685712e-7 +vn -0.98575390 -0.16819410 -6.2779231e-7 +vn -0.97244743 -0.14764511 -0.18040765 +vn -0.97255950 -0.14689270 0.18041773 +vn -0.92677943 -9.8035596e-2 -0.36258642 +vn -0.92558804 -0.10086212 0.36484737 +vn -0.78755245 -0.14823983 -0.59815223 +vn -0.79424983 -6.1027159e-2 0.60451873 +vn -0.53380534 -0.10965903 -0.83846691 +vn -0.48879665 -2.6992545e-2 0.87198007 +vn -0.30000105 -0.23766108 -0.92385961 +vn -0.16842859 0.15163415 0.97398095 +vn -0.61930061 -4.8228389e-2 0.78367134 +vn -0.35060236 3.0857271e-2 0.93601593 +vn -4.6384835e-2 0.27879211 0.95923063 +vn 4.6382646e-2 0.27881032 0.95922544 +vn 0.35065422 3.0863306e-2 0.93599630 +vn 0.61661832 -4.6629254e-2 0.78588012 +vn 0.63937625 -7.8493694e-2 -0.76487696 +vn 0.42778967 -0.14607855 -0.89199611 +vn 0.11341563 -0.31055762 -0.94376420 +vn -0.13847043 -0.45039832 -0.88202454 +vn -0.42773688 -0.14609406 -0.89201888 +vn -0.64313959 -0.11664724 -0.75681232 +vn 0.88566674 -7.1947174e-2 -0.45871346 +vn 0.96116166 -0.12474705 -0.24618375 +vn 0.98100117 -0.16306294 -0.10510555 +vn 0.98107284 -0.16262709 0.10511190 +vn 0.96121344 -0.12371583 0.24650178 +vn 0.88587864 -7.0072903e-2 0.45859440 +vn -0.87615912 -0.11796604 -0.46736412 +vn -0.96143037 -0.12468456 -0.24516403 +vn -0.98100650 -0.16303054 -0.10510611 +vn -0.98107815 -0.16259469 0.10511245 +vn -0.96081278 -0.12504487 0.24739155 +vn -0.88490826 -7.6133815e-2 0.45950083 +vn 0.98574833 -0.16822670 -6.2740642e-7 +vn 0.97255472 -0.14692488 0.18041729 +vn 0.97244262 -0.14767729 -0.18040721 +vn 0.92642794 -9.6561947e-2 0.36387781 +vn 0.92640810 -9.8075299e-2 -0.36352340 +vn 0.79297239 -5.6324747e-2 0.60664842 +vn 0.79690338 -6.2844453e-2 -0.60082907 +vn 0.48887565 -2.7005520e-2 0.87193538 +vn 0.53388048 -0.10966206 -0.83841867 +vn 0.16844436 0.15165588 0.97397484 +vn 0.30738353 -0.15647677 -0.93863219 +vn -8.2085085e-7 0.33004417 0.94396549 +vn -3.6613470e-2 -0.51263939 -0.85782300 +vn -0.73268762 -0.56638902 0.37732259 +vn -0.79719105 -0.56840920 0.20346355 +vn -0.81160979 -0.57812425 8.4035148e-2 +vn -0.81155947 -0.57818932 -8.4073404e-2 +vn -0.79794026 -0.56800016 -0.20166103 +vn -0.70464782 -0.59656316 -0.38416642 +vn 0.73368358 -0.56527459 0.37705841 +vn 0.79793628 -0.56767282 0.20259631 +vn 0.81165130 -0.57806760 8.4023884e-2 +vn 0.81156457 -0.57818175 -8.4076192e-2 +vn 0.79785121 -0.56787824 -0.20235551 +vn 0.73481608 -0.56397257 -0.37680269 +vn -0.51619024 -0.61670775 -0.59432246 +vn -0.36188168 -0.61599449 -0.69970882 +vn -0.15589199 -0.73569603 -0.65912748 +vn 0.14413439 -0.68016541 -0.71874912 +vn 0.36193967 -0.61594070 -0.69972618 +vn 0.52183238 -0.58275542 -0.62296637 +vn 0.50660670 -0.58037705 0.63758305 +vn 0.36307185 -0.60547769 0.70822002 +vn 0.17619693 -0.64914973 0.73997247 +vn -0.17618036 -0.64921853 0.73991606 +vn -0.36302482 -0.60567587 0.70807465 +vn -0.50858947 -0.58093863 0.63548962 +vn -0.28658788 -0.62573234 0.72548359 +vn -0.25529862 -0.67666891 -0.69060973 +vn -0.42353728 -0.58462952 0.69197145 +vn -0.45601486 -0.59608521 -0.66085768 +vn -0.64857528 -0.57750203 0.49582407 +vn -0.61151470 -0.63271564 -0.47510072 +vn -0.76784459 -0.56915251 0.29407500 +vn -0.76929147 -0.56820934 -0.29211089 +vn -0.80854351 -0.57031448 0.14490958 +vn -0.80851472 -0.57035784 -0.14489954 +vn -0.81414403 -0.58066298 -2.6423032e-5 +vn 0.81415928 -0.58064159 -3.1712934e-5 +vn 0.80866365 -0.57015279 0.14487546 +vn 0.80851526 -0.57035662 -0.14490134 +vn 0.76900917 -0.56792009 0.29341383 +vn 0.76923854 -0.56783238 -0.29298201 +vn 0.64748724 -0.57710741 0.49770203 +vn 0.65320550 -0.57400645 -0.49380074 +vn 0.42364170 -0.58426383 0.69221635 +vn 0.45382736 -0.59214190 -0.66588940 +vn 0.28662104 -0.62562256 0.72556516 +vn 0.28386626 -0.63114683 -0.72185429 +vn -1.4715966e-5 -0.66350934 0.74816800 +vn -4.0470625e-2 -0.72641031 -0.68606865 +vn -4.2716907e-7 0.44911744 0.89347273 +vn -0.14511482 0.19787156 0.96942691 +vn 4.4090035e-2 -0.30197224 0.95229661 +vn -1.8943595e-2 0.47631983 0.87906800 +vn 1.8939617e-2 0.47631198 0.87907234 +vn -4.4090712e-2 -0.30199226 0.95229023 +vn 0.14507849 0.19786503 0.96943368 +vn -0.30672642 -0.43240970 0.84790374 +vn -1.3771448e-6 -0.62000464 0.78459814 +vn -4.6734130e-2 -0.59915335 0.79926915 +vn -0.19620414 -0.56427945 0.80193057 +vn 0.19617501 -0.56426177 0.80195014 +vn 4.6718182e-2 -0.59915118 0.79927172 +vn 0.30666116 -0.43239734 0.84793365 +vn -0.26011140 -0.67403369 0.69139037 +vn 2.6697104e-6 -0.73623483 0.67672615 +vn 0.26012450 -0.67401013 0.69140841 +vn 0.57109763 -0.36756896 0.73398948 +vn 0.65264383 0.13932192 0.74474522 +vn 0.35815678 0.53276001 0.76674017 +vn 2.5992138e-6 0.65633020 0.75447377 +vn -0.35816017 0.53280202 0.76670940 +vn -0.65269949 0.13935456 0.74469033 +vn -0.57112968 -0.36760141 0.73394829 +vn -0.26045191 -0.95495181 -0.14223867 +vn 2.6863871e-6 -0.99134750 -0.13126363 +vn 0.26047548 -0.95495334 -0.14218522 +vn 0.82339308 -0.53775075 -0.18124010 +vn 0.93176015 0.34057175 -0.12583287 +vn 0.48392484 0.87328777 -5.6437723e-2 +vn 2.8961500e-6 0.99974540 -2.2564212e-2 +vn -0.48389467 0.87329795 -5.6538749e-2 +vn -0.93172475 0.34059597 -0.12602924 +vn -0.82335455 -0.53775126 -0.18141352 +vn -0.25463656 -0.94279507 -0.21516896 +vn 1.9542332e-6 -0.97858245 -0.20585527 +vn 0.25465120 -0.94279683 -0.21514394 +vn 0.79504114 -0.51901622 -0.31389768 +vn 0.89109152 0.34670378 -0.29283511 +vn 0.46408400 0.85646317 -0.22604620 +vn 2.2283580e-6 0.98361801 -0.18026536 +vn -0.46405992 0.85646348 -0.22609446 +vn -0.89106038 0.34671305 -0.29291888 +vn -0.79501231 -0.51901741 -0.31396873 +vn -0.29391504 -0.94088834 -0.16835402 +vn 6.5253642e-7 -0.98374063 -0.17959503 +vn 0.29391797 -0.94088741 -0.16835409 +vn 0.82055736 -0.51658233 -0.24459828 +vn 0.89371415 0.32784649 -0.30625430 +vn 0.45982188 0.81531399 -0.35189052 +vn 7.2381492e-7 0.93499351 -0.35466483 +vn -0.45981848 0.81531657 -0.35188899 +vn -0.89371866 0.32784828 -0.30623922 +vn -0.82055890 -0.51658727 -0.24458267 +vn -0.37380068 -0.92741313 -1.3339263e-2 +vn 5.1198909e-15 -0.99924319 -3.8897882e-2 +vn 0.37380068 -0.92741313 -1.3339263e-2 +vn 0.87965349 -0.47555933 -7.2840179e-3 +vn 0.93934071 0.32940132 -9.5570955e-2 +vn 0.49917119 0.83543743 -0.22994005 +vn -1.3637264e-15 0.96005762 -0.27980238 +vn -0.49917119 0.83543743 -0.22994005 +vn -0.93934071 0.32940132 -9.5570955e-2 +vn -0.87965349 -0.47555933 -7.2840179e-3 +vn -0.43701282 -0.83953967 0.32278932 +vn 1.3541920e-15 -0.95674771 0.29091892 +vn 0.43701282 -0.83953967 0.32278932 +vn 0.85918232 -0.35634248 0.36718629 +vn 0.89933569 0.33146351 0.28517934 +vn 0.50977048 0.84718173 0.14972366 +vn -8.8997083e-15 0.99711417 7.5916565e-2 +vn -0.50977048 0.84718173 0.14972366 +vn -0.89933569 0.33146351 0.28517934 +vn -0.85918232 -0.35634248 0.36718629 +vn -0.41006239 -0.65987844 0.62961042 +vn 3.3460383e-16 -0.80852549 0.58846115 +vn 0.41006239 -0.65987844 0.62961042 +vn 0.74180940 -0.21265148 0.63600170 +vn 0.76054086 0.31499523 0.56776368 +vn 0.44264662 0.75462635 0.48435838 +vn -6.7162372e-15 0.90469718 0.42605518 +vn -0.44264662 0.75462635 0.48435838 +vn -0.76054086 0.31499523 0.56776368 +vn -0.74180940 -0.21265148 0.63600170 +vn -0.34625091 -0.47179981 0.81087314 +vn 5.3234410e-16 -0.59817081 0.80136863 +vn 0.34625091 -0.47179981 0.81087314 +vn 0.61756841 -0.12356464 0.77675030 +vn 0.62319054 0.29825838 0.72296299 +vn 0.35780805 0.63097661 0.68836176 +vn -2.3843152e-15 0.74566647 0.66631938 +vn -0.35780805 0.63097661 0.68836176 +vn -0.62319054 0.29825838 0.72296299 +vn -0.61756841 -0.12356464 0.77675030 +vn -0.22243338 -0.21486866 0.95097573 +vn 1.5464970e-15 -0.27058412 0.96269633 +vn 0.22243338 -0.21486866 0.95097573 +vn 0.39579006 -1.4739605e-2 0.91822273 +vn 0.39498284 0.25974753 0.88120360 +vn 0.22155911 0.45316419 0.86345456 +vn 4.1571133e-16 0.51574926 0.85673958 +vn -0.22155911 0.45316419 0.86345456 +vn -0.39498284 0.25974753 0.88120360 +vn -0.39579006 -1.4739605e-2 0.91822273 +vn -0.12420668 -0.37005066 -0.92067107 +vn -0.29652757 -0.34332693 -0.89117788 +vn -0.27959789 0.37108260 -0.88550704 +vn -1.9625696e-6 0.65107408 -0.75901419 +vn 0.27960828 0.37108541 -0.88550259 +vn 0.29654648 -0.34330898 -0.89117850 +vn 0.12662466 -0.36422486 -0.92266269 +vn -4.7060799e-2 0.62489085 -0.77929244 +vn 2.7239733e-3 0.73798053 -0.67481650 +vn 5.2758303e-2 0.62005979 -0.78277865 +vn -0.56991022 -0.67158893 -0.47346664 +vn -0.72376095 -0.10356063 -0.68223550 +vn -0.42626263 0.76386375 -0.48457439 +vn -4.5952607e-6 0.95643618 -0.29194150 +vn 0.42626571 0.76386728 -0.48456611 +vn 0.72377490 -0.10352287 -0.68222644 +vn 0.56936251 -0.67150856 -0.47423895 +vn -5.2842145e-3 -0.39003916 0.92078311 +vn 6.9807354e-3 -0.41602125 0.90932810 +vn 1.7029189e-2 -0.38500676 0.92275663 +vn -0.60616007 -0.77127727 -0.19416833 +vn -0.93185154 0.11985476 -0.34247269 +vn -0.45235328 0.84902075 -0.27302064 +vn -5.1770767e-6 0.97141615 -0.23738296 +vn 0.45235234 0.84902183 -0.27301884 +vn 0.93184953 0.11989697 -0.34246337 +vn 0.60635362 -0.77107886 -0.19435196 +vn 0.19869167 -0.97427306 -0.10636553 +vn -2.9385826e-4 -0.99447455 -0.10497755 +vn -0.19876755 -0.97431268 -0.10585962 +vn -0.54889642 -0.80437228 -0.22737187 +vn -0.90846679 9.2497388e-2 -0.40759332 +vn -0.42783751 0.83597557 -0.34365667 +vn -2.4841058e-6 0.94644913 -0.32285297 +vn 0.42784282 0.83597288 -0.34365660 +vn 0.90846915 9.2540909e-2 -0.40757820 +vn 0.54895647 -0.80432808 -0.22738324 +vn 0.15358769 -0.98015194 -0.12535149 +vn -3.0345305e-7 -0.99320540 -0.11637450 +vn -0.15356461 -0.98015630 -0.12534568 +vn -0.51964257 -0.53678477 -0.66470573 +vn -0.63969826 0.27208646 -0.71885680 +vn -0.28305595 0.72776905 -0.62468515 +vn 3.0200027e-6 0.79250303 -0.60986798 +vn 0.28306883 0.72776392 -0.62468530 +vn 0.63971457 0.27211190 -0.71883265 +vn 0.51969493 -0.53673073 -0.66470843 +vn 0.13008507 -0.79127821 -0.59745851 +vn 5.3669484e-6 -0.79156976 -0.61107882 +vn -0.13005713 -0.79128358 -0.59745748 +g Turtle_turtle_auv +usemtl turtle_auv +s 1 +f 1/23/1 5/88/5 527/95/527 244/30/244 +f 1/22/1 244/26/244 455/15/455 243/13/243 +f 2/1042/2 386/1049/386 479/1047/479 246/1041/246 +f 2/1042/2 578/1031/578 533/1029/533 247/1040/247 +f 3/42/3 244/30/244 527/95/527 8/100/8 +f 3/40/3 250/51/250 454/28/454 249/20/249 +f 4/41/4 245/27/245 480/14/480 251/21/251 +f 4/37/4 252/49/252 529/103/529 9/96/9 +f 5/88/5 13/153/13 20/158/20 527/95/527 +f 6/1037/6 254/1033/254 535/1013/535 577/1023/577 +f 6/1037/6 385/1046/385 478/1043/478 254/1033/254 +f 7/1036/7 247/1040/247 533/1029/533 576/1022/576 +f 7/1036/7 384/1045/384 456/1048/456 247/1040/247 +f 8/100/8 20/158/20 24/175/24 526/110/526 +f 8/100/8 526/110/526 250/54/250 3/42/3 +f 8/100/8 527/95/527 20/158/20 +f 9/96/9 528/91/528 245/25/245 4/37/4 +f 10/634/10 26/668/26 522/670/522 258/636/258 +f 10/634/10 248/588/248 449/593/449 257/635/257 +f 11/70/11 250/54/250 526/110/526 18/135/18 +f 11/61/11 260/83/260 453/62/453 259/45/259 +f 12/64/12 252/53/252 481/31/481 261/47/261 +f 12/60/12 262/75/262 530/136/530 19/114/19 +f 13/153/13 29/190/29 36/197/36 20/158/20 +f 14/641/14 253/600/253 448/610/448 263/647/263 +f 14/641/14 257/635/257 449/593/449 253/600/253 +f 15/642/15 31/676/31 523/681/523 264/649/264 +f 15/642/15 258/636/258 522/670/522 31/676/31 +f 16/1028/16 266/1012/266 536/991/536 575/1003/575 +f 16/1028/16 383/1039/383 477/1032/477 266/1012/266 +f 17/1027/17 256/1034/256 532/1014/532 574/1002/574 +f 17/1027/17 382/1038/382 457/1044/457 256/1034/256 +f 18/135/18 525/147/525 260/94/260 11/70/11 +f 18/135/18 526/110/526 24/175/24 +f 19/114/19 529/103/529 252/49/252 12/60/12 +f 19/114/19 530/136/530 43/184/43 25/168/25 +f 20/158/20 36/197/36 44/203/44 24/175/24 +f 21/155/21 37/193/37 29/190/29 13/153/13 +f 21/155/21 528/91/528 9/96/9 +f 22/659/22 265/621/265 447/633/447 269/666/269 +f 22/659/22 269/666/269 519/687/519 38/685/38 +f 23/662/23 264/649/264 523/681/523 39/686/39 +f 23/662/23 267/623/267 451/615/451 264/649/264 +f 24/175/24 42/192/42 525/147/525 18/135/18 +f 24/175/24 44/203/44 48/213/48 42/192/42 +f 25/168/25 45/199/45 37/193/37 21/155/21 +f 25/168/25 529/103/529 19/114/19 +f 26/668/26 50/703/50 522/670/522 +f 27/115/27 260/94/260 525/147/525 34/164/34 +f 27/108/27 272/142/272 433/116/433 271/92/271 +f 28/107/28 262/85/262 482/63/482 273/82/273 +f 28/97/28 274/122/274 483/169/483 35/149/35 +f 29/190/29 53/220/53 60/223/60 36/197/36 +f 30/675/30 521/669/521 257/635/257 14/641/14 +f 31/676/31 55/708/55 523/681/523 +f 31/676/31 522/670/522 50/703/50 55/708/55 +f 32/999/32 276/983/276 543/965/543 573/981/573 +f 32/999/32 381/1020/381 470/1000/470 276/983/276 +f 33/998/33 268/1011/268 531/990/531 572/980/572 +f 33/998/33 380/1019/380 458/1035/458 268/1011/268 +f 34/164/34 505/186/505 272/151/272 27/115/27 +f 34/164/34 525/147/525 42/192/42 +f 35/149/35 483/169/483 43/184/43 +f 35/149/35 530/136/530 262/75/262 28/97/28 +f 36/197/36 60/223/60 68/228/68 44/203/44 +f 37/193/37 61/221/61 53/220/53 29/190/29 +f 38/685/38 520/680/520 263/647/263 22/659/22 +f 39/686/39 63/714/63 524/693/524 +f 39/686/39 523/681/523 55/708/55 63/714/63 +f 39/686/39 524/693/524 270/667/270 23/662/23 +f 40/674/40 275/653/275 434/671/434 279/698/279 +f 40/674/40 279/698/279 506/704/506 46/692/46 +f 41/679/41 270/667/270 524/693/524 47/699/47 +f 41/679/41 277/658/277 452/639/452 270/667/270 +f 42/192/42 505/186/505 34/164/34 +f 43/184/43 49/206/49 45/199/45 25/168/25 +f 43/184/43 67/217/67 73/232/73 49/206/49 +f 43/184/43 483/169/483 59/196/59 67/217/67 +f 43/184/43 530/136/530 35/149/35 +f 44/203/44 68/228/68 72/235/72 48/213/48 +f 45/199/45 69/226/69 61/221/61 37/193/37 +f 46/692/46 519/687/519 269/666/269 40/674/40 +f 47/699/47 484/705/484 280/701/280 41/679/41 +f 47/699/47 524/693/524 63/714/63 484/705/484 +f 48/213/48 72/235/72 66/222/66 42/192/42 +f 49/206/49 73/232/73 69/226/69 45/199/45 +f 50/703/50 74/745/74 79/752/79 55/708/55 +f 51/178/51 272/151/272 505/186/505 58/208/58 +f 51/176/51 282/209/282 431/200/431 281/160/281 +f 52/167/52 274/138/274 459/113/459 283/154/283 +f 52/159/52 284/198/284 485/218/485 59/196/59 +f 53/220/53 77/241/77 84/244/84 60/223/60 +f 54/707/54 50/703/50 521/669/521 30/675/30 +f 54/707/54 78/751/78 74/745/74 50/703/50 +f 55/708/55 79/752/79 87/753/87 63/714/63 +f 56/963/56 286/942/286 544/924/544 571/951/571 +f 56/963/56 379/978/379 469/955/469 286/942/286 +f 57/970/57 278/984/278 554/964/554 570/949/570 +f 57/970/57 378/988/378 411/1001/411 278/984/278 +f 57/970/57 687/947/687 288/954/288 +f 58/208/58 503/225/503 282/210/282 51/178/51 +f 59/196/59 483/169/483 274/122/274 52/159/52 +f 59/196/59 485/218/485 67/217/67 +f 60/223/60 84/244/84 92/248/92 68/228/68 +f 61/221/61 85/243/85 77/241/77 53/220/53 +f 62/713/62 54/707/54 520/680/520 38/685/38 +f 62/713/62 86/748/86 78/751/78 54/707/54 +f 62/713/62 506/704/506 70/718/70 +f 63/714/63 87/753/87 486/737/486 71/719/71 +f 64/711/64 285/700/285 432/720/432 289/729/289 +f 64/711/64 289/729/289 504/735/504 70/718/70 +f 65/715/65 280/701/280 484/705/484 71/719/71 +f 65/715/65 287/702/287 412/672/412 280/701/280 +f 66/222/66 58/208/58 505/186/505 42/192/42 +f 66/222/66 90/245/90 503/225/503 58/208/58 +f 67/217/67 91/240/91 97/251/97 73/232/73 +f 67/217/67 485/218/485 83/238/83 91/240/91 +f 68/228/68 92/248/92 96/255/96 72/235/72 +f 69/226/69 93/246/93 85/243/85 61/221/61 +f 70/718/70 504/735/504 86/748/86 62/713/62 +f 70/718/70 506/704/506 279/698/279 64/711/64 +f 71/719/71 484/705/484 63/714/63 +f 71/719/71 486/737/486 290/730/290 65/715/65 +f 72/235/72 96/255/96 90/245/90 66/222/66 +f 73/232/73 97/251/97 93/246/93 69/226/69 +f 74/745/74 98/779/98 100/782/100 79/752/79 +f 75/236/75 282/210/282 503/225/503 82/239/82 +f 75/237/75 292/257/292 429/256/429 291/234/291 +f 76/233/76 284/201/284 460/195/460 293/230/293 +f 76/231/76 294/253/294 487/259/487 83/238/83 +f 77/241/77 121/271/121 119/272/119 84/244/84 +f 78/751/78 99/777/99 98/779/98 74/745/74 +f 79/752/79 100/782/100 102/784/102 87/753/87 +f 80/215/80 377/216/377 468/182/468 296/179/296 +f 80/214/80 780/205/780 779/202/779 569/211/569 +f 81/310/81 288/283/288 687/285/687 688/314/688 +f 81/310/81 376/308/376 413/282/413 288/283/288 +f 82/239/82 501/260/501 292/258/292 75/236/75 +f 82/239/82 503/225/503 90/245/90 +f 83/238/83 485/218/485 284/198/284 76/231/76 +f 83/238/83 487/259/487 91/240/91 +f 84/244/84 119/272/119 117/275/117 92/248/92 +f 85/243/85 120/270/120 121/271/121 77/241/77 +f 86/748/86 101/783/101 99/777/99 78/751/78 +f 86/748/86 504/735/504 94/755/94 +f 87/753/87 102/784/102 488/772/488 95/756/95 +f 88/749/88 295/739/295 430/767/430 299/769/299 +f 88/749/88 299/769/299 502/771/502 94/755/94 +f 89/754/89 290/730/290 486/737/486 95/756/95 +f 89/754/89 297/741/297 414/722/414 290/730/290 +f 90/245/90 113/269/113 501/260/501 82/239/82 +f 91/240/91 114/279/114 116/278/116 97/251/97 +f 91/240/91 487/259/487 112/280/112 114/279/114 +f 92/248/92 117/275/117 115/273/115 96/255/96 +f 93/246/93 118/276/118 120/270/120 85/243/85 +f 94/755/94 502/771/502 101/783/101 86/748/86 +f 94/755/94 504/735/504 289/729/289 88/749/88 +f 95/756/95 486/737/486 87/753/87 +f 95/756/95 488/772/488 300/770/300 89/754/89 +f 96/255/96 115/273/115 113/269/113 90/245/90 +f 97/251/97 116/278/116 118/276/118 93/246/93 +f 98/779/98 142/826/142 135/822/135 100/782/100 +f 99/777/99 134/823/134 142/826/142 98/779/98 +f 100/782/100 135/822/135 127/821/127 102/784/102 +f 101/783/101 126/825/126 134/823/134 99/777/99 +f 101/783/101 500/795/500 122/816/122 126/825/126 +f 101/783/101 502/771/502 103/778/103 +f 102/784/102 490/794/490 104/785/104 +f 103/778/103 500/795/500 101/783/101 +f 103/778/103 502/771/502 299/769/299 105/780/105 +f 104/785/104 488/772/488 102/784/102 +f 104/785/104 490/794/490 304/799/304 106/786/106 +f 105/780/105 299/769/299 430/767/430 301/781/301 +f 105/780/105 302/800/302 500/795/500 103/778/103 +f 106/786/106 300/770/300 488/772/488 104/785/104 +f 106/786/106 304/799/304 418/804/418 303/787/303 +f 107/131/107 296/179/296 468/182/468 305/133/305 +f 107/131/107 782/132/782 781/172/781 296/179/296 +f 108/367/108 308/408/308 417/409/417 307/366/307 +f 108/367/108 683/368/683 685/401/685 308/408/308 +f 109/274/109 292/258/292 501/260/501 111/277/111 +f 109/264/109 375/263/375 429/256/429 292/257/292 +f 110/281/110 310/300/310 489/292/489 112/280/112 +f 110/265/110 374/266/374 462/297/462 310/295/310 +f 111/277/111 499/289/499 309/294/309 109/274/109 +f 111/277/111 501/260/501 113/269/113 +f 112/280/112 487/259/487 294/253/294 110/281/110 +f 112/280/112 489/292/489 131/311/131 114/279/114 +f 113/269/113 499/289/499 111/277/111 +f 114/279/114 131/311/131 125/301/125 116/278/116 +f 115/273/115 124/298/124 130/307/130 113/269/113 +f 116/278/116 125/301/125 133/304/133 118/276/118 +f 117/275/117 132/302/132 124/298/124 115/273/115 +f 118/276/118 133/304/133 141/305/141 120/270/120 +f 119/272/119 140/306/140 132/302/132 117/275/117 +f 120/270/120 141/305/141 145/309/145 121/271/121 +f 121/271/121 145/309/145 140/306/140 119/272/119 +f 122/816/122 498/834/498 126/825/126 +f 122/816/122 500/795/500 302/800/302 128/824/128 +f 123/814/123 492/832/492 314/848/314 129/820/129 +f 124/298/124 148/326/148 154/346/154 130/307/130 +f 125/301/125 149/332/149 157/339/157 133/304/133 +f 126/825/126 150/863/150 158/868/158 134/823/134 +f 126/825/126 498/834/498 146/855/146 150/863/150 +f 127/821/127 123/814/123 490/794/490 102/784/102 +f 127/821/127 492/832/492 123/814/123 +f 128/824/128 302/800/302 428/806/428 311/830/311 +f 128/824/128 312/849/312 498/834/498 122/816/122 +f 129/820/129 304/799/304 490/794/490 123/814/123 +f 129/820/129 314/848/314 420/850/420 313/829/313 +f 130/307/130 138/317/138 499/289/499 113/269/113 +f 130/307/130 497/340/497 138/317/138 +f 131/311/131 155/350/155 149/332/149 125/301/125 +f 131/311/131 489/292/489 139/318/139 +f 132/302/132 156/335/156 148/326/148 124/298/124 +f 133/304/133 157/339/157 165/347/165 141/305/141 +f 134/823/134 158/868/158 166/875/166 142/826/142 +f 135/822/135 159/867/159 151/862/151 127/821/127 +f 136/34/136 306/72/306 467/71/467 315/32/315 +f 136/34/136 784/46/784 783/78/783 306/72/306 +f 137/434/137 318/463/318 419/468/419 317/439/317 +f 137/434/137 682/431/682 684/462/684 318/463/318 +f 138/317/138 497/340/497 319/353/319 143/325/143 +f 139/318/139 489/292/489 310/300/310 144/333/144 +f 139/318/139 491/349/491 155/350/155 131/311/131 +f 140/306/140 164/345/164 156/335/156 132/302/132 +f 141/305/141 165/347/165 169/348/169 145/309/145 +f 142/826/142 166/875/166 159/867/159 135/822/135 +f 143/325/143 309/294/309 499/289/499 138/317/138 +f 143/319/143 373/323/373 427/291/427 309/290/309 +f 144/333/144 320/369/320 491/349/491 139/318/139 +f 144/324/144 372/327/372 463/359/463 320/355/320 +f 145/309/145 169/348/169 164/345/164 140/306/140 +f 146/855/146 496/872/496 150/863/150 +f 146/855/146 498/834/498 312/849/312 152/865/152 +f 147/854/147 494/871/494 324/878/324 153/861/153 +f 148/326/148 172/352/172 178/376/178 154/346/154 +f 149/332/149 173/356/173 181/361/181 157/339/157 +f 150/863/150 174/892/174 514/897/514 158/868/158 +f 150/863/150 513/887/513 174/892/174 +f 151/862/151 147/854/147 492/832/492 127/821/127 +f 151/862/151 494/871/494 147/854/147 +f 152/865/152 312/849/312 426/852/426 321/879/321 +f 152/865/152 322/883/322 496/872/496 146/855/146 +f 153/861/153 314/848/314 492/832/492 147/854/147 +f 153/861/153 324/878/324 422/905/422 323/876/323 +f 154/346/154 162/357/162 497/340/497 130/307/130 +f 154/346/154 178/376/178 495/378/495 162/357/162 +f 155/350/155 179/381/179 173/356/173 149/332/149 +f 155/350/155 491/349/491 163/372/163 +f 156/335/156 180/358/180 172/352/172 148/326/148 +f 157/339/157 181/361/181 189/373/189 165/347/165 +f 158/868/158 182/902/182 515/907/515 166/875/166 +f 158/868/158 514/897/514 182/902/182 +f 159/867/159 517/895/517 175/891/175 151/862/151 +f 160/609/160 316/632/316 466/617/466 325/587/325 +f 160/609/160 563/624/563 547/655/547 316/632/316 +f 161/595/161 328/579/328 421/558/421 327/576/327 +f 161/595/161 562/625/562 549/605/549 328/579/328 +f 161/595/161 684/627/684 677/637/677 562/625/562 +f 162/357/162 495/378/495 329/403/329 167/382/167 +f 163/372/163 491/349/491 320/369/320 168/390/168 +f 163/372/163 493/385/493 179/381/179 155/350/155 +f 164/345/164 188/371/188 180/358/180 156/335/156 +f 165/347/165 189/373/189 193/377/193 169/348/169 +f 166/875/166 515/907/515 190/908/190 +f 166/875/166 516/906/516 183/900/183 159/867/159 +f 167/382/167 319/353/319 497/340/497 162/357/162 +f 167/380/167 371/386/371 425/354/425 319/351/319 +f 168/390/168 330/417/330 493/385/493 163/372/163 +f 168/384/168 370/389/370 464/418/464 330/407/330 +f 169/348/169 193/377/193 188/371/188 164/345/164 +f 170/884/170 176/903/176 332/911/332 513/887/513 +f 170/884/170 496/872/496 322/883/322 176/903/176 +f 171/882/171 494/871/494 151/862/151 518/885/518 +f 172/352/172 180/358/180 196/383/196 178/376/178 +f 174/892/174 194/918/194 341/930/341 514/897/514 +f 174/892/174 513/887/513 332/911/332 194/918/194 +f 175/891/175 518/885/518 151/862/151 +f 176/903/176 322/883/322 424/909/424 331/926/331 +f 177/898/177 324/878/324 494/871/494 171/882/171 +f 177/898/177 334/910/334 446/936/446 333/921/333 +f 178/376/178 507/405/507 186/388/186 +f 179/381/179 197/387/197 181/361/181 173/356/173 +f 179/381/179 493/385/493 187/404/187 +f 179/381/179 512/411/512 203/420/203 197/387/197 +f 181/361/181 197/387/197 205/394/205 189/373/189 +f 182/902/182 198/934/198 345/938/345 515/907/515 +f 182/902/182 514/897/514 341/930/341 198/934/198 +f 183/900/183 517/895/517 159/867/159 +f 184/562/184 326/581/326 465/559/465 335/539/335 +f 184/562/184 561/583/561 548/604/548 326/581/326 +f 185/563/185 338/549/338 440/527/440 337/540/337 +f 185/563/185 560/584/560 537/571/537 338/549/338 +f 186/388/186 495/378/495 178/376/178 +f 186/388/186 507/405/507 339/442/339 191/421/191 +f 187/404/187 493/385/493 330/417/330 192/436/192 +f 187/404/187 512/411/512 179/381/179 +f 188/371/188 204/391/204 196/383/196 180/358/180 +f 189/373/189 205/394/205 209/399/209 193/377/193 +f 190/908/190 515/907/515 345/938/345 206/940/206 +f 190/908/190 516/906/516 166/875/166 +f 191/421/191 329/403/329 495/378/495 186/388/186 +f 191/419/191 369/433/369 423/413/423 329/402/329 +f 192/436/192 340/447/340 512/411/512 187/404/187 +f 192/422/192 368/443/368 476/451/476 340/438/340 +f 193/377/193 209/399/209 204/391/204 188/371/188 +f 194/918/194 332/911/332 441/941/441 342/952/342 +f 194/918/194 342/952/342 442/959/442 341/930/341 +f 195/916/195 334/910/334 518/885/518 175/891/175 +f 196/383/196 202/412/202 507/405/507 178/376/178 +f 196/383/196 508/423/508 202/412/202 +f 197/387/197 511/428/511 213/437/213 205/394/205 +f 198/934/198 341/930/341 442/959/442 346/968/346 +f 198/934/198 346/968/346 443/973/443 345/938/345 +f 199/932/199 343/928/343 517/895/517 183/900/183 +f 200/531/200 336/548/336 471/526/471 349/520/349 +f 200/531/200 559/556/559 542/570/542 336/548/336 +f 201/532/201 352/524/352 439/515/439 351/521/351 +f 201/532/201 558/557/558 538/546/538 352/524/352 +f 202/412/202 508/423/508 354/469/354 207/454/207 +f 203/420/203 511/428/511 197/387/197 +f 203/420/203 512/411/512 340/447/340 208/460/208 +f 204/391/204 212/432/212 508/423/508 196/383/196 +f 204/391/204 509/441/509 212/432/212 +f 205/394/205 510/445/510 217/446/217 209/399/209 +f 206/940/206 345/938/345 443/973/443 353/977/353 +f 206/940/206 347/937/347 516/906/516 190/908/190 +f 207/454/207 339/442/339 507/405/507 202/412/202 +f 207/453/207 367/471/367 435/452/435 339/440/339 +f 208/460/208 355/472/355 511/428/511 203/420/203 +f 208/449/208 366/470/366 475/478/475 355/464/355 +f 209/399/209 217/446/217 509/441/509 204/391/204 +f 210/523/210 350/525/350 472/516/472 357/514/357 +f 210/523/210 357/514/357 437/512/437 356/519/356 +f 210/523/210 557/538/557 541/547/541 350/525/350 +f 211/522/211 556/537/556 539/529/539 358/518/358 +f 212/432/212 509/441/509 361/486/361 215/477/215 +f 213/437/213 510/445/510 205/394/205 +f 213/437/213 511/428/511 355/472/355 216/480/216 +f 214/517/214 356/519/356 437/512/437 360/510/360 +f 214/517/214 555/528/555 540/530/540 356/519/356 +f 215/477/215 354/469/354 508/423/508 212/432/212 +f 215/473/215 365/489/365 436/481/436 354/466/354 +f 216/480/216 362/487/362 510/445/510 213/437/213 +f 216/474/216 364/490/364 474/496/474 362/482/362 +f 217/446/217 510/445/510 362/487/362 218/488/218 +f 218/488/218 361/486/361 509/441/509 217/446/217 +f 218/485/218 363/497/363 473/495/473 361/483/361 +f 219/504/219 360/509/360 437/507/437 401/502/401 +f 219/504/219 401/502/401 473/495/473 363/497/363 +f 219/504/219 402/503/402 438/508/438 360/509/360 +f 220/499/220 359/506/359 438/508/438 402/503/402 +f 220/499/220 402/503/402 474/496/474 364/490/364 +f 220/499/220 403/492/403 439/500/439 359/506/359 +f 221/498/221 400/494/400 436/481/436 365/489/365 +f 221/498/221 401/502/401 437/507/437 357/505/357 +f 222/479/222 351/491/351 439/500/439 403/492/403 +f 222/479/222 403/492/403 475/478/475 366/470/366 +f 222/479/222 404/465/404 440/475/440 351/491/351 +f 223/484/223 399/467/399 435/452/435 367/471/367 +f 224/450/224 337/458/337 440/475/440 404/465/404 +f 224/450/224 392/426/392 421/444/421 337/458/337 +f 224/450/224 404/465/404 476/451/476 368/443/368 +f 225/448/225 393/424/393 423/413/423 369/433/369 +f 226/400/226 327/410/327 421/444/421 392/426/392 +f 226/400/226 391/375/391 419/379/419 327/410/327 +f 226/400/226 392/426/392 464/418/464 370/389/370 +f 227/392/227 394/360/394 425/354/425 371/386/371 +f 228/331/228 317/344/317 419/379/419 391/375/391 +f 228/331/228 390/299/390 417/303/417 317/344/317 +f 228/331/228 391/375/391 463/359/463 372/327/372 +f 229/328/229 395/293/395 427/291/427 373/323/373 +f 230/267/230 307/268/307 417/303/417 390/299/390 +f 230/267/230 389/247/389 415/242/415 307/268/307 +f 230/267/230 390/299/390 462/297/462 374/266/374 +f 231/262/231 396/254/396 429/256/429 375/263/375 +f 232/227/232 388/185/388 413/177/413 376/219/376 +f 233/229/233 291/234/291 429/256/429 396/254/396 +f 233/229/233 396/254/396 468/250/468 377/224/377 +f 233/229/233 397/194/397 431/200/431 291/234/291 +f 234/143/234 387/98/387 411/80/411 378/134/378 +f 235/152/235 281/160/281 431/200/431 397/194/397 +f 235/152/235 397/194/397 469/187/469 379/141/379 +f 235/152/235 398/101/398 433/116/433 281/160/281 +f 236/67/236 410/52/410 458/35/458 380/57/380 +f 237/69/237 271/92/271 433/116/433 398/101/398 +f 237/69/237 398/101/398 470/90/470 381/55/381 +f 237/69/237 405/50/405 453/62/453 271/92/271 +f 238/29/238 409/18/409 457/10/457 382/19/382 +f 239/24/239 259/45/259 453/62/453 405/50/405 +f 239/24/239 405/50/405 477/36/477 383/17/383 +f 239/24/239 406/16/406 454/28/454 259/45/259 +f 240/11/240 408/7/408 456/2/456 384/4/384 +f 241/12/241 249/20/249 454/28/454 406/16/406 +f 241/12/241 406/16/406 478/9/478 385/5/385 +f 241/12/241 407/8/407 455/15/455 249/20/249 +f 242/6/242 243/13/243 455/15/455 407/8/407 +f 242/6/242 407/8/407 479/3/479 386/1/386 +f 243/13/243 480/14/480 245/27/245 1/22/1 +f 245/25/245 528/91/528 5/88/5 1/23/1 +f 246/1041/246 479/1047/479 385/1046/385 6/1037/6 +f 246/1041/246 534/1030/534 578/1031/578 2/1042/2 +f 247/1040/247 456/1048/456 386/1049/386 2/1042/2 +f 248/588/248 661/545/661 630/551/630 449/593/449 +f 249/20/249 455/15/455 244/26/244 3/40/3 +f 251/21/251 480/14/480 408/7/408 240/11/240 +f 251/21/251 481/31/481 252/53/252 4/41/4 +f 253/600/253 660/561/660 631/574/631 448/610/448 +f 254/1033/254 478/1043/478 383/1039/383 16/1028/16 +f 255/601/255 450/592/450 258/636/258 15/642/15 +f 255/601/255 659/560/659 629/550/629 450/592/450 +f 256/1034/256 457/1044/457 384/1045/384 7/1036/7 +f 257/635/257 521/669/521 26/668/26 10/634/10 +f 258/636/258 450/592/450 248/588/248 10/634/10 +f 259/45/259 454/28/454 250/51/250 11/61/11 +f 261/47/261 481/31/481 409/18/409 238/29/238 +f 261/47/261 482/63/482 262/85/262 12/64/12 +f 263/647/263 448/610/448 265/621/265 22/659/22 +f 263/647/263 520/680/520 30/675/30 14/641/14 +f 264/649/264 451/615/451 255/601/255 15/642/15 +f 265/621/265 658/589/658 632/611/632 447/633/447 +f 266/1012/266 477/1032/477 381/1020/381 32/999/32 +f 267/623/267 657/594/657 628/575/628 451/615/451 +f 268/1011/268 458/1035/458 382/1038/382 17/1027/17 +f 269/666/269 447/633/447 275/653/275 40/674/40 +f 270/667/270 452/639/452 267/623/267 23/662/23 +f 271/92/271 453/62/453 260/83/260 27/108/27 +f 273/82/273 459/113/459 274/138/274 28/107/28 +f 273/82/273 482/63/482 410/52/410 236/67/236 +f 275/653/275 656/628/656 639/652/639 434/671/434 +f 276/983/276 470/1000/470 379/978/379 56/963/56 +f 277/658/277 655/631/655 627/616/627 452/639/452 +f 278/984/278 411/1001/411 380/1019/380 33/998/33 +f 279/698/279 434/671/434 285/700/285 64/711/64 +f 280/701/280 412/672/412 277/658/277 41/679/41 +f 281/160/281 433/116/433 272/142/272 51/176/51 +f 283/154/283 459/113/459 387/98/387 234/143/234 +f 283/154/283 460/195/460 284/201/284 52/167/52 +f 285/700/285 654/678/654 640/709/640 432/720/432 +f 286/942/286 469/955/469 377/935/377 80/922/80 +f 287/702/287 653/684/653 650/660/650 412/672/412 +f 288/954/288 413/969/413 378/988/378 57/970/57 +f 289/729/289 432/720/432 295/739/295 88/749/88 +f 290/730/290 414/722/414 287/702/287 65/715/65 +f 291/234/291 431/200/431 282/209/282 75/237/75 +f 293/230/293 460/195/460 388/185/388 232/227/232 +f 293/230/293 461/249/461 294/252/294 76/233/76 +f 294/252/294 461/249/461 374/266/374 110/265/110 +f 295/739/295 652/733/652 641/762/641 430/767/430 +f 296/179/296 781/172/781 780/207/780 80/215/80 +f 297/741/297 651/738/651 649/716/649 414/722/414 +f 298/330/298 415/329/415 376/308/376 81/310/81 +f 298/330/298 686/336/686 683/368/683 108/367/108 +f 300/770/300 416/768/416 297/741/297 89/754/89 +f 301/781/301 428/806/428 302/800/302 105/780/105 +f 301/781/301 430/767/430 641/762/641 674/776/674 +f 303/787/303 416/768/416 300/770/300 106/786/106 +f 303/787/303 418/804/418 647/807/647 673/788/673 +f 305/133/305 467/71/467 306/72/306 107/131/107 +f 305/261/305 468/250/468 396/254/396 231/262/231 +f 306/72/306 783/78/783 782/132/782 107/131/107 +f 307/366/307 415/329/415 298/330/298 108/367/108 +f 308/408/308 685/401/685 682/431/682 137/434/137 +f 309/290/309 427/291/427 375/263/375 109/264/109 +f 310/295/310 462/297/462 372/327/372 144/324/144 +f 311/830/311 426/852/426 312/849/312 128/824/128 +f 311/830/311 428/806/428 642/809/642 672/835/672 +f 313/829/313 418/804/418 304/799/304 129/820/129 +f 313/829/313 420/850/420 646/858/646 671/831/671 +f 315/640/315 466/617/466 316/632/316 136/657/136 +f 315/334/315 467/296/467 395/293/395 229/328/229 +f 316/632/316 547/655/547 565/677/565 136/657/136 +f 317/439/317 417/409/417 308/408/308 137/434/137 +f 318/618/318 684/627/684 161/595/161 +f 319/351/319 425/354/425 373/323/373 143/319/143 +f 320/355/320 463/359/463 370/389/370 168/384/168 +f 321/879/321 424/909/424 322/883/322 152/865/152 +f 321/879/321 426/852/426 643/866/643 670/899/670 +f 323/876/323 420/850/420 314/848/314 153/861/153 +f 323/876/323 422/905/422 645/919/645 669/893/669 +f 325/587/325 465/559/465 326/581/326 160/609/160 +f 325/406/325 466/374/466 394/360/394 227/392/227 +f 326/581/326 548/604/548 563/624/563 160/609/160 +f 327/576/327 419/596/419 318/618/318 161/595/161 +f 328/579/328 549/605/549 560/584/560 185/563/185 +f 329/402/329 423/413/423 371/386/371 167/380/167 +f 330/407/330 464/418/464 368/443/368 192/422/192 +f 331/926/331 424/909/424 644/927/644 668/946/668 +f 331/926/331 441/941/441 332/911/332 176/903/176 +f 333/921/333 422/905/422 324/878/324 177/898/177 +f 333/921/333 446/936/446 633/956/633 667/943/667 +f 335/459/335 465/435/465 393/424/393 225/448/225 +f 335/539/335 471/526/471 336/548/336 184/562/184 +f 336/548/336 542/570/542 561/583/561 184/562/184 +f 337/540/337 421/558/421 328/579/328 185/563/185 +f 338/549/338 537/571/537 558/557/558 201/532/201 +f 339/440/339 435/452/435 369/433/369 191/419/191 +f 340/438/340 476/451/476 366/470/366 208/449/208 +f 342/952/342 441/941/441 638/958/638 666/974/666 +f 343/928/343 445/957/445 344/950/344 195/916/195 +f 344/950/344 445/957/445 634/987/634 665/971/665 +f 344/950/344 446/936/446 334/910/334 195/916/195 +f 346/968/346 442/959/442 637/989/637 664/997/664 +f 347/937/347 444/972/444 348/967/348 199/932/199 +f 348/967/348 444/972/444 635/1008/635 663/996/663 +f 348/967/348 445/957/445 343/928/343 199/932/199 +f 349/493/349 471/476/471 399/467/399 223/484/223 +f 349/520/349 472/516/472 350/525/350 200/531/200 +f 350/525/350 541/547/541 559/556/559 200/531/200 +f 351/521/351 440/527/440 338/549/338 201/532/201 +f 352/524/352 538/546/538 556/537/556 211/522/211 +f 353/977/353 443/973/443 636/1009/636 662/1010/662 +f 353/977/353 444/972/444 347/937/347 206/940/206 +f 354/466/354 436/481/436 367/471/367 207/453/207 +f 355/464/355 475/478/475 364/490/364 216/474/216 +f 356/519/356 540/530/540 557/538/557 210/523/210 +f 357/505/357 472/501/472 400/494/400 221/498/221 +f 358/518/358 438/511/438 359/513/359 211/522/211 +f 358/518/358 539/529/539 555/528/555 214/517/214 +f 359/513/359 439/515/439 352/524/352 211/522/211 +f 360/510/360 438/511/438 358/518/358 214/517/214 +f 361/483/361 473/495/473 365/489/365 215/473/215 +f 362/482/362 474/496/474 363/497/363 218/485/218 +f 363/497/363 474/496/474 402/503/402 219/504/219 +f 364/490/364 475/478/475 403/492/403 220/499/220 +f 365/489/365 473/495/473 401/502/401 221/498/221 +f 366/470/366 476/451/476 404/465/404 222/479/222 +f 367/471/367 436/481/436 400/494/400 223/484/223 +f 368/443/368 464/418/464 392/426/392 224/450/224 +f 369/433/369 435/452/435 399/467/399 225/448/225 +f 370/389/370 463/359/463 391/375/391 226/400/226 +f 371/386/371 423/413/423 393/424/393 227/392/227 +f 372/327/372 462/297/462 390/299/390 228/331/228 +f 373/323/373 425/354/425 394/360/394 229/328/229 +f 374/266/374 461/249/461 389/247/389 230/267/230 +f 375/263/375 427/291/427 395/293/395 231/262/231 +f 376/219/376 415/242/415 389/247/389 232/227/232 +f 377/224/377 469/187/469 397/194/397 233/229/233 +f 378/134/378 413/177/413 388/185/388 234/143/234 +f 379/141/379 470/90/470 398/101/398 235/152/235 +f 380/57/380 411/80/411 387/98/387 236/67/236 +f 381/55/381 477/36/477 405/50/405 237/69/237 +f 382/19/382 458/35/458 410/52/410 238/29/238 +f 383/17/383 478/9/478 406/16/406 239/24/239 +f 384/4/384 457/10/457 409/18/409 240/11/240 +f 385/5/385 479/3/479 407/8/407 241/12/241 +f 386/1/386 456/2/456 408/7/408 242/6/242 +f 387/98/387 459/113/459 273/82/273 236/67/236 +f 388/185/388 460/195/460 283/154/283 234/143/234 +f 389/247/389 461/249/461 293/230/293 232/227/232 +f 393/424/393 465/435/465 325/406/325 227/392/227 +f 394/360/394 466/374/466 315/334/315 229/328/229 +f 395/293/395 467/296/467 305/261/305 231/262/231 +f 399/467/399 471/476/471 335/459/335 225/448/225 +f 400/494/400 472/501/472 349/493/349 223/484/223 +f 408/7/408 480/14/480 243/13/243 242/6/242 +f 409/18/409 481/31/481 251/21/251 240/11/240 +f 410/52/410 482/63/482 261/47/261 238/29/238 +f 412/672/412 650/660/650 655/631/655 277/658/277 +f 414/722/414 649/716/649 653/684/653 287/702/287 +f 416/768/416 648/766/648 651/738/651 297/741/297 +f 432/720/432 640/709/640 652/733/652 295/739/295 +f 434/671/434 639/652/639 654/678/654 285/700/285 +f 447/633/447 632/611/632 656/628/656 275/653/275 +f 448/610/448 631/574/631 658/589/658 265/621/265 +f 449/593/449 630/551/630 660/561/660 253/600/253 +f 450/592/450 629/550/629 661/545/661 248/588/248 +f 451/615/451 628/575/628 659/560/659 255/601/255 +f 452/639/452 627/616/627 657/594/657 267/623/267 +f 506/704/506 62/713/62 519/687/519 46/692/46 +f 513/887/513 150/863/150 496/872/496 170/884/170 +f 516/906/516 347/937/347 199/932/199 183/900/183 +f 517/895/517 343/928/343 195/916/195 175/891/175 +f 518/885/518 334/910/334 177/898/177 171/882/171 +f 519/687/519 62/713/62 38/685/38 +f 520/680/520 54/707/54 30/675/30 +f 521/669/521 50/703/50 26/668/26 +f 528/91/528 21/155/21 13/153/13 5/88/5 +f 529/103/529 25/168/25 21/155/21 9/96/9 +f 531/990/531 574/1002/574 583/994/583 613/985/613 +f 532/1014/532 576/1022/576 581/1015/581 612/1007/612 +f 533/1029/533 578/1031/578 579/1026/579 611/1024/611 +f 534/1030/534 577/1023/577 580/1016/580 610/1025/610 +f 535/1013/535 575/1003/575 582/995/582 609/1006/609 +f 536/991/536 573/981/573 584/976/584 608/986/608 +f 537/571/537 560/584/560 619/591/619 607/578/607 +f 538/546/538 558/557/558 617/566/617 606/554/606 +f 539/529/539 556/537/556 615/543/615 605/535/605 +f 540/530/540 555/528/555 614/533/614 604/536/604 +f 541/547/541 557/538/557 616/544/616 603/555/603 +f 542/570/542 559/556/559 618/565/618 602/577/602 +f 543/965/543 571/951/571 586/945/586 601/961/601 +f 544/924/544 569/901/569 588/894/588 600/917/600 +f 545/173/545 567/128/567 626/126/626 599/174/599 +f 545/173/545 788/170/788 787/130/787 567/128/567 +f 546/74/546 565/39/565 624/38/624 598/73/598 +f 546/74/546 786/77/786 785/48/785 565/39/565 +f 547/655/547 563/624/563 622/629/622 597/661/597 +f 548/604/548 561/583/561 620/590/620 596/612/596 +f 549/605/549 562/625/562 621/630/621 595/613/595 +f 550/455/550 564/425/564 623/427/623 594/456/594 +f 551/393/551 566/363/566 625/362/625 593/395/593 +f 552/342/552 568/316/568 589/315/589 592/341/592 +f 552/342/552 679/337/679 681/313/681 568/316/568 +f 553/923/553 570/949/570 587/944/587 591/914/591 +f 553/923/553 680/939/680 570/949/570 +f 554/964/554 572/980/572 585/975/585 590/960/590 +f 562/625/562 677/637/677 550/656/550 +f 564/425/564 550/455/550 677/457/677 676/429/676 +f 565/39/565 785/48/785 784/44/784 136/33/136 +f 566/363/566 551/393/551 678/398/678 675/364/675 +f 567/128/567 787/130/787 786/77/786 546/74/546 +f 568/316/568 681/313/681 680/286/680 553/288/553 +f 569/901/569 544/924/544 286/942/286 80/922/80 +f 569/211/569 779/202/779 788/170/788 545/173/545 +f 570/949/570 680/939/680 687/947/687 57/970/57 +f 571/951/571 543/965/543 276/983/276 56/963/56 +f 572/980/572 554/964/554 278/984/278 33/998/33 +f 573/981/573 536/991/536 266/1012/266 32/999/32 +f 574/1002/574 531/990/531 268/1011/268 17/1027/17 +f 575/1003/575 535/1013/535 254/1033/254 16/1028/16 +f 576/1022/576 532/1014/532 256/1034/256 7/1036/7 +f 577/1023/577 534/1030/534 246/1041/246 6/1037/6 +f 579/534/579 610/542/610 630/551/630 661/545/661 +f 580/553/580 609/567/609 631/574/631 660/561/660 +f 581/552/581 611/541/611 629/550/629 659/560/659 +f 582/580/582 608/603/608 632/611/632 658/589/658 +f 583/585/583 612/568/612 628/575/628 657/594/657 +f 584/620/584 601/645/601 639/652/639 656/628/656 +f 585/626/585 613/606/613 627/616/627 655/631/655 +f 586/673/586 600/706/600 640/709/640 654/678/654 +f 587/682/587 590/654/590 650/660/650 653/684/653 +f 588/731/588 599/761/599 641/762/641 652/733/652 +f 589/736/589 591/712/591 649/716/649 651/738/651 +f 590/960/590 587/944/587 570/949/570 554/964/554 +f 591/287/591 589/315/589 568/316/568 553/288/553 +f 592/341/592 625/362/625 566/363/566 552/342/552 +f 593/395/593 623/427/623 564/425/564 551/393/551 +f 593/808/593 625/789/625 673/788/673 647/807/647 +f 594/664/594 621/630/621 562/625/562 550/656/550 +f 594/864/594 623/833/623 671/831/671 646/858/646 +f 595/613/595 619/591/619 560/584/560 549/605/549 +f 595/925/595 621/896/621 669/893/669 645/919/645 +f 596/931/596 620/953/620 668/946/668 644/927/644 +f 596/612/596 622/629/622 563/624/563 548/604/548 +f 597/870/597 622/904/622 670/899/670 643/866/643 +f 597/661/597 624/683/624 565/677/565 547/655/547 +f 598/810/598 624/847/624 672/835/672 642/809/642 +f 598/73/598 626/126/626 567/128/567 546/74/546 +f 599/174/599 588/212/588 569/211/569 545/173/545 +f 599/761/599 626/775/626 674/776/674 641/762/641 +f 600/917/600 586/945/586 571/951/571 544/924/544 +f 601/961/601 584/976/584 573/981/573 543/965/543 +f 602/966/602 618/982/618 666/974/666 638/958/638 +f 602/577/602 620/590/620 561/583/561 542/570/542 +f 603/993/603 616/1005/616 664/997/664 637/989/637 +f 603/555/603 618/565/618 559/556/559 541/547/541 +f 604/1018/604 614/1021/614 662/1010/662 636/1009/636 +f 604/536/604 616/544/616 557/538/557 540/530/540 +f 605/535/605 614/533/614 555/528/555 539/529/539 +f 605/1017/605 615/1004/615 663/996/663 635/1008/635 +f 606/554/606 615/543/615 556/537/556 538/546/538 +f 606/992/606 617/979/617 665/971/665 634/987/634 +f 607/578/607 617/566/617 558/557/558 537/571/537 +f 607/962/607 619/948/619 667/943/667 633/956/633 +f 608/986/608 582/995/582 575/1003/575 536/991/536 +f 609/1006/609 580/1016/580 577/1023/577 535/1013/535 +f 610/1025/610 579/1026/579 578/1031/578 534/1030/534 +f 611/1024/611 581/1015/581 576/1022/576 533/1029/533 +f 612/1007/612 583/994/583 574/1002/574 532/1014/532 +f 613/985/613 585/975/585 572/980/572 531/990/531 +f 633/956/633 665/971/665 617/979/617 607/962/607 +f 634/987/634 663/996/663 615/1004/615 606/992/606 +f 635/1008/635 662/1010/662 614/1021/614 605/1017/605 +f 636/1009/636 664/997/664 616/1005/616 604/1018/604 +f 637/989/637 666/974/666 618/982/618 603/993/603 +f 638/958/638 668/946/668 620/953/620 602/966/602 +f 642/809/642 674/776/674 626/775/626 598/810/598 +f 643/866/643 672/835/672 624/847/624 597/870/597 +f 644/927/644 670/899/670 622/904/622 596/931/596 +f 645/919/645 667/943/667 619/948/619 595/925/595 +f 646/858/646 669/893/669 621/896/621 594/864/594 +f 647/807/647 671/831/671 623/833/623 593/808/593 +f 648/766/648 673/788/673 625/789/625 592/764/592 +f 651/738/651 648/766/648 592/764/592 589/736/589 +f 652/733/652 640/709/640 600/706/600 588/731/588 +f 653/684/653 649/716/649 591/712/591 587/682/587 +f 654/678/654 639/652/639 601/645/601 586/673/586 +f 655/631/655 650/660/650 590/654/590 585/626/585 +f 656/628/656 632/611/632 608/603/608 584/620/584 +f 657/594/657 627/616/627 613/606/613 583/585/583 +f 658/589/658 631/574/631 609/567/609 582/580/582 +f 659/560/659 628/575/628 612/568/612 581/552/581 +f 660/561/660 630/551/630 610/542/610 580/553/580 +f 661/545/661 629/550/629 611/541/611 579/534/579 +f 662/1010/662 635/1008/635 444/972/444 353/977/353 +f 663/996/663 634/987/634 445/957/445 348/967/348 +f 664/997/664 636/1009/636 443/973/443 346/968/346 +f 665/971/665 633/956/633 446/936/446 344/950/344 +f 666/974/666 637/989/637 442/959/442 342/952/342 +f 667/943/667 645/919/645 422/905/422 333/921/333 +f 668/946/668 638/958/638 441/941/441 331/926/331 +f 669/893/669 646/858/646 420/850/420 323/876/323 +f 670/899/670 644/927/644 424/909/424 321/879/321 +f 671/831/671 647/807/647 418/804/418 313/829/313 +f 672/835/672 643/866/643 426/852/426 311/830/311 +f 673/788/673 648/766/648 416/768/416 303/787/303 +f 674/776/674 642/809/642 428/806/428 301/781/301 +f 675/364/675 679/337/679 552/342/552 566/363/566 +f 675/364/675 690/365/690 689/338/689 679/337/679 +f 676/429/676 677/457/677 684/461/684 682/430/682 +f 676/429/676 678/398/678 551/393/551 564/425/564 +f 676/429/676 692/414/692 691/397/691 678/398/678 +f 678/398/678 691/397/691 690/365/690 675/364/675 +f 679/337/679 689/338/689 698/321/698 681/313/681 +f 681/313/681 688/312/688 687/284/687 680/286/680 +f 681/313/681 698/321/698 697/320/697 688/312/688 +f 682/430/682 693/415/693 692/414/692 676/429/676 +f 683/368/683 695/370/695 694/396/694 685/401/685 +f 685/401/685 694/396/694 693/416/693 682/431/682 +f 686/336/686 696/343/696 695/370/695 683/368/683 +f 688/314/688 686/336/686 298/330/298 81/310/81 +f 688/314/688 697/322/697 696/343/696 686/336/686 +f 689/802/689 699/803/699 708/793/708 698/792/698 +f 690/846/690 700/845/700 699/803/699 689/802/689 +f 691/881/691 701/880/701 700/845/700 690/846/690 +f 692/913/692 702/912/702 701/880/701 691/881/691 +f 693/614/693 703/607/703 702/582/702 692/586/692 +f 694/651/694 704/650/704 703/607/703 693/614/693 +f 695/697/695 705/696/705 704/650/704 694/651/694 +f 696/723/696 706/724/706 705/696/705 695/697/695 +f 697/742/697 707/743/707 706/724/706 696/723/696 +f 698/757/698 708/758/708 707/743/707 697/742/697 +f 699/803/699 709/801/709 718/790/718 708/793/708 +f 700/845/700 710/844/710 709/801/709 699/803/699 +f 701/880/701 711/886/711 710/844/710 700/845/700 +f 702/912/702 712/920/712 711/886/711 701/880/701 +f 703/607/703 713/602/713 712/573/712 702/582/702 +f 704/650/704 714/646/714 713/602/713 703/607/703 +f 705/696/705 715/695/715 714/646/714 704/650/704 +f 706/724/706 716/726/716 715/695/715 705/696/705 +f 707/743/707 717/747/717 716/726/716 706/724/706 +f 708/758/708 718/760/718 717/747/717 707/743/707 +f 709/801/709 719/796/719 728/774/728 718/790/718 +f 710/844/710 720/842/720 719/796/719 709/801/709 +f 711/886/711 721/890/721 720/842/720 710/844/710 +f 712/920/712 722/929/722 721/890/721 711/886/711 +f 713/602/713 723/597/723 722/569/722 712/573/712 +f 714/646/714 724/643/724 723/597/723 713/602/713 +f 715/695/715 725/694/725 724/643/724 714/646/714 +f 716/726/716 726/727/726 725/694/725 715/695/715 +f 717/747/717 727/750/727 726/727/726 716/726/716 +f 718/760/718 728/763/728 727/750/727 717/747/717 +f 719/796/719 729/797/729 738/773/738 728/774/728 +f 720/842/720 730/843/730 729/797/729 719/796/719 +f 721/890/721 731/889/731 730/843/730 720/842/720 +f 722/929/722 732/933/732 731/889/731 721/890/721 +f 723/597/723 733/598/733 732/564/732 722/569/722 +f 724/643/724 734/644/734 733/598/733 723/597/723 +f 725/694/725 735/691/735 734/644/734 724/643/724 +f 726/727/726 736/725/736 735/691/735 725/694/725 +f 727/750/727 737/746/737 736/725/736 726/727/726 +f 728/763/728 738/765/738 737/746/737 727/750/727 +f 729/797/729 739/805/739 748/791/748 738/773/738 +f 730/843/730 740/836/740 739/805/739 729/797/729 +f 731/889/731 741/877/741 740/836/740 730/843/730 +f 732/933/732 742/915/742 741/877/741 731/889/731 +f 733/598/733 743/608/743 742/572/742 732/564/732 +f 734/644/734 744/648/744 743/608/743 733/598/733 +f 735/691/735 745/690/745 744/648/744 734/644/734 +f 736/725/736 746/721/746 745/690/745 735/691/735 +f 737/746/737 747/740/747 746/721/746 736/725/736 +f 738/765/738 748/759/748 747/740/747 737/746/737 +f 739/805/739 749/813/749 758/798/758 748/791/748 +f 740/836/740 750/837/750 749/813/749 739/805/739 +f 741/877/741 751/869/751 750/837/750 740/836/740 +f 742/915/742 752/888/752 751/869/751 741/877/741 +f 743/608/743 753/622/753 752/599/752 742/572/742 +f 744/648/744 754/663/754 753/622/753 743/608/743 +f 745/690/745 755/689/755 754/663/754 744/648/744 +f 746/721/746 756/717/756 755/689/755 745/690/745 +f 747/740/747 757/732/757 756/717/756 746/721/746 +f 748/759/748 758/744/758 757/732/757 747/740/747 +f 749/813/749 759/818/759 768/811/768 758/798/758 +f 750/837/750 760/838/760 759/818/759 749/813/749 +f 751/869/751 761/857/761 760/838/760 750/837/750 +f 752/888/752 762/874/762 761/857/761 751/869/751 +f 753/622/753 763/638/763 762/619/762 752/599/752 +f 754/663/754 764/665/764 763/638/763 753/622/753 +f 755/689/755 765/688/765 764/665/764 754/663/754 +f 756/717/756 766/710/766 765/688/765 755/689/755 +f 757/732/757 767/728/767 766/710/766 756/717/756 +f 758/744/758 768/734/768 767/728/767 757/732/757 +f 759/818/759 769/827/769 778/815/778 768/811/768 +f 760/838/760 770/839/770 769/827/769 759/818/759 +f 761/857/761 771/853/771 770/839/770 760/838/760 +f 762/874/762 772/860/772 771/853/771 761/857/761 +f 763/873/763 773/859/773 772/860/772 762/874/762 +f 764/856/764 774/851/774 773/859/773 763/873/763 +f 765/841/765 775/840/775 774/851/774 764/856/764 +f 766/819/766 776/828/776 775/840/775 765/841/765 +f 767/812/767 777/817/777 776/828/776 766/819/766 +f 768/811/768 778/815/778 777/817/777 767/812/767 +f 770/839/770 771/853/771 772/860/772 773/859/773 774/851/774 775/840/775 776/828/776 777/817/777 778/815/778 769/827/769 +f 779/202/779 789/188/789 798/165/798 788/170/788 +f 780/205/780 790/191/790 789/188/789 779/202/779 +f 781/76/781 791/79/791 790/56/790 780/43/780 +f 782/119/782 792/117/792 791/79/791 781/76/781 +f 783/171/783 793/166/793 792/117/792 782/119/782 +f 784/204/784 794/189/794 793/166/793 783/171/783 +f 785/48/785 795/59/795 794/58/794 784/44/784 +f 786/77/786 796/81/796 795/59/795 785/48/785 +f 787/130/787 797/129/797 796/81/796 786/77/786 +f 788/170/788 798/165/798 797/129/797 787/130/787 +f 789/188/789 799/180/799 808/157/808 798/165/798 +f 790/191/790 800/183/800 799/180/799 789/188/789 +f 791/79/791 801/89/801 800/65/800 790/56/790 +f 792/117/792 802/118/802 801/89/801 791/79/791 +f 793/166/793 803/156/803 802/118/802 792/117/792 +f 794/189/794 804/181/804 803/156/803 793/166/793 +f 795/59/795 805/68/805 804/66/804 794/58/794 +f 796/81/796 806/93/806 805/68/805 795/59/795 +f 797/129/797 807/127/807 806/93/806 796/81/796 +f 798/165/798 808/157/808 807/127/807 797/129/797 +f 799/180/799 809/162/809 818/150/818 808/157/808 +f 800/183/800 810/163/810 809/162/809 799/180/799 +f 801/89/801 811/99/811 810/84/810 800/65/800 +f 802/118/802 812/120/812 811/99/811 801/89/801 +f 803/156/803 813/148/813 812/120/812 802/118/802 +f 804/181/804 814/161/814 813/148/813 803/156/803 +f 805/68/805 815/87/815 814/86/814 804/66/804 +f 806/93/806 816/102/816 815/87/815 805/68/805 +f 807/127/807 817/125/817 816/102/816 806/93/806 +f 808/157/808 818/150/818 817/125/817 807/127/807 +f 809/162/809 819/145/819 828/139/828 818/150/818 +f 810/163/810 820/146/820 819/145/819 809/162/809 +f 811/99/811 821/109/821 820/104/820 810/84/810 +f 812/120/812 822/121/822 821/109/821 811/99/811 +f 813/148/813 823/137/823 822/121/822 812/120/812 +f 814/161/814 824/144/824 823/137/823 813/148/813 +f 815/87/815 825/106/825 824/105/824 814/86/814 +f 816/102/816 826/112/826 825/106/825 815/87/815 +f 817/125/817 827/123/827 826/112/826 816/102/816 +f 818/150/818 828/139/828 827/123/827 817/125/817 +f 820/146/820 821/140/821 822/124/822 823/111/823 824/105/824 825/106/825 826/112/826 827/123/827 828/139/828 819/145/819 diff --git a/res/models/turtle.png b/res/models/turtle.png new file mode 100644 index 0000000..f3f767b Binary files /dev/null and b/res/models/turtle.png differ diff --git a/res/models/turtle.wings b/res/models/turtle.wings new file mode 100644 index 0000000..18bd0f9 Binary files /dev/null and b/res/models/turtle.wings differ diff --git a/res/models/turtle.xcf b/res/models/turtle.xcf new file mode 100644 index 0000000..66e1a2a Binary files /dev/null and b/res/models/turtle.xcf differ diff --git a/res/models/turtle2.mtl b/res/models/turtle2.mtl new file mode 100644 index 0000000..7c02a3b --- /dev/null +++ b/res/models/turtle2.mtl @@ -0,0 +1,11 @@ +# Exported from Wings 3D 1.4.1 +newmtl turtle_auv +Ns 100.0 +d 1.0 +illum 2 +Kd 1.0 1.0 1.0 +Ka 1.0 1.0 1.0 +Ks 1.0 1.0 1.0 +Ke 0.0 0.0 0.0 +map_Kd turtle.png + diff --git a/res/models/turtle2.obj b/res/models/turtle2.obj new file mode 100644 index 0000000..850efba --- /dev/null +++ b/res/models/turtle2.obj @@ -0,0 +1,3558 @@ +# Exported from Wings 3D 1.4.1 +mtllib turtle2.mtl +o Turtle +#828 vertices, 846 faces +v -0.63892347 1.0361964e-2 -6.7720502e-2 +v -0.71141091 -0.14517023 -6.7720502e-2 +v -0.60872850 1.0361964e-2 -0.25900121 +v -0.60872850 1.0361964e-2 0.12356021 +v -0.61401292 0.22818987 -6.7720502e-2 +v -0.68113604 -0.14438060 -0.28221772 +v -0.68113604 -0.14438060 0.14677671 +v -0.58543788 0.21805274 -0.25588272 +v -0.58543788 0.21805274 0.12044172 +v -0.52203990 -0.35875201 -6.7866664e-2 +v -0.54917675 1.0361964e-2 -0.40717517 +v -0.54911785 1.0361964e-2 0.27173416 +v -0.53852346 0.39245786 -6.7720502e-2 +v -0.50535567 -0.35703996 -0.22957335 +v -0.50530340 -0.35728753 9.3782954e-2 +v -0.62441251 -0.14240805 -0.45236962 +v -0.62434257 -0.14240805 0.31692862 +v -0.52989716 0.19446011 -0.40129688 +v -0.52984140 0.19446011 0.26585588 +v -0.51893383 0.37855881 -0.23450844 +v -0.51893383 0.37855881 9.9067439e-2 +v -0.47011299 -0.35079182 -0.37224349 +v -0.46995675 -0.35110463 0.23626750 +v -0.47516854 0.34449510 -0.37043609 +v -0.47516982 0.34449510 0.23499508 +v -0.44004381 -0.39519050 -6.7993201e-2 +v -0.46569191 1.0361964e-2 -0.50685805 +v -0.46562882 1.0361964e-2 0.37141705 +v -0.45765534 0.49744040 -6.7720502e-2 +v -0.42469567 -0.39261424 -0.21656538 +v -0.42463094 -0.39288758 8.0493666e-2 +v -0.54430270 -0.14060754 -0.56922181 +v -0.54426798 -0.14060754 0.43378081 +v -0.45548415 0.16839093 -0.49723083 +v -0.45542382 0.16839093 0.36178982 +v -0.44544873 0.48444932 -0.21089047 +v -0.44544873 0.48444932 7.5449463e-2 +v -0.40059249 -0.38361143 -0.35511597 +v -0.40042130 -0.38385027 0.21883943 +v -0.42243700 -0.34535430 -0.46684081 +v -0.42205956 -0.34500124 0.33058042 +v -0.42283986 0.30408143 -0.46687314 +v -0.42278691 0.30408143 0.33143214 +v -0.41742182 0.45094094 -0.33382239 +v -0.41742282 0.45094094 0.19838139 +v -0.38708073 -0.37264289 -0.43430582 +v -0.38675152 -0.37247645 0.29789310 +v -0.38114705 0.40805984 -0.42802402 +v -0.38110298 0.40805984 0.29258302 +v -0.36154674 -0.41200556 -6.8120264e-2 +v -0.36666463 1.0361964e-2 -0.58632480 +v -0.36668856 5.1758591e-2 0.45088379 +v -0.35901213 0.58350552 -6.7720502e-2 +v -0.33939928 -0.40924707 -0.23521779 +v -0.33931318 -0.40940612 9.8811107e-2 +v -0.41787410 -0.14240805 -0.65448568 +v -0.41741189 -0.10728267 0.51907207 +v -0.35412834 0.19446011 -0.56808483 +v -0.36031953 0.22242044 0.43264382 +v -0.34595237 0.56265696 -0.23450844 +v -0.34595237 0.56265696 9.9067439e-2 +v -0.32435900 -0.39584073 -0.37854423 +v -0.32413998 -0.39542025 0.24180760 +v -0.32224976 -0.35099829 -0.51728704 +v -0.32152802 -0.34749622 0.37989940 +v -0.32085386 0.34449510 -0.52179365 +v -0.32084441 0.35218426 0.38635265 +v -0.31652027 0.51156142 -0.37043609 +v -0.31652114 0.51156142 0.23499508 +v -0.30301304 -0.38368417 -0.45132429 +v -0.30256462 -0.38113157 0.31412340 +v -0.28151937 0.45094094 -0.46687314 +v -0.28148327 0.45094094 0.33143214 +v -0.17876963 -0.43384145 -6.8366096e-2 +v -0.20683061 3.7295770e-2 -0.65466444 +v -0.20714384 0.16997126 0.51925431 +v -0.20466338 0.66384632 -6.7720502e-2 +v -0.17404109 -0.42786489 -0.23590162 +v -0.17396930 -0.42792313 9.8939905e-2 +v -0.23318122 -0.11163005 -0.72447946 +v -0.23318914 7.1406158e-4 0.58698613 +v -0.20340247 0.22982247 -0.63220773 +v -0.19654531 0.30449387 0.48628775 +v -0.19513838 0.63343490 -0.25588272 +v -0.19513838 0.63343490 0.12044172 +v -0.17535623 -0.40212485 -0.39383156 +v -0.17423453 -0.40825033 0.25743979 +v -0.17282906 -0.36821449 -0.55301995 +v -0.17312518 -0.36059141 0.41536851 +v -0.17688086 0.37855881 -0.56808483 +v -0.17999204 0.42115161 0.43264382 +v -0.17436275 0.56265696 -0.40129688 +v -0.17436328 0.56265696 0.26585588 +v -0.15748191 -0.38869536 -0.47432182 +v -0.15622901 -0.39144796 0.33828098 +v -0.15148499 0.48444932 -0.49723083 +v -0.15148853 0.49247653 0.36178982 +v 1.8786653e-5 -0.44092184 -6.8450573e-2 +v 1.5574414e-5 -0.43381224 -0.24052457 +v 2.2921355e-5 -0.43417266 0.10336176 +v 9.1293204e-6 -0.40968347 -0.41505517 +v 2.8475625e-5 -0.41254758 0.27845387 +v 8.5954064e-6 -0.40980183 -0.48758387 +v 3.7333543e-8 -0.39947022 0.35236179 +v 1.0026215e-5 -0.37997780 -0.57279038 +v 5.0636754e-5 -0.37523011 0.42990180 +v 4.2821259e-6 -2.1358227e-2 -0.75367035 +v 4.8831978e-6 0.14432352 0.61459842 +v 1.4006481e-5 8.7469345e-2 -0.68377829 +v 1.1140975e-5 0.30123700 0.54696273 +v 1.4606087e-5 0.26260200 -0.65975966 +v 1.4794054e-5 0.36034475 0.50652926 +v 1.9580378e-5 0.39245786 -0.58697306 +v 1.9571389e-5 0.44841869 0.44385937 +v -3.3985064e-5 0.49744040 -0.50900039 +v -3.4213935e-5 0.51512224 0.37355938 +v 1.1062942e-5 0.58350552 -0.41388905 +v 1.1062936e-5 0.58350552 0.27844804 +v 1.1077009e-5 0.66384632 -0.26506669 +v 1.1077009e-5 0.66384632 0.12962568 +v 1.1077009e-5 0.69919489 -6.7720502e-2 +v 0.15748397 -0.38839206 -0.47432048 +v 0.15622485 -0.39142734 0.33845248 +v 0.15140921 0.48444932 -0.49723083 +v 0.15141319 0.49247653 0.36178982 +v 0.17536905 -0.40200628 -0.39382904 +v 0.17428957 -0.40841640 0.25755546 +v 0.17283113 -0.36792546 -0.55301922 +v 0.17320680 -0.36047605 0.41545160 +v 0.17990294 0.37855881 -0.56808483 +v 0.18002172 0.42115161 0.43264382 +v 0.17438487 0.56265696 -0.40129688 +v 0.17438540 0.56265696 0.26585588 +v 0.17407200 -0.42786912 -0.23589528 +v 0.17401550 -0.42797180 9.8981887e-2 +v 0.23317738 -0.11162354 -0.72447946 +v 0.23318809 7.1406158e-4 0.58698613 +v 0.20342201 0.22982070 -0.63220773 +v 0.19656680 0.30449387 0.48628775 +v 0.19516054 0.63343490 -0.25588272 +v 0.19516054 0.63343490 0.12044172 +v 0.17880715 -0.43385540 -6.8349989e-2 +v 0.20684872 3.7293881e-2 -0.65466444 +v 0.20716089 0.16997126 0.51925431 +v 0.20468554 0.66384632 -6.7720502e-2 +v 0.30292845 -0.38368473 -0.45132232 +v 0.30253717 -0.38110728 0.31428507 +v 0.28142438 0.45094094 -0.46687314 +v 0.28138929 0.45094094 0.33143214 +v 0.32438436 -0.39584180 -0.37854092 +v 0.32420868 -0.39545000 0.24190522 +v 0.32214551 -0.35099857 -0.51728588 +v 0.32147569 -0.34746303 0.38001743 +v 0.32074317 0.34449510 -0.52179365 +v 0.32073435 0.35218426 0.38635265 +v 0.31654238 0.51156142 -0.37043609 +v 0.31654325 0.51156142 0.23499508 +v 0.33942887 -0.40925023 -0.23520957 +v 0.33936428 -0.40942571 9.8859945e-2 +v 0.41784215 -0.14240805 -0.65448568 +v 0.41738187 -0.10728267 0.51907207 +v 0.36024328 0.19446011 -0.56808483 +v 0.36031845 0.22242044 0.43264382 +v 0.34597452 0.56265696 -0.23450844 +v 0.34597452 0.56265696 9.9067439e-2 +v 0.36158372 -0.41201346 -6.8100300e-2 +v 0.36666088 1.0361964e-2 -0.58632480 +v 0.36668600 5.1758591e-2 0.45088379 +v 0.35903428 0.58350552 -6.7720502e-2 +v 0.38696950 -0.37264333 -0.43430387 +v 0.38670861 -0.37247813 0.29799583 +v 0.38102943 0.40805984 -0.42802402 +v 0.38098621 0.40805984 0.29258302 +v 0.40061737 -0.38361232 -0.35511261 +v 0.40049676 -0.38386266 0.21892697 +v 0.42230630 -0.34535457 -0.46683940 +v 0.42202212 -0.34499839 0.33069914 +v 0.42270554 0.30408143 -0.46687314 +v 0.42265346 0.30408143 0.33143214 +v 0.41744392 0.45094094 -0.33382239 +v 0.41744492 0.45094094 0.19838139 +v 0.42472414 -0.39261653 -0.21655771 +v 0.42468000 -0.39289701 8.0533724e-2 +v 0.54424188 -0.14060754 -0.56922181 +v 0.54420828 -0.14060754 0.43378081 +v 0.45533646 0.16839093 -0.49723083 +v 0.45527701 0.16839093 0.36178982 +v 0.44547088 0.48444932 -0.21089047 +v 0.44547088 0.48444932 7.5449463e-2 +v 0.44007841 -0.39519511 -6.7976735e-2 +v 0.46554111 1.0361964e-2 -0.50685805 +v 0.46547892 1.0361964e-2 0.37141705 +v 0.45767750 0.49744040 -6.7720502e-2 +v 0.47013630 -0.35079237 -0.37224100 +v 0.47005267 -0.35110915 0.23638229 +v 0.47519064 0.34449510 -0.37043609 +v 0.47519191 0.34449510 0.23499508 +v 0.50538160 -0.35704126 -0.22956781 +v 0.50535278 -0.35729212 9.3821238e-2 +v 0.62419533 -0.14240805 -0.45236962 +v 0.62412594 -0.14240805 0.31692862 +v 0.52972892 0.19446011 -0.40129688 +v 0.52392283 0.19446011 0.26585588 +v 0.51895598 0.37855881 -0.23450844 +v 0.51895598 0.37855881 9.9067439e-2 +v 0.52207136 -0.35875452 -6.7853727e-2 +v 0.54900157 1.0361964e-2 -0.40717517 +v 0.54300270 1.0361964e-2 0.27173416 +v 0.53854561 0.39245786 -6.7720502e-2 +v 0.68115820 -0.14438060 -0.28221772 +v 0.68115820 -0.14438060 0.14677671 +v 0.58546004 0.21805274 -0.25588272 +v 0.58546004 0.21805274 0.12044172 +v 0.71143306 -0.14517023 -6.7720502e-2 +v 0.60875065 1.0361964e-2 -0.25900121 +v 0.60875065 1.0361964e-2 0.12356021 +v 0.61403508 0.22818987 -6.7720502e-2 +v 0.63894562 1.0361964e-2 -6.7720502e-2 +v 0.72433704 -3.4392527e-2 -6.7720502e-2 +v 0.69162907 -3.4392527e-2 0.14981282 +v 0.69162907 -3.4392527e-2 -0.28525383 +v 0.62999281 -3.4392527e-2 0.32011635 +v 0.63006311 -3.4392527e-2 -0.45555735 +v 0.54637325 -3.4392527e-2 0.43573328 +v 0.54640710 -3.4392527e-2 -0.57117429 +v 0.42131059 1.6959282e-3 0.52431686 +v 0.42144535 -3.4392527e-2 -0.65984547 +v 0.23661898 0.12048094 0.59815518 +v 0.23663137 -7.2554764e-3 -0.73457543 +v 1.5349495e-6 0.25431627 0.62911276 +v 2.7645921e-6 5.7083768e-2 -0.76611231 +v -0.23662503 0.12048094 0.59815518 +v -0.23663792 -7.2584233e-3 -0.73457543 +v -0.42134282 1.6959282e-3 0.52431686 +v -0.42147905 -3.4392527e-2 -0.65984547 +v -0.54643377 -3.4392527e-2 0.43573328 +v -0.54646873 -3.4392527e-2 -0.57117429 +v -0.63021242 -3.4392527e-2 0.32011635 +v -0.63028326 -3.4392527e-2 -0.45555735 +v -0.69160691 -3.4392527e-2 0.14981282 +v -0.69160691 -3.4392527e-2 -0.28525383 +v -0.72431488 -3.4392527e-2 -6.7720502e-2 +v -0.68768905 -6.5726513e-3 -6.7720502e-2 +v -0.63061995 1.0361964e-2 -0.16639360 +v -0.63061995 1.0361964e-2 3.0952591e-2 +v -0.70315325 -0.14495827 -0.17806437 +v -0.70315325 -0.14495827 4.2623362e-2 +v -0.61065131 -0.30435074 -6.7729640e-2 +v -0.65595073 -6.5726513e-3 -0.27394469 +v -0.58153174 1.0361964e-2 -0.33947787 +v -0.65595073 -6.5726513e-3 0.13850368 +v -0.58153314 1.0361964e-2 0.20403686 +v -0.58934405 -0.30364241 -0.25193843 +v -0.65538942 -0.14349541 -0.37399005 +v -0.58930635 -0.30378413 0.11644172 +v -0.65539107 -0.14349541 0.23854904 +v -0.51774812 -0.35858416 -0.14629331 +v -0.51772703 -0.35870545 1.0546608e-2 +v -0.59504862 -6.5726513e-3 -0.43459108 +v -0.50896950 1.0361964e-2 -0.46144472 +v -0.59498283 -6.5726513e-3 0.29915008 +v -0.50890699 1.0361964e-2 0.32600371 +v -0.49164902 -0.35444211 -0.30328381 +v -0.49155226 -0.35476672 0.16742250 +v -0.54182430 -0.30047046 -0.40679800 +v -0.58232769 -0.14122385 -0.51634472 +v -0.54157705 -0.30064883 0.27104051 +v -0.58225326 -0.14122385 0.38090371 +v -0.45096543 -0.34755573 -0.42535376 +v -0.45067551 -0.34772580 0.28926380 +v -0.50580731 -6.5726513e-3 -0.54318798 +v -0.42504741 1.0361964e-2 -0.54798672 +v -0.51468789 -6.5726513e-3 0.40774697 +v -0.42503632 2.4870463e-2 0.41254572 +v -0.47495020 -0.29812005 -0.51480056 +v -0.48719832 -0.14122385 -0.61430741 +v -0.47444547 -0.29772465 0.37875619 +v -0.48715680 -0.13519250 0.47886640 +v -0.37854949 -0.34769525 -0.49419722 +v -0.37802868 -0.34589482 0.35753067 +v -0.39763947 -6.5726513e-3 -0.62801187 +v -0.29370691 1.5752426e-2 -0.62336636 +v -0.39761820 3.2964579e-2 0.49255513 +v -0.29375608 8.5919166e-2 0.48803094 +v -0.36666626 -0.30092946 -0.58495675 +v -0.33284436 -0.14251083 -0.69264080 +v -0.36548980 -0.29856331 0.44732769 +v -0.33260593 -7.6096228e-2 0.55719279 +v -0.25123961 -0.35478105 -0.53693842 +v -0.24831352 -0.35243454 0.39983047 +v -0.22375290 2.1834912e-2 -0.70019590 +v -0.10672242 8.0060062e-2 -0.67577208 +v -0.22390146 0.15425840 0.56425514 +v -0.12445609 0.27438933 0.54042012 +v -0.19916445 -0.31853844 -0.63595634 +v -0.11997580 -3.0429430e-2 -0.74570835 +v -0.19725301 -0.32085857 0.49368363 +v -0.13851430 0.11658565 0.60719049 +v -8.3489853e-2 -0.37841693 -0.56918244 +v -8.3524558e-2 -0.37083351 0.42622057 +v 1.4986576e-5 -0.35679907 -0.65518518 +v 8.3505922e-2 -0.37831841 -0.56473465 +v 2.7945526e-5 -0.34695544 0.51059931 +v 8.3628318e-2 -0.37089319 0.42623458 +v 1.3418484e-6 2.1552468e-2 -0.77801657 +v 0.11998120 -3.0428003e-2 -0.74570835 +v 1.5349495e-6 0.20469396 0.64020031 +v 0.13851955 0.11658565 0.60719049 +v 0.10674792 8.0058228e-2 -0.67577208 +v 0.12447511 0.27438933 0.54042012 +v 0.19918327 -0.31854348 -0.63595603 +v 0.25120986 -0.35440201 -0.53693742 +v 0.19729559 -0.32082601 0.49372036 +v 0.24827807 -0.35234112 0.40000538 +v 0.24124702 -5.6276139e-2 -0.74665109 +v 0.33282745 -0.14250554 -0.69264080 +v 0.24102089 6.4459456e-2 0.60971314 +v 0.33259127 -7.6096228e-2 0.55719279 +v 0.29371477 1.5752552e-2 -0.62336636 +v 0.29376476 8.5919166e-2 0.48803094 +v 0.36665810 -0.30092957 -0.58495621 +v 0.37843069 -0.34769552 -0.49419594 +v 0.36552204 -0.29854708 0.44739267 +v 0.37797769 -0.34588540 0.35763437 +v 0.43065050 -8.3982926e-2 -0.67197210 +v 0.48715131 -0.14122385 -0.61430741 +v 0.43041322 -4.9891076e-2 0.53636684 +v 0.48711118 -0.13519250 0.47886640 +v 0.42503227 1.0361964e-2 -0.54798672 +v 0.42502248 2.4870463e-2 0.41254572 +v 0.47478968 -0.29812018 -0.51479983 +v 0.45082964 -0.34755610 -0.42535196 +v 0.47451904 -0.29773213 0.37898853 +v 0.45063854 -0.34772092 0.28939685 +v 0.55927828 -8.3982926e-2 -0.58247337 +v 0.58212362 -0.14122385 -0.51634472 +v 0.55924356 -8.3982926e-2 0.44703237 +v 0.58204986 -0.14122385 0.38090371 +v 0.50880660 1.0361964e-2 -0.46144472 +v 0.50874485 1.0361964e-2 0.32600371 +v 0.49167346 -0.35444300 -0.30328005 +v 0.54184540 -0.30047071 -0.40679669 +v 0.49162320 -0.35477194 0.16749101 +v 0.54179799 -0.30065343 0.27126756 +v 0.51777634 -0.35858610 -0.14628472 +v 0.58936663 -0.30364299 -0.25193550 +v 0.51776448 -0.35870876 1.0567837e-2 +v 0.58935123 -0.30378616 0.11647265 +v 0.64353706 -8.3982926e-2 -0.46362435 +v 0.65541149 -0.14349541 -0.37399005 +v 0.64346489 -8.3982926e-2 0.32818334 +v 0.65541313 -0.14349541 0.23854904 +v 0.61067758 -0.30435184 -6.7721999e-2 +v 0.58155382 1.0361964e-2 -0.33947787 +v 0.58155522 1.0361964e-2 0.20403686 +v 0.70317540 -0.14495827 -0.17806437 +v 0.70415315 -8.3982926e-2 -0.28929431 +v 0.70317540 -0.14495827 4.2623362e-2 +v 0.70415315 -8.3982926e-2 0.15385330 +v 0.73668336 -8.3982926e-2 -6.7720502e-2 +v 0.63064211 1.0361964e-2 -0.16639360 +v 0.63064211 1.0361964e-2 3.0952591e-2 +v 0.68771121 -6.5726513e-3 -6.7720502e-2 +v 0.65597288 -6.5726513e-3 0.13850368 +v 0.65597288 -6.5726513e-3 -0.27394469 +v 0.59478267 -6.5726513e-3 0.29915008 +v 0.59484788 -6.5726513e-3 -0.43459108 +v 0.51464288 -6.5726513e-3 0.40774697 +v 0.50563361 -6.5726513e-3 -0.54318798 +v 0.39759875 3.2964579e-2 0.49255513 +v 0.39761871 -6.5726513e-3 -0.62801187 +v 0.22390514 0.15425840 0.56425514 +v 0.22375698 2.1835635e-2 -0.70019590 +v 5.2572289e-6 0.28311275 0.59447807 +v 7.6126672e-6 7.9513238e-2 -0.73079785 +v -0.24103145 6.4459456e-2 0.60971314 +v -0.24125737 -5.6285614e-2 -0.74665109 +v -0.43045020 -4.9891076e-2 0.53636684 +v -0.43068916 -8.3982926e-2 -0.67197210 +v -0.55931030 -8.3982926e-2 0.44703237 +v -0.55934611 -8.3982926e-2 -0.58247337 +v -0.64369188 -8.3982926e-2 0.32818334 +v -0.64376457 -8.3982926e-2 -0.46362435 +v -0.70413099 -8.3982926e-2 0.15385330 +v -0.70413099 -8.3982926e-2 -0.28929431 +v -0.73666120 -8.3982926e-2 -6.7720502e-2 +v -0.48976787 -2.7425993e-2 0.48205309 +v -0.33635312 3.3630832e-2 0.56453951 +v -0.14133034 0.22657215 0.62073249 +v 0.14133341 0.22657215 0.62073249 +v 0.33633552 3.3630832e-2 0.56453951 +v 0.48972108 -2.7425993e-2 0.48205309 +v 0.48975047 -3.4392527e-2 -0.61749410 +v 0.33677167 -3.1487848e-2 -0.70045306 +v 0.12195761 4.2666183e-2 -0.75747113 +v -0.12195515 4.2665103e-2 -0.75747113 +v -0.33679088 -3.1496217e-2 -0.70045306 +v -0.48979857 -3.4392527e-2 -0.61749410 +v 0.58559737 -3.4392527e-2 -0.51866139 +v 0.66371781 -3.4392527e-2 -0.37746415 +v 0.71537498 -3.4392527e-2 -0.17979843 +v 0.71537498 -3.4392527e-2 4.4357430e-2 +v 0.66371949 -3.4392527e-2 0.24202315 +v 0.58552298 -3.4392527e-2 0.38322038 +v -0.58580309 -3.4392527e-2 -0.51866139 +v -0.66369575 -3.4392527e-2 -0.37746415 +v -0.71535282 -3.4392527e-2 -0.17979843 +v -0.71535282 -3.4392527e-2 4.4357430e-2 +v -0.66369742 -3.4392527e-2 0.24202315 +v -0.58572802 -3.4392527e-2 0.38322038 +v -0.50106333 -7.9391290e-2 0.49399413 +v -0.43060506 -0.29751298 0.41639590 +v -0.34310805 -1.7551728e-2 0.57644085 +v -0.28656277 -0.30648977 0.47370790 +v -0.14354156 0.17672983 0.63199675 +v -9.9609700e-2 -0.33951186 0.50623007 +v 0.14354463 0.17672983 0.63199675 +v 9.9663398e-2 -0.33952337 0.50624127 +v 0.34308660 -1.7551728e-2 0.57644085 +v 0.28659827 -0.30645677 0.47377218 +v 0.50101090 -7.9391290e-2 0.49399413 +v 0.43066637 -0.29750894 0.41649079 +v 0.46151840 -6.5726513e-3 -0.58730294 +v 0.43124867 -0.29922608 -0.55287700 +v 0.31810367 -1.2812752e-3 -0.66718834 +v 0.28821676 -0.32103650 -0.61317691 +v 0.11539409 6.7759399e-2 -0.72239809 +v 0.10096425 -0.34108570 -0.65111487 +v -0.11538170 6.7759732e-2 -0.72239809 +v -0.10093709 -0.34113248 -0.65575238 +v -0.31811120 -1.2850942e-3 -0.66718834 +v -0.28821029 -0.32103565 -0.61317734 +v -0.46155225 -6.5726513e-3 -0.58730294 +v -0.42389003 -0.29922596 -0.55287762 +v 0.55212835 -6.5726513e-3 -0.49379343 +v 0.62820942 -6.5726513e-3 -0.36105270 +v 0.72778644 -8.3982926e-2 -0.18181388 +v 0.72778644 -8.3982926e-2 4.6372877e-2 +v 0.67671622 -8.3982926e-2 0.24810781 +v 0.59881813 -8.3982926e-2 0.39312682 +v 0.51474101 -0.29887449 -0.46655518 +v 0.57103034 -0.30224953 -0.33427105 +v 0.60508073 -0.30443051 -0.16109277 +v 0.60507404 -0.30450338 2.5644136e-2 +v 0.57100384 -0.30243878 0.19878419 +v 0.51458409 -0.29893282 0.33094465 +v -0.51491148 -0.29887432 -0.46655612 +v -0.57100868 -0.30224913 -0.33427299 +v -0.60505683 -0.30442969 -0.16109739 +v -0.60504256 -0.30450191 2.5629852e-2 +v -0.57091781 -0.30243602 0.19870654 +v -0.51450119 -0.29893017 0.33068226 +v -0.55231554 -6.5726513e-3 -0.49379343 +v -0.62818735 -6.5726513e-3 -0.36105270 +v -0.67897738 -6.5726513e-3 -0.17403341 +v -0.72776428 -8.3982926e-2 4.6372877e-2 +v -0.67669416 -8.3982926e-2 0.24810781 +v -0.60981462 -8.3982926e-2 0.39312682 +v -0.46153110 4.6586746e-3 0.45186193 +v -0.31789641 6.5958498e-2 0.53153218 +v -0.13419106 0.25555356 0.58627572 +v 0.13419809 0.25555356 0.58627572 +v 0.31789009 6.5958498e-2 0.53153218 +v 0.46149858 4.6586746e-3 0.45186193 +v 0.50104602 -8.3982926e-2 -0.62943514 +v 0.34371878 -8.2715175e-2 -0.71260324 +v 0.12425911 3.9646463e-4 -0.76943820 +v -0.12425943 3.9214495e-4 -0.76943820 +v -0.34374231 -8.2724825e-2 -0.71260324 +v -0.50109977 -8.3982926e-2 -0.62943514 +v 0.59889454 -8.3982926e-2 -0.52856782 +v 0.67671450 -8.3982926e-2 -0.38354882 +v 0.67899954 -6.5726513e-3 -0.17403341 +v 0.67899954 -6.5726513e-3 3.8592405e-2 +v 0.62821098 -6.5726513e-3 0.22561170 +v 0.55205929 -6.5726513e-3 0.35835243 +v -0.59910755 -8.3982926e-2 -0.52856782 +v -0.67669244 -8.3982926e-2 -0.38354882 +v -0.72776428 -8.3982926e-2 -0.18181388 +v -0.67897738 -6.5726513e-3 3.8592405e-2 +v -0.62818891 -6.5726513e-3 0.22561170 +v -0.55224577 -6.5726513e-3 0.35835243 +v -0.41176398 0.18724561 0.39721682 +v -0.34740386 -0.37840272 0.30324901 +v -0.28192533 0.26088342 0.46470527 +v -0.22015203 -0.38672823 0.32808444 +v -0.10900565 0.33690732 0.51403329 +v -5.9695247e-2 -0.39717565 0.34940795 +v 0.10902978 0.33690732 0.51403329 +v 5.9697101e-2 -0.39720399 0.34945188 +v 0.28193683 0.26088342 0.46470527 +v 0.22016926 -0.38663273 0.32844302 +v 0.41175421 0.18724561 0.39721682 +v 0.34736372 -0.37840220 0.30335836 +v 0.41175825 0.18142552 -0.53265783 +v 0.34768225 -0.37938252 -0.43996258 +v 0.28179220 0.20625642 -0.60014628 +v 0.22169915 -0.38189039 -0.46417751 +v 0.10170452 0.25121116 -0.64598369 +v 6.0240277e-2 -0.40469936 -0.49113734 +v -0.10167581 0.25121308 -0.64598369 +v -6.0226246e-2 -0.40478091 -0.49447871 +v -0.28178048 0.20625642 -0.60014628 +v -0.22172328 -0.38229433 -0.46417921 +v -0.40476606 0.18142552 -0.53265783 +v -0.34777977 -0.37938198 -0.43996465 +v 0.49246817 0.18142552 -0.44926386 +v 0.55720006 0.20625642 -0.32858980 +v 0.59974756 0.22312130 -0.16180161 +v 0.59974756 0.22312130 2.6360609e-2 +v 0.55720134 0.20625642 0.19314880 +v 0.49241013 0.18142552 0.31382285 +v 0.39240060 -0.37933540 -0.39736079 +v 0.41584852 -0.38969211 -0.27724435 +v 0.43670878 -0.39462238 -0.12551232 +v 0.43669479 -0.39473969 -1.0454956e-2 +v 0.41577843 -0.39003821 0.14116834 +v 0.39219309 -0.37947953 0.26111038 +v -0.39250767 -0.37933477 -0.39736332 +v -0.41582172 -0.38969045 -0.27724990 +v -0.43667689 -0.39461853 -0.12552494 +v -0.43665567 -0.39473389 -1.0478274e-2 +v -0.41571782 -0.39002742 0.14111021 +v -0.39223635 -0.37947069 0.26101081 +v -0.49262489 0.18142552 -0.44926386 +v -0.55717798 0.20625642 -0.32858980 +v -0.59972540 0.22312130 -0.16180161 +v -0.59972540 0.22312130 2.6360609e-2 +v -0.55717926 0.20625642 0.19314880 +v -0.49256609 0.18142552 0.31382285 +v -0.55255314 -0.18358798 0.35898979 +v -0.62116294 -0.18358798 0.22300931 +v -0.66572123 -0.18358798 3.6845158e-2 +v -0.66572123 -0.18358798 -0.17228616 +v -0.62116141 -0.18358798 -0.35845031 +v -0.55287051 -0.18358798 -0.49467218 +v 0.55261342 -0.18358798 0.35923118 +v 0.62118501 -0.18358798 0.22300931 +v 0.66574339 -0.18358798 3.6845158e-2 +v 0.66574339 -0.18358798 -0.17228616 +v 0.62118348 -0.18358798 -0.35845031 +v 0.55268237 -0.18358798 -0.49467218 +v -0.46263292 -0.18358798 -0.58767904 +v -0.31519721 -0.19932383 -0.66052495 +v -0.11340245 -0.22914512 -0.70876124 +v 0.11341763 -0.22914585 -0.70961657 +v 0.31519110 -0.19932114 -0.66052495 +v 0.46259803 -0.18358798 -0.58767904 +v 0.46169625 -0.18358798 0.45129312 +v 0.31019122 -0.20107761 0.51611632 +v 0.10925768 -0.26765391 0.54217020 +v -0.10923333 -0.26765391 0.54217020 +v -0.31019261 -0.20107761 0.51611632 +v -0.46172932 -0.18358798 0.45129312 +v 0.67335106 -0.18358798 -6.7720502e-2 +v 0.64540250 -0.18358798 0.13566080 +v 0.64540250 -0.18358798 -0.27110180 +v 0.59173356 -0.18358798 0.29786470 +v 0.59179817 -0.18358798 -0.43330570 +v 0.51706349 -0.18358798 0.40978326 +v 0.51709499 -0.18358798 -0.54522427 +v 0.39277072 -0.18351970 0.48515774 +v 0.39622542 -0.18358798 -0.62511318 +v 0.21345598 -0.22735912 0.53421503 +v 0.22055385 -0.19294018 -0.69000399 +v 1.4007196e-5 -0.28227684 0.54508400 +v 9.1033421e-6 -0.24639950 -0.71281608 +v -0.21344217 -0.22735912 0.53421503 +v -0.22054748 -0.19294391 -0.69000399 +v -0.39278773 -0.18351970 0.48515774 +v -0.39624590 -0.18358798 -0.62511318 +v -0.51683462 -0.18358798 0.40953948 +v -0.51714293 -0.18358798 -0.54522427 +v -0.59170705 -0.18358798 0.29762983 +v -0.59199779 -0.18358798 -0.43330570 +v -0.64538035 -0.18358798 0.13566080 +v -0.64538035 -0.18358798 -0.27110180 +v -0.67332891 -0.18358798 -6.7720502e-2 +v -0.67464172 -0.20679473 -6.7665981e-2 +v -0.64712106 -0.20679473 -0.27165402 +v -0.64712106 -0.20679473 0.13632206 +v -0.59479751 -0.20679473 -0.43494907 +v -0.59442169 -0.20679473 0.29929052 +v -0.52042138 -0.20679473 -0.54801377 +v -0.52001600 -0.20679473 0.41234975 +v -0.39821231 -0.20679473 -0.62753360 +v -0.39575420 -0.20681469 0.48891905 +v -0.22125769 -0.22475477 -0.69162740 +v -0.21614610 -0.25100744 0.54254121 +v -0.46470182 -0.20679473 0.45440275 +v -0.31274256 -0.22470977 0.52059244 +v -0.11057025 -0.29129317 0.55466943 +v 0.11058961 -0.29129317 0.55466944 +v 0.31273821 -0.22470976 0.52059245 +v 0.46466595 -0.20679473 0.45440275 +v 0.46533720 -0.20679473 -0.59043235 +v 0.31646284 -0.22402655 -0.66254084 +v 0.11372761 -0.25307490 -0.71094768 +v -0.11371419 -0.25307511 -0.70997705 +v -0.31647103 -0.22402960 -0.66254084 +v -0.46537475 -0.20679473 -0.59043235 +v 0.55584912 -0.20679473 -0.49699324 +v 0.62342392 -0.20679473 -0.35949101 +v 0.66718000 -0.20679473 -0.17249667 +v 0.66718000 -0.20679473 3.7164707e-2 +v 0.62342651 -0.20679473 0.22415905 +v 0.55578263 -0.20679473 0.36166128 +v -0.55604029 -0.20679473 -0.49699324 +v -0.62340280 -0.20679473 -0.35949101 +v -0.66715878 -0.20679473 -0.17249667 +v -0.66715878 -0.20679473 3.7164707e-2 +v -0.62340539 -0.20679473 0.22415905 +v -0.55562998 -0.20679473 0.36132694 +v 0.67466294 -0.20679473 -6.7665981e-2 +v 0.64714228 -0.20679473 0.13632206 +v 0.64714228 -0.20679473 -0.27165402 +v 0.59453285 -0.20679473 0.29961711 +v 0.59459509 -0.20679473 -0.43494907 +v 0.52034202 -0.20679473 0.41268181 +v 0.52037059 -0.20679473 -0.54801377 +v 0.39573429 -0.20681469 0.48891905 +v 0.39818948 -0.20679473 -0.62753360 +v 0.21615594 -0.25100742 0.54254122 +v 0.22126217 -0.22474960 -0.69162740 +v 1.1287989e-5 -0.30575798 0.55926811 +v 8.2443345e-6 -0.28362137 -0.69910931 +v -0.55054611 -0.22996832 0.35753219 +v -0.61710303 -0.22996832 0.22129070 +v -0.65992396 -0.22996832 3.6052063e-2 +v -0.65992396 -0.22996832 -0.17138636 +v -0.61710050 -0.22996832 -0.35662528 +v -0.55101199 -0.22996832 -0.49325693 +v 0.55075744 -0.22996832 0.35792191 +v 0.61712395 -0.22996832 0.22129070 +v 0.65994499 -0.22996832 3.6052063e-2 +v 0.65994499 -0.22996832 -0.17138636 +v 0.61712142 -0.22996832 -0.35662528 +v 0.55082308 -0.22996832 -0.49325693 +v -0.46119532 -0.22996832 -0.58582832 +v -0.31325567 -0.24795082 -0.65659347 +v -0.11246491 -0.28766806 -0.68657517 +v 0.11247962 -0.28766715 -0.70397298 +v 0.31324893 -0.24795246 -0.65659347 +v 0.46115937 -0.22996832 -0.58582832 +v 0.46062644 -0.22996832 0.44994503 +v 0.31027512 -0.24825727 0.51600463 +v 0.10988589 -0.31455689 0.55281284 +v -0.10986626 -0.31455662 0.55281254 +v -0.31027827 -0.24825762 0.51600395 +v -0.46066077 -0.22996832 0.44994503 +v -0.21487197 -0.27463575 0.53905628 +v -0.21889430 -0.24951480 -0.68507537 +v -0.39254007 -0.22999892 0.48445581 +v -0.39439705 -0.22996832 -0.62226895 +v -0.51541879 -0.22996832 0.40822884 +v -0.50693720 -0.22996832 -0.54394860 +v -0.58863285 -0.22996832 0.29582725 +v -0.58905974 -0.22996832 -0.43154352 +v -0.64032455 -0.22996832 0.13421594 +v -0.64032455 -0.22996832 -0.26955035 +v -0.66723564 -0.22996832 -6.7667131e-2 +v 0.66725667 -0.22996832 -6.7667131e-2 +v 0.64034558 -0.22996832 0.13421594 +v 0.64034558 -0.22996832 -0.26955035 +v 0.58879860 -0.22996832 0.29620873 +v 0.58885997 -0.22996832 -0.43154352 +v 0.51580562 -0.22996832 0.40861345 +v 0.51583390 -0.22996832 -0.54394860 +v 0.39252138 -0.22999891 0.48445584 +v 0.39437575 -0.22996832 -0.62226895 +v 0.21488254 -0.27463512 0.53905701 +v 0.21890015 -0.24951064 -0.68507537 +v 1.1324215e-5 -0.32883365 0.55798534 +v 8.8815416e-6 -0.31109038 -0.68266243 +v 1.8721358e-5 -0.24727572 0.51334492 +v 0.21951854 -0.18358428 0.49979726 +v 0.32092865 -0.14102571 0.53520810 +v 0.11845049 -0.22603452 0.50870409 +v -0.11841729 -0.22603452 0.50870409 +v -0.32093602 -0.14102571 0.53520810 +v -0.21949663 -0.18358428 0.49979726 +v 0.22225426 -6.2624627e-2 0.50770693 +v 1.8329154e-5 8.9440677e-2 0.52001715 +v 0.32685395 -0.10766006 0.54586422 +v 0.12124661 6.6239328e-2 0.51531923 +v -0.12121452 6.6239328e-2 0.51531923 +v -0.32686485 -0.10766006 0.54586422 +v -0.22223372 -6.2624627e-2 0.50770693 +v -0.11421153 -0.18859649 0.51016978 +v 1.8966137e-5 -0.20934469 0.51492110 +v 0.11424554 -0.18859649 0.51016978 +v 0.16990478 -0.15146904 0.50086359 +v 0.17110281 -7.8447240e-2 0.50692335 +v 0.10882401 3.0126069e-2 0.51392362 +v 1.8886503e-5 5.0972704e-2 0.51841784 +v -0.10878982 3.0126069e-2 0.51392362 +v -0.17107371 -7.8447240e-2 0.50692335 +v -0.16987456 -0.15146904 0.50086359 +v -0.11390791 -0.19125294 0.57121932 +v 1.0764600e-5 -0.21159692 0.57576399 +v 0.11392591 -0.19125294 0.57121932 +v 0.16914168 -0.15416023 0.56232829 +v 0.17015388 -8.1985511e-2 0.56812557 +v 0.10844376 2.4696902e-2 0.57490464 +v 1.0713423e-5 4.5890846e-2 0.57918331 +v -0.10842556 2.4696902e-2 0.57490464 +v -0.17014026 -8.1985511e-2 0.56812557 +v -0.16912698 -0.15416023 0.56232829 +v -0.12657429 -0.20991544 0.61658314 +v 4.2827541e-6 -0.23131098 0.62144592 +v 0.12657866 -0.20991544 0.61658314 +v 0.18832195 -0.16828146 0.60715413 +v 0.18936423 -8.7886758e-2 0.61329530 +v 0.12060526 2.9396443e-2 0.62061426 +v 4.3141153e-6 5.4280692e-2 0.62509619 +v -0.12060050 2.9396443e-2 0.62061426 +v -0.18936497 -8.7886758e-2 0.61329530 +v -0.18832162 -0.16828146 0.60715413 +v -0.13730255 -0.22030758 0.66686892 +v 1.5349491e-6 -0.25249767 0.67726139 +v 0.13730562 -0.22030758 0.66686892 +v 0.20787321 -0.17121769 0.65737341 +v 0.20820777 -7.8591683e-2 0.65895796 +v 0.13173082 4.4625218e-2 0.66131384 +v 1.5349491e-6 7.6400773e-2 0.66412007 +v -0.13172775 4.4625218e-2 0.66131384 +v -0.20820470 -7.8591683e-2 0.65895796 +v -0.20787014 -0.17121769 0.65737341 +v -0.15081056 -0.24407332 0.75302391 +v 1.5349491e-6 -0.28633676 0.76838054 +v 0.15081363 -0.24407332 0.75302391 +v 0.22911849 -0.16988901 0.73164192 +v 0.22931363 -5.6708965e-2 0.72682055 +v 0.14480784 9.2054523e-2 0.72081824 +v 1.5349491e-6 0.12978730 0.72212999 +v -0.14480477 9.2054523e-2 0.72081824 +v -0.22931056 -5.6708965e-2 0.72682055 +v -0.22911542 -0.16988901 0.73164192 +v -0.13969305 -0.23243055 0.82387888 +v 1.5349490e-6 -0.27315153 0.83758493 +v 0.13969612 -0.23243055 0.82387888 +v 0.21276009 -0.15542754 0.80271332 +v 0.21286058 -3.7950392e-2 0.79707211 +v 0.13428385 0.10971139 0.79308229 +v 1.5349491e-6 0.14417370 0.79660345 +v -0.13428078 0.10971139 0.79308229 +v -0.21285751 -3.7950392e-2 0.79707211 +v -0.21275702 -0.15542754 0.80271332 +v -0.10526122 -0.19060280 0.89123932 +v 1.5349490e-6 -0.21053509 0.89324941 +v 0.10526429 -0.19060280 0.89123932 +v 0.16277331 -0.12154430 0.87121747 +v 0.16289932 -2.8042317e-2 0.86636874 +v 0.10207239 8.4935150e-2 0.86199495 +v 1.5349491e-6 0.11218664 0.86268705 +v -0.10206932 8.4935150e-2 0.86199495 +v -0.16289625 -2.8042317e-2 0.86636874 +v -0.16277024 -0.12154430 0.87121747 +v -7.4627024e-2 -0.14544289 0.91776746 +v 1.5349490e-6 -0.16516970 0.92252648 +v 7.4630094e-2 -0.14544289 0.91776746 +v 0.11700275 -9.7966072e-2 0.90847033 +v 0.11669322 -2.9703094e-2 0.90366473 +v 7.2809891e-2 4.1374622e-2 0.90109448 +v 1.5349491e-6 6.5319596e-2 0.90102503 +v -7.2806821e-2 4.1374622e-2 0.90109448 +v -0.11669015 -2.9703094e-2 0.90366473 +v -0.11699968 -9.7966072e-2 0.90847033 +v -5.9920950e-2 -9.7733397e-2 0.93414397 +v 1.5349490e-6 -0.11240489 0.93792260 +v 5.9924020e-2 -9.7733397e-2 0.93414397 +v 8.3936041e-2 -7.3508348e-2 0.92828031 +v 8.3359965e-2 -4.6487239e-2 0.92673981 +v 5.4079461e-2 -2.3156816e-3 0.92576033 +v 1.5349491e-6 1.5371838e-2 0.92585631 +v -5.4076391e-2 -2.3156816e-3 0.92576033 +v -8.3356896e-2 -4.6487239e-2 0.92673981 +v -8.3932972e-2 -7.3508348e-2 0.92828031 +v -0.19139942 -0.18374137 -0.69850450 +v -0.20091675 -0.12390598 -0.73002438 +v -0.10520374 -5.5386397e-2 -0.75031697 +v 4.2644748e-6 -4.1495240e-2 -0.75527248 +v 0.10520937 -5.5385138e-2 -0.75031698 +v 0.20091479 -0.12390058 -0.73002434 +v 0.19140517 -0.18373853 -0.69850442 +v 0.10054852 -0.21496552 -0.71837921 +v 8.5597470e-6 -0.22388088 -0.71896985 +v -0.10053424 -0.21496484 -0.71753380 +v -0.15638127 -0.19381966 -0.68907731 +v -0.16036632 -0.13379472 -0.73326164 +v -9.2653920e-2 -7.5469912e-2 -0.77474681 +v 3.6018632e-6 -5.8717514e-2 -0.79120998 +v 9.2659504e-2 -7.5467981e-2 -0.77474679 +v 0.16036930 -0.13379049 -0.73326155 +v 0.15638852 -0.19381679 -0.68907718 +v 8.9381018e-2 -0.23284229 -0.70176810 +v 7.6136722e-6 -0.24974054 -0.71012354 +v -8.9368061e-2 -0.23284278 -0.70049632 +v -0.12806404 -0.20674861 -0.76538088 +v -0.13132751 -0.15759250 -0.80956522 +v -7.5875931e-2 -0.10406402 -0.84345453 +v 3.9086415e-6 -7.9589176e-2 -0.84651590 +v 7.5882421e-2 -0.10406217 -0.84345416 +v 0.13133187 -0.15758904 -0.80956512 +v 0.12807190 -0.20674625 -0.76538076 +v 7.3197578e-2 -0.22713792 -0.76282978 +v 7.1940240e-6 -0.23220369 -0.76137017 +v -7.3185049e-2 -0.22713716 -0.76282828 +v -8.1446746e-2 -0.19166023 -0.87044505 +v -8.3522315e-2 -0.15978493 -0.90417055 +v -4.8255109e-2 -0.12808167 -0.92300469 +v 4.4692185e-6 -0.11871770 -0.92855343 +v 4.8263203e-2 -0.12808064 -0.92300419 +v 8.3529053e-2 -0.15978263 -0.90416886 +v 8.1455711e-2 -0.19165870 -0.87044444 +v 4.6555643e-2 -0.21098130 -0.86598864 +v 6.5587217e-6 -0.21920489 -0.86591043 +v -4.6543708e-2 -0.21098152 -0.86598805 +v -3.7415384e-2 -0.19026720 -0.97974881 +v -3.8368940e-2 -0.17861668 -0.98124480 +v -2.2166503e-2 -0.16775024 -0.98240351 +v 4.8812986e-6 -0.16320273 -0.98366268 +v 2.2175878e-2 -0.16775031 -0.98240327 +v 3.8377692e-2 -0.17861687 -0.98124425 +v 3.7425159e-2 -0.19026735 -0.97974842 +v 2.1391392e-2 -0.18485095 -0.98721276 +v 5.8412569e-6 -0.18115742 -0.99132043 +v -2.1380252e-2 -0.18485092 -0.98721283 +vt 1.4699972e-2 0.62463149 +vt 1.7568090e-2 0.57942934 +vt 1.7844723e-2 0.66969902 +vt 2.5694925e-2 0.53702042 +vt 2.5859044e-2 0.71157587 +vt 2.6439066e-2 0.62460228 +vt 2.9246019e-2 0.58114934 +vt 2.9406655e-2 0.66796562 +vt 3.5125644e-2 0.74690651 +vt 3.6123860e-2 0.50113991 +vt 3.6939827e-2 0.54033069 +vt 3.6987015e-2 0.70848435 +vt 3.9393174e-2 0.62457293 +vt 4.2164999e-2 0.58360926 +vt 4.2164999e-2 0.66550196 +vt 4.5811016e-2 0.74256240 +vt 4.6435016e-2 0.77705737 +vt 4.6754031e-2 0.50579027 +vt 4.8246356e-2 0.47159392 +vt 4.9333364e-2 0.70398272 +vt 4.9333364e-2 0.54512850 +vt 5.4976663e-2 0.62456873 +vt 5.5290194e-2 0.62710168 +vt 5.6646707e-2 0.77106817 +vt 5.6790623e-2 0.59189466 +vt 5.7219021e-2 0.66255949 +vt 5.7219021e-2 0.58655173 +vt 5.7618642e-2 0.73598386 +vt 5.8084121e-2 0.47756123 +vt 5.8271880e-2 0.66234267 +vt 5.8465836e-2 0.51267966 +vt 5.8874084e-2 8.2416183e-2 +vt 5.9550063e-2 0.13227794 +vt 6.0791752e-2 7.0983736e-2 +vt 6.0952480e-2 0.44863288 +vt 6.1179690e-2 0.80205027 +vt 6.2000367e-2 0.55879039 +vt 6.2377665e-2 0.11609845 +vt 6.2547432e-2 0.11758030 +vt 6.4033991e-2 0.69822725 +vt 6.4033991e-2 0.55088397 +vt 6.5121953e-2 0.69561902 +vt 6.6520311e-2 0.12227641 +vt 6.7216260e-2 0.13309515 +vt 6.8081900e-2 0.76250752 +vt 6.8458677e-2 7.0075410e-2 +vt 6.9266477e-2 0.48606507 +vt 6.9474486e-2 0.12054248 +vt 6.9624704e-2 0.52996482 +vt 7.0918773e-2 0.79448528 +vt 7.1753759e-2 0.72791739 +vt 7.2095842e-2 0.45523507 +vt 7.2619639e-2 0.52106883 +vt 7.4586777e-2 0.72444649 +vt 7.5975997e-2 0.82282074 +vt 7.6156736e-2 0.12382144 +vt 7.6297024e-2 0.42946160 +vt 7.6850989e-2 0.13340619 +vt 7.7795717e-2 0.11726505 +vt 7.8777082e-2 0.50519284 +vt 8.1525047e-2 0.75191609 +vt 8.1740624e-2 0.78380969 +vt 8.2420311e-2 0.46514348 +vt 8.2717418e-2 0.49650164 +vt 8.3057583e-2 0.14670897 +vt 8.3748082e-2 0.15350585 +vt 8.4489210e-2 0.43727210 +vt 8.4521992e-2 0.13802773 +vt 8.4731569e-2 0.81375749 +vt 8.5757971e-2 0.74910030 +vt 8.6675186e-2 9.4135526e-2 +vt 8.7691764e-2 8.5997943e-2 +vt 8.7930426e-2 0.11982748 +vt 8.8005178e-2 0.12091118 +vt 8.9179455e-2 0.48447456 +vt 8.9265728e-2 0.12352452 +vt 9.1063753e-2 0.12425112 +vt 9.1202181e-2 8.3114962e-2 +vt 9.2248074e-2 0.13165811 +vt 9.3680661e-2 0.41327851 +vt 9.3717334e-2 0.11846896 +vt 9.3983079e-2 0.44812667 +vt 9.4258746e-2 0.77091567 +vt 9.4418131e-2 0.17332045 +vt 9.4850057e-2 0.47721325 +vt 9.5104977e-2 0.18009216 +vt 9.5597330e-2 0.16862252 +vt 9.5923331e-2 0.62614586 +vt 9.6235236e-2 0.15273045 +vt 9.6431925e-2 0.84070733 +vt 9.6965488e-2 0.59636676 +vt 9.7296538e-2 0.80150116 +vt 9.7561553e-2 0.13606334 +vt 9.8332668e-2 0.76935604 +vt 9.8351871e-2 0.65588208 +vt 0.10028473 0.56644132 +vt 0.10046336 0.46634528 +vt 0.10149071 0.42186542 +vt 0.10279911 0.17654056 +vt 0.10319445 0.68568666 +vt 0.10380084 0.83057550 +vt 0.10389030 0.16618533 +vt 0.10511520 0.54282522 +vt 0.10514846 0.19610256 +vt 0.10583159 0.20071264 +vt 0.10605749 0.19957948 +vt 0.10746518 0.46152929 +vt 0.10868948 0.78659466 +vt 0.10899884 0.19572428 +vt 0.10944095 0.70901881 +vt 0.10968224 0.20170285 +vt 0.10986777 0.20201812 +vt 0.11012102 0.43369873 +vt 0.11131653 0.51908330 +vt 0.11210598 0.78667684 +vt 0.11242134 0.81732661 +vt 0.11426731 0.13518137 +vt 0.11426741 0.15200477 +vt 0.11426746 0.12401301 +vt 0.11426757 0.17748769 +vt 0.11426767 0.19578260 +vt 0.11451965 0.45219792 +vt 0.11494988 0.20340361 +vt 0.11495113 0.20233597 +vt 0.11495190 0.16566161 +vt 0.11495381 0.11462049 +vt 0.11495439 0.13534207 +vt 0.11495481 0.12076239 +vt 0.11495510 0.11979810 +vt 0.11495573 0.12387411 +vt 0.11620318 8.8544748e-2 +vt 0.11620320 8.5889351e-2 +vt 0.11620390 9.8521565e-2 +vt 0.11630596 0.40073373 +vt 0.11736110 0.73235951 +vt 0.11803264 0.50187438 +vt 0.11953639 0.19572421 +vt 0.11984131 0.44802724 +vt 0.12003206 0.20201814 +vt 0.12021980 0.20170293 +vt 0.12077963 0.85602075 +vt 0.12263429 0.80110010 +vt 0.12322547 0.40950869 +vt 0.12338659 0.19610242 +vt 0.12384265 0.19957959 +vt 0.12406972 0.20071281 +vt 0.12549847 0.74887033 +vt 0.12573580 0.17654035 +vt 0.12575170 0.48465685 +vt 0.12601450 0.16618515 +vt 0.12636651 0.80104557 +vt 0.12669314 0.84533807 +vt 0.12819525 0.62535684 +vt 0.13020955 0.42165384 +vt 0.13071045 0.57608225 +vt 0.13229920 0.15273023 +vt 0.13234803 0.13606296 +vt 0.13288913 0.67436004 +vt 0.13319340 0.43942982 +vt 0.13374368 0.83143999 +vt 0.13411634 0.17331983 +vt 0.13430959 0.16862260 +vt 0.13480319 0.18009250 +vt 0.13494284 0.76511652 +vt 0.13619544 0.11810973 +vt 0.13628609 0.13165798 +vt 0.13766796 0.43666887 +vt 0.13770697 0.53438304 +vt 0.13858034 0.47374829 +vt 0.13884923 0.12401238 +vt 0.13926846 0.12352444 +vt 0.14120491 8.3114779e-2 +vt 0.14190689 0.12066965 +vt 0.14197989 0.11955332 +vt 0.14216719 0.71518668 +vt 0.14219706 0.81439284 +vt 0.14295729 0.38906603 +vt 0.14418638 0.81498567 +vt 0.14471533 8.5997737e-2 +vt 0.14539033 0.13802762 +vt 0.14547616 0.14670872 +vt 0.14573332 9.4134903e-2 +vt 0.14616665 0.15350567 +vt 0.14651797 0.50240812 +vt 0.14930165 0.39805061 +vt 0.14947429 0.77555941 +vt 0.14967099 0.86946075 +vt 0.15212256 0.11726491 +vt 0.15237659 0.12382114 +vt 0.15272212 0.62476489 +vt 0.15307084 0.13340596 +vt 0.15313139 0.74574064 +vt 0.15414637 0.58409868 +vt 0.15453081 0.85847160 +vt 0.15481852 0.41101285 +vt 0.15521856 0.46467419 +vt 0.15561102 0.66521913 +vt 0.15664279 0.42745557 +vt 0.15822308 0.54789079 +vt 0.15977774 0.84418295 +vt 0.15981268 0.42681643 +vt 0.16044445 0.12054233 +vt 0.16138767 0.70066661 +vt 0.16201186 0.12227605 +vt 0.16270781 0.13309483 +vt 0.16344417 0.51869034 +vt 0.16395023 7.0074637e-2 +vt 0.16431545 0.78495276 +vt 0.16593999 0.82676375 +vt 0.16641429 0.82739926 +vt 0.16737108 0.11758007 +vt 0.16753841 0.11609813 +vt 0.16827749 0.72878395 +vt 0.17037587 0.13227754 +vt 0.17161756 7.0982796e-2 +vt 0.17353679 8.2414816e-2 +vt 0.17385959 0.48674435 +vt 0.17728897 0.45558611 +vt 0.17753789 0.38323676 +vt 0.17767158 0.62420076 +vt 0.17951562 0.57802418 +vt 0.18009537 0.75897858 +vt 0.18061457 0.67010573 +vt 0.18296178 0.87697366 +vt 0.18317087 0.79386622 +vt 0.18333565 0.53827002 +vt 0.18398425 0.39298530 +vt 0.18611418 0.70878193 +vt 0.18667255 0.86670489 +vt 0.18764865 0.40611443 +vt 0.18807873 0.42438714 +vt 0.18838554 0.50772686 +vt 0.18962184 0.42200312 +vt 0.18990407 0.85289185 +vt 0.19265076 0.73745264 +vt 0.19311298 0.83542167 +vt 0.19341629 0.83580999 +vt 0.20177435 0.44975414 +vt 0.20496162 0.80028992 +vt 0.21151878 0.47533816 +vt 0.21209563 0.62351070 +vt 0.21378289 0.38531406 +vt 0.21412752 0.57231309 +vt 0.21412752 0.67470831 +vt 0.21505996 0.77007141 +vt 0.21655289 0.53014388 +vt 0.21699095 0.39447945 +vt 0.21837276 0.71519743 +vt 0.21880257 0.40650963 +vt 0.21929229 0.87760986 +vt 0.22006863 0.49966318 +vt 0.22016891 0.42178279 +vt 0.22090758 0.42894823 +vt 0.22111859 0.86888366 +vt 0.22240454 0.74427893 +vt 0.22248586 0.85619398 +vt 0.22390276 0.83995948 +vt 0.22474335 0.83631959 +vt 0.22696098 0.44365999 +vt 0.23055022 0.80290234 +vt 0.25353668 0.87768578 +vt 0.25353794 0.87004910 +vt 0.25354088 0.85770151 +vt 0.25354507 0.84176953 +vt 0.25361414 0.42168412 +vt 0.25362852 0.40596273 +vt 0.25364975 0.39379768 +vt 0.25367098 0.38408854 +vt 0.25571426 0.77447154 +vt 0.25575697 0.56981420 +vt 0.25575697 0.62351070 +vt 0.25575697 0.67720721 +vt 0.25576388 0.74686230 +vt 0.25579586 0.83799917 +vt 0.25580793 0.71800868 +vt 0.25583306 0.52677674 +vt 0.25584173 0.80457076 +vt 0.25587403 0.49691383 +vt 0.25593752 0.47264171 +vt 0.25599829 0.44688646 +vt 0.25604879 0.42888066 +vt 0.27362782 0.13668852 +vt 0.27621400 0.12590377 +vt 0.27695518 0.10440522 +vt 0.27762891 0.11986916 +vt 0.27836412 0.10054154 +vt 0.28031121 8.9393285e-2 +vt 0.28091719 9.3577166e-2 +vt 0.28122634 0.80280382 +vt 0.28319193 0.83997462 +vt 0.28459981 0.85620829 +vt 0.28503138 0.44381578 +vt 0.28595920 0.86889830 +vt 0.28675373 0.83629424 +vt 0.28714360 0.42180578 +vt 0.28778145 0.87762421 +vt 0.28850769 0.40653765 +vt 0.28917497 0.74420513 +vt 0.29031203 0.39452568 +vt 0.29115685 0.42916273 +vt 0.29166567 0.49977378 +vt 0.29330472 0.71522446 +vt 0.29351375 0.38537788 +vt 0.29511036 0.53020395 +vt 0.29738641 0.57231309 +vt 0.29738641 0.67470831 +vt 0.29740850 0.76982390 +vt 0.29774548 0.15348957 +vt 0.29941830 0.62351070 +vt 0.29971107 0.14132996 +vt 0.30031085 0.47552117 +vt 0.30181980 0.11594471 +vt 0.30247025 9.8239759e-2 +vt 0.30252577 0.11612549 +vt 0.30326647 8.2695023e-2 +vt 0.30390904 8.7344842e-2 +vt 0.30641745 0.80044600 +vt 0.31013643 0.45003232 +vt 0.31367254 0.83582929 +vt 0.31397751 0.11359852 +vt 0.31426247 0.10306492 +vt 0.31469894 0.11433008 +vt 0.31718119 0.85291240 +vt 0.31765872 0.42203796 +vt 0.31817661 0.83569214 +vt 0.31898895 0.73754962 +vt 0.31963977 0.40616657 +vt 0.32040674 0.86672489 +vt 0.32076701 0.17101829 +vt 0.32206441 0.15876213 +vt 0.32329307 0.39305926 +vt 0.32332333 0.50791713 +vt 0.32390157 0.42480672 +vt 0.32411486 0.87699715 +vt 0.32520126 0.70844944 +vt 0.32639937 0.13206338 +vt 0.32649082 9.0619997e-2 +vt 0.32749028 9.6218087e-2 +vt 0.32799454 0.53848914 +vt 0.32815490 0.79409096 +vt 0.32835559 7.5021349e-2 +vt 0.32867330 8.0172096e-2 +vt 0.32938739 0.12784881 +vt 0.32973198 0.38331606 +vt 0.33097580 0.67027907 +vt 0.33142345 0.75903448 +vt 0.33214404 0.57793790 +vt 0.33380937 0.62420275 +vt 0.33451669 0.45594798 +vt 0.33781474 0.48702155 +vt 0.34113437 0.82678171 +vt 0.34306873 0.72875896 +vt 0.34541973 0.82765809 +vt 0.34730458 0.84420602 +vt 0.34746274 0.42686835 +vt 0.34795863 0.51888872 +vt 0.34870020 0.78436896 +vt 0.35026640 0.70057670 +vt 0.35246023 0.41107532 +vt 0.35255065 0.85849286 +vt 0.35342572 0.54793469 +vt 0.35463427 7.2236706e-2 +vt 0.35463492 7.7565880e-2 +vt 0.35463604 8.6785078e-2 +vt 0.35463610 9.2445907e-2 +vt 0.35483618 0.17623612 +vt 0.35494149 0.16376117 +vt 0.35517803 0.13590855 +vt 0.35519291 0.42800886 +vt 0.35521621 0.13136673 +vt 0.35585090 0.66520837 +vt 0.35646467 0.46508170 +vt 0.35733058 0.58418850 +vt 0.35741225 0.86947595 +vt 0.35798391 0.39808991 +vt 0.35837108 0.74553641 +vt 0.35874451 0.62481387 +vt 0.36356177 0.77490476 +vt 0.36431882 0.38908692 +vt 0.36488453 0.81438321 +vt 0.36495010 0.50268103 +vt 0.36766397 0.81507427 +vt 0.36928253 0.71530959 +vt 0.36959011 0.43668048 +vt 0.37298834 0.47415990 +vt 0.37333398 0.83144220 +vt 0.37379156 0.53453787 +vt 0.37668301 0.76500718 +vt 0.37703928 0.42167318 +vt 0.37846835 0.44002505 +vt 0.37862160 0.67426325 +vt 0.38037659 0.84534568 +vt 0.38059567 8.0172096e-2 +vt 0.38072294 0.57617432 +vt 0.38091219 7.5021347e-2 +vt 0.38109950 0.12828204 +vt 0.38178099 9.6218087e-2 +vt 0.38278026 9.0619997e-2 +vt 0.38324612 0.62535701 +vt 0.38400925 0.40951334 +vt 0.38401599 0.13254608 +vt 0.38441887 0.80110922 +vt 0.38559418 0.80090014 +vt 0.38570314 0.48502649 +vt 0.38610153 0.74870313 +vt 0.38629160 0.85603690 +vt 0.38739351 0.44802021 +vt 0.38789664 0.15931365 +vt 0.38898800 0.17158983 +vt 0.39092633 0.40073907 +vt 0.39335184 0.50217212 +vt 0.39413775 0.73236821 +vt 0.39462827 0.81734949 +vt 0.39500789 0.10306492 +vt 0.39529259 0.11359852 +vt 0.39601117 0.11501129 +vt 0.39697764 0.45277128 +vt 0.39712740 0.43369555 +vt 0.39834645 0.78656848 +vt 0.39933158 0.51890576 +vt 0.39961912 0.78638721 +vt 0.39970776 0.46149668 +vt 0.40210972 0.70899692 +vt 0.40326514 0.83057628 +vt 0.40535743 8.7344842e-2 +vt 0.40574381 0.42184197 +vt 0.40599905 8.2695023e-2 +vt 0.40623042 0.54300873 +vt 0.40679814 9.8239759e-2 +vt 0.40744826 0.11594471 +vt 0.40815052 0.11701039 +vt 0.40826313 0.68551295 +vt 0.40972865 0.80150027 +vt 0.41053741 0.14225844 +vt 0.41064702 0.84068796 +vt 0.41091052 0.46685890 +vt 0.41106666 0.56656409 +vt 0.41228675 0.47716725 +vt 0.41229674 0.15444926 +vt 0.41275249 0.77090468 +vt 0.41308918 0.65575261 +vt 0.41318988 0.76929876 +vt 0.41324082 0.44810678 +vt 0.41354836 0.41325736 +vt 0.41439735 0.59638835 +vt 0.41546859 0.62609693 +vt 0.42211353 0.48491275 +vt 0.42232130 0.81375461 +vt 0.42267373 0.49651061 +vt 0.42271226 0.43724019 +vt 0.42472333 0.46511543 +vt 0.42525873 0.78380606 +vt 0.42550476 0.75190230 +vt 0.42579992 0.74886958 +vt 0.42834567 9.3577166e-2 +vt 0.42895093 8.9393285e-2 +vt 0.43089732 0.10054154 +vt 0.43091488 0.42944615 +vt 0.43107181 0.82280928 +vt 0.43187414 0.50493790 +vt 0.43230541 0.10440522 +vt 0.43297369 0.12117061 +vt 0.43428641 0.12722806 +vt 0.43448446 0.52103547 +vt 0.43500724 0.45519006 +vt 0.43530978 0.72790997 +vt 0.43609129 0.79448163 +vt 0.43668991 0.13805462 +vt 0.43692826 0.72445578 +vt 0.43783668 0.48606602 +vt 0.43893462 0.76249905 +vt 0.44156180 0.53009793 +vt 0.44304416 0.69822725 +vt 0.44304416 0.55088397 +vt 0.44408537 0.44808772 +vt 0.44584172 0.80204048 +vt 0.44638225 0.69531703 +vt 0.44863948 0.51266513 +vt 0.44899431 0.47757768 +vt 0.44925078 0.55880527 +vt 0.44944598 0.73597447 +vt 0.44985913 0.58655173 +vt 0.44985913 0.66255949 +vt 0.45035955 0.77106211 +vt 0.45210047 0.62457296 +vt 0.45310638 0.66215679 +vt 0.45447875 0.59189142 +vt 0.45602042 0.62698867 +vt 0.45774479 0.70398272 +vt 0.45774479 0.54512850 +vt 0.45879569 0.47156363 +vt 0.46035551 0.50578501 +vt 0.46056573 0.77705152 +vt 0.46125902 0.74255596 +vt 0.46491315 0.66550196 +vt 0.46491315 0.58360926 +vt 0.46768382 0.62457606 +vt 0.47009019 0.70848313 +vt 0.47014566 0.54033924 +vt 0.47098785 0.50113520 +vt 0.47194531 0.74690820 +vt 0.47767051 0.66796969 +vt 0.47782006 0.58114870 +vt 0.48064192 0.62460323 +vt 0.48121833 0.71157566 +vt 0.48139516 0.53703506 +vt 0.48923243 0.66970525 +vt 0.48949313 0.57942836 +vt 0.49238032 0.62463023 +vt 0.51640180 0.62532389 +vt 0.51809929 0.58273135 +vt 0.51809929 0.66804072 +vt 0.52260840 0.54271404 +vt 0.52260840 0.70838817 +vt 0.52784323 0.50766791 +vt 0.52784356 0.74381759 +vt 0.53085590 0.62524131 +vt 0.53239804 0.58404698 +vt 0.53239804 0.66655278 +vt 0.53417365 0.77398618 +vt 0.53418742 0.47796331 +vt 0.53650784 0.54526468 +vt 0.53650784 0.70564754 +vt 0.54128045 0.51113846 +vt 0.54128077 0.74014090 +vt 0.54269122 0.79857761 +vt 0.54270579 0.45399554 +vt 0.54417222 0.62534471 +vt 0.54562373 0.58630517 +vt 0.54562373 0.66449052 +vt 0.54706540 0.76966635 +vt 0.54707864 0.48205879 +vt 0.54757678 0.62521695 +vt 0.54874280 0.62586617 +vt 0.54900449 0.58607746 +vt 0.54900449 0.66446097 +vt 0.54950467 0.54950426 +vt 0.54950467 0.70157558 +vt 0.55024980 0.81900732 +vt 0.55025643 0.43411895 +vt 0.55075161 0.66478094 +vt 0.55102118 0.58724200 +vt 0.55282759 0.54914668 +vt 0.55282759 0.70167167 +vt 0.55393381 0.62588386 +vt 0.55412524 0.51701750 +vt 0.55412553 0.73440065 +vt 0.55490598 0.79388279 +vt 0.55492005 0.45844011 +vt 0.55592045 0.66405697 +vt 0.55612669 0.58797392 +vt 0.55659774 0.70182385 +vt 0.55677729 0.55087633 +vt 0.55735244 0.51647379 +vt 0.55735293 0.73467586 +vt 0.55973210 0.76259116 +vt 0.55974443 0.48923795 +vt 0.56064378 0.41698810 +vt 0.56136022 0.83697107 +vt 0.56165232 0.70040559 +vt 0.56173922 0.55220462 +vt 0.56203656 0.81391850 +vt 0.56204297 0.43893852 +vt 0.56274845 0.16093661 +vt 0.56285333 0.76308780 +vt 0.56286520 0.48846503 +vt 0.56374245 0.51875226 +vt 0.56443101 0.73466567 +vt 0.56483229 0.13579041 +vt 0.56719520 0.78580670 +vt 0.56720836 0.46656886 +vt 0.56783820 0.18435295 +vt 0.56827775 0.11873201 +vt 0.56854916 0.52059364 +vt 0.56928704 0.73265990 +vt 0.56946744 0.40176469 +vt 0.57024586 0.78655411 +vt 0.57025855 0.46554000 +vt 0.57208399 0.42250465 +vt 0.57225875 0.49093023 +vt 0.57302621 0.83117025 +vt 0.57311340 0.10397345 +vt 0.57398509 0.80495455 +vt 0.57399111 0.44791788 +vt 0.57415811 0.76249331 +vt 0.57455842 8.3875358e-2 +vt 0.57479133 0.85336553 +vt 0.57595457 0.62590265 +vt 0.57685870 0.49327992 +vt 0.57701499 0.80587633 +vt 0.57702044 0.44671313 +vt 0.57759727 0.65962298 +vt 0.57760373 0.59229077 +vt 0.57870999 0.75988821 +vt 0.58099243 0.40807861 +vt 0.58103575 0.38752953 +vt 0.58112291 0.13832737 +vt 0.58148411 0.15921171 +vt 0.58196847 0.20697890 +vt 0.58201676 0.55969592 +vt 0.58224887 0.69259171 +vt 0.58248305 0.12289030 +vt 0.58317636 0.46756363 +vt 0.58438284 0.82120724 +vt 0.58455490 0.43278583 +vt 0.58637430 0.78549972 +vt 0.58637864 0.10720754 +vt 0.58639932 0.17880117 +vt 0.58643656 0.84667029 +vt 0.58732618 0.53019550 +vt 0.58751169 0.47045587 +vt 0.58751508 0.82211924 +vt 0.58764315 0.43150431 +vt 0.58770791 8.6579339e-2 +vt 0.58808631 0.72226871 +vt 0.59055973 0.78240132 +vt 0.59117781 0.86916834 +vt 0.59225846 0.39455110 +vt 0.59409209 0.22036069 +vt 0.59427047 0.44841955 +vt 0.59536912 0.50419726 +vt 0.59644076 0.19939954 +vt 0.59699873 0.74827339 +vt 0.59704640 0.83566587 +vt 0.59769479 0.42060699 +vt 0.59819562 0.80381452 +vt 0.59832414 0.39869287 +vt 0.60008971 0.45126014 +vt 0.60032653 0.83645883 +vt 0.60079811 0.41908151 +vt 0.60188933 0.80024050 +vt 0.60267229 0.86152827 +vt 0.60305026 0.48276328 +vt 0.60314327 0.62582957 +vt 0.60432511 0.59782802 +vt 0.60443761 0.65389124 +vt 0.60470946 0.40257692 +vt 0.60491715 0.21333151 +vt 0.60538190 0.76931930 +vt 0.60656499 0.88272502 +vt 0.60773138 0.56811375 +vt 0.60806428 0.68367267 +vt 0.60901373 0.13919089 +vt 0.60988252 0.15766409 +vt 0.61002027 0.43147269 +vt 0.61019533 0.12573761 +vt 0.61153572 0.54185663 +vt 0.61219695 0.17620526 +vt 0.61228089 0.71002123 +vt 0.61261637 0.11015157 +vt 0.61334383 8.9504291e-2 +vt 0.61346241 0.43550469 +vt 0.61402027 0.46532801 +vt 0.61458934 0.81930652 +vt 0.61498518 0.84940424 +vt 0.61621576 0.40953537 +vt 0.61682137 0.87425812 +vt 0.61698106 0.78613513 +vt 0.61741462 0.51725780 +vt 0.61768329 0.81523649 +vt 0.61863343 0.85004446 +vt 0.61864538 0.73447579 +vt 0.61868366 0.19525168 +vt 0.61945167 0.40774414 +vt 0.62210782 0.20945653 +vt 0.62269117 0.49835018 +vt 0.62445200 0.75317891 +vt 0.62714985 0.62572688 +vt 0.62802825 0.60528190 +vt 0.62813920 0.64617727 +vt 0.62822037 0.45123219 +vt 0.62937199 0.79920543 +vt 0.62952055 0.41646382 +vt 0.63049575 0.48347066 +vt 0.63127751 0.57295868 +vt 0.63162625 0.67851402 +vt 0.63203655 0.86111322 +vt 0.63253201 0.42093862 +vt 0.63258581 0.76764504 +vt 0.63367393 0.55138792 +vt 0.63428519 0.70004347 +vt 0.63433498 0.83231410 +vt 0.63691111 0.86158058 +vt 0.63695293 0.82799494 +vt 0.63773317 0.52369730 +vt 0.63878588 0.72755574 +vt 0.63987835 0.50868637 +vt 0.64006221 0.20842101 +vt 0.64030083 0.19475027 +vt 0.64062323 0.17628017 +vt 0.64095224 0.15743218 +vt 0.64118550 0.49552250 +vt 0.64123896 0.74242362 +vt 0.64126822 0.13933227 +vt 0.64148809 0.12670014 +vt 0.64174981 0.11162218 +vt 0.64210268 9.1300133e-2 +vt 0.64268339 0.47354578 +vt 0.64282891 0.75542566 +vt 0.64438891 0.43918979 +vt 0.64482645 0.77703941 +vt 0.64741347 0.81026691 +vt 0.64921159 0.62562071 +vt 0.65218256 0.49348752 +vt 0.65371800 0.75715028 +vt 0.65480411 0.40428213 +vt 0.65525027 0.56636738 +vt 0.65559704 0.68477911 +vt 0.65729791 0.40922817 +vt 0.65796952 0.21008251 +vt 0.65845460 0.46504339 +vt 0.65906671 0.84221866 +vt 0.65909008 0.51539580 +vt 0.66011282 0.73532221 +vt 0.66047371 0.78490828 +vt 0.66131557 0.83769491 +vt 0.66188733 0.19600580 +vt 0.66466099 0.48935377 +vt 0.66609854 0.76091413 +vt 0.66740083 0.42972230 +vt 0.66903480 0.17719737 +vt 0.66966827 0.81931980 +vt 0.67090761 9.0509824e-2 +vt 0.67091748 0.11116987 +vt 0.67199484 0.15874836 +vt 0.67279603 0.12683089 +vt 0.67350774 0.14031695 +vt 0.67501454 0.21455505 +vt 0.67849527 0.45776891 +vt 0.68086136 0.79180030 +vt 0.68279180 0.39258257 +vt 0.68397196 0.20092734 +vt 0.68461805 0.39803747 +vt 0.68558774 0.22195772 +vt 0.68734174 0.48438878 +vt 0.68742498 0.84861994 +vt 0.68891429 0.76568912 +vt 0.68917110 0.84405863 +vt 0.69252972 0.42054524 +vt 0.69472609 0.18069190 +vt 0.69498364 0.82571229 +vt 0.69663116 8.8480696e-2 +vt 0.69724258 0.10914280 +vt 0.69817098 0.20900711 +vt 0.70011258 0.62537822 +vt 0.70032182 0.16128588 +vt 0.70059076 0.12495235 +vt 0.70066683 0.50970189 +vt 0.70090761 0.45218875 +vt 0.70141138 0.14042690 +vt 0.70142156 0.56611100 +vt 0.70144628 0.68456330 +vt 0.70161005 0.74051096 +vt 0.70185324 0.79693465 +vt 0.70543478 0.48075678 +vt 0.70662758 0.76912636 +vt 0.70986695 8.6235360e-2 +vt 0.71061247 0.10637188 +vt 0.71308222 0.18688797 +vt 0.71493210 0.12129134 +vt 0.71559815 0.38808853 +vt 0.71672011 0.39938455 +vt 0.71778064 0.13845963 +vt 0.71854777 0.85048184 +vt 0.71898595 0.16366340 +vt 0.71969409 0.84602117 +vt 0.72120532 0.41469323 +vt 0.72243120 0.82901830 +vt 0.72624349 0.44668051 +vt 0.72675506 0.80026985 +vt 0.73290614 0.47384739 +vt 0.73330905 0.77283605 +vt 0.74132603 0.15539057 +vt 0.74528607 0.12194336 +vt 0.74964590 0.39372066 +vt 0.74964849 0.40208891 +vt 0.74969528 0.56447406 +vt 0.74969862 0.47637094 +vt 0.74969870 0.62534682 +vt 0.74969888 0.44544398 +vt 0.74970092 0.41562328 +vt 0.74970226 0.68612604 +vt 0.74972334 0.50219042 +vt 0.74973797 0.74775962 +vt 0.74974416 0.77378656 +vt 0.74977082 0.80135863 +vt 0.74977482 0.83010045 +vt 0.74979125 0.84692247 +vt 0.74979716 0.85141491 +vt 0.75044526 9.8826564e-2 +vt 0.75184605 0.18781835 +vt 0.75506376 5.0662344e-2 +vt 0.75541575 7.7930646e-2 +vt 0.76618303 0.77285046 +vt 0.76648140 0.47500524 +vt 0.77206139 0.12406372 +vt 0.77252760 0.15889485 +vt 0.77264878 0.21499518 +vt 0.77278501 0.80026740 +vt 0.77316794 0.44824188 +vt 0.77403105 0.10253185 +vt 0.77643305 5.4913000e-2 +vt 0.77681374 8.1976403e-2 +vt 0.77710497 0.82899934 +vt 0.77818426 0.18263615 +vt 0.77823029 0.41633388 +vt 0.77983813 0.84596416 +vt 0.78098211 0.85041530 +vt 0.78221250 0.39462255 +vt 0.78361193 0.38724929 +vt 0.78492856 0.22071243 +vt 0.78501161 0.23343727 +vt 0.78807788 0.20263711 +vt 0.79286876 0.76916919 +vt 0.79380003 0.22600311 +vt 0.79394289 0.48079294 +vt 0.79395459 0.23105238 +vt 0.79629673 0.21206463 +vt 0.79678507 0.24676949 +vt 0.79768783 0.79696059 +vt 0.79786840 0.74052354 +vt 0.79795811 0.68457424 +vt 0.79796897 0.56610933 +vt 0.79850907 0.45218379 +vt 0.79876571 0.50974134 +vt 0.79928469 0.62537989 +vt 0.80024222 0.22162862 +vt 0.80181026 0.23935874 +vt 0.80453900 0.82571414 +vt 0.80687841 0.42052259 +vt 0.81030337 0.84405642 +vt 0.81059309 0.76578504 +vt 0.81203466 0.84861880 +vt 0.81206379 0.48441501 +vt 0.81462549 0.39781329 +vt 0.81631883 0.18138671 +vt 0.81631883 0.19894216 +vt 0.81631883 0.20850188 +vt 0.81631883 0.21898700 +vt 0.81631883 0.24270142 +vt 0.81631883 0.25128796 +vt 0.81631883 0.12631828 +vt 0.81631883 0.15984931 +vt 0.81631974 0.10337673 +vt 0.81632188 8.3422966e-2 +vt 0.81632477 5.6718511e-2 +vt 0.81657060 0.39234447 +vt 0.81866790 0.79184653 +vt 0.82094658 0.45777682 +vt 0.82988809 0.81936098 +vt 0.83082740 0.23935874 +vt 0.83208091 0.42969284 +vt 0.83239543 0.22162862 +vt 0.83340403 0.76090325 +vt 0.83473167 0.48941852 +vt 0.83585259 0.24676949 +vt 0.83634093 0.21206463 +vt 0.83820799 0.83777126 +vt 0.83868307 0.23105238 +vt 0.83883762 0.22600311 +vt 0.83907217 0.78490689 +vt 0.83936978 0.73527164 +vt 0.84032375 0.51545322 +vt 0.84045270 0.84231191 +vt 0.84096947 0.46510600 +vt 0.84221525 0.40908688 +vt 0.84379651 0.68474754 +vt 0.84413575 0.56640346 +vt 0.84455978 0.20263711 +vt 0.84473107 0.40411423 +vt 0.84578281 0.75709645 +vt 0.84720308 0.49355596 +vt 0.84762605 0.23343727 +vt 0.84770909 0.22071243 +vt 0.85014450 0.62563788 +vt 0.85220501 0.81030069 +vt 0.85445339 0.18263615 +vt 0.85474383 0.77699630 +vt 0.85514967 0.43923013 +vt 0.85582902 8.1976538e-2 +vt 0.85621523 5.4913160e-2 +vt 0.85668279 0.75534099 +vt 0.85671442 0.47363784 +vt 0.85819025 0.49559937 +vt 0.85822794 0.74232971 +vt 0.85860702 0.10253179 +vt 0.85949065 0.50875820 +vt 0.85998888 0.21499518 +vt 0.86011006 0.15889484 +vt 0.86057628 0.12406368 +vt 0.86068059 0.72745237 +vt 0.86166189 0.52377250 +vt 0.86268202 0.82809361 +vt 0.86301504 0.86159484 +vt 0.86510916 0.69996195 +vt 0.86530126 0.83244004 +vt 0.86570934 0.55145009 +vt 0.86698235 0.76755067 +vt 0.86708498 0.42092733 +vt 0.86773423 0.67845125 +vt 0.86787208 0.86112761 +vt 0.86809109 0.57301735 +vt 0.86888719 0.48356916 +vt 0.87012862 0.41644284 +vt 0.87031874 0.79918515 +vt 0.87118631 0.64616822 +vt 0.87131536 0.60532820 +vt 0.87217910 0.62575614 +vt 0.87322935 0.45155820 +vt 0.87509452 0.75303554 +vt 0.87667732 0.49844404 +vt 0.87722603 7.7931117e-2 +vt 0.87758337 5.0662878e-2 +vt 0.88055629 0.40776116 +vt 0.88079161 0.18781835 +vt 0.88080295 0.73433217 +vt 0.88137766 0.85006313 +vt 0.88197974 0.51734615 +vt 0.88206185 0.81527988 +vt 0.88219164 9.8826490e-2 +vt 0.88274636 0.78606739 +vt 0.88305683 0.87427342 +vt 0.88377696 0.40955241 +vt 0.88501143 0.84942298 +vt 0.88517383 0.81938273 +vt 0.88537514 0.46544008 +vt 0.88613579 0.43564436 +vt 0.88711165 0.70983050 +vt 0.88735162 0.12194339 +vt 0.88784315 0.54195219 +vt 0.88958832 0.43161355 +vt 0.89122663 0.68358105 +vt 0.89131164 0.15539058 +vt 0.89162483 0.56821315 +vt 0.89329179 0.88274093 +vt 0.89420456 0.76918833 +vt 0.89482239 0.65384275 +vt 0.89498664 0.59791822 +vt 0.89526204 0.40259466 +vt 0.89612846 0.62587592 +vt 0.89632031 0.48287559 +vt 0.89731131 0.86154805 +vt 0.89800461 0.80026804 +vt 0.89927536 0.41910249 +vt 0.89974962 0.83648133 +vt 0.90143581 0.45188253 +vt 0.90163557 0.39871101 +vt 0.90173793 0.80384253 +vt 0.90236327 0.42062796 +vt 0.90261588 0.74799318 +vt 0.90301535 0.83568839 +vt 0.90403433 0.50430115 +vt 0.90539174 0.44848622 +vt 0.90769030 0.39456961 +vt 0.90878427 0.86918887 +vt 0.90928584 0.78217032 +vt 0.91124742 0.72203685 +vt 0.91185161 0.47057099 +vt 0.91206867 0.53031535 +vt 0.91249313 0.43152850 +vt 0.91262211 0.82214478 +vt 0.91351091 0.78524009 +vt 0.91362442 0.84669399 +vt 0.91556604 0.43281001 +vt 0.91573923 0.82123277 +vt 0.91619522 0.46770409 +vt 0.91698547 0.69233692 +vt 0.91734816 0.55984743 +vt 0.91889253 0.38754873 +vt 0.91904925 0.40810095 +vt 0.92088645 0.75961562 +vt 0.92155439 0.65958908 +vt 0.92168320 0.59244870 +vt 0.92248912 0.49336962 +vt 0.92309477 0.44686667 +vt 0.92317246 0.80590435 +vt 0.92323264 0.62598422 +vt 0.92525121 0.85339007 +vt 0.92546100 0.76214863 +vt 0.92612764 0.44803771 +vt 0.92618673 0.80498253 +vt 0.92708343 0.49101114 +vt 0.92709712 0.83119709 +vt 0.92803587 0.42253013 +vt 0.92992062 0.46569495 +vt 0.92999926 0.78658278 +vt 0.93010884 0.73213383 +vt 0.93055660 0.40178784 +vt 0.93088181 0.52072007 +vt 0.93297353 0.46668837 +vt 0.93303435 0.78583533 +vt 0.93495255 0.73410661 +vt 0.93569556 0.51887576 +vt 0.93735552 0.48861871 +vt 0.93742755 0.76311815 +vt 0.93744769 0.70012643 +vt 0.93766508 0.55239038 +vt 0.93813195 0.43896665 +vt 0.93813860 0.81394791 +vt 0.93874626 0.83699880 +vt 0.93946000 0.41701443 +vt 0.94047785 0.48935673 +vt 0.94053357 0.76262150 +vt 0.94247489 0.70150620 +vt 0.94263616 0.55107296 +vt 0.94291010 0.73470904 +vt 0.94291060 0.51650622 +vt 0.94311934 0.66396455 +vt 0.94315460 0.58820982 +vt 0.94516285 0.62602381 +vt 0.94531555 0.45846911 +vt 0.94532982 0.79391294 +vt 0.94612313 0.73443383 +vt 0.94612342 0.51704994 +vt 0.94745599 0.54918035 +vt 0.94745599 0.70170586 +vt 0.94825459 0.66469119 +vt 0.94825814 0.58750028 +vt 0.94990301 0.43414798 +vt 0.94990987 0.81903766 +vt 0.95032903 0.62602350 +vt 0.95076498 0.54953796 +vt 0.95076498 0.70160980 +vt 0.95129646 0.58611221 +vt 0.95129646 0.66449599 +vt 0.95273066 0.62525219 +vt 0.95319660 0.48208977 +vt 0.95321000 0.76969831 +vt 0.95466356 0.58633996 +vt 0.95466356 0.66452558 +vt 0.95612166 0.62538000 +vt 0.95753064 0.79860876 +vt 0.95897643 0.74017591 +vt 0.95897674 0.51117268 +vt 0.95958278 0.45395070 +vt 0.96377214 0.54530024 +vt 0.96377214 0.70568365 +vt 0.96607576 0.47799539 +vt 0.96608969 0.77401927 +vt 0.96790133 0.58408372 +vt 0.96790133 0.66658980 +vt 0.96945074 0.62527858 +vt 0.97240072 0.74385389 +vt 0.97240105 0.50770340 +vt 0.97765965 0.54275096 +vt 0.97765965 0.70842565 +vt 0.98218926 0.66807919 +vt 0.98218926 0.58276953 +vt 0.98389446 0.62536264 +vn -0.77391663 0.63328749 0.0000000e+0 +vn -0.83427666 -0.55134604 3.5429699e-18 +vn -0.74514095 0.63293905 -0.21012645 +vn -0.74514265 0.63293895 0.21012070 +vn -0.96188565 0.27345198 7.0779893e-18 +vn -0.81666189 -0.53976398 -0.20425036 +vn -0.81666364 -0.53976389 0.20424358 +vn -0.92546293 0.26345943 -0.27222690 +vn -0.92546456 0.26345992 0.27222090 +vn -0.46436394 -0.88564429 -5.7553882e-4 +vn -0.66244761 0.63821238 -0.39223478 +vn -0.66231857 0.63818504 0.39249708 +vn -0.86063277 0.50922612 2.1151053e-17 +vn -0.45198635 -0.88645626 -9.9517005e-2 +vn -0.45228059 -0.88638123 9.8846270e-2 +vn -0.75314617 -0.52334555 -0.39859790 +vn -0.75096153 -0.53865513 0.38197831 +vn -0.82949197 0.24828166 -0.50029919 +vn -0.82932665 0.24815170 0.50063763 +vn -0.84705018 0.47602785 -0.23643916 +vn -0.84705084 0.47602820 0.23643610 +vn -0.43654630 -0.87824817 -0.19521137 +vn -0.43553299 -0.87825713 0.19742194 +vn -0.77342739 0.44628862 -0.45015169 +vn -0.77335922 0.44620022 0.45035639 +vn -0.30794043 -0.95140527 -8.3877561e-4 +vn -0.54505848 0.63606629 -0.54619678 +vn -0.59693313 0.63339784 0.49242057 +vn -0.72825251 0.68530889 1.4090579e-17 +vn -0.29745093 -0.95180287 -7.4794676e-2 +vn -0.29675281 -0.95210139 7.3761179e-2 +vn -0.62485907 -0.50198891 -0.59796177 +vn -0.59944846 -0.51195288 0.61527701 +vn -0.68021334 0.21224397 -0.70161407 +vn -0.70995893 0.20981102 0.67226308 +vn -0.70477758 0.66392434 -0.24998606 +vn -0.70477795 0.66392488 0.24998360 +vn -0.29126576 -0.94521674 -0.14740956 +vn -0.28673850 -0.94627002 0.14951282 +vn -0.35050311 -0.86187893 -0.36648639 +vn -0.34061082 -0.86264210 0.37394233 +vn -0.63881313 0.39364103 -0.66103292 +vn -0.66142517 0.40280169 0.63266701 +vn -0.64639092 0.61201911 -0.45564392 +vn -0.64635143 0.61198270 0.45574883 +vn -0.27719523 -0.91609692 -0.28970544 +vn -0.26399355 -0.91534972 0.30404324 +vn -0.58267057 0.55610512 -0.59265682 +vn -0.58705084 0.56030650 0.58431835 +vn -0.17395988 -0.98475255 -6.1376964e-4 +vn -0.40374457 0.63820361 -0.65550475 +vn -0.58009357 0.60217463 0.54852271 +vn -0.55418258 0.83239514 1.4124619e-17 +vn -0.15910505 -0.98399198 -8.0282991e-2 +vn -0.16095934 -0.98396462 7.6848667e-2 +vn -0.41155415 -0.49036251 -0.76822379 +vn -0.30726624 -0.40006023 0.86344616 +vn -0.49382073 0.24451392 -0.83447830 +vn -0.55511816 0.26675581 0.78783575 +vn -0.53349298 0.80023275 -0.27388462 +vn -0.53349277 0.80023338 0.27388320 +vn -0.14169397 -0.97606643 -0.16497617 +vn -0.14446632 -0.97468099 0.17066474 +vn -0.20620305 -0.89187140 -0.40254901 +vn -0.19111307 -0.87829938 0.43825335 +vn -0.46059449 0.44742111 -0.76659446 +vn -0.51623701 0.48604785 0.70516441 +vn -0.48229917 0.72361224 -0.49373356 +vn -0.48649190 0.72443587 0.48838336 +vn -0.12244079 -0.94716467 -0.29645801 +vn -0.13622441 -0.93827218 0.31794375 +vn -0.44668220 0.60725703 -0.65704940 +vn -0.47624349 0.63170823 0.61166727 +vn -7.6633187e-2 -0.99705926 -4.3409419e-4 +vn -0.39338597 0.62896952 -0.67055560 +vn -0.68137890 0.54114072 0.49283822 +vn -0.31313108 0.94970992 3.5570958e-17 +vn -7.1857633e-2 -0.99345859 -8.8749717e-2 +vn -7.4175996e-2 -0.99420814 7.7769566e-2 +vn -0.14330918 -0.35086841 -0.92539388 +vn 0.31776858 -0.48906992 0.81230151 +vn -0.30782606 0.28923973 -0.90641243 +vn -0.44430670 0.34552121 0.82656316 +vn -0.29899392 0.90294328 -0.30870061 +vn -0.29899375 0.90294351 0.30870011 +vn -8.1480785e-2 -0.98472472 -0.15387692 +vn -8.3106950e-2 -0.98084270 0.17618410 +vn -0.18701548 -0.92658847 -0.32628060 +vn -0.16682678 -0.91663509 0.36324776 +vn -0.29656295 0.48031105 -0.82544031 +vn -0.32196663 0.57995342 0.74832581 +vn -0.26471259 0.79450512 -0.54652435 +vn -0.27474578 0.80602629 0.52424839 +vn -0.14699618 -0.97001848 -0.19353623 +vn -0.10937211 -0.95550132 0.27396161 +vn -0.24158022 0.65427423 -0.71663395 +vn -0.28310259 0.72359081 0.62949922 +vn -5.8327418e-5 -0.99999981 -6.1304384e-4 +vn 7.5879607e-5 -0.99559009 -9.3810297e-2 +vn -2.1933508e-4 -0.99677062 8.0301170e-2 +vn 3.7119163e-4 -0.99688086 -7.8920340e-2 +vn -2.9441895e-4 -0.98660607 0.16312076 +vn 5.1052442e-3 -0.98627520 -0.16503080 +vn -3.2683779e-4 -0.97096295 0.23922970 +vn 8.8891365e-3 -0.94493812 -0.32712830 +vn -2.7846467e-4 -0.94665477 0.32224939 +vn 4.0499716e-6 -0.22968512 -0.97326499 +vn -2.7901234e-6 -0.65822393 0.75282220 +vn 5.0867395e-6 0.69033903 -0.72348602 +vn 1.7400657e-6 0.75854533 0.65162028 +vn 3.4902690e-6 0.32655009 -0.94517990 +vn 1.7236861e-6 0.55335684 0.83294430 +vn -4.7936259e-4 0.50985540 -0.86025998 +vn 5.2839354e-6 0.67357361 0.73912015 +vn -2.7075006e-4 0.67295367 -0.73968459 +vn 4.2804719e-6 0.76689196 0.64177623 +vn 4.6288827e-7 0.82362288 -0.56713786 +vn 1.9401648e-7 0.84562688 0.53377447 +vn 3.3219525e-10 0.94648265 -0.32275469 +vn 3.3208447e-10 0.94648269 0.32275457 +vn -7.1403971e-18 1.00000000 4.2842383e-17 +vn 0.14604614 -0.96970976 -0.19578946 +vn 0.10961543 -0.95515100 0.27508368 +vn 0.24224100 0.65539809 -0.71538287 +vn 0.28316641 0.72357430 0.62948949 +vn 8.1596277e-2 -0.98443459 -0.15566179 +vn 8.3256657e-2 -0.98068547 0.17698683 +vn 0.18100744 -0.92741604 -0.32731604 +vn 0.16715165 -0.91650084 0.36343711 +vn 0.29582159 0.47997063 -0.82590422 +vn 0.32208258 0.58002429 0.74822098 +vn 0.26471932 0.79444327 -0.54661098 +vn 0.27475145 0.80596069 0.52434626 +vn 7.1850014e-2 -0.99344064 -8.8956578e-2 +vn 7.4105101e-2 -0.99423432 7.7501937e-2 +vn 0.14333227 -0.35084486 -0.92539923 +vn -0.31783668 -0.48909447 0.81226009 +vn 0.30714077 0.28676351 -0.90743112 +vn 0.44438848 0.34553014 0.82651545 +vn 0.29899392 0.90294327 -0.30870064 +vn 0.29899375 0.90294350 0.30870014 +vn 7.6604577e-2 -0.99706142 -5.1626076e-4 +vn 0.39340731 0.62894554 -0.67056558 +vn 0.68137845 0.54107351 0.49291263 +vn 0.31313108 0.94970992 4.2685150e-17 +vn 0.12089164 -0.94705553 -0.29744082 +vn 0.13637258 -0.93799203 0.31870594 +vn 0.44752915 0.60783015 -0.65594220 +vn 0.47632234 0.63154591 0.61177348 +vn 0.14140097 -0.97600222 -0.16560625 +vn 0.14478589 -0.97455438 0.17111638 +vn 0.20054194 -0.89311897 -0.40264306 +vn 0.19097091 -0.87821291 0.43848853 +vn 0.45995777 0.45453606 -0.76278163 +vn 0.51640538 0.48622829 0.70491668 +vn 0.48231899 0.72346351 -0.49393212 +vn 0.48651108 0.72428627 0.48858609 +vn 0.15904959 -0.98399267 -8.0384470e-2 +vn 0.16114851 -0.98394671 7.6681305e-2 +vn 0.41161808 -0.49030780 -0.76822445 +vn 0.30733185 -0.40003046 0.86343660 +vn 0.48893709 0.24450937 -0.83735040 +vn 0.55524369 0.26696351 0.78767692 +vn 0.53349299 0.80023272 -0.27388469 +vn 0.53349278 0.80023335 0.27388328 +vn 0.17401407 -0.98474294 -6.7318275e-4 +vn 0.40031314 0.63301591 -0.66260112 +vn 0.58016371 0.60210800 0.54852167 +vn 0.55418258 0.83239514 2.1186928e-17 +vn 0.27733713 -0.91602766 -0.28978860 +vn 0.26402144 -0.91526978 0.30425962 +vn 0.58248521 0.55589280 -0.59303809 +vn 0.58687016 0.56009676 0.58470081 +vn 0.29123128 -0.94515823 -0.14785219 +vn 0.28678135 -0.94620457 0.14984450 +vn 0.35295969 -0.86362615 -0.35995739 +vn 0.34010638 -0.86286334 0.37389103 +vn 0.64748521 0.39740612 -0.65025478 +vn 0.66517987 0.40162237 0.62947217 +vn 0.64626591 0.61190849 -0.45596970 +vn 0.64622736 0.61187268 0.45607240 +vn 0.29746917 -0.95179547 -7.4816324e-2 +vn 0.29683164 -0.95208381 7.3670831e-2 +vn 0.62545723 -0.50192393 -0.59739067 +vn 0.61687762 -0.49739217 0.60996969 +vn 0.70142318 0.20909869 -0.68138335 +vn 0.71057988 0.20976831 0.67162005 +vn 0.70477756 0.66392432 -0.24998618 +vn 0.70477793 0.66392485 0.24998372 +vn 0.30797964 -0.95139255 -8.7198913e-4 +vn 0.55531374 0.63303223 -0.53934854 +vn 0.59738677 0.63342912 0.49182984 +vn 0.72825251 0.68530889 1.4090579e-17 +vn 0.43632311 -0.87822623 -0.19580817 +vn 0.43509880 -0.87844122 0.19756029 +vn 0.77322093 0.44600054 -0.45079143 +vn 0.77334560 0.43873917 0.45765109 +vn 0.45200190 -0.88644651 -9.9533273e-2 +vn 0.45234348 -0.88636507 9.8703331e-2 +vn 0.75271385 -0.52323092 -0.39956384 +vn 0.75256550 -0.52320046 0.39988305 +vn 0.82900110 0.24786201 -0.50131986 +vn 0.82846722 0.23761203 0.50713172 +vn 0.84705015 0.47602783 -0.23643932 +vn 0.84705081 0.47602818 0.23643626 +vn 0.46439720 -0.88562682 -6.0897023e-4 +vn 0.66207855 0.63812013 -0.39300725 +vn 0.66094019 0.64124385 0.38982611 +vn 0.86063277 0.50922612 2.1151053e-17 +vn 0.81666179 -0.53976399 -0.20425072 +vn 0.81666355 -0.53976390 0.20424394 +vn 0.92546285 0.26345940 -0.27222722 +vn 0.92546447 0.26345989 0.27222122 +vn 0.83427666 -0.55134604 0.0000000e+0 +vn 0.74514086 0.63293905 -0.21012676 +vn 0.74514256 0.63293896 0.21012101 +vn 0.96188565 0.27345198 7.0779893e-18 +vn 0.77391663 0.63328749 0.0000000e+0 +vn 0.83388878 0.55193251 0.0000000e+0 +vn 0.79966125 0.56250755 0.21006461 +vn 0.79965946 0.56250763 -0.21007120 +vn 0.70093324 0.59652742 0.39095732 +vn 0.70107571 0.59655708 -0.39065650 +vn 0.59914980 0.60246961 0.52730436 +vn 0.56316916 0.62444741 -0.54120784 +vn 0.55907496 0.55201669 0.61863783 +vn 0.39940120 0.58081099 -0.70932170 +vn 0.63064427 0.45143407 0.63126468 +vn 0.38677904 0.54766846 -0.74193075 +vn 1.2764358e-7 0.52620327 0.85035882 +vn -7.0485601e-7 0.59999015 -0.80000739 +vn -0.63063455 0.45149921 0.63122779 +vn -0.38676115 0.54768999 -0.74192418 +vn -0.55899845 0.55209584 0.61863634 +vn -0.39931130 0.58084898 -0.70934121 +vn -0.58005693 0.61662324 0.53226847 +vn -0.56276244 0.62430869 -0.54179065 +vn -0.69805384 0.61244546 0.37098706 +vn -0.70148750 0.59667151 -0.38974145 +vn -0.79966135 0.56250755 0.21006425 +vn -0.79965956 0.56250763 -0.21007085 +vn -0.83388878 0.55193251 -9.2135255e-18 +vn -0.47131779 0.88196346 -1.0546728e-17 +vn -0.76555435 0.63184700 -0.12122667 +vn -0.76555435 0.63184700 0.12122667 +vn -0.82791376 -0.54790696 -0.11981972 +vn -0.82791376 -0.54790696 0.11981972 +vn -0.67276927 -0.73985231 -2.5330856e-4 +vn -0.44788492 0.88573747 -0.12193535 +vn -0.71737942 0.63446934 -0.28777670 +vn -0.44788593 0.88573745 0.12193176 +vn -0.71727799 0.63447112 0.28802548 +vn -0.66404662 -0.73345273 -0.14522115 +vn -0.80075831 -0.53198828 -0.27527188 +vn -0.66431653 -0.73324571 0.14503198 +vn -0.80027494 -0.53244491 0.27579419 +vn -0.45918168 -0.88653326 -5.6665459e-2 +vn -0.45938330 -0.88649622 5.5600636e-2 +vn -0.37973933 0.89905815 -0.21792768 +vn -0.59555556 0.63404148 -0.49325954 +vn -0.37967735 0.89904258 0.21809986 +vn -0.59648463 0.63732271 0.48787893 +vn -0.44246517 -0.88442275 -0.14839467 +vn -0.44238602 -0.88439176 0.14881471 +vn -0.62211636 -0.72788762 -0.28835889 +vn -0.70674058 -0.50787621 -0.49252361 +vn -0.62167232 -0.72718924 0.29106586 +vn -0.69081791 -0.53845369 0.48253316 +vn -0.42166077 -0.86899909 -0.25892620 +vn -0.41831801 -0.86892596 0.26453302 +vn -0.29808682 0.90961054 -0.28940096 +vn -0.47364934 0.63952797 -0.60552479 +vn -0.36375236 0.89798812 0.24759152 +vn -0.61685513 0.61327954 0.49333351 +vn -0.49330107 -0.70802700 -0.50532349 +vn -0.49040512 -0.50078576 -0.71324360 +vn -0.48700027 -0.72038427 0.49383929 +vn -0.43664224 -0.46121429 0.77241500 +vn -0.26477501 -0.86422018 -0.42780566 +vn -0.24154520 -0.86518193 0.43944981 +vn -0.24197828 0.89129286 -0.38346257 +vn -0.39027440 0.63235434 -0.66918897 +vn -0.49031825 0.83923411 0.23510448 +vn -0.59997598 0.57743673 0.55371079 +vn -0.34703901 -0.73080819 -0.58777829 +vn -0.28849988 -0.44763163 -0.84640046 +vn -0.29893170 -0.72927139 0.61546981 +vn -5.1468539e-2 -0.43008138 0.90132180 +vn -0.17229929 -0.92036747 -0.35105082 +vn -0.18067160 -0.89561529 0.40648619 +vn -0.38315645 0.85798194 -0.34213759 +vn -0.25709102 0.66238847 -0.70366592 +vn -0.73276399 0.66092564 0.16196983 +vn -0.44890563 0.67486403 0.58569810 +vn -0.22026653 -0.75927291 -0.61236207 +vn -4.1123976e-2 -0.23077415 -0.97213791 +vn -0.25325495 -0.82931070 0.49810209 +vn 0.27419998 -0.58173235 0.76576879 +vn -0.13617509 -0.93579314 -0.32518848 +vn -0.10979064 -0.93707481 0.33141639 +vn -1.4828342e-3 -0.79845788 -0.60204884 +vn 0.13867399 -0.93506659 -0.32622079 +vn -1.1855262e-4 -0.92740894 0.37404897 +vn 0.10994103 -0.93703384 0.33148235 +vn 3.1960077e-6 -0.13916925 -0.99026861 +vn 4.1135909e-2 -0.23076888 -0.97213865 +vn -1.9430158e-7 -8.6627604e-2 0.99624076 +vn -0.27424636 -0.58175810 0.76573262 +vn 0.25710652 0.66236930 -0.70367830 +vn 0.44890134 0.67481953 0.58575267 +vn 0.22936836 -0.77685769 -0.58641477 +vn 0.17093156 -0.92092409 -0.35025880 +vn 0.25342700 -0.82926072 0.49809780 +vn 0.18052586 -0.89548483 0.40683822 +vn 0.20481379 -8.0810799e-2 -0.97545934 +vn 0.28853727 -0.44758492 -0.84641242 +vn 0.20890018 -5.8095054e-2 0.97620985 +vn 5.1475692e-2 -0.43008291 0.90132067 +vn 0.38647156 0.63115378 -0.67252110 +vn 0.60001674 0.57736516 0.55374126 +vn 0.33977569 -0.72933930 -0.59381535 +vn 0.26340134 -0.86771835 -0.42152651 +vn 0.29883319 -0.72903120 0.61580211 +vn 0.24117179 -0.86522196 0.43957608 +vn 0.47093599 -2.9417104e-2 -0.88167677 +vn 0.49050084 -0.50072456 -0.71322075 +vn 0.45749179 -3.0994513e-2 0.88867351 +vn 0.43652177 -0.46056830 0.77286842 +vn 0.48491504 0.63327889 -0.60317099 +vn 0.61728069 0.61324477 0.49284420 +vn 0.49732744 -0.71834481 -0.48646290 +vn 0.42148266 -0.86890644 -0.25952644 +vn 0.48544601 -0.72129045 0.49404682 +vn 0.41764770 -0.86916033 0.26482205 +vn 0.72278852 -8.1252752e-3 -0.69102151 +vn 0.70728822 -0.50773196 -0.49188579 +vn 0.72297896 -1.0451657e-2 0.69079098 +vn 0.70741930 -0.50769310 0.49173739 +vn 0.59565460 0.63399515 -0.49319950 +vn 0.61031279 0.64057673 0.46602549 +vn 0.44247556 -0.88441555 -0.14840659 +vn 0.62206572 -0.72756469 -0.28928163 +vn 0.44240490 -0.88444314 0.14845282 +vn 0.62150991 -0.72754528 0.29052244 +vn 0.45920471 -0.88651993 -5.6687173e-2 +vn 0.66405686 -0.73344157 -0.14523070 +vn 0.45943264 -0.88647473 5.5535657e-2 +vn 0.66450027 -0.73310656 0.14489366 +vn 0.87825718 -2.9565278e-2 -0.47727373 +vn 0.80037622 -0.53201997 -0.27631986 +vn 0.87805922 -2.9562727e-2 0.47763799 +vn 0.80026418 -0.53203069 0.27662355 +vn 0.67280588 -0.73981901 -2.7703905e-4 +vn 0.71703774 0.63447424 -0.28861622 +vn 0.70574182 0.63762014 0.30881877 +vn 0.82791376 -0.54790696 -0.11981972 +vn 0.96714514 -5.8765614e-2 -0.24733962 +vn 0.82791376 -0.54790696 0.11981972 +vn 0.96714720 -5.8765610e-2 0.24733154 +vn 0.99742577 -7.1706524e-2 -3.6623320e-18 +vn 0.76555435 0.63184700 -0.12122667 +vn 0.76555435 0.63184700 0.12122667 +vn 0.47131779 0.88196346 0.0000000e+0 +vn 0.44788588 0.88573745 0.12193195 +vn 0.44788486 0.88573747 -0.12193554 +vn 0.37451565 0.90179046 0.21566639 +vn 0.37957866 0.89899948 -0.21844904 +vn 0.36401089 0.89798318 0.24722919 +vn 0.29823568 0.90967211 -0.28905384 +vn 0.49041449 0.83915909 0.23517156 +vn 0.24204882 0.89127124 -0.38346832 +vn 0.73279359 0.66085823 0.16211091 +vn 0.38317534 0.85795751 -0.34217768 +vn 1.2474645e-6 0.86838113 0.49589738 +vn 3.3178197e-6 0.92356832 -0.38343390 +vn -0.20889301 -5.8077975e-2 0.97621240 +vn -0.20478580 -8.0822991e-2 -0.97546421 +vn -0.45742344 -3.0986204e-2 0.88870898 +vn -0.47086509 -2.9422853e-2 -0.88171445 +vn -0.69941539 -8.0914243e-3 0.71466960 +vn -0.72213908 -8.1254232e-3 -0.69170017 +vn -0.89290143 -2.6412440e-2 0.44947682 +vn -0.87885299 -2.9572302e-2 -0.47617529 +vn -0.96714731 -5.8765609e-2 0.24733111 +vn -0.96714525 -5.8765614e-2 -0.24733918 +vn -0.99742577 -7.1706524e-2 3.6623320e-18 +vn -0.57767515 0.57664694 0.57772808 +vn -0.57430863 0.50801441 0.64194311 +vn -0.40722427 0.49349591 0.76852468 +vn 0.40722879 0.49346389 0.76854284 +vn 0.57434859 0.50793869 0.64196728 +vn 0.57777197 0.57656295 0.57771508 +vn 0.46499021 0.60764599 -0.64385593 +vn 0.38065412 0.55765772 -0.73764511 +vn 0.25938381 0.57687782 -0.77455278 +vn -0.25937739 0.57689277 -0.77454380 +vn -0.38059475 0.55767902 -0.73765964 +vn -0.46487644 0.60760482 -0.64397692 +vn 0.63566710 0.61332766 -0.46878195 +vn 0.76657944 0.57833022 -0.27908802 +vn 0.82291551 0.55437223 -0.12442462 +vn 0.82291551 0.55437223 0.12442462 +vn 0.76646821 0.57833937 0.27937441 +vn 0.64466948 0.60601811 0.46598638 +vn -0.63528634 0.61333568 -0.46928734 +vn -0.76695767 0.57830501 -0.27809936 +vn -0.82291551 0.55437223 -0.12442462 +vn -0.82291551 0.55437223 0.12442462 +vn -0.76684555 0.57831450 0.27838866 +vn -0.62386245 0.63695534 0.45286151 +vn -0.56900582 -1.8450180e-2 0.82212649 +vn -0.36907843 -0.71814911 0.58995167 +vn -0.34214587 -4.4139918e-2 0.93860954 +vn -0.27596586 -0.77031667 0.57485222 +vn -8.8408273e-2 -7.6400091e-2 0.99315004 +vn -0.16948740 -0.89561270 0.41128083 +vn 8.8406856e-2 -7.6408909e-2 0.99314949 +vn 0.16962220 -0.89553025 0.41140476 +vn 0.34218301 -4.4151547e-2 0.93859545 +vn 0.27584955 -0.77024915 0.57499850 +vn 0.56909233 -1.8456598e-2 0.82206646 +vn 0.36780819 -0.71811604 0.59078464 +vn 0.26177549 0.90326394 -0.33998214 +vn 0.38866246 -0.71443125 -0.58183287 +vn 0.29277511 0.87860168 -0.37728214 +vn 0.27081247 -0.75910632 -0.59196132 +vn 0.27560956 0.89285310 -0.35616388 +vn 0.17730863 -0.80540662 -0.56558097 +vn -0.27559418 0.89287234 -0.35612755 +vn -0.17124067 -0.76580191 -0.61985810 +vn -0.29273043 0.87861760 -0.37727975 +vn -0.27129656 -0.75828796 -0.59278795 +vn -0.26162203 0.90323709 -0.34017155 +vn -0.39386211 -0.71215470 -0.58112676 +vn 0.33199939 0.90572385 -0.26351606 +vn 0.42216104 0.89213660 -0.16084881 +vn 0.98690651 -6.8210334e-2 -0.14616052 +vn 0.98690651 -6.8210334e-2 0.14616052 +vn 0.94189702 -4.5371549e-2 0.33282341 +vn 0.81538233 -1.4599218e-2 0.57873873 +vn 0.58147204 -0.72097340 -0.37694511 +vn 0.64730823 -0.73209401 -0.21220371 +vn 0.66914898 -0.73843459 -8.3390606e-2 +vn 0.66941035 -0.73825528 8.2879041e-2 +vn 0.64764139 -0.73174685 0.21238448 +vn 0.57816667 -0.72209605 0.37986918 +vn -0.57975144 -0.71551984 -0.38976868 +vn -0.64724217 -0.73224296 -0.21189106 +vn -0.66913000 -0.73845336 -8.3376788e-2 +vn -0.66933282 -0.73831991 8.2929475e-2 +vn -0.64721800 -0.73187565 0.21322967 +vn -0.57912091 -0.72114599 0.38022025 +vn -0.33189801 0.90572275 -0.26364753 +vn -0.42237559 0.89212861 -0.16032902 +vn -0.46436880 0.88272753 -7.1789421e-2 +vn -0.98690651 -6.8210334e-2 0.14616052 +vn -0.94233484 -4.5368022e-2 0.33158225 +vn -0.81375571 -9.0037635e-3 0.58113731 +vn -0.44818364 0.86718929 0.21705798 +vn -0.59650517 0.77419310 0.21167576 +vn -0.51404727 0.78265578 0.35100616 +vn 0.51405184 0.78261230 0.35109641 +vn 0.59657063 0.77411396 0.21178068 +vn 0.44829980 0.86714901 0.21697899 +vn 0.57349083 -1.4243522e-2 -0.81908815 +vn 0.36055409 -4.7471556e-2 -0.93152949 +vn 8.1692378e-2 -0.12214984 -0.98914396 +vn -8.1679221e-2 -0.12215911 -0.98914390 +vn -0.36050630 -4.7484621e-2 -0.93154732 +vn -0.57340371 -1.4243777e-2 -0.81914913 +vn 0.81525034 -1.4601433e-2 -0.57892460 +vn 0.94202438 -4.5370614e-2 -0.33246290 +vn 0.46436880 0.88272753 -7.1789421e-2 +vn 0.46436880 0.88272753 7.1789421e-2 +vn 0.41810587 0.89385420 0.16190167 +vn 0.34173690 0.90500174 0.25335298 +vn -0.81469713 -1.4605616e-2 -0.57970273 +vn -0.94246294 -4.5367059e-2 -0.33121812 +vn -0.98690651 -6.8210334e-2 -0.14616052 +vn -0.46436880 0.88272753 7.1789421e-2 +vn -0.42231038 0.89213203 0.16048171 +vn -0.34233643 0.90363510 0.25738953 +vn -0.65110367 0.23155865 0.72280330 +vn -0.17491016 -0.93098566 0.32042493 +vn -0.46667384 0.30036831 0.83186201 +vn -0.12848357 -0.94455651 0.30216713 +vn -0.28511714 0.46888296 0.83597667 +vn -7.0722641e-2 -0.96636064 0.24727599 +vn 0.28512037 0.46886775 0.83598410 +vn 7.0482720e-2 -0.96630087 0.24757788 +vn 0.46681311 0.30048502 0.83174171 +vn 0.12881513 -0.94408102 0.30350896 +vn 0.65178778 0.23166069 0.72215374 +vn 0.17492144 -0.93085436 0.32080003 +vn 0.62042502 0.22399680 -0.75159712 +vn 0.19834502 -0.93278243 -0.30095878 +vn 0.41372066 0.26029326 -0.87240050 +vn 0.11083289 -0.96005399 -0.25692879 +vn 0.16678178 0.31014076 -0.93594687 +vn 0.10433745 -0.98032017 -0.16758897 +vn -0.16723774 0.31064851 -0.93569709 +vn -0.10103848 -0.98093395 -0.16601145 +vn -0.41868875 0.26338615 -0.86909578 +vn -0.11163333 -0.96033390 -0.25553239 +vn -0.59741773 0.22541495 -0.76959740 +vn -0.19823074 -0.93284454 -0.30084156 +vn 0.74743527 0.22299128 -0.62579183 +vn 0.88885377 0.25742647 -0.37903903 +vn 0.95074985 0.26803381 -0.15566826 +vn 0.95074985 0.26803381 0.15566826 +vn 0.87761535 0.25057099 0.40866304 +vn 0.76417371 0.22139568 0.60582381 +vn 0.29142076 -0.93621546 -0.19640406 +vn 0.29302582 -0.94945698 -0.11254917 +vn 0.30177358 -0.95245261 -4.2032515e-2 +vn 0.30154947 -0.95259059 4.0485557e-2 +vn 0.29087452 -0.95007266 0.11293338 +vn 0.28372716 -0.93721680 0.20278949 +vn -0.29138042 -0.93633037 -0.19591553 +vn -0.29301435 -0.94946225 -0.11253455 +vn -0.30174397 -0.95246317 -4.2005751e-2 +vn -0.30149187 -0.95260630 4.0544797e-2 +vn -0.29078719 -0.95008479 0.11305616 +vn -0.28368573 -0.93734277 0.20226452 +vn -0.74740518 0.22317124 -0.62576361 +vn -0.88921692 0.25765175 -0.37803287 +vn -0.95074985 0.26803381 -0.15566826 +vn -0.95074985 0.26803381 0.15566826 +vn -0.88910986 0.25758439 0.37833046 +vn -0.74737800 0.22310651 0.62581915 +vn -0.79641653 -0.27568153 0.53825682 +vn -0.89925336 -0.31657133 0.30187081 +vn -0.92895184 -0.34672323 0.12973623 +vn -0.92884253 -0.34702136 -0.12972174 +vn -0.89997333 -0.31620333 -0.30010575 +vn -0.79728780 -0.27215180 -0.53876298 +vn 0.79825162 -0.27081959 0.53800659 +vn 0.89968140 -0.31553952 0.30167564 +vn 0.92894504 -0.34674179 0.12973529 +vn 0.92883573 -0.34703992 -0.12972079 +vn 0.89957085 -0.31624446 -0.30126688 +vn 0.79783040 -0.27210517 -0.53798274 +vn -0.53564245 -0.26989184 -0.80015346 +vn -0.32635191 -0.23167234 -0.91641822 +vn -0.12502137 -0.18615513 -0.97453370 +vn 0.12441521 -0.18354458 -0.97510627 +vn 0.32639437 -0.23165619 -0.91640718 +vn 0.53572894 -0.26987815 -0.80010018 +vn 0.49225398 -0.21123385 0.84443252 +vn 0.18011317 7.8458466e-2 0.98051186 +vn -9.3636744e-2 0.54845433 0.83092118 +vn 9.3624225e-2 0.54844114 0.83093129 +vn -0.18008322 7.8460310e-2 0.98051722 +vn -0.49384630 -0.21253740 0.84317476 +vn 0.93604468 -0.35188117 -3.9384017e-7 +vn 0.91630858 -0.33329954 0.22201352 +vn 0.91612923 -0.33381460 -0.22197985 +vn 0.85045475 -0.29439929 0.43595387 +vn 0.85034268 -0.29544665 -0.43546367 +vn 0.69022762 -0.25432619 0.67742455 +vn 0.69812652 -0.26380958 -0.66560038 +vn 0.36925480 -0.19084832 0.90952065 +vn 0.43830194 -0.26949395 -0.85747561 +vn -7.1279787e-2 0.37705509 0.92344391 +vn 0.23233615 -0.20501926 -0.95078232 +vn -1.6957753e-6 0.57546199 0.81782853 +vn -3.8698031e-3 -0.27912601 -0.96024668 +vn 7.1265696e-2 0.37704664 0.92344844 +vn -0.22971216 -0.20734113 -0.95091639 +vn -0.36918714 -0.19085473 0.90954677 +vn -0.43823622 -0.26951153 -0.85750367 +vn -0.69025946 -0.25800391 0.67599990 +vn -0.69747513 -0.26380827 -0.66628345 +vn -0.84929035 -0.29778954 0.43592120 +vn -0.85086439 -0.29549019 -0.43441379 +vn -0.91631500 -0.33328115 0.22201461 +vn -0.91613566 -0.33379621 -0.22198095 +vn -0.93605171 -0.35186246 -3.9410599e-7 +vn -0.99232313 -0.12367217 -3.9811138e-7 +vn -0.96749558 -0.10769376 -0.22881076 +vn -0.96755444 -0.10716158 0.22881170 +vn -0.89320710 -7.0304543e-2 -0.44411524 +vn -0.89170998 -7.2294767e-2 0.44679612 +vn -0.71673568 -0.10541193 -0.68933177 +vn -0.72041506 -4.1780221e-2 0.69228358 +vn -0.44636713 -6.9895848e-2 -0.89211600 +vn -0.40294105 -1.8096509e-2 0.91504701 +vn -0.24505308 -0.15270276 -0.95740841 +vn -0.12899443 9.5733469e-2 0.98701345 +vn -0.52805596 -3.1505637e-2 0.84862494 +vn -0.28201636 1.7498258e-2 0.95925001 +vn -3.0868449e-2 0.18351297 0.98253251 +vn 3.0866103e-2 0.18352484 0.98253036 +vn 0.28206049 1.7501629e-2 0.95923697 +vn 0.52523735 -3.0411059e-2 0.85041219 +vn 0.54849028 -5.0806822e-2 -0.83461194 +vn 0.35170581 -9.0614372e-2 -0.93171458 +vn 8.9973883e-2 -0.18446486 -0.97871212 +vn -0.11923482 -0.29380513 -0.94839950 +vn -0.35165972 -9.0625728e-2 -0.93173087 +vn -0.55513464 -7.8965296e-2 -0.82800363 +vn 0.83337279 -5.0759476e-2 -0.55037557 +vn 0.94675067 -9.0548885e-2 -0.30897261 +vn 0.98371516 -0.11955508 -0.13420534 +vn 0.98375217 -0.11924538 0.13420957 +vn 0.94670127 -8.9820335e-2 0.30933642 +vn 0.83355083 -4.9472147e-2 0.55022316 +vn -0.82350776 -8.4627399e-2 -0.56095736 +vn -0.94715181 -9.0513300e-2 -0.30775117 +vn -0.98371795 -0.11953171 -0.13420571 +vn -0.98375495 -0.11922201 0.13420994 +vn -0.94625377 -9.0765520e-2 0.31042782 +vn -0.83259631 -5.3708949e-2 0.55127010 +vn 0.99232019 -0.12369576 -3.9786702e-7 +vn 0.96755190 -0.10718465 0.22881165 +vn 0.96749302 -0.10771683 -0.22881070 +vn 0.89254990 -6.9262742e-2 0.44559773 +vn 0.89266061 -7.0318395e-2 -0.44521046 +vn 0.71894448 -3.8521429e-2 0.69399923 +vn 0.72352395 -4.2846048e-2 -0.68896830 +vn 0.40301307 -1.8104588e-2 0.91501513 +vn 0.44643785 -6.9896816e-2 -0.89208054 +vn 0.12900640 9.5746690e-2 0.98701060 +vn 0.24869164 -9.4186113e-2 -0.96399245 +vn -7.5345449e-7 0.22123845 0.97521974 +vn -3.4246825e-2 -0.32640713 -0.94460867 +vn -0.75644666 -0.42584864 0.49642864 +vn -0.85343831 -0.44110847 0.27760829 +vn -0.88276235 -0.45522410 0.11619665 +vn -0.88271959 -0.45529195 -0.11625559 +vn -0.85431822 -0.44090602 -0.27521312 +vn -0.73446557 -0.44761532 -0.51009887 +vn 0.75714711 -0.42518453 0.49592980 +vn 0.85414296 -0.44050451 0.27639752 +vn 0.88279548 -0.45516468 0.11617768 +vn 0.88272364 -0.45528309 -0.11625958 +vn 0.85412106 -0.44073510 -0.27609743 +vn 0.75819058 -0.42396032 -0.49538339 +vn -0.50790682 -0.43894231 -0.74118844 +vn -0.34126939 -0.42612607 -0.83782562 +vn -0.15606468 -0.52130014 -0.83898151 +vn 0.14202677 -0.48296298 -0.86404580 +vn 0.34131787 -0.42608034 -0.83782913 +vn 0.50215730 -0.40946688 -0.76169214 +vn 0.48462050 -0.40764405 0.77393107 +vn 0.34185040 -0.43342072 0.83383738 +vn 0.17868831 -0.53666137 0.82466057 +vn -0.17868248 -0.53676081 0.82459711 +vn -0.34184909 -0.43364655 0.83372050 +vn -0.48702711 -0.40831794 0.77206286 +vn -0.27862846 -0.47599941 0.83414072 +vn -0.24518015 -0.47272247 -0.84641607 +vn -0.39620918 -0.40644915 0.82329665 +vn -0.43417778 -0.41505612 -0.79951114 +vn -0.65078771 -0.42295263 0.63054456 +vn -0.62944887 -0.46514977 -0.62243860 +vn -0.80929328 -0.43588800 0.39375887 +vn -0.81085469 -0.43540882 -0.39106756 +vn -0.87279549 -0.44563753 0.19908599 +vn -0.87277383 -0.44568584 -0.19907277 +vn -0.88855741 -0.45876544 -3.9538694e-5 +vn 0.88856944 -0.45874214 -4.7572506e-5 +vn 0.87289288 -0.44547326 0.19902660 +vn 0.87277436 -0.44568364 -0.19907539 +vn 0.81027673 -0.43498685 0.39273153 +vn 0.81057718 -0.43495193 -0.39214978 +vn 0.64930934 -0.42267111 0.63225510 +vn 0.65539765 -0.41989105 -0.62781003 +vn 0.39623597 -0.40605927 0.82347613 +vn 0.43063261 -0.41038558 -0.80382786 +vn 0.27864195 -0.47586306 0.83421401 +vn 0.26837702 -0.44343440 -0.85518402 +vn -2.0652369e-5 -0.57187262 0.82034243 +vn -3.7637649e-2 -0.51318649 -0.85745147 +vn -7.9212221e-7 0.33052967 0.94379560 +vn -0.12333094 0.14162587 0.98220751 +vn 5.5955227e-2 -0.18885523 0.98040946 +vn -3.4108240e-2 0.34424027 0.93826183 +vn 3.4101690e-2 0.34423031 0.93826573 +vn -5.5954929e-2 -0.18887025 0.98040659 +vn 0.12329942 0.14161950 0.98221239 +vn -0.30089808 -0.30607822 0.90320345 +vn -2.4230663e-6 -0.51627693 0.85642170 +vn -4.4502314e-2 -0.40299270 0.91412058 +vn -0.21970324 -0.44574849 0.86777807 +vn 0.21966334 -0.44572302 0.86780125 +vn 4.4481847e-2 -0.40298910 0.91412316 +vn 0.30082671 -0.30606066 0.90323317 +vn -0.31292271 -0.65230945 0.69034177 +vn 3.3901048e-6 -0.72900092 0.68451272 +vn 0.31293007 -0.65227041 0.69037531 +vn 0.60424957 -0.32530242 0.72736565 +vn 0.66728475 0.12646322 0.73398782 +vn 0.39861528 0.49757168 0.77040787 +vn 2.9010668e-6 0.65224099 0.75801167 +vn -0.39863459 0.49762442 0.77036381 +vn -0.66736378 0.12649680 0.73391018 +vn -0.60430093 -0.32534503 0.72730392 +vn -0.34348252 -0.90866423 -0.23737960 +vn 4.1307037e-6 -0.97388648 -0.22703551 +vn 0.34351618 -0.90867379 -0.23729427 +vn 0.84956819 -0.46637940 -0.24642269 +vn 0.95164314 0.26220380 -0.16007657 +vn 0.57381476 0.81447135 -8.5866419e-2 +vn 4.1578083e-6 0.99918944 -4.0254996e-2 +vn -0.57378067 0.81447944 -8.6017389e-2 +vn -0.95159620 0.26222164 -0.16032620 +vn -0.84950745 -0.46637463 -0.24664105 +vn -0.32785955 -0.87438100 -0.35772332 +vn 3.0763436e-6 -0.93521667 -0.35407595 +vn 0.32788042 -0.87438842 -0.35768608 +vn 0.79650661 -0.44053125 -0.41413698 +vn 0.89040380 0.26044609 -0.37329467 +vn 0.53561300 0.76885806 -0.34925061 +vn 3.5347613e-6 0.95092796 -0.30941238 +vn -0.53557980 0.76884956 -0.34932025 +vn -0.89035934 0.26045072 -0.37339747 +vn -0.79646508 -0.44052768 -0.41422063 +vn -0.38113413 -0.87977738 -0.28412769 +vn 9.7711916e-7 -0.94985135 -0.31270178 +vn 0.38113742 -0.87977602 -0.28412748 +vn 0.83685661 -0.44190805 -0.32309176 +vn 0.88761078 0.24220790 -0.39176836 +vn 0.51049338 0.68343138 -0.52184103 +vn 1.1579728e-6 0.82919629 -0.55895753 +vn -0.51049126 0.68343359 -0.52184020 +vn -0.88761778 0.24221033 -0.39175098 +vn -0.83686083 -0.44191301 -0.32307407 +vn -0.48194580 -0.87575064 -2.8090349e-2 +vn 9.5380455e-15 -0.99767432 -6.8161218e-2 +vn 0.48194580 -0.87575064 -2.8090349e-2 +vn 0.91629252 -0.40036337 -1.0825317e-2 +vn 0.95983097 0.25069648 -0.12599910 +vn 0.57913380 0.73564454 -0.35132770 +vn 2.0149377e-15 0.89481531 -0.44643651 +vn -0.57913380 0.73564454 -0.35132770 +vn -0.95983097 0.25069648 -0.12599910 +vn -0.91629252 -0.40036337 -1.0825317e-2 +vn -0.50418347 -0.72532766 0.46872041 +vn 8.5797535e-16 -0.88792797 0.45998252 +vn 0.50418347 -0.72532766 0.46872041 +vn 0.84764493 -0.27262967 0.45516056 +vn 0.90167108 0.24808626 0.35417858 +vn 0.59713947 0.77184338 0.21836264 +vn -1.2539067e-14 0.99190960 0.12694625 +vn -0.59713947 0.77184338 0.21836264 +vn -0.90167108 0.24808626 0.35417858 +vn -0.84764493 -0.27262967 0.45516056 +vn -0.39633476 -0.47688822 0.78453577 +vn 2.2144057e-16 -0.61647709 0.78737284 +vn 0.39633476 -0.47688822 0.78453577 +vn 0.67145349 -0.14221864 0.72727166 +vn 0.71084577 0.21645847 0.66921149 +vn 0.46196177 0.59941927 0.65367260 +vn -9.0051230e-15 0.77697459 0.62953196 +vn -0.46196177 0.59941927 0.65367260 +vn -0.71084577 0.21645847 0.66921149 +vn -0.67145349 -0.14221864 0.72727166 +vn -0.30024919 -0.29843704 0.90597227 +vn 9.4444167e-16 -0.38914938 0.92117466 +vn 0.30024919 -0.29843704 0.90597227 +vn 0.52833482 -7.4697520e-2 0.84574381 +vn 0.54974399 0.19069941 0.81327442 +vn 0.33618195 0.43285623 0.83643122 +vn -3.0116168e-15 0.53246030 0.84645498 +vn -0.33618195 0.43285623 0.83643122 +vn -0.54974399 0.19069941 0.81327442 +vn -0.52833482 -7.4697520e-2 0.84574381 +vn -0.18335686 -0.12793478 0.97468608 +vn 2.1940421e-15 -0.16056747 0.98702487 +vn 0.18335686 -0.12793478 0.97468608 +vn 0.32858758 -1.0821162e-2 0.94441151 +vn 0.33837989 0.15640208 0.92792103 +vn 0.19764188 0.28517150 0.93787787 +vn 5.2977039e-16 0.33080729 0.94369833 +vn -0.19764188 0.28517150 0.93787787 +vn -0.33837989 0.15640208 0.92792103 +vn -0.32858758 -1.0821162e-2 0.94441151 +vn -4.9448560e-2 -0.13113536 -0.99013048 +vn -0.23993560 -0.22905857 -0.94337855 +vn -0.23740697 0.28268306 -0.92936980 +vn -2.2873781e-6 0.51901448 -0.85476545 +vn 0.23741525 0.28268577 -0.92936686 +vn 0.23995149 -0.22904324 -0.94337823 +vn 5.0709516e-2 -0.12768104 -0.99051810 +vn -0.18258022 0.68873639 -0.70164567 +vn 7.6943571e-3 0.88441286 -0.46664193 +vn 0.18691478 0.68684843 -0.70235468 +vn -0.60527876 -0.50103667 -0.61854659 +vn -0.65857135 -6.1430964e-2 -0.75000668 +vn -0.44269403 0.64308675 -0.62486912 +vn -5.6822186e-6 0.87709587 -0.48031535 +vn 0.44269643 0.64309135 -0.62486269 +vn 0.65858224 -6.1403351e-2 -0.74999937 +vn 0.60430516 -0.50078812 -0.61969874 +vn 4.8062746e-2 -0.53488974 0.84355375 +vn 5.5154610e-3 -0.57677884 0.81688172 +vn -3.9625825e-2 -0.52968981 0.84726531 +vn -0.68156706 -0.67574102 -0.28078536 +vn -0.90020107 9.5204068e-2 -0.42494025 +vn -0.52481715 0.74073080 -0.41938627 +vn -6.5908549e-6 0.91506743 -0.40330088 +vn 0.52481534 0.74073327 -0.41938418 +vn 0.90020210 9.5237639e-2 -0.42493054 +vn 0.68174272 -0.67544444 -0.28107236 +vn 0.26921475 -0.94500944 -0.18568949 +vn -4.1608364e-4 -0.98239072 -0.18683762 +vn -0.26936412 -0.94513814 -0.18481574 +vn -0.61841878 -0.71135087 -0.33397329 +vn -0.86528430 7.1772028e-2 -0.49611677 +vn -0.48727508 0.70686228 -0.51274625 +vn -3.2073219e-6 0.85466534 -0.51917930 +vn 0.48727929 0.70685995 -0.51274545 +vn 0.86529015 7.1806766e-2 -0.49610154 +vn 0.61847182 -0.71130098 -0.33398131 +vn 0.20898402 -0.95307403 -0.21903328 +vn -4.5001468e-7 -0.97847335 -0.20637323 +vn -0.20895476 -0.95308246 -0.21902449 +vn -0.51516187 -0.48664662 -0.70553761 +vn -0.61054499 0.16357830 -0.77490448 +vn -0.30970113 0.55291265 -0.77354561 +vn 2.4308323e-6 0.62979469 -0.77676164 +vn 0.30971216 0.55290767 -0.77354475 +vn 0.61055973 0.16360157 -0.77488795 +vn 0.51520381 -0.48660246 -0.70553744 +vn 0.15747931 -0.75022103 -0.64215938 +vn 4.4102954e-6 -0.74884654 -0.66274344 +vn -0.15745050 -0.75022859 -0.64215761 +g Turtle_turtle_auv +usemtl turtle_auv +s 1 +f 1/23/1 5/88/5 527/95/527 244/30/244 +f 1/22/1 244/26/244 455/15/455 243/13/243 +f 2/1042/2 386/1049/386 479/1047/479 246/1041/246 +f 2/1042/2 578/1031/578 533/1029/533 247/1040/247 +f 3/42/3 244/30/244 527/95/527 8/100/8 +f 3/40/3 250/51/250 454/28/454 249/20/249 +f 4/41/4 245/27/245 480/14/480 251/21/251 +f 4/37/4 252/49/252 529/103/529 9/96/9 +f 5/88/5 13/153/13 20/158/20 527/95/527 +f 6/1037/6 254/1033/254 535/1013/535 577/1023/577 +f 6/1037/6 385/1046/385 478/1043/478 254/1033/254 +f 7/1036/7 247/1040/247 533/1029/533 576/1022/576 +f 7/1036/7 384/1045/384 456/1048/456 247/1040/247 +f 8/100/8 20/158/20 24/175/24 526/110/526 +f 8/100/8 526/110/526 250/54/250 3/42/3 +f 8/100/8 527/95/527 20/158/20 +f 9/96/9 528/91/528 245/25/245 4/37/4 +f 10/634/10 26/668/26 522/670/522 258/636/258 +f 10/634/10 248/588/248 449/593/449 257/635/257 +f 11/70/11 250/54/250 526/110/526 18/135/18 +f 11/61/11 260/83/260 453/62/453 259/45/259 +f 12/64/12 252/53/252 481/31/481 261/47/261 +f 12/60/12 262/75/262 530/136/530 19/114/19 +f 13/153/13 29/190/29 36/197/36 20/158/20 +f 14/641/14 253/600/253 448/610/448 263/647/263 +f 14/641/14 257/635/257 449/593/449 253/600/253 +f 15/642/15 31/676/31 523/681/523 264/649/264 +f 15/642/15 258/636/258 522/670/522 31/676/31 +f 16/1028/16 266/1012/266 536/991/536 575/1003/575 +f 16/1028/16 383/1039/383 477/1032/477 266/1012/266 +f 17/1027/17 256/1034/256 532/1014/532 574/1002/574 +f 17/1027/17 382/1038/382 457/1044/457 256/1034/256 +f 18/135/18 525/147/525 260/94/260 11/70/11 +f 18/135/18 526/110/526 24/175/24 +f 19/114/19 529/103/529 252/49/252 12/60/12 +f 19/114/19 530/136/530 43/184/43 25/168/25 +f 20/158/20 36/197/36 44/203/44 24/175/24 +f 21/155/21 37/193/37 29/190/29 13/153/13 +f 21/155/21 528/91/528 9/96/9 +f 22/659/22 265/621/265 447/633/447 269/666/269 +f 22/659/22 269/666/269 519/687/519 38/685/38 +f 23/662/23 264/649/264 523/681/523 39/686/39 +f 23/662/23 267/623/267 451/615/451 264/649/264 +f 24/175/24 42/192/42 525/147/525 18/135/18 +f 24/175/24 44/203/44 48/213/48 42/192/42 +f 25/168/25 45/199/45 37/193/37 21/155/21 +f 25/168/25 529/103/529 19/114/19 +f 26/668/26 50/703/50 522/670/522 +f 27/115/27 260/94/260 525/147/525 34/164/34 +f 27/108/27 272/142/272 433/116/433 271/92/271 +f 28/107/28 262/85/262 482/63/482 273/82/273 +f 28/97/28 274/122/274 483/169/483 35/149/35 +f 29/190/29 53/220/53 60/223/60 36/197/36 +f 30/675/30 521/669/521 257/635/257 14/641/14 +f 31/676/31 55/708/55 523/681/523 +f 31/676/31 522/670/522 50/703/50 55/708/55 +f 32/999/32 276/983/276 543/965/543 573/981/573 +f 32/999/32 381/1020/381 470/1000/470 276/983/276 +f 33/998/33 268/1011/268 531/990/531 572/980/572 +f 33/998/33 380/1019/380 458/1035/458 268/1011/268 +f 34/164/34 505/186/505 272/151/272 27/115/27 +f 34/164/34 525/147/525 42/192/42 +f 35/149/35 483/169/483 43/184/43 +f 35/149/35 530/136/530 262/75/262 28/97/28 +f 36/197/36 60/223/60 68/228/68 44/203/44 +f 37/193/37 61/221/61 53/220/53 29/190/29 +f 38/685/38 520/680/520 263/647/263 22/659/22 +f 39/686/39 63/714/63 524/693/524 +f 39/686/39 523/681/523 55/708/55 63/714/63 +f 39/686/39 524/693/524 270/667/270 23/662/23 +f 40/674/40 275/653/275 434/671/434 279/698/279 +f 40/674/40 279/698/279 506/704/506 46/692/46 +f 41/679/41 270/667/270 524/693/524 47/699/47 +f 41/679/41 277/658/277 452/639/452 270/667/270 +f 42/192/42 505/186/505 34/164/34 +f 43/184/43 49/206/49 45/199/45 25/168/25 +f 43/184/43 67/217/67 73/232/73 49/206/49 +f 43/184/43 483/169/483 59/196/59 67/217/67 +f 43/184/43 530/136/530 35/149/35 +f 44/203/44 68/228/68 72/235/72 48/213/48 +f 45/199/45 69/226/69 61/221/61 37/193/37 +f 46/692/46 519/687/519 269/666/269 40/674/40 +f 47/699/47 484/705/484 280/701/280 41/679/41 +f 47/699/47 524/693/524 63/714/63 484/705/484 +f 48/213/48 72/235/72 66/222/66 42/192/42 +f 49/206/49 73/232/73 69/226/69 45/199/45 +f 50/703/50 74/745/74 79/752/79 55/708/55 +f 51/178/51 272/151/272 505/186/505 58/208/58 +f 51/176/51 282/209/282 431/200/431 281/160/281 +f 52/167/52 274/138/274 459/113/459 283/154/283 +f 52/159/52 284/198/284 485/218/485 59/196/59 +f 53/220/53 77/241/77 84/244/84 60/223/60 +f 54/707/54 50/703/50 521/669/521 30/675/30 +f 54/707/54 78/751/78 74/745/74 50/703/50 +f 55/708/55 79/752/79 87/753/87 63/714/63 +f 56/963/56 286/942/286 544/924/544 571/951/571 +f 56/963/56 379/978/379 469/955/469 286/942/286 +f 57/970/57 278/984/278 554/964/554 570/949/570 +f 57/970/57 378/988/378 411/1001/411 278/984/278 +f 57/970/57 687/947/687 288/954/288 +f 58/208/58 503/225/503 282/210/282 51/178/51 +f 59/196/59 483/169/483 274/122/274 52/159/52 +f 59/196/59 485/218/485 67/217/67 +f 60/223/60 84/244/84 92/248/92 68/228/68 +f 61/221/61 85/243/85 77/241/77 53/220/53 +f 62/713/62 54/707/54 520/680/520 38/685/38 +f 62/713/62 86/748/86 78/751/78 54/707/54 +f 62/713/62 506/704/506 70/718/70 +f 63/714/63 87/753/87 486/737/486 71/719/71 +f 64/711/64 285/700/285 432/720/432 289/729/289 +f 64/711/64 289/729/289 504/735/504 70/718/70 +f 65/715/65 280/701/280 484/705/484 71/719/71 +f 65/715/65 287/702/287 412/672/412 280/701/280 +f 66/222/66 58/208/58 505/186/505 42/192/42 +f 66/222/66 90/245/90 503/225/503 58/208/58 +f 67/217/67 91/240/91 97/251/97 73/232/73 +f 67/217/67 485/218/485 83/238/83 91/240/91 +f 68/228/68 92/248/92 96/255/96 72/235/72 +f 69/226/69 93/246/93 85/243/85 61/221/61 +f 70/718/70 504/735/504 86/748/86 62/713/62 +f 70/718/70 506/704/506 279/698/279 64/711/64 +f 71/719/71 484/705/484 63/714/63 +f 71/719/71 486/737/486 290/730/290 65/715/65 +f 72/235/72 96/255/96 90/245/90 66/222/66 +f 73/232/73 97/251/97 93/246/93 69/226/69 +f 74/745/74 98/779/98 100/782/100 79/752/79 +f 75/236/75 282/210/282 503/225/503 82/239/82 +f 75/237/75 292/257/292 429/256/429 291/234/291 +f 76/233/76 284/201/284 460/195/460 293/230/293 +f 76/231/76 294/253/294 487/259/487 83/238/83 +f 77/241/77 121/271/121 119/272/119 84/244/84 +f 78/751/78 99/777/99 98/779/98 74/745/74 +f 79/752/79 100/782/100 102/784/102 87/753/87 +f 80/215/80 377/216/377 468/182/468 296/179/296 +f 80/214/80 780/205/780 779/202/779 569/211/569 +f 81/310/81 288/283/288 687/285/687 688/314/688 +f 81/310/81 376/308/376 413/282/413 288/283/288 +f 82/239/82 501/260/501 292/258/292 75/236/75 +f 82/239/82 503/225/503 90/245/90 +f 83/238/83 485/218/485 284/198/284 76/231/76 +f 83/238/83 487/259/487 91/240/91 +f 84/244/84 119/272/119 117/275/117 92/248/92 +f 85/243/85 120/270/120 121/271/121 77/241/77 +f 86/748/86 101/783/101 99/777/99 78/751/78 +f 86/748/86 504/735/504 94/755/94 +f 87/753/87 102/784/102 488/772/488 95/756/95 +f 88/749/88 295/739/295 430/767/430 299/769/299 +f 88/749/88 299/769/299 502/771/502 94/755/94 +f 89/754/89 290/730/290 486/737/486 95/756/95 +f 89/754/89 297/741/297 414/722/414 290/730/290 +f 90/245/90 113/269/113 501/260/501 82/239/82 +f 91/240/91 114/279/114 116/278/116 97/251/97 +f 91/240/91 487/259/487 112/280/112 114/279/114 +f 92/248/92 117/275/117 115/273/115 96/255/96 +f 93/246/93 118/276/118 120/270/120 85/243/85 +f 94/755/94 502/771/502 101/783/101 86/748/86 +f 94/755/94 504/735/504 289/729/289 88/749/88 +f 95/756/95 486/737/486 87/753/87 +f 95/756/95 488/772/488 300/770/300 89/754/89 +f 96/255/96 115/273/115 113/269/113 90/245/90 +f 97/251/97 116/278/116 118/276/118 93/246/93 +f 98/779/98 142/826/142 135/822/135 100/782/100 +f 99/777/99 134/823/134 142/826/142 98/779/98 +f 100/782/100 135/822/135 127/821/127 102/784/102 +f 101/783/101 126/825/126 134/823/134 99/777/99 +f 101/783/101 500/795/500 122/816/122 126/825/126 +f 101/783/101 502/771/502 103/778/103 +f 102/784/102 490/794/490 104/785/104 +f 103/778/103 500/795/500 101/783/101 +f 103/778/103 502/771/502 299/769/299 105/780/105 +f 104/785/104 488/772/488 102/784/102 +f 104/785/104 490/794/490 304/799/304 106/786/106 +f 105/780/105 299/769/299 430/767/430 301/781/301 +f 105/780/105 302/800/302 500/795/500 103/778/103 +f 106/786/106 300/770/300 488/772/488 104/785/104 +f 106/786/106 304/799/304 418/804/418 303/787/303 +f 107/131/107 296/179/296 468/182/468 305/133/305 +f 107/131/107 782/132/782 781/172/781 296/179/296 +f 108/367/108 308/408/308 417/409/417 307/366/307 +f 108/367/108 683/368/683 685/401/685 308/408/308 +f 109/274/109 292/258/292 501/260/501 111/277/111 +f 109/264/109 375/263/375 429/256/429 292/257/292 +f 110/281/110 310/300/310 489/292/489 112/280/112 +f 110/265/110 374/266/374 462/297/462 310/295/310 +f 111/277/111 499/289/499 309/294/309 109/274/109 +f 111/277/111 501/260/501 113/269/113 +f 112/280/112 487/259/487 294/253/294 110/281/110 +f 112/280/112 489/292/489 131/311/131 114/279/114 +f 113/269/113 499/289/499 111/277/111 +f 114/279/114 131/311/131 125/301/125 116/278/116 +f 115/273/115 124/298/124 130/307/130 113/269/113 +f 116/278/116 125/301/125 133/304/133 118/276/118 +f 117/275/117 132/302/132 124/298/124 115/273/115 +f 118/276/118 133/304/133 141/305/141 120/270/120 +f 119/272/119 140/306/140 132/302/132 117/275/117 +f 120/270/120 141/305/141 145/309/145 121/271/121 +f 121/271/121 145/309/145 140/306/140 119/272/119 +f 122/816/122 498/834/498 126/825/126 +f 122/816/122 500/795/500 302/800/302 128/824/128 +f 123/814/123 492/832/492 314/848/314 129/820/129 +f 124/298/124 148/326/148 154/346/154 130/307/130 +f 125/301/125 149/332/149 157/339/157 133/304/133 +f 126/825/126 150/863/150 158/868/158 134/823/134 +f 126/825/126 498/834/498 146/855/146 150/863/150 +f 127/821/127 123/814/123 490/794/490 102/784/102 +f 127/821/127 492/832/492 123/814/123 +f 128/824/128 302/800/302 428/806/428 311/830/311 +f 128/824/128 312/849/312 498/834/498 122/816/122 +f 129/820/129 304/799/304 490/794/490 123/814/123 +f 129/820/129 314/848/314 420/850/420 313/829/313 +f 130/307/130 138/317/138 499/289/499 113/269/113 +f 130/307/130 497/340/497 138/317/138 +f 131/311/131 155/350/155 149/332/149 125/301/125 +f 131/311/131 489/292/489 139/318/139 +f 132/302/132 156/335/156 148/326/148 124/298/124 +f 133/304/133 157/339/157 165/347/165 141/305/141 +f 134/823/134 158/868/158 166/875/166 142/826/142 +f 135/822/135 159/867/159 151/862/151 127/821/127 +f 136/34/136 306/72/306 467/71/467 315/32/315 +f 136/34/136 784/46/784 783/78/783 306/72/306 +f 137/434/137 318/463/318 419/468/419 317/439/317 +f 137/434/137 682/431/682 684/462/684 318/463/318 +f 138/317/138 497/340/497 319/353/319 143/325/143 +f 139/318/139 489/292/489 310/300/310 144/333/144 +f 139/318/139 491/349/491 155/350/155 131/311/131 +f 140/306/140 164/345/164 156/335/156 132/302/132 +f 141/305/141 165/347/165 169/348/169 145/309/145 +f 142/826/142 166/875/166 159/867/159 135/822/135 +f 143/325/143 309/294/309 499/289/499 138/317/138 +f 143/319/143 373/323/373 427/291/427 309/290/309 +f 144/333/144 320/369/320 491/349/491 139/318/139 +f 144/324/144 372/327/372 463/359/463 320/355/320 +f 145/309/145 169/348/169 164/345/164 140/306/140 +f 146/855/146 496/872/496 150/863/150 +f 146/855/146 498/834/498 312/849/312 152/865/152 +f 147/854/147 494/871/494 324/878/324 153/861/153 +f 148/326/148 172/352/172 178/376/178 154/346/154 +f 149/332/149 173/356/173 181/361/181 157/339/157 +f 150/863/150 174/892/174 514/897/514 158/868/158 +f 150/863/150 513/887/513 174/892/174 +f 151/862/151 147/854/147 492/832/492 127/821/127 +f 151/862/151 494/871/494 147/854/147 +f 152/865/152 312/849/312 426/852/426 321/879/321 +f 152/865/152 322/883/322 496/872/496 146/855/146 +f 153/861/153 314/848/314 492/832/492 147/854/147 +f 153/861/153 324/878/324 422/905/422 323/876/323 +f 154/346/154 162/357/162 497/340/497 130/307/130 +f 154/346/154 178/376/178 495/378/495 162/357/162 +f 155/350/155 179/381/179 173/356/173 149/332/149 +f 155/350/155 491/349/491 163/372/163 +f 156/335/156 180/358/180 172/352/172 148/326/148 +f 157/339/157 181/361/181 189/373/189 165/347/165 +f 158/868/158 182/902/182 515/907/515 166/875/166 +f 158/868/158 514/897/514 182/902/182 +f 159/867/159 517/895/517 175/891/175 151/862/151 +f 160/609/160 316/632/316 466/617/466 325/587/325 +f 160/609/160 563/624/563 547/655/547 316/632/316 +f 161/595/161 328/579/328 421/558/421 327/576/327 +f 161/595/161 562/625/562 549/605/549 328/579/328 +f 161/595/161 684/627/684 677/637/677 562/625/562 +f 162/357/162 495/378/495 329/403/329 167/382/167 +f 163/372/163 491/349/491 320/369/320 168/390/168 +f 163/372/163 493/385/493 179/381/179 155/350/155 +f 164/345/164 188/371/188 180/358/180 156/335/156 +f 165/347/165 189/373/189 193/377/193 169/348/169 +f 166/875/166 515/907/515 190/908/190 +f 166/875/166 516/906/516 183/900/183 159/867/159 +f 167/382/167 319/353/319 497/340/497 162/357/162 +f 167/380/167 371/386/371 425/354/425 319/351/319 +f 168/390/168 330/417/330 493/385/493 163/372/163 +f 168/384/168 370/389/370 464/418/464 330/407/330 +f 169/348/169 193/377/193 188/371/188 164/345/164 +f 170/884/170 176/903/176 332/911/332 513/887/513 +f 170/884/170 496/872/496 322/883/322 176/903/176 +f 171/882/171 494/871/494 151/862/151 518/885/518 +f 172/352/172 180/358/180 196/383/196 178/376/178 +f 174/892/174 194/918/194 341/930/341 514/897/514 +f 174/892/174 513/887/513 332/911/332 194/918/194 +f 175/891/175 518/885/518 151/862/151 +f 176/903/176 322/883/322 424/909/424 331/926/331 +f 177/898/177 324/878/324 494/871/494 171/882/171 +f 177/898/177 334/910/334 446/936/446 333/921/333 +f 178/376/178 507/405/507 186/388/186 +f 179/381/179 197/387/197 181/361/181 173/356/173 +f 179/381/179 493/385/493 187/404/187 +f 179/381/179 512/411/512 203/420/203 197/387/197 +f 181/361/181 197/387/197 205/394/205 189/373/189 +f 182/902/182 198/934/198 345/938/345 515/907/515 +f 182/902/182 514/897/514 341/930/341 198/934/198 +f 183/900/183 517/895/517 159/867/159 +f 184/562/184 326/581/326 465/559/465 335/539/335 +f 184/562/184 561/583/561 548/604/548 326/581/326 +f 185/563/185 338/549/338 440/527/440 337/540/337 +f 185/563/185 560/584/560 537/571/537 338/549/338 +f 186/388/186 495/378/495 178/376/178 +f 186/388/186 507/405/507 339/442/339 191/421/191 +f 187/404/187 493/385/493 330/417/330 192/436/192 +f 187/404/187 512/411/512 179/381/179 +f 188/371/188 204/391/204 196/383/196 180/358/180 +f 189/373/189 205/394/205 209/399/209 193/377/193 +f 190/908/190 515/907/515 345/938/345 206/940/206 +f 190/908/190 516/906/516 166/875/166 +f 191/421/191 329/403/329 495/378/495 186/388/186 +f 191/419/191 369/433/369 423/413/423 329/402/329 +f 192/436/192 340/447/340 512/411/512 187/404/187 +f 192/422/192 368/443/368 476/451/476 340/438/340 +f 193/377/193 209/399/209 204/391/204 188/371/188 +f 194/918/194 332/911/332 441/941/441 342/952/342 +f 194/918/194 342/952/342 442/959/442 341/930/341 +f 195/916/195 334/910/334 518/885/518 175/891/175 +f 196/383/196 202/412/202 507/405/507 178/376/178 +f 196/383/196 508/423/508 202/412/202 +f 197/387/197 511/428/511 213/437/213 205/394/205 +f 198/934/198 341/930/341 442/959/442 346/968/346 +f 198/934/198 346/968/346 443/973/443 345/938/345 +f 199/932/199 343/928/343 517/895/517 183/900/183 +f 200/531/200 336/548/336 471/526/471 349/520/349 +f 200/531/200 559/556/559 542/570/542 336/548/336 +f 201/532/201 352/524/352 439/515/439 351/521/351 +f 201/532/201 558/557/558 538/546/538 352/524/352 +f 202/412/202 508/423/508 354/469/354 207/454/207 +f 203/420/203 511/428/511 197/387/197 +f 203/420/203 512/411/512 340/447/340 208/460/208 +f 204/391/204 212/432/212 508/423/508 196/383/196 +f 204/391/204 509/441/509 212/432/212 +f 205/394/205 510/445/510 217/446/217 209/399/209 +f 206/940/206 345/938/345 443/973/443 353/977/353 +f 206/940/206 347/937/347 516/906/516 190/908/190 +f 207/454/207 339/442/339 507/405/507 202/412/202 +f 207/453/207 367/471/367 435/452/435 339/440/339 +f 208/460/208 355/472/355 511/428/511 203/420/203 +f 208/449/208 366/470/366 475/478/475 355/464/355 +f 209/399/209 217/446/217 509/441/509 204/391/204 +f 210/523/210 350/525/350 472/516/472 357/514/357 +f 210/523/210 357/514/357 437/512/437 356/519/356 +f 210/523/210 557/538/557 541/547/541 350/525/350 +f 211/522/211 556/537/556 539/529/539 358/518/358 +f 212/432/212 509/441/509 361/486/361 215/477/215 +f 213/437/213 510/445/510 205/394/205 +f 213/437/213 511/428/511 355/472/355 216/480/216 +f 214/517/214 356/519/356 437/512/437 360/510/360 +f 214/517/214 555/528/555 540/530/540 356/519/356 +f 215/477/215 354/469/354 508/423/508 212/432/212 +f 215/473/215 365/489/365 436/481/436 354/466/354 +f 216/480/216 362/487/362 510/445/510 213/437/213 +f 216/474/216 364/490/364 474/496/474 362/482/362 +f 217/446/217 510/445/510 362/487/362 218/488/218 +f 218/488/218 361/486/361 509/441/509 217/446/217 +f 218/485/218 363/497/363 473/495/473 361/483/361 +f 219/504/219 360/509/360 437/507/437 401/502/401 +f 219/504/219 401/502/401 473/495/473 363/497/363 +f 219/504/219 402/503/402 438/508/438 360/509/360 +f 220/499/220 359/506/359 438/508/438 402/503/402 +f 220/499/220 402/503/402 474/496/474 364/490/364 +f 220/499/220 403/492/403 439/500/439 359/506/359 +f 221/498/221 400/494/400 436/481/436 365/489/365 +f 221/498/221 401/502/401 437/507/437 357/505/357 +f 222/479/222 351/491/351 439/500/439 403/492/403 +f 222/479/222 403/492/403 475/478/475 366/470/366 +f 222/479/222 404/465/404 440/475/440 351/491/351 +f 223/484/223 399/467/399 435/452/435 367/471/367 +f 224/450/224 337/458/337 440/475/440 404/465/404 +f 224/450/224 392/426/392 421/444/421 337/458/337 +f 224/450/224 404/465/404 476/451/476 368/443/368 +f 225/448/225 393/424/393 423/413/423 369/433/369 +f 226/400/226 327/410/327 421/444/421 392/426/392 +f 226/400/226 391/375/391 419/379/419 327/410/327 +f 226/400/226 392/426/392 464/418/464 370/389/370 +f 227/392/227 394/360/394 425/354/425 371/386/371 +f 228/331/228 317/344/317 419/379/419 391/375/391 +f 228/331/228 390/299/390 417/303/417 317/344/317 +f 228/331/228 391/375/391 463/359/463 372/327/372 +f 229/328/229 395/293/395 427/291/427 373/323/373 +f 230/267/230 307/268/307 417/303/417 390/299/390 +f 230/267/230 389/247/389 415/242/415 307/268/307 +f 230/267/230 390/299/390 462/297/462 374/266/374 +f 231/262/231 396/254/396 429/256/429 375/263/375 +f 232/227/232 388/185/388 413/177/413 376/219/376 +f 233/229/233 291/234/291 429/256/429 396/254/396 +f 233/229/233 396/254/396 468/250/468 377/224/377 +f 233/229/233 397/194/397 431/200/431 291/234/291 +f 234/143/234 387/98/387 411/80/411 378/134/378 +f 235/152/235 281/160/281 431/200/431 397/194/397 +f 235/152/235 397/194/397 469/187/469 379/141/379 +f 235/152/235 398/101/398 433/116/433 281/160/281 +f 236/67/236 410/52/410 458/35/458 380/57/380 +f 237/69/237 271/92/271 433/116/433 398/101/398 +f 237/69/237 398/101/398 470/90/470 381/55/381 +f 237/69/237 405/50/405 453/62/453 271/92/271 +f 238/29/238 409/18/409 457/10/457 382/19/382 +f 239/24/239 259/45/259 453/62/453 405/50/405 +f 239/24/239 405/50/405 477/36/477 383/17/383 +f 239/24/239 406/16/406 454/28/454 259/45/259 +f 240/11/240 408/7/408 456/2/456 384/4/384 +f 241/12/241 249/20/249 454/28/454 406/16/406 +f 241/12/241 406/16/406 478/9/478 385/5/385 +f 241/12/241 407/8/407 455/15/455 249/20/249 +f 242/6/242 243/13/243 455/15/455 407/8/407 +f 242/6/242 407/8/407 479/3/479 386/1/386 +f 243/13/243 480/14/480 245/27/245 1/22/1 +f 245/25/245 528/91/528 5/88/5 1/23/1 +f 246/1041/246 479/1047/479 385/1046/385 6/1037/6 +f 246/1041/246 534/1030/534 578/1031/578 2/1042/2 +f 247/1040/247 456/1048/456 386/1049/386 2/1042/2 +f 248/588/248 661/545/661 630/551/630 449/593/449 +f 249/20/249 455/15/455 244/26/244 3/40/3 +f 251/21/251 480/14/480 408/7/408 240/11/240 +f 251/21/251 481/31/481 252/53/252 4/41/4 +f 253/600/253 660/561/660 631/574/631 448/610/448 +f 254/1033/254 478/1043/478 383/1039/383 16/1028/16 +f 255/601/255 450/592/450 258/636/258 15/642/15 +f 255/601/255 659/560/659 629/550/629 450/592/450 +f 256/1034/256 457/1044/457 384/1045/384 7/1036/7 +f 257/635/257 521/669/521 26/668/26 10/634/10 +f 258/636/258 450/592/450 248/588/248 10/634/10 +f 259/45/259 454/28/454 250/51/250 11/61/11 +f 261/47/261 481/31/481 409/18/409 238/29/238 +f 261/47/261 482/63/482 262/85/262 12/64/12 +f 263/647/263 448/610/448 265/621/265 22/659/22 +f 263/647/263 520/680/520 30/675/30 14/641/14 +f 264/649/264 451/615/451 255/601/255 15/642/15 +f 265/621/265 658/589/658 632/611/632 447/633/447 +f 266/1012/266 477/1032/477 381/1020/381 32/999/32 +f 267/623/267 657/594/657 628/575/628 451/615/451 +f 268/1011/268 458/1035/458 382/1038/382 17/1027/17 +f 269/666/269 447/633/447 275/653/275 40/674/40 +f 270/667/270 452/639/452 267/623/267 23/662/23 +f 271/92/271 453/62/453 260/83/260 27/108/27 +f 273/82/273 459/113/459 274/138/274 28/107/28 +f 273/82/273 482/63/482 410/52/410 236/67/236 +f 275/653/275 656/628/656 639/652/639 434/671/434 +f 276/983/276 470/1000/470 379/978/379 56/963/56 +f 277/658/277 655/631/655 627/616/627 452/639/452 +f 278/984/278 411/1001/411 380/1019/380 33/998/33 +f 279/698/279 434/671/434 285/700/285 64/711/64 +f 280/701/280 412/672/412 277/658/277 41/679/41 +f 281/160/281 433/116/433 272/142/272 51/176/51 +f 283/154/283 459/113/459 387/98/387 234/143/234 +f 283/154/283 460/195/460 284/201/284 52/167/52 +f 285/700/285 654/678/654 640/709/640 432/720/432 +f 286/942/286 469/955/469 377/935/377 80/922/80 +f 287/702/287 653/684/653 650/660/650 412/672/412 +f 288/954/288 413/969/413 378/988/378 57/970/57 +f 289/729/289 432/720/432 295/739/295 88/749/88 +f 290/730/290 414/722/414 287/702/287 65/715/65 +f 291/234/291 431/200/431 282/209/282 75/237/75 +f 293/230/293 460/195/460 388/185/388 232/227/232 +f 293/230/293 461/249/461 294/252/294 76/233/76 +f 294/252/294 461/249/461 374/266/374 110/265/110 +f 295/739/295 652/733/652 641/762/641 430/767/430 +f 296/179/296 781/172/781 780/207/780 80/215/80 +f 297/741/297 651/738/651 649/716/649 414/722/414 +f 298/330/298 415/329/415 376/308/376 81/310/81 +f 298/330/298 686/336/686 683/368/683 108/367/108 +f 300/770/300 416/768/416 297/741/297 89/754/89 +f 301/781/301 428/806/428 302/800/302 105/780/105 +f 301/781/301 430/767/430 641/762/641 674/776/674 +f 303/787/303 416/768/416 300/770/300 106/786/106 +f 303/787/303 418/804/418 647/807/647 673/788/673 +f 305/133/305 467/71/467 306/72/306 107/131/107 +f 305/261/305 468/250/468 396/254/396 231/262/231 +f 306/72/306 783/78/783 782/132/782 107/131/107 +f 307/366/307 415/329/415 298/330/298 108/367/108 +f 308/408/308 685/401/685 682/431/682 137/434/137 +f 309/290/309 427/291/427 375/263/375 109/264/109 +f 310/295/310 462/297/462 372/327/372 144/324/144 +f 311/830/311 426/852/426 312/849/312 128/824/128 +f 311/830/311 428/806/428 642/809/642 672/835/672 +f 313/829/313 418/804/418 304/799/304 129/820/129 +f 313/829/313 420/850/420 646/858/646 671/831/671 +f 315/640/315 466/617/466 316/632/316 136/657/136 +f 315/334/315 467/296/467 395/293/395 229/328/229 +f 316/632/316 547/655/547 565/677/565 136/657/136 +f 317/439/317 417/409/417 308/408/308 137/434/137 +f 318/618/318 684/627/684 161/595/161 +f 319/351/319 425/354/425 373/323/373 143/319/143 +f 320/355/320 463/359/463 370/389/370 168/384/168 +f 321/879/321 424/909/424 322/883/322 152/865/152 +f 321/879/321 426/852/426 643/866/643 670/899/670 +f 323/876/323 420/850/420 314/848/314 153/861/153 +f 323/876/323 422/905/422 645/919/645 669/893/669 +f 325/587/325 465/559/465 326/581/326 160/609/160 +f 325/406/325 466/374/466 394/360/394 227/392/227 +f 326/581/326 548/604/548 563/624/563 160/609/160 +f 327/576/327 419/596/419 318/618/318 161/595/161 +f 328/579/328 549/605/549 560/584/560 185/563/185 +f 329/402/329 423/413/423 371/386/371 167/380/167 +f 330/407/330 464/418/464 368/443/368 192/422/192 +f 331/926/331 424/909/424 644/927/644 668/946/668 +f 331/926/331 441/941/441 332/911/332 176/903/176 +f 333/921/333 422/905/422 324/878/324 177/898/177 +f 333/921/333 446/936/446 633/956/633 667/943/667 +f 335/459/335 465/435/465 393/424/393 225/448/225 +f 335/539/335 471/526/471 336/548/336 184/562/184 +f 336/548/336 542/570/542 561/583/561 184/562/184 +f 337/540/337 421/558/421 328/579/328 185/563/185 +f 338/549/338 537/571/537 558/557/558 201/532/201 +f 339/440/339 435/452/435 369/433/369 191/419/191 +f 340/438/340 476/451/476 366/470/366 208/449/208 +f 342/952/342 441/941/441 638/958/638 666/974/666 +f 343/928/343 445/957/445 344/950/344 195/916/195 +f 344/950/344 445/957/445 634/987/634 665/971/665 +f 344/950/344 446/936/446 334/910/334 195/916/195 +f 346/968/346 442/959/442 637/989/637 664/997/664 +f 347/937/347 444/972/444 348/967/348 199/932/199 +f 348/967/348 444/972/444 635/1008/635 663/996/663 +f 348/967/348 445/957/445 343/928/343 199/932/199 +f 349/493/349 471/476/471 399/467/399 223/484/223 +f 349/520/349 472/516/472 350/525/350 200/531/200 +f 350/525/350 541/547/541 559/556/559 200/531/200 +f 351/521/351 440/527/440 338/549/338 201/532/201 +f 352/524/352 538/546/538 556/537/556 211/522/211 +f 353/977/353 443/973/443 636/1009/636 662/1010/662 +f 353/977/353 444/972/444 347/937/347 206/940/206 +f 354/466/354 436/481/436 367/471/367 207/453/207 +f 355/464/355 475/478/475 364/490/364 216/474/216 +f 356/519/356 540/530/540 557/538/557 210/523/210 +f 357/505/357 472/501/472 400/494/400 221/498/221 +f 358/518/358 438/511/438 359/513/359 211/522/211 +f 358/518/358 539/529/539 555/528/555 214/517/214 +f 359/513/359 439/515/439 352/524/352 211/522/211 +f 360/510/360 438/511/438 358/518/358 214/517/214 +f 361/483/361 473/495/473 365/489/365 215/473/215 +f 362/482/362 474/496/474 363/497/363 218/485/218 +f 363/497/363 474/496/474 402/503/402 219/504/219 +f 364/490/364 475/478/475 403/492/403 220/499/220 +f 365/489/365 473/495/473 401/502/401 221/498/221 +f 366/470/366 476/451/476 404/465/404 222/479/222 +f 367/471/367 436/481/436 400/494/400 223/484/223 +f 368/443/368 464/418/464 392/426/392 224/450/224 +f 369/433/369 435/452/435 399/467/399 225/448/225 +f 370/389/370 463/359/463 391/375/391 226/400/226 +f 371/386/371 423/413/423 393/424/393 227/392/227 +f 372/327/372 462/297/462 390/299/390 228/331/228 +f 373/323/373 425/354/425 394/360/394 229/328/229 +f 374/266/374 461/249/461 389/247/389 230/267/230 +f 375/263/375 427/291/427 395/293/395 231/262/231 +f 376/219/376 415/242/415 389/247/389 232/227/232 +f 377/224/377 469/187/469 397/194/397 233/229/233 +f 378/134/378 413/177/413 388/185/388 234/143/234 +f 379/141/379 470/90/470 398/101/398 235/152/235 +f 380/57/380 411/80/411 387/98/387 236/67/236 +f 381/55/381 477/36/477 405/50/405 237/69/237 +f 382/19/382 458/35/458 410/52/410 238/29/238 +f 383/17/383 478/9/478 406/16/406 239/24/239 +f 384/4/384 457/10/457 409/18/409 240/11/240 +f 385/5/385 479/3/479 407/8/407 241/12/241 +f 386/1/386 456/2/456 408/7/408 242/6/242 +f 387/98/387 459/113/459 273/82/273 236/67/236 +f 388/185/388 460/195/460 283/154/283 234/143/234 +f 389/247/389 461/249/461 293/230/293 232/227/232 +f 393/424/393 465/435/465 325/406/325 227/392/227 +f 394/360/394 466/374/466 315/334/315 229/328/229 +f 395/293/395 467/296/467 305/261/305 231/262/231 +f 399/467/399 471/476/471 335/459/335 225/448/225 +f 400/494/400 472/501/472 349/493/349 223/484/223 +f 408/7/408 480/14/480 243/13/243 242/6/242 +f 409/18/409 481/31/481 251/21/251 240/11/240 +f 410/52/410 482/63/482 261/47/261 238/29/238 +f 412/672/412 650/660/650 655/631/655 277/658/277 +f 414/722/414 649/716/649 653/684/653 287/702/287 +f 416/768/416 648/766/648 651/738/651 297/741/297 +f 432/720/432 640/709/640 652/733/652 295/739/295 +f 434/671/434 639/652/639 654/678/654 285/700/285 +f 447/633/447 632/611/632 656/628/656 275/653/275 +f 448/610/448 631/574/631 658/589/658 265/621/265 +f 449/593/449 630/551/630 660/561/660 253/600/253 +f 450/592/450 629/550/629 661/545/661 248/588/248 +f 451/615/451 628/575/628 659/560/659 255/601/255 +f 452/639/452 627/616/627 657/594/657 267/623/267 +f 506/704/506 62/713/62 519/687/519 46/692/46 +f 513/887/513 150/863/150 496/872/496 170/884/170 +f 516/906/516 347/937/347 199/932/199 183/900/183 +f 517/895/517 343/928/343 195/916/195 175/891/175 +f 518/885/518 334/910/334 177/898/177 171/882/171 +f 519/687/519 62/713/62 38/685/38 +f 520/680/520 54/707/54 30/675/30 +f 521/669/521 50/703/50 26/668/26 +f 528/91/528 21/155/21 13/153/13 5/88/5 +f 529/103/529 25/168/25 21/155/21 9/96/9 +f 531/990/531 574/1002/574 583/994/583 613/985/613 +f 532/1014/532 576/1022/576 581/1015/581 612/1007/612 +f 533/1029/533 578/1031/578 579/1026/579 611/1024/611 +f 534/1030/534 577/1023/577 580/1016/580 610/1025/610 +f 535/1013/535 575/1003/575 582/995/582 609/1006/609 +f 536/991/536 573/981/573 584/976/584 608/986/608 +f 537/571/537 560/584/560 619/591/619 607/578/607 +f 538/546/538 558/557/558 617/566/617 606/554/606 +f 539/529/539 556/537/556 615/543/615 605/535/605 +f 540/530/540 555/528/555 614/533/614 604/536/604 +f 541/547/541 557/538/557 616/544/616 603/555/603 +f 542/570/542 559/556/559 618/565/618 602/577/602 +f 543/965/543 571/951/571 586/945/586 601/961/601 +f 544/924/544 569/901/569 588/894/588 600/917/600 +f 545/173/545 567/128/567 626/126/626 599/174/599 +f 545/173/545 788/170/788 787/130/787 567/128/567 +f 546/74/546 565/39/565 624/38/624 598/73/598 +f 546/74/546 786/77/786 785/48/785 565/39/565 +f 547/655/547 563/624/563 622/629/622 597/661/597 +f 548/604/548 561/583/561 620/590/620 596/612/596 +f 549/605/549 562/625/562 621/630/621 595/613/595 +f 550/455/550 564/425/564 623/427/623 594/456/594 +f 551/393/551 566/363/566 625/362/625 593/395/593 +f 552/342/552 568/316/568 589/315/589 592/341/592 +f 552/342/552 679/337/679 681/313/681 568/316/568 +f 553/923/553 570/949/570 587/944/587 591/914/591 +f 553/923/553 680/939/680 570/949/570 +f 554/964/554 572/980/572 585/975/585 590/960/590 +f 562/625/562 677/637/677 550/656/550 +f 564/425/564 550/455/550 677/457/677 676/429/676 +f 565/39/565 785/48/785 784/44/784 136/33/136 +f 566/363/566 551/393/551 678/398/678 675/364/675 +f 567/128/567 787/130/787 786/77/786 546/74/546 +f 568/316/568 681/313/681 680/286/680 553/288/553 +f 569/901/569 544/924/544 286/942/286 80/922/80 +f 569/211/569 779/202/779 788/170/788 545/173/545 +f 570/949/570 680/939/680 687/947/687 57/970/57 +f 571/951/571 543/965/543 276/983/276 56/963/56 +f 572/980/572 554/964/554 278/984/278 33/998/33 +f 573/981/573 536/991/536 266/1012/266 32/999/32 +f 574/1002/574 531/990/531 268/1011/268 17/1027/17 +f 575/1003/575 535/1013/535 254/1033/254 16/1028/16 +f 576/1022/576 532/1014/532 256/1034/256 7/1036/7 +f 577/1023/577 534/1030/534 246/1041/246 6/1037/6 +f 579/534/579 610/542/610 630/551/630 661/545/661 +f 580/553/580 609/567/609 631/574/631 660/561/660 +f 581/552/581 611/541/611 629/550/629 659/560/659 +f 582/580/582 608/603/608 632/611/632 658/589/658 +f 583/585/583 612/568/612 628/575/628 657/594/657 +f 584/620/584 601/645/601 639/652/639 656/628/656 +f 585/626/585 613/606/613 627/616/627 655/631/655 +f 586/673/586 600/706/600 640/709/640 654/678/654 +f 587/682/587 590/654/590 650/660/650 653/684/653 +f 588/731/588 599/761/599 641/762/641 652/733/652 +f 589/736/589 591/712/591 649/716/649 651/738/651 +f 590/960/590 587/944/587 570/949/570 554/964/554 +f 591/287/591 589/315/589 568/316/568 553/288/553 +f 592/341/592 625/362/625 566/363/566 552/342/552 +f 593/395/593 623/427/623 564/425/564 551/393/551 +f 593/808/593 625/789/625 673/788/673 647/807/647 +f 594/664/594 621/630/621 562/625/562 550/656/550 +f 594/864/594 623/833/623 671/831/671 646/858/646 +f 595/613/595 619/591/619 560/584/560 549/605/549 +f 595/925/595 621/896/621 669/893/669 645/919/645 +f 596/931/596 620/953/620 668/946/668 644/927/644 +f 596/612/596 622/629/622 563/624/563 548/604/548 +f 597/870/597 622/904/622 670/899/670 643/866/643 +f 597/661/597 624/683/624 565/677/565 547/655/547 +f 598/810/598 624/847/624 672/835/672 642/809/642 +f 598/73/598 626/126/626 567/128/567 546/74/546 +f 599/174/599 588/212/588 569/211/569 545/173/545 +f 599/761/599 626/775/626 674/776/674 641/762/641 +f 600/917/600 586/945/586 571/951/571 544/924/544 +f 601/961/601 584/976/584 573/981/573 543/965/543 +f 602/966/602 618/982/618 666/974/666 638/958/638 +f 602/577/602 620/590/620 561/583/561 542/570/542 +f 603/993/603 616/1005/616 664/997/664 637/989/637 +f 603/555/603 618/565/618 559/556/559 541/547/541 +f 604/1018/604 614/1021/614 662/1010/662 636/1009/636 +f 604/536/604 616/544/616 557/538/557 540/530/540 +f 605/535/605 614/533/614 555/528/555 539/529/539 +f 605/1017/605 615/1004/615 663/996/663 635/1008/635 +f 606/554/606 615/543/615 556/537/556 538/546/538 +f 606/992/606 617/979/617 665/971/665 634/987/634 +f 607/578/607 617/566/617 558/557/558 537/571/537 +f 607/962/607 619/948/619 667/943/667 633/956/633 +f 608/986/608 582/995/582 575/1003/575 536/991/536 +f 609/1006/609 580/1016/580 577/1023/577 535/1013/535 +f 610/1025/610 579/1026/579 578/1031/578 534/1030/534 +f 611/1024/611 581/1015/581 576/1022/576 533/1029/533 +f 612/1007/612 583/994/583 574/1002/574 532/1014/532 +f 613/985/613 585/975/585 572/980/572 531/990/531 +f 633/956/633 665/971/665 617/979/617 607/962/607 +f 634/987/634 663/996/663 615/1004/615 606/992/606 +f 635/1008/635 662/1010/662 614/1021/614 605/1017/605 +f 636/1009/636 664/997/664 616/1005/616 604/1018/604 +f 637/989/637 666/974/666 618/982/618 603/993/603 +f 638/958/638 668/946/668 620/953/620 602/966/602 +f 642/809/642 674/776/674 626/775/626 598/810/598 +f 643/866/643 672/835/672 624/847/624 597/870/597 +f 644/927/644 670/899/670 622/904/622 596/931/596 +f 645/919/645 667/943/667 619/948/619 595/925/595 +f 646/858/646 669/893/669 621/896/621 594/864/594 +f 647/807/647 671/831/671 623/833/623 593/808/593 +f 648/766/648 673/788/673 625/789/625 592/764/592 +f 651/738/651 648/766/648 592/764/592 589/736/589 +f 652/733/652 640/709/640 600/706/600 588/731/588 +f 653/684/653 649/716/649 591/712/591 587/682/587 +f 654/678/654 639/652/639 601/645/601 586/673/586 +f 655/631/655 650/660/650 590/654/590 585/626/585 +f 656/628/656 632/611/632 608/603/608 584/620/584 +f 657/594/657 627/616/627 613/606/613 583/585/583 +f 658/589/658 631/574/631 609/567/609 582/580/582 +f 659/560/659 628/575/628 612/568/612 581/552/581 +f 660/561/660 630/551/630 610/542/610 580/553/580 +f 661/545/661 629/550/629 611/541/611 579/534/579 +f 662/1010/662 635/1008/635 444/972/444 353/977/353 +f 663/996/663 634/987/634 445/957/445 348/967/348 +f 664/997/664 636/1009/636 443/973/443 346/968/346 +f 665/971/665 633/956/633 446/936/446 344/950/344 +f 666/974/666 637/989/637 442/959/442 342/952/342 +f 667/943/667 645/919/645 422/905/422 333/921/333 +f 668/946/668 638/958/638 441/941/441 331/926/331 +f 669/893/669 646/858/646 420/850/420 323/876/323 +f 670/899/670 644/927/644 424/909/424 321/879/321 +f 671/831/671 647/807/647 418/804/418 313/829/313 +f 672/835/672 643/866/643 426/852/426 311/830/311 +f 673/788/673 648/766/648 416/768/416 303/787/303 +f 674/776/674 642/809/642 428/806/428 301/781/301 +f 675/364/675 679/337/679 552/342/552 566/363/566 +f 675/364/675 690/365/690 689/338/689 679/337/679 +f 676/429/676 677/457/677 684/461/684 682/430/682 +f 676/429/676 678/398/678 551/393/551 564/425/564 +f 676/429/676 692/414/692 691/397/691 678/398/678 +f 678/398/678 691/397/691 690/365/690 675/364/675 +f 679/337/679 689/338/689 698/321/698 681/313/681 +f 681/313/681 688/312/688 687/284/687 680/286/680 +f 681/313/681 698/321/698 697/320/697 688/312/688 +f 682/430/682 693/415/693 692/414/692 676/429/676 +f 683/368/683 695/370/695 694/396/694 685/401/685 +f 685/401/685 694/396/694 693/416/693 682/431/682 +f 686/336/686 696/343/696 695/370/695 683/368/683 +f 688/314/688 686/336/686 298/330/298 81/310/81 +f 688/314/688 697/322/697 696/343/696 686/336/686 +f 689/802/689 699/803/699 708/793/708 698/792/698 +f 690/846/690 700/845/700 699/803/699 689/802/689 +f 691/881/691 701/880/701 700/845/700 690/846/690 +f 692/913/692 702/912/702 701/880/701 691/881/691 +f 693/614/693 703/607/703 702/582/702 692/586/692 +f 694/651/694 704/650/704 703/607/703 693/614/693 +f 695/697/695 705/696/705 704/650/704 694/651/694 +f 696/723/696 706/724/706 705/696/705 695/697/695 +f 697/742/697 707/743/707 706/724/706 696/723/696 +f 698/757/698 708/758/708 707/743/707 697/742/697 +f 699/803/699 709/801/709 718/790/718 708/793/708 +f 700/845/700 710/844/710 709/801/709 699/803/699 +f 701/880/701 711/886/711 710/844/710 700/845/700 +f 702/912/702 712/920/712 711/886/711 701/880/701 +f 703/607/703 713/602/713 712/573/712 702/582/702 +f 704/650/704 714/646/714 713/602/713 703/607/703 +f 705/696/705 715/695/715 714/646/714 704/650/704 +f 706/724/706 716/726/716 715/695/715 705/696/705 +f 707/743/707 717/747/717 716/726/716 706/724/706 +f 708/758/708 718/760/718 717/747/717 707/743/707 +f 709/801/709 719/796/719 728/774/728 718/790/718 +f 710/844/710 720/842/720 719/796/719 709/801/709 +f 711/886/711 721/890/721 720/842/720 710/844/710 +f 712/920/712 722/929/722 721/890/721 711/886/711 +f 713/602/713 723/597/723 722/569/722 712/573/712 +f 714/646/714 724/643/724 723/597/723 713/602/713 +f 715/695/715 725/694/725 724/643/724 714/646/714 +f 716/726/716 726/727/726 725/694/725 715/695/715 +f 717/747/717 727/750/727 726/727/726 716/726/716 +f 718/760/718 728/763/728 727/750/727 717/747/717 +f 719/796/719 729/797/729 738/773/738 728/774/728 +f 720/842/720 730/843/730 729/797/729 719/796/719 +f 721/890/721 731/889/731 730/843/730 720/842/720 +f 722/929/722 732/933/732 731/889/731 721/890/721 +f 723/597/723 733/598/733 732/564/732 722/569/722 +f 724/643/724 734/644/734 733/598/733 723/597/723 +f 725/694/725 735/691/735 734/644/734 724/643/724 +f 726/727/726 736/725/736 735/691/735 725/694/725 +f 727/750/727 737/746/737 736/725/736 726/727/726 +f 728/763/728 738/765/738 737/746/737 727/750/727 +f 729/797/729 739/805/739 748/791/748 738/773/738 +f 730/843/730 740/836/740 739/805/739 729/797/729 +f 731/889/731 741/877/741 740/836/740 730/843/730 +f 732/933/732 742/915/742 741/877/741 731/889/731 +f 733/598/733 743/608/743 742/572/742 732/564/732 +f 734/644/734 744/648/744 743/608/743 733/598/733 +f 735/691/735 745/690/745 744/648/744 734/644/734 +f 736/725/736 746/721/746 745/690/745 735/691/735 +f 737/746/737 747/740/747 746/721/746 736/725/736 +f 738/765/738 748/759/748 747/740/747 737/746/737 +f 739/805/739 749/813/749 758/798/758 748/791/748 +f 740/836/740 750/837/750 749/813/749 739/805/739 +f 741/877/741 751/869/751 750/837/750 740/836/740 +f 742/915/742 752/888/752 751/869/751 741/877/741 +f 743/608/743 753/622/753 752/599/752 742/572/742 +f 744/648/744 754/663/754 753/622/753 743/608/743 +f 745/690/745 755/689/755 754/663/754 744/648/744 +f 746/721/746 756/717/756 755/689/755 745/690/745 +f 747/740/747 757/732/757 756/717/756 746/721/746 +f 748/759/748 758/744/758 757/732/757 747/740/747 +f 749/813/749 759/818/759 768/811/768 758/798/758 +f 750/837/750 760/838/760 759/818/759 749/813/749 +f 751/869/751 761/857/761 760/838/760 750/837/750 +f 752/888/752 762/874/762 761/857/761 751/869/751 +f 753/622/753 763/638/763 762/619/762 752/599/752 +f 754/663/754 764/665/764 763/638/763 753/622/753 +f 755/689/755 765/688/765 764/665/764 754/663/754 +f 756/717/756 766/710/766 765/688/765 755/689/755 +f 757/732/757 767/728/767 766/710/766 756/717/756 +f 758/744/758 768/734/768 767/728/767 757/732/757 +f 759/818/759 769/827/769 778/815/778 768/811/768 +f 760/838/760 770/839/770 769/827/769 759/818/759 +f 761/857/761 771/853/771 770/839/770 760/838/760 +f 762/874/762 772/860/772 771/853/771 761/857/761 +f 763/873/763 773/859/773 772/860/772 762/874/762 +f 764/856/764 774/851/774 773/859/773 763/873/763 +f 765/841/765 775/840/775 774/851/774 764/856/764 +f 766/819/766 776/828/776 775/840/775 765/841/765 +f 767/812/767 777/817/777 776/828/776 766/819/766 +f 768/811/768 778/815/778 777/817/777 767/812/767 +f 770/839/770 771/853/771 772/860/772 773/859/773 774/851/774 775/840/775 776/828/776 777/817/777 778/815/778 769/827/769 +f 779/202/779 789/188/789 798/165/798 788/170/788 +f 780/205/780 790/191/790 789/188/789 779/202/779 +f 781/76/781 791/79/791 790/56/790 780/43/780 +f 782/119/782 792/117/792 791/79/791 781/76/781 +f 783/171/783 793/166/793 792/117/792 782/119/782 +f 784/204/784 794/189/794 793/166/793 783/171/783 +f 785/48/785 795/59/795 794/58/794 784/44/784 +f 786/77/786 796/81/796 795/59/795 785/48/785 +f 787/130/787 797/129/797 796/81/796 786/77/786 +f 788/170/788 798/165/798 797/129/797 787/130/787 +f 789/188/789 799/180/799 808/157/808 798/165/798 +f 790/191/790 800/183/800 799/180/799 789/188/789 +f 791/79/791 801/89/801 800/65/800 790/56/790 +f 792/117/792 802/118/802 801/89/801 791/79/791 +f 793/166/793 803/156/803 802/118/802 792/117/792 +f 794/189/794 804/181/804 803/156/803 793/166/793 +f 795/59/795 805/68/805 804/66/804 794/58/794 +f 796/81/796 806/93/806 805/68/805 795/59/795 +f 797/129/797 807/127/807 806/93/806 796/81/796 +f 798/165/798 808/157/808 807/127/807 797/129/797 +f 799/180/799 809/162/809 818/150/818 808/157/808 +f 800/183/800 810/163/810 809/162/809 799/180/799 +f 801/89/801 811/99/811 810/84/810 800/65/800 +f 802/118/802 812/120/812 811/99/811 801/89/801 +f 803/156/803 813/148/813 812/120/812 802/118/802 +f 804/181/804 814/161/814 813/148/813 803/156/803 +f 805/68/805 815/87/815 814/86/814 804/66/804 +f 806/93/806 816/102/816 815/87/815 805/68/805 +f 807/127/807 817/125/817 816/102/816 806/93/806 +f 808/157/808 818/150/818 817/125/817 807/127/807 +f 809/162/809 819/145/819 828/139/828 818/150/818 +f 810/163/810 820/146/820 819/145/819 809/162/809 +f 811/99/811 821/109/821 820/104/820 810/84/810 +f 812/120/812 822/121/822 821/109/821 811/99/811 +f 813/148/813 823/137/823 822/121/822 812/120/812 +f 814/161/814 824/144/824 823/137/823 813/148/813 +f 815/87/815 825/106/825 824/105/824 814/86/814 +f 816/102/816 826/112/826 825/106/825 815/87/815 +f 817/125/817 827/123/827 826/112/826 816/102/816 +f 818/150/818 828/139/828 827/123/827 817/125/817 +f 820/146/820 821/140/821 822/124/822 823/111/823 824/105/824 825/106/825 826/112/826 827/123/827 828/139/828 819/145/819 diff --git a/res/models/turtle2.wings b/res/models/turtle2.wings new file mode 100644 index 0000000..81f9c87 Binary files /dev/null and b/res/models/turtle2.wings differ diff --git a/src/com/mykaruga/models/Models.java b/src/com/mykaruga/models/Models.java new file mode 100644 index 0000000..c034346 --- /dev/null +++ b/src/com/mykaruga/models/Models.java @@ -0,0 +1,86 @@ +package com.mykaruga.models; + + +import static org.lwjgl.opengl.GL11.*; + +import java.io.File; +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import net.spritegen.App; +import net.spritegen.Constants; +import net.spritegen.textures.TextureManager; +import net.spritegen.util.Utils; + +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.porcupine.math.Calc; +import com.porcupine.math.Calc.Buffers; + + +public class Models { + + public static RenderModel turtle; + + + public static void load() { + turtle = new RenderModel(App.modelFile.getAbsolutePath()); + } + + private static int beginList = -1; + private static int endList = -1; + + + public static void renderBegin() { + if (beginList == -1) { + beginList = glGenLists(1); + glNewList(beginList, GL_COMPILE); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + + float spec = (float) App.cfg.mat_specular; + float amb = (float) App.cfg.mat_ambient; + float diff = (float) App.cfg.mat_diffuse; + + FloatBuffer buff = Calc.Buffers.alloc(4); + + Calc.Buffers.fill(buff, amb, amb, amb, 1.0f); + glMaterial(GL_FRONT, GL_AMBIENT, Buffers.mkFillBuff(amb, amb, amb, 1f)); + + buff.clear(); + Calc.Buffers.fill(buff, spec, spec, spec, 1.0f); + glLight(GL_LIGHT0, GL_SPECULAR, buff); + glMaterial(GL_FRONT, GL_SPECULAR, Buffers.mkFillBuff(spec, spec, spec, 1f)); + + buff.clear(); + Calc.Buffers.fill(buff, diff, diff, diff, 1.0f); + glLight(GL_LIGHT0, GL_DIFFUSE, buff); + glMaterial(GL_FRONT, GL_DIFFUSE, Buffers.mkFillBuff(diff, diff, diff, 1f)); + glMaterialf(GL_FRONT, GL_SHININESS, 8); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + glColor4d(1, 1, 1, 1); + glEndList(); + } + glCallList(beginList); + } + + public static void renderEnd() { + if (endList == -1) { + endList = glGenLists(1); + glNewList(endList, GL_COMPILE); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_CULL_FACE); + TextureManager.unbind(); + glDisable(GL_TEXTURE_2D); + glEndList(); + } + glCallList(endList); + } + +} diff --git a/src/com/mykaruga/models/wavefront/loader/Face.java b/src/com/mykaruga/models/wavefront/loader/Face.java new file mode 100644 index 0000000..c09ee47 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/Face.java @@ -0,0 +1,67 @@ +package com.mykaruga.models.wavefront.loader; + + + +public class Face { + + public static final int GL_TRIANGLES = 3; + public static final int GL_QUADS = 4; + + private Vertex[] vertices; + private Vertex[] normals; + private TextureCoordinate[] textures; + private Material material; + + private int type; + + public Face copy() { + Face f = new Face(); + f.setVertices(vertices); + f.setNormals(normals); + f.setTextures(textures); + f.setMaterial(material); + return f; + } + + public Vertex[] getVertices() { + return vertices; + } + + public void setVertices(Vertex[] vertices) { + this.vertices = vertices; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public Vertex[] getNormals() { + return normals; + } + + public void setNormals(Vertex[] normals) { + this.normals = normals; + } + + public TextureCoordinate[] getTextures() { + return textures; + } + + public void setTextures(TextureCoordinate[] textures) { + this.textures = textures; + } + + public Material getMaterial() { + return material; + } + + public void setMaterial(Material material) { + this.material = material; + } + + +} diff --git a/src/com/mykaruga/models/wavefront/loader/LineParserFactory.java b/src/com/mykaruga/models/wavefront/loader/LineParserFactory.java new file mode 100644 index 0000000..e4764a3 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/LineParserFactory.java @@ -0,0 +1,37 @@ +package com.mykaruga.models.wavefront.loader; + + +import java.util.Hashtable; + +import com.mykaruga.models.wavefront.parser.DefaultParser; +import com.mykaruga.models.wavefront.parser.LineParser; + + + + +public abstract class LineParserFactory { + + protected Hashtable parsers = new Hashtable(); + protected RenderModel object = null; + + + public LineParser getLineParser(String line) { + if (line == null) return null; + + line = line.replaceAll(" ", " "); + line = line.replaceAll(" ", ""); + String[] lineWords = line.split(" "); + + if (lineWords.length < 1) return new DefaultParser(); + + String lineType = lineWords[0]; + + LineParser parser = parsers.get(lineType); + if (parser == null) { + parser = new DefaultParser(); + } + + parser.setWords(lineWords); + return parser; + } +} diff --git a/src/com/mykaruga/models/wavefront/loader/Material.java b/src/com/mykaruga/models/wavefront/loader/Material.java new file mode 100644 index 0000000..04633f6 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/Material.java @@ -0,0 +1,50 @@ +package com.mykaruga.models.wavefront.loader; + + +import org.newdawn.slick.opengl.Texture; + + +public class Material { + + private Texture texture; + private Vertex Kd; + private String name; + + public Material(String name) { + this.name = name; + } + + public Material(Material other) { + //this.texture = other.texture; + this.Kd = other.Kd; + this.name = other.name; + } + + public Texture getTexture() { + return texture; + } + + public Material setTexture(Texture texture) { + this.texture = texture; + return this; + } + + public Vertex getKd() { + return Kd; + } + + public void setKa(Vertex kd) { + Kd = kd; + } + + @Override + public String toString() { + return "MAT." + name; + } + + public String getName() { + return name; + } + + +} diff --git a/src/com/mykaruga/models/wavefront/loader/NormalParser.java b/src/com/mykaruga/models/wavefront/loader/NormalParser.java new file mode 100644 index 0000000..824d2e0 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/NormalParser.java @@ -0,0 +1,33 @@ +package com.mykaruga.models.wavefront.loader; + + +import com.mykaruga.models.wavefront.parser.LineParser; + + +public class NormalParser extends LineParser { + + Vertex vertex = null; + + public NormalParser() {} + + @Override + public void parse() { + vertex = new Vertex(); + + try { + vertex.setX(Float.parseFloat(words[1])); + vertex.setY(Float.parseFloat(words[2])); + vertex.setZ(Float.parseFloat(words[3])); + } catch (Exception e) { + throw new RuntimeException("NormalParser Error"); + } + + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + wavefrontObject.getNormals().add(vertex); + + } + +} diff --git a/src/com/mykaruga/models/wavefront/loader/RenderModel.java b/src/com/mykaruga/models/wavefront/loader/RenderModel.java new file mode 100644 index 0000000..de35036 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/RenderModel.java @@ -0,0 +1,300 @@ +package com.mykaruga.models.wavefront.loader; + + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Map.Entry; + +import net.spritegen.textures.TextureManager; +import net.spritegen.util.Log; + +import org.lwjgl.opengl.GL11; +import org.newdawn.slick.opengl.Texture; +import org.newdawn.slick.util.ResourceLoader; + +import com.mykaruga.models.wavefront.parser.LineParser; +import com.mykaruga.models.wavefront.parser.obj.ObjLineParserFactory; + + + +/** + * OBJ 3D object loaded and pre-rendered. + * + * @author Fabien Sanglard + */ +public class RenderModel { + + private static final boolean DEBUG = true; + + public String replTexture = null; + + private ArrayList vertices = new ArrayList(); + private ArrayList normals = new ArrayList(); + private ArrayList textures = new ArrayList(); + private ArrayList faces = new ArrayList(); + + private ObjLineParserFactory parserFactory; + private Hashtable materials = new Hashtable(); + + // This variable is used for both parsing and rendition + private Material currentMaterial; + + private String contextfolder = ""; + + public double radius = 0; + + /** + * Load object with alternate texture. + * + * @param fileName + * @param textureName + */ + public RenderModel(String fileName, String textureName) { + this.replTexture = textureName; + + int lastSlashIndex = fileName.lastIndexOf('/'); + if (lastSlashIndex != -1) this.contextfolder = fileName.substring(0, lastSlashIndex + 1); + + lastSlashIndex = fileName.lastIndexOf('\\'); + if (lastSlashIndex != -1) this.contextfolder = fileName.substring(0, lastSlashIndex + 1); + + parse(fileName); + + calculateRadius(); + + } + +// /** +// * Load object with alternate texture. +// * +// * @param fileName +// * @param textureName +// */ +// public RenderModel(RenderModel other, String textureName) { +// this.vertices = other.vertices; +// this.normals = other.normals; +// this.textures = other.textures; +// this.contextfolder = other.contextfolder; +// this.radius = other.radius; +// +// String pathToTextureBinary = getContextfolder() + textureName; +// Texture texture = TextureManager.load(pathToTextureBinary); +// for (Entry e : other.materials.entrySet()) { +// materials.put(e.getKey(), new Material(e.getValue()).setTexture(texture)); +// } +// for (Face f : other.faces) { +// Face f2; +// faces.add(f2 = f.copy()); +// f2.setMaterial(materials.get(f2.getMaterial().getName())); +// } +// +// } + + public RenderModel(String fileName) { + int lastSlashIndex = fileName.lastIndexOf('/'); + if (lastSlashIndex != -1) this.contextfolder = fileName.substring(0, lastSlashIndex + 1); + + lastSlashIndex = fileName.lastIndexOf('\\'); + if (lastSlashIndex != -1) this.contextfolder = fileName.substring(0, lastSlashIndex + 1); + + parse(fileName); + + calculateRadius(); + } + + + + private void calculateRadius() { + double currentNorm = 0; + for (Vertex vertex : vertices) { + currentNorm = vertex.norm(); + if (currentNorm > radius) radius = currentNorm; + } + + } + + + public String getContextfolder() { + return contextfolder; + } + + + public void parse(String fileName) { + parserFactory = new ObjLineParserFactory(this); + + + InputStream fileInput = ResourceLoader.getResourceAsStream(fileName); + if (fileInput == null) { + // Could not find the file in the jar. + try { + File file = new File(fileName); + if (file.exists()) fileInput = new FileInputStream(file); + } catch (Exception e2) { + e2.printStackTrace(); + } + } + + + BufferedReader in = null; + + try { + in = new BufferedReader(new InputStreamReader(fileInput)); + + String currentLine = null; + while ((currentLine = in.readLine()) != null) + parseLine(currentLine); + + in.close(); + + } catch (Exception e) { + Log.e("Error reading file " + fileName, e); + throw new RuntimeException(e); + } + + +// +// Log.finest("Loaded OBJ from file " + fileName); +// Log.finest(getVertices().size() + " vertices."); +// Log.finest(getNormals().size() + " normals."); +// Log.finest(getTextures().size() + " textures coordinates."); +// Log.finest(getFaces().size() + " faces."); + } + + private int lineCounter = 0; + + private void parseLine(String currentLine) { + if ("".equals(currentLine)) return; + + LineParser parser = parserFactory.getLineParser(currentLine); + try { + parser.parse(); + parser.incoporateResults(this); + } catch (Throwable t) { + Log.e("ERROR at line " + lineCounter + " : " + currentLine, t); + System.exit(1); + } + lineCounter++; + } + + public int displayListId = 0; + + public void render() { + + + if (displayListId != 0) { + GL11.glCallList(displayListId); + return; + } + + displayListId = GL11.glGenLists(1); + + GL11.glNewList(displayListId, GL11.GL_COMPILE); + + Face face = null; + Material material = new Material("__non_existant"); + + for (int i = 0; i < getFaces().size(); i++) { + face = getFaces().get(i); + + if (!material.equals(face.getMaterial())) { + // Set texture and setColor + material = face.getMaterial(); + if (material == null) { + Log.w("No material in model!"); + } else if (material.getTexture() != null) { + GL11.glBindTexture(GL11.GL_TEXTURE_2D, material.getTexture().getTextureID()); + } else + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); + + if (material != null && material.getKd() != null) + GL11.glColor3f(material.getKd().getX(), material.getKd().getY(), material.getKd().getZ()); + } + + if (face.getType() == Face.GL_TRIANGLES) { + GL11.glBegin(GL11.GL_TRIANGLES); + } else if (face.getType() == Face.GL_QUADS) { + GL11.glBegin(GL11.GL_QUADS); + } else { + GL11.glBegin(GL11.GL_POLYGON); + } + + Vertex vertex = null; + Vertex normal = null; + TextureCoordinate textureCoo = null; + for (int j = 0; j < face.getVertices().length; j++) { + vertex = face.getVertices()[j]; + if (j < face.getNormals().length && face.getNormals()[j] != null) { + normal = face.getNormals()[j]; + GL11.glNormal3f(normal.getX(), normal.getY(), normal.getZ()); + } + + if (j < face.getTextures().length && face.getTextures()[j] != null) { + textureCoo = face.getTextures()[j]; + GL11.glTexCoord2f(textureCoo.getU(), textureCoo.getV()); + //GL11.glTexCoord2f(textureCoo.getV(),textureCoo.getU()); + } + + GL11.glVertex3f(vertex.getX(), vertex.getY(), vertex.getZ()); + } + GL11.glEnd(); + } + GL11.glEndList(); + } + + public void setMaterials(Hashtable materials) { + this.materials = materials; + } + + public void setTextures(ArrayList textures) { + this.textures = textures; + } + + public ArrayList getTextures() { + return textures; + } + + public void setVertices(ArrayList vertices) { + this.vertices = vertices; + } + + public ArrayList getVertices() { + return vertices; + } + + public void setFaces(ArrayList faces) { + this.faces = faces; + } + + public ArrayList getFaces() { + return faces; + } + + public void setNormals(ArrayList normals) { + this.normals = normals; + } + + public ArrayList getNormals() { + return normals; + } + + public Hashtable getMaterials() { + + return this.materials; + } + + public Material getCurrentMaterial() { + return currentMaterial; + } + + public void setCurrentMaterial(Material currentMaterial) { + this.currentMaterial = currentMaterial; + } + + + +} diff --git a/src/com/mykaruga/models/wavefront/loader/TextureCoordinate.java b/src/com/mykaruga/models/wavefront/loader/TextureCoordinate.java new file mode 100644 index 0000000..0a54a9f --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/TextureCoordinate.java @@ -0,0 +1,35 @@ +package com.mykaruga.models.wavefront.loader; + + +public class TextureCoordinate { + + private float u; + private float v; + private float w; + + public float getU() { + return u; + } + + public void setU(float u) { + this.u = u; + } + + public float getV() { + return v; + } + + public void setV(float v) { + this.v = v; + } + + public float getW() { + return w; + } + + public void setW(float w) { + this.w = w; + } + + +} diff --git a/src/com/mykaruga/models/wavefront/loader/Vertex.java b/src/com/mykaruga/models/wavefront/loader/Vertex.java new file mode 100644 index 0000000..d8b2397 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/loader/Vertex.java @@ -0,0 +1,45 @@ +package com.mykaruga.models.wavefront.loader; + + +public class Vertex { + + private float x; + private float y; + private float z; + + public Vertex(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Vertex() {} + + public float getX() { + return x; + } + + public void setX(float x) { + this.x = x; + } + + public float getY() { + return y; + } + + public void setY(float y) { + this.y = y; + } + + public float getZ() { + return z; + } + + public void setZ(float z) { + this.z = z; + } + + public double norm() { + return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)); + } +} diff --git a/src/com/mykaruga/models/wavefront/parser/CommentParser.java b/src/com/mykaruga/models/wavefront/parser/CommentParser.java new file mode 100644 index 0000000..b7ae5f2 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/CommentParser.java @@ -0,0 +1,15 @@ +package com.mykaruga.models.wavefront.parser; + + +import com.mykaruga.models.wavefront.loader.RenderModel; + + +public class CommentParser extends LineParser { + + @Override + public void incoporateResults(RenderModel wavefrontObject) {} + + @Override + public void parse() {} + +} diff --git a/src/com/mykaruga/models/wavefront/parser/DefaultParser.java b/src/com/mykaruga/models/wavefront/parser/DefaultParser.java new file mode 100644 index 0000000..ed0165c --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/DefaultParser.java @@ -0,0 +1,19 @@ +package com.mykaruga.models.wavefront.parser; + + +import com.mykaruga.models.wavefront.loader.RenderModel; + + +public class DefaultParser extends LineParser { + + public DefaultParser() {} + + @Override + public void parse() { + + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) {} + +} diff --git a/src/com/mykaruga/models/wavefront/parser/LineParser.java b/src/com/mykaruga/models/wavefront/parser/LineParser.java new file mode 100644 index 0000000..5aa4a74 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/LineParser.java @@ -0,0 +1,19 @@ +package com.mykaruga.models.wavefront.parser; + + +import com.mykaruga.models.wavefront.loader.RenderModel; + + +public abstract class LineParser { + + protected String[] words = null; + + public void setWords(String[] words) { + this.words = words; + } + + public abstract void parse(); + + public abstract void incoporateResults(RenderModel wavefrontObject); + +} diff --git a/src/com/mykaruga/models/wavefront/parser/mtl/KdMapParser.java b/src/com/mykaruga/models/wavefront/parser/mtl/KdMapParser.java new file mode 100644 index 0000000..d578f3e --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/mtl/KdMapParser.java @@ -0,0 +1,41 @@ +package com.mykaruga.models.wavefront.parser.mtl; + + +import net.spritegen.textures.TextureManager; + +import org.newdawn.slick.opengl.Texture; + +import com.mykaruga.models.wavefront.loader.Material; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.LineParser; + + +public class KdMapParser extends LineParser { + + private Texture texture = null; + private RenderModel object = null; + private String textureFileName = null; + + public KdMapParser(RenderModel object) { + this.object = object; + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + + if (texture != null) { + Material currentMaterial = wavefrontObject.getCurrentMaterial(); + currentMaterial.setTexture(texture); + } + } + + @Override + public void parse() { + String textureFileName = words[words.length - 1]; + String pathToTextureBinary = object.getContextfolder() + (object.replTexture == null ? textureFileName : object.replTexture); + + // load texture, if already loaded, use the same instance. + texture = TextureManager.load(pathToTextureBinary); + } + +} diff --git a/src/com/mykaruga/models/wavefront/parser/mtl/KdParser.java b/src/com/mykaruga/models/wavefront/parser/mtl/KdParser.java new file mode 100644 index 0000000..ba531d3 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/mtl/KdParser.java @@ -0,0 +1,35 @@ +package com.mykaruga.models.wavefront.parser.mtl; + + +import com.mykaruga.models.wavefront.loader.Material; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.loader.Vertex; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class KdParser extends LineParser { + + Vertex kd = null; + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + Material currentMaterial = wavefrontObject.getCurrentMaterial(); + currentMaterial.setKa(kd); + + } + + @Override + public void parse() { + kd = new Vertex(); + + try { + kd.setX(Float.parseFloat(words[1])); + kd.setY(Float.parseFloat(words[2])); + kd.setZ(Float.parseFloat(words[3])); + } catch (Exception e) { + throw new RuntimeException("VertexParser Error"); + } + } + +} diff --git a/src/com/mykaruga/models/wavefront/parser/mtl/MaterialFileParser.java b/src/com/mykaruga/models/wavefront/parser/mtl/MaterialFileParser.java new file mode 100644 index 0000000..c949b5c --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/mtl/MaterialFileParser.java @@ -0,0 +1,74 @@ +package com.mykaruga.models.wavefront.parser.mtl; + + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Hashtable; + + +import org.newdawn.slick.util.ResourceLoader; + +import com.mykaruga.models.wavefront.loader.Material; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class MaterialFileParser extends LineParser { + + Hashtable materials = new Hashtable(); + private RenderModel object; + private MtlLineParserFactory parserFactory = null; + + public MaterialFileParser(RenderModel object) { + this.object = object; + this.parserFactory = new MtlLineParserFactory(object); + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + // Material are directly added by the parser, no need to do anything here... + } + + @Override + public void parse() { + String filename = words[1]; + + String pathToMTL = object.getContextfolder() + filename; + + InputStream fileInput = ResourceLoader.getResourceAsStream(pathToMTL); + if (fileInput == null) { + // Could not find the file in the jar. + try { + File file = new File(pathToMTL); + if (file.exists()) fileInput = new FileInputStream(file); + } catch (Exception e2) { + e2.printStackTrace(); + } + } + + try { + BufferedReader in = new BufferedReader(new InputStreamReader(fileInput)); + + String currentLine = null; + while ((currentLine = in.readLine()) != null) { + + LineParser parser = parserFactory.getLineParser(currentLine); + parser.parse(); + parser.incoporateResults(object); + } + + if (in != null) in.close(); + + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error parsing " + pathToMTL); + } + + } + + +} \ No newline at end of file diff --git a/src/com/mykaruga/models/wavefront/parser/mtl/MaterialParser.java b/src/com/mykaruga/models/wavefront/parser/mtl/MaterialParser.java new file mode 100644 index 0000000..65fcc7e --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/mtl/MaterialParser.java @@ -0,0 +1,27 @@ +package com.mykaruga.models.wavefront.parser.mtl; + + +import com.mykaruga.models.wavefront.loader.Material; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class MaterialParser extends LineParser { + + String materialName = ""; + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + Material newMaterial = new Material(materialName); + + wavefrontObject.getMaterials().put(materialName, newMaterial); + wavefrontObject.setCurrentMaterial(newMaterial); + } + + @Override + public void parse() { + materialName = words[1]; + } + +} diff --git a/src/com/mykaruga/models/wavefront/parser/mtl/MtlLineParserFactory.java b/src/com/mykaruga/models/wavefront/parser/mtl/MtlLineParserFactory.java new file mode 100644 index 0000000..715d506 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/mtl/MtlLineParserFactory.java @@ -0,0 +1,24 @@ +package com.mykaruga.models.wavefront.parser.mtl; + + +import com.mykaruga.models.wavefront.loader.LineParserFactory; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.CommentParser; + + + +public class MtlLineParserFactory extends LineParserFactory { + + + + public MtlLineParserFactory(RenderModel object) { + this.object = object; + parsers.put("newmtl", new MaterialParser()); + parsers.put("Kd", new KdParser()); + parsers.put("map_Kd", new KdMapParser(object)); + parsers.put("#", new CommentParser()); + } + + + +} diff --git a/src/com/mykaruga/models/wavefront/parser/obj/FaceParser.java b/src/com/mykaruga/models/wavefront/parser/obj/FaceParser.java new file mode 100644 index 0000000..0a52c1e --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/obj/FaceParser.java @@ -0,0 +1,98 @@ +package com.mykaruga.models.wavefront.parser.obj; + + +import com.mykaruga.models.wavefront.loader.Face; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.loader.TextureCoordinate; +import com.mykaruga.models.wavefront.loader.Vertex; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class FaceParser extends LineParser { + + private Face face; + private Vertex[] vertices; + private Vertex[] normals; + private TextureCoordinate[] textures; + private RenderModel object = null; + + public FaceParser(RenderModel object) { + this.object = object; + } + + @Override + public void parse() { + face = new Face(); + normals = new Vertex[words.length - 1]; + textures = new TextureCoordinate[words.length - 1]; + switch (words.length) { + case 4: + parseTriangles(); + break; + case 5: + parseQuad(); + break; + default: + parsePolygon(); + } + + + } + + private void parseTriangles() { + face.setType(Face.GL_TRIANGLES); + parseLine(3); + } + + private void parsePolygon() { + face.setType(words.length - 1); + parseLine(words.length - 1); + } + + private void parseLine(int vertexCount) { + String[] rawFaces = null; + int currentValue; + vertices = new Vertex[vertexCount]; + for (int i = 1; i <= vertexCount; i++) { + rawFaces = words[i].split("/"); + + // v + currentValue = Integer.parseInt(rawFaces[0]); + vertices[i - 1] = object.getVertices().get(currentValue - 1); // -1 because references starts at 1 + + if (rawFaces.length == 1) continue; + + if (!"".equals(rawFaces[1]) && rawFaces.length == 3) { + currentValue = Integer.parseInt(rawFaces[1]); + if (currentValue <= object.getTextures().size()) // This is to compensate the fact that if no texture is in the obj file, sometimes '1' is put instead of 'blank' (we find coord1/1/coord3 instead of coord1//coord3 or coord1/coord3) + textures[i - 1] = object.getTextures().get(currentValue - 1); // -1 because references starts at 1 + } + + + currentValue = Integer.parseInt(rawFaces[rawFaces.length - 1]); + + normals[i - 1] = object.getNormals().get(currentValue - 1); // -1 because references starts at 1 + } + } + + private void parseQuad() { + face.setType(Face.GL_QUADS); + parseLine(4); + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + + face.setNormals(this.normals); + face.setVertices(this.vertices); + face.setTextures(this.textures); + if (wavefrontObject.getCurrentMaterial() != null) { + face.setMaterial(wavefrontObject.getCurrentMaterial()); + } + wavefrontObject.getFaces().add(face); + + } + + static int faceC = 0; +} diff --git a/src/com/mykaruga/models/wavefront/parser/obj/FreeFormParser.java b/src/com/mykaruga/models/wavefront/parser/obj/FreeFormParser.java new file mode 100644 index 0000000..99ee765 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/obj/FreeFormParser.java @@ -0,0 +1,21 @@ +package com.mykaruga.models.wavefront.parser.obj; + + +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class FreeFormParser extends LineParser { + + public FreeFormParser() {} + + @Override + public void parse() { + + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) {} + +} diff --git a/src/com/mykaruga/models/wavefront/parser/obj/MaterialParser.java b/src/com/mykaruga/models/wavefront/parser/obj/MaterialParser.java new file mode 100644 index 0000000..49b4fef --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/obj/MaterialParser.java @@ -0,0 +1,27 @@ +package com.mykaruga.models.wavefront.parser.obj; + + +import com.mykaruga.models.wavefront.loader.Material; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class MaterialParser extends LineParser { + String materialName = ""; + + @Override + public void parse() { + materialName = words[1]; + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + Material newMaterial = wavefrontObject.getMaterials().get(materialName); + wavefrontObject.setCurrentMaterial(newMaterial); + + } + + + +} diff --git a/src/com/mykaruga/models/wavefront/parser/obj/ObjLineParserFactory.java b/src/com/mykaruga/models/wavefront/parser/obj/ObjLineParserFactory.java new file mode 100644 index 0000000..4609355 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/obj/ObjLineParserFactory.java @@ -0,0 +1,29 @@ +package com.mykaruga.models.wavefront.parser.obj; + + +import com.mykaruga.models.wavefront.loader.LineParserFactory; +import com.mykaruga.models.wavefront.loader.NormalParser; +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.parser.CommentParser; +import com.mykaruga.models.wavefront.parser.mtl.MaterialFileParser; + + + +public class ObjLineParserFactory extends LineParserFactory { + + + + public ObjLineParserFactory(RenderModel object) { + this.object = object; + parsers.put("v", new VertexParser()); + parsers.put("vn", new NormalParser()); + parsers.put("vp", new FreeFormParser()); + parsers.put("vt", new TextureCooParser()); + parsers.put("f", new FaceParser(object)); + parsers.put("#", new CommentParser()); + parsers.put("mtllib", new MaterialFileParser(object)); + parsers.put("usemtl", new MaterialParser()); + } + + +} diff --git a/src/com/mykaruga/models/wavefront/parser/obj/TextureCooParser.java b/src/com/mykaruga/models/wavefront/parser/obj/TextureCooParser.java new file mode 100644 index 0000000..1cf9138 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/obj/TextureCooParser.java @@ -0,0 +1,37 @@ +package com.mykaruga.models.wavefront.parser.obj; + + +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.loader.TextureCoordinate; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class TextureCooParser extends LineParser { + + private TextureCoordinate coordinate = null; + + public TextureCooParser() {} + + @Override + public void parse() { + coordinate = new TextureCoordinate(); + try { + if (words.length >= 2) coordinate.setU(Float.parseFloat(words[1])); + + if (words.length >= 3) coordinate.setV(1 - Float.parseFloat(words[2])); // OBJ origin is at upper left, OpenGL origin is at lower left. + + if (words.length >= 4) coordinate.setW(Float.parseFloat(words[3])); + + } catch (Exception e) { + throw new RuntimeException("TextureParser Error"); + } + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + wavefrontObject.getTextures().add(coordinate); + + } + +} diff --git a/src/com/mykaruga/models/wavefront/parser/obj/VertexParser.java b/src/com/mykaruga/models/wavefront/parser/obj/VertexParser.java new file mode 100644 index 0000000..8d87990 --- /dev/null +++ b/src/com/mykaruga/models/wavefront/parser/obj/VertexParser.java @@ -0,0 +1,34 @@ +package com.mykaruga.models.wavefront.parser.obj; + + +import com.mykaruga.models.wavefront.loader.RenderModel; +import com.mykaruga.models.wavefront.loader.Vertex; +import com.mykaruga.models.wavefront.parser.LineParser; + + + +public class VertexParser extends LineParser { + + Vertex vertex = null; + + public VertexParser() {} + + @Override + public void parse() { + vertex = new Vertex(); + + try { + vertex.setX(Float.parseFloat(words[1])); + vertex.setY(Float.parseFloat(words[2])); + vertex.setZ(Float.parseFloat(words[3])); + } catch (Exception e) { + throw new RuntimeException("VertexParser Error"); + } + } + + @Override + public void incoporateResults(RenderModel wavefrontObject) { + wavefrontObject.getVertices().add(vertex); + } + +} diff --git a/src/com/porcupine/color/HSV.java b/src/com/porcupine/color/HSV.java new file mode 100644 index 0000000..64921b1 --- /dev/null +++ b/src/com/porcupine/color/HSV.java @@ -0,0 +1,152 @@ +package com.porcupine.color; + + +import java.awt.Color; + +import com.porcupine.math.Calc; + + +/** + * HSV color + * + * @author MightyPork + */ +public class HSV { + + /** H */ + public double h; + /** S */ + public double s; + /** V */ + public double v; + + /** + * Create black color 0,0,0 + */ + public HSV() {} + + /** + * Color from HSV 0-1 + * + * @param h + * @param s + * @param v + */ + public HSV(Number h, Number s, Number v) { + this.h = h.doubleValue(); + this.s = s.doubleValue(); + this.v = v.doubleValue(); + norm(); + } + + /** + * @return hue 0-1 + */ + public double h() { + return h; + } + + /** + * @return saturation 0-1 + */ + public double s() { + return s; + } + + /** + * @return value/brightness 0-1 + */ + public double v() { + return v; + } + + /** + * Set color to other color + * + * @param copied copied color + * @return this + */ + public HSV setTo(HSV copied) { + + h = copied.h; + s = copied.s; + v = copied.v; + + norm(); + return this; + } + + /** + * Set to H,S,V 0-1 + * + * @param h hue + * @param s saturation + * @param v value + * @return this + */ + public HSV setTo(Number h, Number s, Number v) { + this.h = h.doubleValue(); + this.s = s.doubleValue(); + this.v = v.doubleValue(); + norm(); + return this; + } + + /** + * Fix numbers out of range 0-1 + */ + public void norm() { + h = Calc.clampd(h, 0, 1); + s = Calc.clampd(s, 0, 1); + v = Calc.clampd(v, 0, 1); + } + + /** + * Convert to RGB + * + * @return RGB representation + */ + public RGB toRGB() { + norm(); + + int rgb = Color.HSBtoRGB((float) h, (float) s, (float) v); + + return RGB.fromHex(rgb); + } + + /** + * Make from RGB + * + * @param color RGB + * @return HSV + */ + public static HSV fromRGB(RGB color) { + return color.toHSV(); + } + + @Override + public String toString() { + return "HSV[" + h + ";" + s + ";" + v + "]"; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (!(obj instanceof HSV)) return false; + return ((HSV) obj).h == h && ((HSV) obj).s == s && ((HSV) obj).v == v; + } + + @Override + public int hashCode() { + return Double.valueOf(h).hashCode() ^ Double.valueOf(s).hashCode() ^ Double.valueOf(v).hashCode(); + } + + /** + * Get a copy + * + * @return copy + */ + public HSV copy() { + return new HSV().setTo(this); + } +} diff --git a/src/com/porcupine/color/RGB.java b/src/com/porcupine/color/RGB.java new file mode 100644 index 0000000..3c8aae6 --- /dev/null +++ b/src/com/porcupine/color/RGB.java @@ -0,0 +1,336 @@ +package com.porcupine.color; + + +import java.awt.Color; + +import com.porcupine.math.Calc; + + +/** + * RGB color + * + * @author MightyPork + */ +public class RGB { + + /** White */ + public static final RGB WHITE = new RGB(1, 1, 1); + /** Black */ + public static final RGB BLACK = new RGB(0, 0, 0); + /** Red */ + public static final RGB RED = new RGB(1, 0, 0); + /** Lime green */ + public static final RGB GREEN = new RGB(0, 1, 0); + /** Blue */ + public static final RGB BLUE = new RGB(0, 0, 1); + /** Yellow */ + public static final RGB YELLOW = new RGB(1, 1, 0); + /** Purple */ + public static final RGB PURPLE = new RGB(1, 0, 1); + /** Cyan */ + public static final RGB CYAN = new RGB(0, 1, 1); + /** orange */ + public static final RGB ORANGE = new RGB(1, 0.6, 0); + /** no color (alpha=0) */ + public static final RGB TRANSPARENT = new RGB(0, 0, 0, 0); + + /** R */ + public double r; + /** G */ + public double g; + /** B */ + public double b; + /** ALPHA */ + public double a = 1; + + /** + * Create black color 0,0,0 + */ + public RGB() {} + + /** + * Get copy with custom alpha + * + * @param alpha alpha to set + * @return copy w/ alpha + */ + public RGB setAlpha(double alpha) { + return copy().setAlpha_ip(alpha); + } + + /** + * set alpha IP + * + * @param alpha alpha to set + * @return this + */ + public RGB setAlpha_ip(double alpha) { + a = alpha; + norm(); + return this; + } + + /** + * Get copy. + * + * @return copy + */ + public RGB copy() { + return new RGB(r, g, b, a); + } + + /** + * Get copy with alpha multiplied by custom value + * + * @param alpha alpha to set + * @return copy w/ alpha + */ + public RGB mulAlpha(double alpha) { + return copy().mulAlpha_ip(alpha); + } + + /** + * Multiply alpha by given number + * + * @param alpha alpha multiplier + * @return this + */ + public RGB mulAlpha_ip(double alpha) { + a *= alpha; + norm(); + return this; + } + + /** + * Color from RGB 0-1 + * + * @param r red + * @param g green + * @param b blue + */ + public RGB(Number r, Number g, Number b) { + this.r = r.doubleValue(); + this.g = g.doubleValue(); + this.b = b.doubleValue(); + norm(); + } + + /** + * Color from RGB 0-1 + * + * @param r red + * @param g green + * @param b blue + * @param a alpha + */ + public RGB(Number r, Number g, Number b, Number a) { + this.r = r.doubleValue(); + this.g = g.doubleValue(); + this.b = b.doubleValue(); + this.a = a.doubleValue(); + norm(); + } + + /** + * Color from hex 0xRRGGBB + * + * @param hex hex integer + */ + public RGB(int hex) { + setTo(RGB.fromHex(hex)); + norm(); + } + + /** + * Color from hex 0xRRGGBB + * + * @param hex hex integer + * @param alpha alpha color + */ + public RGB(int hex, double alpha) { + setTo(RGB.fromHex(hex)); + a = alpha; + norm(); + } + + /** + * Color from other RGB and alpha channel + * + * @param color other RGB color + * @param alpha new alpha channel + */ + public RGB(RGB color, double alpha) { + setTo(color); + setAlpha_ip(alpha); + } + + /** + * @return red channel 0-1 + */ + public double r() { + return r; + } + + /** + * @return green channel 0-1 + */ + public double g() { + return g; + } + + /** + * @return blue channel 0-1 + */ + public double b() { + return b; + } + + /** + * @return alpha 0-1 + */ + public double a() { + return a; + } + + /** + * Set color to other color + * + * @param copied copied color + * @return this + */ + public RGB setTo(RGB copied) { + + r = copied.r; + g = copied.g; + b = copied.b; + a = copied.a; + + norm(); + return this; + } + + /** + * Set to represent hex color + * + * @param hex hex integer RRGGBB + * @return this + */ + public RGB setTo(int hex) { + setTo(RGB.fromHex(hex)); + norm(); + return this; + } + + /** + * Set to R,G,B 0-1 + * + * @param r red + * @param g green + * @param b blue + * @param a alpha + * @return this + */ + public RGB setTo(Number r, Number g, Number b, Number a) { + this.r = r.doubleValue(); + this.g = g.doubleValue(); + this.b = b.doubleValue(); + this.a = a.doubleValue(); + norm(); + return this; + } + + /** + * Set to R,G,B 0-1 + * + * @param r red + * @param g green + * @param b blue + * @return this + */ + public RGB setTo(Number r, Number g, Number b) { + this.r = r.doubleValue(); + this.g = g.doubleValue(); + this.b = b.doubleValue(); + this.a = 1; + norm(); + return this; + } + + /** + * Fix numbers out of range 0-1 + * + * @return this + */ + public RGB norm() { + r = Calc.clampd(r, 0, 1); + g = Calc.clampd(g, 0, 1); + b = Calc.clampd(b, 0, 1); + a = Calc.clampd(a, 0, 1); + return this; + } + + /** + * Get hex value 0xRRGGBB + * + * @return hex value RRGGBB + */ + public int getHex() { + int ri = (int) Math.round(r * 255); + int gi = (int) Math.round(g * 255); + int bi = (int) Math.round(b * 255); + return (ri << 16) | (gi << 8) | bi; + } + + /** + * Convert to HSV + * + * @return HSV representation + */ + public HSV toHSV() { + float[] hsv = { 0, 0, 0 }; + Color.RGBtoHSB((int) (r * 255), (int) (g * 255), (int) (b * 255), hsv); + return new HSV(hsv[0], hsv[1], hsv[2]); + } + + /** + * Create color from hex 0xRRGGBB + * + * @param hex hex RRGGBB + * @return the new color + */ + public static RGB fromHex(int hex) { + int bi = hex & 0xff; + int gi = (hex >> 8) & 0xff; + int ri = (hex >> 16) & 0xff; + return new RGB(ri / 255D, gi / 255D, bi / 255D); + } + + + /** + * Make from HSV + * + * @param color HSV color + * @return RGB + */ + public static RGB fromHSV(HSV color) { + return color.toRGB(); + } + + @Override + public String toString() { + return "RGB[" + r + ";" + g + ";" + b + ";" + a + "]"; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (!(obj instanceof RGB)) return false; + return ((RGB) obj).r == r && ((RGB) obj).g == g && ((RGB) obj).b == b && ((RGB) obj).a == a; + } + + @Override + public int hashCode() { + return Double.valueOf(r).hashCode() ^ Double.valueOf(g).hashCode() ^ Double.valueOf(b).hashCode() ^ Double.valueOf(a).hashCode(); + } + +} diff --git a/src/com/porcupine/coord/Coord.java b/src/com/porcupine/coord/Coord.java new file mode 100644 index 0000000..bde3d6e --- /dev/null +++ b/src/com/porcupine/coord/Coord.java @@ -0,0 +1,729 @@ +package com.porcupine.coord; + + +import java.util.Random; + +import com.porcupine.math.Calc; + + +/** + * Coordinate class, object with three or two double coordinates.
+ * + * @author MightyPork + */ +public class Coord { + /** Zero Coord */ + public static final Coord ZERO = new Coord(0, 0); + /** Coord [1;1;1] */ + public static final Coord ONE = new Coord(1, 1, 1); + + /** RNG */ + protected static Random rand = new Random(); + /** X coordinate */ + public double x = 0; + + /** Y coordinate */ + public double y = 0; + + /** Z coordinate */ + public double z = 0; + + /** + * Create zero coord + */ + public Coord() {} + + /** + * Create 2D coord + * + * @param x x coordinate + * @param y y coordinate + */ + public Coord(Number x, Number y) { + setTo(x, y); + } + + /** + * Create 3D coord + * + * @param x x coordinate + * @param y y coordinate + * @param z z coordinate + */ + public Coord(Number x, Number y, Number z) { + setTo(x, y, z); + } + + /** + * Create coord as a copy of another + * + * @param copied copied coord + */ + public Coord(Coord copied) { + this.x = copied.x; + this.y = copied.y; + this.z = copied.z; + } + + /** + * Convert X and Y coordinates of this coord to a new CoordI. + * + * @return the new CoordI + */ + public CoordI toCoordI() { + return new CoordI((int) Math.round(x), (int) Math.round(y)); + } + + /** + * Generate random coord (gaussian) + * + * @param max max distance from 0 + * @return new coord + */ + public static Coord random(double max) { + return new Coord(Calc.clampd(rand.nextGaussian() * max, -max * 2, max * 2), Calc.clampd(rand.nextGaussian() * max, -max * 2, max * 2), + Calc.clampd(rand.nextGaussian() * max, -max * 2, max * 2)); + } + + /** + * Generate random coord (min-max) + * + * @param min min offset + * @param max max offset + * @return new coord + */ + public static Coord random(double min, double max) { + return new Coord((rand.nextBoolean() ? -1 : 1) * (min + rand.nextDouble() * (max - min)), (rand.nextBoolean() ? -1 : 1) + * (min + rand.nextDouble() * (max - min)), (rand.nextBoolean() ? -1 : 1) * (min + rand.nextDouble() * (max - min))); + } + + /** + * offset randomly in place + * + * @param max max +- offset + * @return this + */ + public Coord random_offset_ip(double max) { + return add(random(max)); + } + + /** + * offset randomly in place + * + * @param min min offset + * @param max max offset + * @return this + */ + public Coord random_offset_ip(double min, double max) { + add(random(min, max)); + return this; + } + + /** + * Set to max values of this and other coord + * + * @param other other coord + */ + public void setMax(Coord other) { + x = Math.max(x, other.x); + y = Math.max(y, other.y); + z = Math.max(z, other.z); + } + + /** + * Set to min values of this and other coord + * + * @param other other coord + */ + public void setMin(Coord other) { + x = Math.min(x, other.x); + y = Math.min(y, other.y); + z = Math.min(z, other.z); + } + + /** + * offset randomly + * + * @param max max +- offset + * @return offset coord + */ + public Coord random_offset(double max) { + Coord r = random(1); + Vec v = new Vec(r); + v.norm_ip(0.00001 + rand.nextDouble() * max); + return copy().add_ip(v); + } + + /** + * offset randomly + * + * @param min min offset + * @param max max offset + * @return offset coord + */ + public Coord random_offset(double min, double max) { + return copy().add_ip(random(min, max)); + } + + /** + * @return X as double + */ + public double x() { + return x; + } + + /** + * @return Y as double + */ + public double y() { + return y; + } + + /** + * @return Z as double + */ + public double z() { + return z; + } + + /** + * @return X as double + */ + public double xd() { + return x; + } + + /** + * @return Y as double + */ + public double yd() { + return y; + } + + /** + * @return Z as double + */ + public double zd() { + return z; + } + + /** + * @return X as double + */ + public float xf() { + return (float) x; + } + + /** + * @return Y as double + */ + public float yf() { + return (float) y; + } + + /** + * @return Z as double + */ + public float zf() { + return (float) z; + } + + + /** + * @return X as double + */ + public int xi() { + return (int) Math.round(x); + } + + /** + * @return Y as double + */ + public int yi() { + return (int) Math.round(y); + } + + /** + * @return Z as double + */ + public int zi() { + return (int) Math.round(z); + } + + /** + * Set 3D coordinates to + * + * @param x x coordinate + * @param y y coordinate + * @param z z coordinate + * @return this + */ + public Coord setTo(Number x, Number y, Number z) { + this.x = x.doubleValue(); + this.y = y.doubleValue(); + this.z = z.doubleValue(); + return this; + } + + /** + * Set 2D coordinates to + * + * @param x x coordinate + * @param y y coordinate + * @return this + */ + public Coord setTo(Number x, Number y) { + setTo(x, y, 0); + return this; + } + + /** + * Set coordinates to match other coord + * + * @param copied coord whose coordinates are used + * @return this + */ + public Coord setTo(Coord copied) { + setTo(copied.x, copied.y, copied.z); + return this; + } + + /** + * Set X coordinate in place + * + * @param x x coordinate + * @return this + */ + public Coord setX_ip(Number x) { + this.x = x.doubleValue(); + return this; + } + + /** + * Set Y coordinate in place + * + * @param y y coordinate + * @return this + */ + public Coord setY_ip(Number y) { + this.y = y.doubleValue(); + return this; + } + + /** + * Set Z coordinate in place + * + * @param z z coordinate + * @return this + */ + public Coord setZ_ip(Number z) { + this.z = z.doubleValue(); + return this; + } + + /** + * Set X coordinate in a copy + * + * @param x x coordinate + * @return copy with set coordinate + */ + public Coord setX(Number x) { + return copy().setX_ip(x); + } + + /** + * Set Y coordinate in a copy + * + * @param y y coordinate + * @return copy with set coordinate + */ + public Coord setY(Number y) { + return copy().setY_ip(y); + } + + /** + * Set Z coordinate in a copy + * + * @param z z coordinate + * @return copy with set coordinate + */ + public Coord setZ(Number z) { + return copy().setZ_ip(z); + } + + + + /** + * Get a copy subtracted by 3D coordinate + * + * @param x x offset + * @param y y offset + * @param z z offset + * @return the offset copy + */ + public Coord sub(Number x, Number y, Number z) { + return copy().sub_ip(x, y, z); + } + + /** + * Get a copy subtracted by 2D coordinate + * + * @param x x offset + * @param y y offset + * @return the offset copy + */ + public Coord sub(Number x, Number y) { + return copy().sub_ip(x, y); + } + + /** + * Get a copy subtracted by vector + * + * @param vec offset + * @return the offset copy + */ + public Coord sub(Coord vec) { + return copy().sub_ip(vec); + } + + /** + * Offset by 3D coordinate in place + * + * @param x x offset + * @param y y offset + * @param z z offset + * @return this + */ + public Coord sub_ip(Number x, Number y, Number z) { + this.x -= x.doubleValue(); + this.y -= y.doubleValue(); + this.z -= z.doubleValue(); + return this; + } + + /** + * Offset by 2D coordinate in place + * + * @param x x offset + * @param y y offset + * @return this + */ + public Coord sub_ip(Number x, Number y) { + this.x -= x.doubleValue(); + this.y -= y.doubleValue(); + return this; + } + + /** + * Offset by vector in place + * + * @param vec offset + * @return this + */ + public Coord sub_ip(Coord vec) { + this.x -= vec.x; + this.y -= vec.y; + this.z -= vec.z; + return this; + } + + /** + * Get a copy offset by 3D coordinate + * + * @param x x offset + * @param y y offset + * @param z z offset + * @return the offset copy + */ + public Coord add(Number x, Number y, Number z) { + return copy().add_ip(x, y, z); + } + + /** + * Get a copy offset by 2D coordinate + * + * @param x x offset + * @param y y offset + * @return the offset copy + */ + public Coord add(Number x, Number y) { + return copy().add_ip(x, y); + } + + /** + * Get a copy offset by vector + * + * @param vec offset + * @return the offset copy + */ + public Coord add(Coord vec) { + return copy().add_ip(vec); + } + + /** + * Offset by 3D coordinate in place + * + * @param x x offset + * @param y y offset + * @param z z offset + * @return this + */ + public Coord add_ip(Number x, Number y, Number z) { + this.x += x.doubleValue(); + this.y += y.doubleValue(); + this.z += z.doubleValue(); + return this; + } + + /** + * Offset by 2D coordinate in place + * + * @param x x offset + * @param y y offset + * @return this + */ + public Coord add_ip(Number x, Number y) { + this.x += x.doubleValue(); + this.y += y.doubleValue(); + return this; + } + + /** + * Offset by vector in place + * + * @param vec offset + * @return this + */ + public Coord add_ip(Coord vec) { + this.x += vec.x; + this.y += vec.y; + this.z += vec.z; + return this; + } + + /** + * @return copy of this vector + */ + public Coord copy() { + return new Coord(x, y, z); + } + + + /** + * Get distance to other point + * + * @param point other point + * @return distance in units + */ + public double distTo(Coord point) { + return Math.sqrt((point.x - x) * (point.x - x) + (point.y - y) * (point.y - y) + (point.z - z) * (point.z - z)); + } + + /** + * Create vector from this point to other point + * + * @param point second point + * @return vector + */ + public Vec vecTo(Coord point) { + return (Vec) (new Vec(point)).add(new Vec(this).neg()); + } + + /** + * Get distance to other point + * + * @param a point a + * @param b point b + * @return distance in units + */ + public static double dist(Coord a, Coord b) { + return a.distTo(b); + } + + /** + * Get middle of line to other point + * + * @param other other point + * @return middle + */ + public Coord midTo(Coord other) { + return add(vecTo(other).scale(0.5)); + } + + private Coord last; + private Vec offs; + + /** + * Store current value as LAST + */ + public void pushLast() { + if (last == null) last = new Coord(); + if (offs == null) offs = new Vec(); + last.setTo(this); + } + + /** + * Apply coordinates change for delta time + */ + public void update() { + if (last == null) last = new Coord(); + if (offs == null) offs = new Vec(); + offs = last.vecTo(this); + } + + /** + * Get coordinate at delta time since LAST + * + * @param delta delta time 0-1 + * @return delta pos + */ + public Coord getDelta(double delta) { + if (last == null) last = new Coord(); + if (offs == null) offs = new Vec(); + return new Coord(this.add(offs.scale(delta))); + } + + @Override + public String toString() { + return "[ " + x + " ; " + y + " ; " + z + " ]"; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (!obj.getClass().isAssignableFrom(Vec.class)) return false; + Vec other = (Vec) obj; + return x == other.x && y == other.y && z == other.z; + } + + @Override + public int hashCode() { + return Double.valueOf(x).hashCode() ^ Double.valueOf(y).hashCode() ^ Double.valueOf(z).hashCode(); + } + + /** + * Multiply by number + * + * @param d number + * @return multiplied copy + */ + public Coord mul(double d) { + return copy().mul_ip(d); + } + + /** + * Multiply by number in place + * + * @param d multiplier + * @return this + */ + public Coord mul_ip(double d) { + x *= d; + y *= d; + z *= d; + return this; + } + + /** + * Multiply coords by number + * + * @param xd x multiplier + * @param yd y multiplier + * @param zd z multiplier + * @return multiplied copy + */ + public Coord mul(double xd, double yd, double zd) { + return copy().mul_ip(xd, yd, zd); + } + + /** + * Multiply coords by number in place + * + * @param xd x multiplier + * @param yd y multiplier + * @param zd z multiplier + * @return this + */ + public Coord mul_ip(double xd, double yd, double zd) { + x *= xd; + y *= yd; + z *= zd; + return this; + } + + /** + * Divide by number in place + * + * @param d number to divide by + * @return this + */ + public Coord div_ip(double d) { + if (d == 0) return this; + x /= d; + y /= d; + z /= d; + return this; + } + + /** + * Get copy divided by number + * + * @param d number to divide by + * @return divided copy + */ + public Coord div(double d) { + return copy().div_ip(d); + } + + /** + * Round in place + * + * @return this + */ + public Coord round_ip() { + x = Math.round(x); + y = Math.round(y); + z = Math.round(z); + return this; + } + + + /** + * Get a copy with rounded coords + * + * @return rounded copy + */ + public Coord round() { + return copy().round_ip(); + } + + /** + * Check if this rectangle in inside a rectangular zone + * + * @param min min coord + * @param max max coord + * @return is inside + */ + public boolean isInRect(Coord min, Coord max) { + return (x >= min.x && x <= max.x) && (y >= min.y && y <= max.y) && (z >= min.z && z <= max.z); + } + + /** + * Check if this rectangle in inside a rectangular zone + * + * @param rect checked rect. + * @return is inside + */ + public boolean isInRect(Rect rect) { + return isInRect(rect.min, rect.max); + } + + /** + * Get size + * + * @return size + */ + public double size() { + return new Vec(this).size(); + } +} diff --git a/src/com/porcupine/coord/CoordI.java b/src/com/porcupine/coord/CoordI.java new file mode 100644 index 0000000..399394b --- /dev/null +++ b/src/com/porcupine/coord/CoordI.java @@ -0,0 +1,159 @@ +package com.porcupine.coord; + + +/** + * Simple integer coordinate class
+ * Unlike Coord, this is suitable for using in array indices etc. + * + * @author MightyPork + */ +public class CoordI { + + /** X coordinate */ + public int x = 0; + /** Y coordinate */ + public int y = 0; + + /** + * Integer 2D Coord + * + * @param x x coord + * @param y y coord + */ + public CoordI(int x, int y) { + this.x = x; + this.y = y; + } + + /** + * Create CoordI as copy of other + * + * @param other coord to copy + */ + public CoordI(CoordI other) { + setTo(other); + } + + /** + * Get copy + * + * @return copy + */ + public CoordI copy() { + return new CoordI(x, y); + } + + /** + * Set coords to + * + * @param x x coord to set + * @param y y coord to set + */ + public void setTo(int x, int y) { + this.x = x; + this.y = y; + } + + /** + * Set to coords from other coord + * + * @param other source coord + */ + public void setTo(CoordI other) { + this.x = other.x; + this.y = other.y; + } + + /** + * Convert to double Coord + * + * @return coord with X and y from this CoordI + */ + public Coord toCoord() { + return new Coord(x, y); + } + + @Override + public String toString() { + return "[ " + x + " ; " + y + " ]"; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (obj instanceof CoordI) return ((CoordI) obj).x == x && ((CoordI) obj).y == y; + return false; + } + + @Override + public int hashCode() { + return x ^ y; + } + + /** + * Add other coordI coordinates in place + * + * @param move coordI to add + * @return this + */ + public CoordI add_ip(CoordI move) { + x += move.x; + y += move.y; + return this; + } + + /** + * Subtract other coordI coordinates in place + * + * @param move coordI to subtract + * @return this + */ + public CoordI sub_ip(CoordI move) { + x -= move.x; + y -= move.y; + return this; + } + + /** + * Middle of this and other coordinate, rounded to CoordI - integers + * + * @param other other coordI + * @return middle CoordI + */ + public CoordI midTo(CoordI other) { + return new CoordI((x + other.x) / 2, (y + other.y) / 2); + } + + /** + * Subtract x,y in a copy + * + * @param x x to subtract + * @param y y to subtract + * @return copy subtracted + */ + public CoordI sub(int x, int y) { + return copy().sub_ip(new CoordI(x, y)); + } + + /** + * Subtract other coordI coordinates in a copy + * + * @param other coordI to subtract + * @return copy subtracted + */ + public CoordI sub(CoordI other) { + return copy().sub_ip(other); + } + + /** + * Add other coordI coordinates in a copy + * + * @param other coordI to add + * @return copy modified + */ + public CoordI add(CoordI other) { + return copy().add_ip(other); + } + + +} diff --git a/src/com/porcupine/coord/Rect.java b/src/com/porcupine/coord/Rect.java new file mode 100644 index 0000000..6cf1010 --- /dev/null +++ b/src/com/porcupine/coord/Rect.java @@ -0,0 +1,639 @@ +package com.porcupine.coord; + + +import com.porcupine.math.Calc; + + +/** + * Rectangle determined by two coordinates - min and max. + * + * @author MightyPork + */ +public class Rect { + + /** Rect [0, 0, 1, 1] */ + public static final Rect ONE = new Rect(0, 0, 1, 1); + /** Rect all zeros */ + public static final Rect ZERO = new Rect(0, 0, 0, 0); + + /** Highest coordinates xy */ + protected Coord max = new Coord(); + /** Lowest coordinates xy */ + protected Coord min = new Coord(); + + /** + * New Rect [0, 0, 0, 0] + */ + public Rect() { + this(0, 0, 0, 0); + } + + /** + * New rect of two coords + * + * @param c1 coord 1 + * @param c2 coord 2 + */ + public Rect(Coord c1, Coord c2) { + this(c1.x, c1.y, c2.x, c2.y); + } + + /** + * New Rect + * + * @param x1 lower x + * @param y1 lower y + * @param x2 upper x + * @param y2 upper y + */ + public Rect(double x1, double y1, double x2, double y2) { + setTo(x1, y1, x2, y2); + } + + /** + * Make rect from min coord and size + * + * @param x1 min x + * @param y1 min y + * @param width size x + * @param height size y + * @return the new rect + */ + public static Rect fromSize(int x1, int y1, int width, int height) { + return new Rect(x1, y1, x1 + width, y1 + height); + } + + /** + * Make rect from min coord and size + * + * @param min min coord + * @param width size x + * @param height size y + * @return the new rect + */ + public static Rect fromSize(Coord min, int width, int height) { + return new Rect(min, min.add(width, height)); + } + + /** + * New rect as a copy of other rect + * + * @param r other rect + */ + public Rect(Rect r) { + this(r.min.x, r.min.y, r.max.x, r.max.y); + } + + /** + * Rect [0, 0, x, y] + * + * @param x width + * @param y height + */ + public Rect(int x, int y) { + this(0, 0, x, y); + } + + /** + * Rect [0, 0, size.x, size.y] + * + * @param size size coord + */ + public Rect(Coord size) { + this(0, 0, size.x, size.y); + } + + /** + * Add X and Y to all coordinates in a copy + * + * @param x x to add + * @param y y to add + * @return copy changed + */ + public Rect add(double x, double y) { + return add(new Vec(x, y)); + } + + /** + * Get offset copy (add) + * + * @param move offset vector + * @return offset copy + */ + public Rect add(Vec move) { + return copy().add_ip(move); + } + + /** + * Add X and Y to all coordinates in place + * + * @param x x to add + * @param y y to add + * @return this + */ + public Rect add_ip(double x, double y) { + return add_ip(new Vec(x, y)); + } + + /** + * Offset in place (add) + * + * @param move offset vector + * @return this + */ + public Rect add_ip(Vec move) { + min.add_ip(move); + max.add_ip(move); + return this; + } + + /** + * Get a copy + * + * @return copy + */ + public Rect copy() { + return new Rect(this); + } + + /** + * Divide in copy + * + * @param factor divisor + * @return offset copy + */ + public Rect div(double factor) { + return copy().div_ip(factor); + } + + /** + * Divide coord in place + * + * @param factor divisor + * @return this + */ + public Rect div_ip(double factor) { + min.div_ip(factor); + max.div_ip(factor); + return this; + } + + /** + * Get rect center + * + * @return center + */ + public Coord getCenter() { + return min.midTo(max); + } + + /** + * Get center of the lower edge. + * + * @return center + */ + public Coord getCenterDown() { + return new Coord((max.x + min.x) / 2, min.y); + } + + /** + * Get center of the left edge. + * + * @return center + */ + public Coord getCenterLeft() { + return new Coord(min.x, (max.y + min.y) / 2); + } + + /** + * Get center of the right edge. + * + * @return center + */ + public Coord getCenterRight() { + return new Coord(max.x, (max.y + min.y) / 2); + } + + /** + * Get center of the top edge. + * + * @return center + */ + public Coord getCenterTop() { + return new Coord((max.x + min.x) / 2, max.y); + } + + /** + * Get left top + * + * @return center + */ + public Coord getLeftTop() { + return new Coord(min.x, max.y); + } + + /** + * Get left bottom + * + * @return center + */ + public Coord getLeftBottom() { + return new Coord(min.x, min.y); + } + + /** + * Get right top + * + * @return center + */ + public Coord getRightTop() { + return new Coord(max.x, max.y); + } + + /** + * Get right bottom + * + * @return center + */ + public Coord getRightBottom() { + return new Coord(max.x, min.y); + } + + /** + * @return highjest coordinates xy + */ + public Coord getMax() { + return max; + } + + /** + * @return lowest coordinates xy + */ + public Coord getMin() { + return min; + } + + /** + * Get size (width, height) as (x,y) + * + * @return coord of width,height + */ + public Coord getSize() { + return new Coord(Math.abs(min.x - max.x), Math.abs(min.y - max.y)); + } + + /** + * Check if point is inside this rectangle + * + * @param point point to test + * @return is inside + */ + public boolean isInside(Coord point) { + return Calc.inRange(point.x, min.x, max.x) && Calc.inRange(point.y, min.y, max.y); + } + + /** + * Multiply in copy + * + * @param factor multiplier + * @return offset copy + */ + public Rect mul(double factor) { + return copy().mul_ip(factor); + } + + /** + * Multiply coord in place + * + * @param factor multiplier + * @return this + */ + public Rect mul_ip(double factor) { + min.mul_ip(factor); + max.mul_ip(factor); + return this; + } + + /** + * Set to [0,0,coord.x,coord.y] + * + * @param coord size coord + */ + public void setTo(Coord coord) { + setTo(0, 0, coord.x, coord.y); + } + + /** + * Set to coordinates + * + * @param x1 lower x + * @param y1 lower y + * @param x2 upper x + * @param y2 upper y + */ + public void setTo(double x1, double y1, double x2, double y2) { + min.x = Calc.min(x1, x2); + min.y = Calc.min(y1, y2); + max.x = Calc.max(x1, x2); + max.y = Calc.max(y1, y2); + } + + /** + * Set to other rect's coordinates + * + * @param r other rect + */ + public void setTo(Rect r) { + min.setTo(r.min); + max.setTo(r.max); + } + + /** + * Subtract X and Y from all coordinates in a copy + * + * @param x x to subtract + * @param y y to subtract + * @return copy changed + */ + public Rect sub(double x, double y) { + return sub(new Vec(x, y)); + } + + /** + * Get offset copy (subtract) + * + * @param move offset vector + * @return offset copy + */ + public Rect sub(Vec move) { + return copy().sub_ip(move); + } + + /** + * Subtract X and Y from all coordinates in place + * + * @param x x to subtract + * @param y y to subtract + * @return this + */ + public Rect sub_ip(double x, double y) { + return sub_ip(new Vec(x, y)); + } + + + /** + * Offset in place (subtract) + * + * @param move offset vector + * @return this + */ + public Rect sub_ip(Vec move) { + min.sub_ip(move); + max.sub_ip(move); + return this; + } + + /** + * Grow to sides in place + * + * @param grow grow size (added to each side) + * @return this + */ + public Rect grow_ip(Coord grow) { + min.sub_ip(grow); + max.add_ip(grow); + return this; + } + + + /** + * Grow to sides in copy + * + * @param grow grow size (added to each side) + * @return grown copy + */ + public Rect grow(Coord grow) { + return copy().grow_ip(grow); + } + + /** + * Grow up in place + * + * @param add added pixels + * @return this + */ + public Rect growUp_ip(double add) { + max.add_ip(0, add); + return this; + } + + + /** + * Grow up in copy + * + * @param add added pixels + * @return grown copy + */ + public Rect growUp(double add) { + return copy().growUp_ip(add); + } + + /** + * Grow down in place + * + * @param down added pixels + * @return this + */ + public Rect growDown_ip(double down) { + min.sub_ip(0, down); + return this; + } + + + /** + * Grow down in copy + * + * @param down added pixels + * @return grown copy + */ + public Rect growDown(double down) { + return copy().growDown_ip(down); + } + + /** + * Grow to left in place + * + * @param left added pixels + * @return this + */ + public Rect growLeft_ip(double left) { + min.sub_ip(left, 0); + return this; + } + + + /** + * Grow to left in copy + * + * @param left added pixels + * @return grown copy + */ + public Rect growLeft(double left) { + return copy().growLeft_ip(left); + } + + /** + * Grow to right in place + * + * @param right added pixels + * @return this + */ + public Rect growRight_ip(double right) { + max.add_ip(right, 0); + return this; + } + + + /** + * Grow to right in copy + * + * @param right added pixels + * @return grown copy + */ + public Rect growRight(double right) { + return copy().growRight_ip(right); + } + + /** + * Grow to sides in place + * + * @param x x to add + * @param y y to add + * @return this + */ + public Rect grow_ip(double x, double y) { + min.sub_ip(x, y); + max.add_ip(x, y); + return this; + } + + + /** + * Grow to sides in copy + * + * @param x x to add + * @param y y to add + * @return grown copy + */ + public Rect grow(double x, double y) { + return copy().grow_ip(x, y); + } + + /** + * Get copy with the same center and width=0 + * + * @return line + */ + public Rect getAxisV() { + return new Rect(getCenterDown(), getCenterTop()); + } + + /** + * Get copy with the same center and height=0 + * + * @return line + */ + public Rect getAxisH() { + return new Rect(getCenterLeft(), getCenterRight()); + } + + /** + * Get top edge rect + * + * @return line + */ + public Rect getEdgeTop() { + return new Rect(getLeftTop(), getRightTop()); + } + + /** + * Get bottom edge rect + * + * @return line + */ + public Rect getEdgeBottom() { + return new Rect(getLeftBottom(), getRightBottom()); + } + + /** + * Get left edge rect + * + * @return line + */ + public Rect getEdgeLeft() { + return new Rect(getLeftBottom(), getLeftTop()); + } + + /** + * Get right edge rect + * + * @return line + */ + public Rect getEdgeRight() { + return new Rect(getRightBottom(), getRightTop()); + } + + @Override + public String toString() { + return "rect{ " + min + " - " + max + " }"; + } + + /** + * @return lower x + */ + public double x1() { + return min.x; + } + + + /** + * @return upper x + */ + public double x2() { + return max.x; + } + + /** + * @return lower y + */ + public double y1() { + return min.y; + } + + /** + * @return upper y + */ + public double y2() { + return max.y; + } + + /** + * Round coords in copy + * + * @return copy, rounded + */ + public Rect round() { + return new Rect(min.round(), max.round()); + } + + /** + * Round this in place + * + * @return this + */ + public Rect round_ip() { + min.round_ip(); + max.round_ip(); + return this; + } +} diff --git a/src/com/porcupine/coord/Vec.java b/src/com/porcupine/coord/Vec.java new file mode 100644 index 0000000..f6b25ad --- /dev/null +++ b/src/com/porcupine/coord/Vec.java @@ -0,0 +1,283 @@ +package com.porcupine.coord; + + +/** + * Vector in 2D/3D space. + * + * @author MightyPork + */ +public class Vec extends Coord { + + /** Zero vector */ + @SuppressWarnings("hiding") + public static final Vec ZERO = new Vec(0, 0, 0); + /** Vec [1;1;1] */ + @SuppressWarnings("hiding") + public static final Vec ONE = new Vec(1, 1, 1); + + /** + * Create zero vector + */ + public Vec() { + super(); + } + + /** + * Create 2D vector + * + * @param x x coordinate + * @param y y coordinate + */ + public Vec(Number x, Number y) { + super(x, y); + } + + /** + * Create 3D vector + * + * @param x x coordinate + * @param y y coordinate + * @param z z coordinate + */ + public Vec(Number x, Number y, Number z) { + super(x, y, z); + } + + /** + * Create vector as a copy of another + * + * @param copied copied vector + */ + public Vec(Coord copied) { + super(copied); + } + + + + /** + * Negate all coordinates (* -1) + * + * @return negated coordinate + */ + public Vec neg() { + return copy().neg_ip(); + } + + /** + * Negate all coordinates (* -1), in place + * + * @return this + */ + public Vec neg_ip() { + scale_ip(-1); + return this; + } + + /** + * Multiply all coordinates by factor; scalar multiplication + * + * @param factor multiplier + * @return copy multiplied + */ + public Vec scale(double factor) { + return copy().scale_ip(factor); + } + + /** + * Multiply all coordinates by factor, in place + * + * @param factor multiplier + * @return this + */ + public Vec scale_ip(double factor) { + return (Vec) mul_ip(factor); + } + + /** + * Multiply by other vector, vector multiplication + * + * @param vec other vector + * @return copy multiplied + */ + public Vec cross(Vec vec) { + return copy().cross_ip(vec); + } + + /** + * Multiply by other vector, vector multiplication; in place + * + * @param vec other vector + * @return this + */ + public Vec cross_ip(Vec vec) { + setTo(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x); + return this; + } + + /** + * Get dot product + * + * @param vec other vector + * @return dot product + */ + public double dot(Vec vec) { + return x * vec.x + y * vec.y + z * vec.z; + } + + /** + * Get vector size + * + * @return vector size in units + */ + @Override + public double size() { + return Math.sqrt(x * x + y * y + z * z); + } + + /** + * Scale vector to given size + * + * @param size size we need + * @return scaled vector + */ + public Vec norm(double size) { + return copy().norm_ip(size); + } + + /** + * Scale vector to given size, in place + * + * @param size size we need + * @return scaled vector + */ + public Vec norm_ip(double size) { + if (size() == 0) { + z = -1; + } + if (size == 0) { + setTo(0, 0, 0); + return this; + } + double k = size / size(); + scale_ip(k); + return this; + } + + + // STATIC + + /** + * Get vector size + * + * @param vec vector to get size of + * @return size in units + */ + public static double size(Vec vec) { + return vec.size(); + } + + /** + * Get dot product of two vectors + * + * @param a 1st vector + * @param b 2nd vector + * @return dot product + */ + public static double dot(Vec a, Vec b) { + return a.dot(b); + } + + /** + * Get cross product of two vectors + * + * @param a 1st vector + * @param b 2nd vector + * @return cross product + */ + public static Vec cross(Vec a, Vec b) { + return a.cross(b); + } + + /** + * Scale vector + * + * @param a vector + * @param scale + * @return scaled copy + */ + public static Vec scale(Vec a, double scale) { + return a.scale(scale); + } + + @Override + public Vec copy() { + return new Vec(this); + } + + /** + * Generate random coord (gaussian) + * + * @param max max distance from 0 + * @return new coord + */ + public static Vec random(double max) { + return new Vec(Coord.random(max)); + } + + /** + * Generate random coord (min-max) + * + * @param max max distance from 0 + * @return new coord + */ + public static Vec random(double min, double max) { + return new Vec(Coord.random(min, max)); + } + + /** + * offset randomly in place + * + * @param max max +- offset + * @return this + */ + @Override + public Vec random_offset_ip(double max) { + return (Vec) super.random_offset_ip(max); + } + + /** + * offset randomly in place + * + * @param min min offset + * @param max max offset + * @return this + */ + @Override + public Vec random_offset_ip(double min, double max) { + return (Vec) super.random_offset_ip(min, max); + } + + /** + * offset randomly + * + * @param max max +- offset + * @return offset coord + */ + @Override + public Vec random_offset(double max) { + return (Vec) super.random_offset(max); + } + + /** + * offset randomly + * + * @param min min offset + * @param max max offset + * @return offset coord + */ + @Override + public Vec random_offset(double min, double max) { + return (Vec) super.random_offset(min, max); + } + +} diff --git a/src/com/porcupine/ion/AbstractIonList.java b/src/com/porcupine/ion/AbstractIonList.java new file mode 100644 index 0000000..537d987 --- /dev/null +++ b/src/com/porcupine/ion/AbstractIonList.java @@ -0,0 +1,64 @@ +package com.porcupine.ion; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; + + +/** + * Ionizable Arraylist + * + * @author MightyPork + * @param + */ +public abstract class AbstractIonList extends ArrayList implements Ionizable { + + @Override + public void ionRead(InputStream in) throws IOException { + while (true) { + byte b = StreamUtils.readByte(in); + + if (b == IonMarks.ENTRY) { + T value = (T) Ion.readObject(in); + add(value); + } else if (b == IonMarks.END) { + break; + } else { + throw new RuntimeException("Unexpected mark in AbstractIonList: " + Integer.toHexString(b)); + } + } + ionReadCustomData(in); + } + + @Override + public void ionWrite(OutputStream out) throws IOException { + for (T entry : this) { + if (entry instanceof IonizableOptional && !((IonizableOptional) entry).ionShouldSave()) continue; + StreamUtils.writeByte(out, IonMarks.ENTRY); + Ion.writeObject(out, entry); + } + StreamUtils.writeByte(out, IonMarks.END); + ionWriteCustomData(out); + } + + /** + * Read custom data of this AbstractIonList implementation + * + * @param in input stream + */ + public void ionReadCustomData(InputStream in) {} + + /** + * Write custom data of this AbstractIonList implementation + * + * @param out output stream + */ + public void ionWriteCustomData(OutputStream out) {} + + + @Override + public abstract byte ionMark(); + +} diff --git a/src/com/porcupine/ion/AbstractIonMap.java b/src/com/porcupine/ion/AbstractIonMap.java new file mode 100644 index 0000000..4857726 --- /dev/null +++ b/src/com/porcupine/ion/AbstractIonMap.java @@ -0,0 +1,75 @@ +package com.porcupine.ion; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.LinkedHashMap; + + +/** + * Ionizable HashMap + * + * @author MightyPork + * @param + */ +public abstract class AbstractIonMap extends LinkedHashMap implements Ionizable { + + @Override + public V get(Object key) { + return super.get(key); + } + + @Override + public V put(String key, V value) { + return super.put(key, value); + } + + @Override + public void ionRead(InputStream in) throws IOException { + while (true) { + byte b = StreamUtils.readByte(in); + if (b == IonMarks.ENTRY) { + String key = StreamUtils.readStringBytes(in); + V value = (V) Ion.readObject(in); + put(key, value); + } else if (b == IonMarks.END) { + break; + } else { + throw new RuntimeException("Unexpected mark in IonMap: " + Integer.toHexString(b)); + } + } + ionReadCustomData(in); + } + + @Override + public void ionWrite(OutputStream out) throws IOException { + for (java.util.Map.Entry entry : entrySet()) { + StreamUtils.writeByte(out, IonMarks.ENTRY); + StreamUtils.writeStringBytes(out, entry.getKey()); + Ion.writeObject(out, entry.getValue()); + } + StreamUtils.writeByte(out, IonMarks.END); + ionWriteCustomData(out); + } + + /** + * Read custom data of this AbstractIonMap implementation + * + * @param in input stream + */ + public void ionReadCustomData(InputStream in) {} + + /** + * Write custom data of this AbstractIonMap implementation + * + * @param out output stream + */ + public void ionWriteCustomData(OutputStream out) {} + + @Override + public byte ionMark() { + return IonMarks.MAP; + } + +} diff --git a/src/com/porcupine/ion/Ion.java b/src/com/porcupine/ion/Ion.java new file mode 100644 index 0000000..6fff06d --- /dev/null +++ b/src/com/porcupine/ion/Ion.java @@ -0,0 +1,261 @@ +package com.porcupine.ion; + + +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +import com.porcupine.math.Calc; + + +/** + * Universal data storage system + * + * @author MightyPork + */ +public class Ion { + + /** Ionizables */ + private static Map> customIonizables = new HashMap>(); + + // register default ionizables + static { + registerIonizable(IonMarks.MAP, IonMap.class); + registerIonizable(IonMarks.LIST, IonList.class); + } + + /** + * Register new Ionizable for direct reconstructing. + * + * @param mark byte mark to be used, see {@link IonMarks} for reference. + * @param objClass class of the registered Ionizable + */ + public static void registerIonizable(byte mark, Class objClass) { + if (customIonizables.containsKey(mark)) { + throw new RuntimeException("IonMark " + mark + " is already used @ " + objClass.getSimpleName()); + } + customIonizables.put(mark, objClass); + } + + + + /** + * Load Ion object from file. + * + * @param file file path + * @return the loaded object + */ + public static Object fromFile(String file) { + return fromFile(new File(file)); + } + + + /** + * Load Ion object from file. + * + * @param file file + * @return the loaded object + */ + public static Object fromFile(File file) { + try { + InputStream in = new FileInputStream(file); + + Object obj = fromStream(in); + + in.close(); + return obj; + } catch (FileNotFoundException e) { + System.err.println("Could not find ION file " + file); + return null; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Load Ion object from stream. + * + * @param in input stream + * @return the loaded object + */ + public static Object fromStream(InputStream in) { + try { + return readObject(in); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Store Ion object to file. + * + * @param path file path + * @param obj object to store + */ + public static void toFile(String path, Object obj) { + toFile(new File(path), obj); + } + + /** + * Store Ion object to file. + * + * @param path file path + * @param obj object to store + */ + public static void toFile(File path, Object obj) { + try { + String f = path.toString(); + File dir = new File(f.substring(0, f.lastIndexOf(File.separator))); + + dir.mkdirs(); + + OutputStream out = new FileOutputStream(path); + + toStream(out, obj); + + out.flush(); + out.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Store Ion object to output stream. + * + * @param out output stream * + * @param obj object to store + */ + public static void toStream(OutputStream out, Object obj) { + try { + writeObject(out, obj); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + /** + * Read single ionizable or primitive object from input stream + * + * @param in input stream + * @return the loaded object + */ + public static Object readObject(InputStream in) { + try { + int bi = in.read(); + if (bi == -1) throw new RuntimeException("Unexpected end of stream."); + byte b = (byte) bi; + if (customIonizables.containsKey(b)) { + Ionizable ion = ((Ionizable) customIonizables.get(b).newInstance()); + ion.ionRead(in); + return ion; + } + + switch (b) { + case IonMarks.BOOLEAN: + return StreamUtils.readBoolean(in); + case IonMarks.BYTE: + return StreamUtils.readByte(in); + case IonMarks.CHAR: + return StreamUtils.readChar(in); + case IonMarks.SHORT: + return StreamUtils.readShort(in); + case IonMarks.INT: + return StreamUtils.readInt(in); + case IonMarks.LONG: + return StreamUtils.readLong(in); + case IonMarks.FLOAT: + return StreamUtils.readFloat(in); + case IonMarks.DOUBLE: + return StreamUtils.readDouble(in); + case IonMarks.STRING: + String s = StreamUtils.readString(in); + return s; + default: + throw new RuntimeException("Invalid Ion mark " + Integer.toHexString(bi)); + } + + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + + /** + * Write single ionizable or primitive object to output stream + * + * @param out output stream + * @param obj stored object + */ + public static void writeObject(OutputStream out, Object obj) { + try { + if (obj instanceof Ionizable) { + out.write(((Ionizable) obj).ionMark()); + ((Ionizable) obj).ionWrite(out); + return; + } + + if (obj instanceof Boolean) { + out.write(IonMarks.BOOLEAN); + StreamUtils.writeBoolean(out, (Boolean) obj); + return; + } + + if (obj instanceof Byte) { + out.write(IonMarks.BYTE); + StreamUtils.writeByte(out, (Byte) obj); + return; + } + + if (obj instanceof Character) { + out.write(IonMarks.CHAR); + StreamUtils.writeChar(out, (Character) obj); + return; + } + + if (obj instanceof Short) { + out.write(IonMarks.SHORT); + StreamUtils.writeShort(out, (Short) obj); + return; + } + + if (obj instanceof Integer) { + out.write(IonMarks.INT); + StreamUtils.writeInt(out, (Integer) obj); + return; + } + + if (obj instanceof Long) { + out.write(IonMarks.LONG); + StreamUtils.writeLong(out, (Long) obj); + return; + } + + if (obj instanceof Float) { + out.write(IonMarks.FLOAT); + StreamUtils.writeFloat(out, (Float) obj); + return; + } + + if (obj instanceof Double) { + out.write(IonMarks.DOUBLE); + StreamUtils.writeDouble(out, (Double) obj); + return; + } + + if (obj instanceof String) { + out.write(IonMarks.STRING); + StreamUtils.writeString(out, (String) obj); + return; + } + + throw new RuntimeException(Calc.className(obj) + " can't be stored to Ion storage."); + + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + +} diff --git a/src/com/porcupine/ion/IonList.java b/src/com/porcupine/ion/IonList.java new file mode 100644 index 0000000..d40b998 --- /dev/null +++ b/src/com/porcupine/ion/IonList.java @@ -0,0 +1,144 @@ +package com.porcupine.ion; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; + + +/** + * Ionizable Arraylist + * + * @author MightyPork + */ +@SuppressWarnings("javadoc") +public class IonList extends ArrayList implements Ionizable { + + public boolean getBoolean(int index) { + return (Boolean) get(index); + } + + public boolean getBool(int index) { + return (Boolean) get(index); + } + + public byte getByte(int index) { + return (Byte) get(index); + } + + public char getChar(int index) { + return (Character) get(index); + } + + public char getCharacter(int index) { + return (Character) get(index); + } + + public short getShort(int index) { + return (Short) get(index); + } + + public int getInteger(int index) { + return (Integer) get(index); + } + + public int getInt(int index) { + return (Integer) get(index); + } + + public long getLong(int index) { + return (Long) get(index); + } + + public float getFloat(int index) { + return (Float) get(index); + } + + public double getDouble(int index) { + return (Double) get(index); + } + + public String getString(int index) { + return (String) get(index); + } + + @Override + public Object get(int index) { + return super.get(index); + } + + public void addBoolean(boolean num) { + add(num); + } + + public void addBool(boolean num) { + add(num); + } + + public void addByte(int num) { + add((byte) num); + } + + public void addChar(char num) { + add(num); + } + + public void addShort(int num) { + add((short) num); + } + + public void addInteger(int num) { + add(num); + } + + public void addInt(int num) { + add(num); + } + + public void addLong(long num) { + add(num); + } + + public void addFloat(double num) { + add((float) num); + } + + public void addDouble(double num) { + add(num); + } + + public void addString(String num) { + add(num); + } + + @Override + public void ionRead(InputStream in) throws IOException { + while (true) { + byte b = StreamUtils.readByte(in); + if (b == IonMarks.ENTRY) { + Object value = Ion.readObject(in); + add(value); + } else if (b == IonMarks.END) { + break; + } else { + throw new RuntimeException("Unexpected mark in IonList: " + Integer.toHexString(b)); + } + } + } + + @Override + public void ionWrite(OutputStream out) throws IOException { + for (Object entry : this) { + StreamUtils.writeByte(out, IonMarks.ENTRY); + Ion.writeObject(out, entry); + } + StreamUtils.writeByte(out, IonMarks.END); + } + + @Override + public byte ionMark() { + return IonMarks.LIST; + } + +} diff --git a/src/com/porcupine/ion/IonMap.java b/src/com/porcupine/ion/IonMap.java new file mode 100644 index 0000000..f679743 --- /dev/null +++ b/src/com/porcupine/ion/IonMap.java @@ -0,0 +1,143 @@ +package com.porcupine.ion; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.LinkedHashMap; +import java.util.Map.Entry; + + +/** + * Ionizable HashMap + * + * @author MightyPork + */ +@SuppressWarnings("javadoc") +public class IonMap extends LinkedHashMap implements Ionizable { + + public boolean getBoolean(String key) { + return (Boolean) get(key); + } + + public boolean getBool(String key) { + return (Boolean) get(key); + } + + public byte getByte(String key) { + return (Byte) get(key); + } + + public char getChar(String key) { + return (Character) get(key); + } + + public short getShort(String key) { + return (Short) get(key); + } + + public int getInt(String key) { + return (Integer) get(key); + } + + public long getLong(String key) { + return (Long) get(key); + } + + public float getFloat(String key) { + return (Float) get(key); + } + + public double getDouble(String key) { + return (Double) get(key); + } + + public String getString(String key) { + return (String) get(key); + } + + @Override + public Object get(Object arg0) { + return super.get(arg0); + } + + public void putBoolean(String key, boolean num) { + put(key, num); + } + + public void putBool(String key, boolean num) { + put(key, num); + } + + public void putByte(String key, int num) { + put(key, (byte) num); + } + + public void putChar(String key, char num) { + put(key, num); + } + + public void putCharacter(String key, char num) { + put(key, num); + } + + public void putShort(String key, int num) { + put(key, num); + } + + public void putInt(String key, int num) { + put(key, num); + } + + public void putInteger(String key, int num) { + put(key, num); + } + + public void putLong(String key, long num) { + put(key, num); + } + + public void putFloat(String key, double num) { + put(key, (float) num); + } + + public void putDouble(String key, double num) { + put(key, num); + } + + public void putString(String key, String num) { + put(key, num); + } + + @Override + public void ionRead(InputStream in) throws IOException { + while (true) { + byte b = StreamUtils.readByte(in); + if (b == IonMarks.ENTRY) { + String key = StreamUtils.readStringBytes(in); + Object value = Ion.readObject(in); + put(key, value); + } else if (b == IonMarks.END) { + break; + } else { + throw new RuntimeException("Unexpected mark in IonMap: " + Integer.toHexString(b)); + } + } + } + + @Override + public void ionWrite(OutputStream out) throws IOException { + for (Entry entry : entrySet()) { + StreamUtils.writeByte(out, IonMarks.ENTRY); + StreamUtils.writeStringBytes(out, entry.getKey()); + Ion.writeObject(out, entry.getValue()); + } + StreamUtils.writeByte(out, IonMarks.END); + } + + @Override + public byte ionMark() { + return IonMarks.MAP; + } + +} diff --git a/src/com/porcupine/ion/IonMarks.java b/src/com/porcupine/ion/IonMarks.java new file mode 100644 index 0000000..1fb018f --- /dev/null +++ b/src/com/porcupine/ion/IonMarks.java @@ -0,0 +1,57 @@ +package com.porcupine.ion; + + +/** + * Byte marks used to structure data in Ion files. + * + * @author MightyPork + */ +public class IonMarks { + + /** Null value */ + public static final byte NULL = 0; + + /** Boolean value */ + public static final byte BOOLEAN = 1; + + /** Byte value */ + public static final byte BYTE = 2; + + /** Character value */ + public static final byte CHAR = 3; + + /** Short value */ + public static final byte SHORT = 4; + + /** Integer value */ + public static final byte INT = 5; + + /** Long value */ + public static final byte LONG = 6; + + /** Float value */ + public static final byte FLOAT = 7; + + /** Double value */ + public static final byte DOUBLE = 8; + + /** String value */ + public static final byte STRING = 9; + + /** List value (begin) - contains entries, ends with END */ + public static final byte LIST = 10; + + /** Map value (begin) - contains entries, ends with END */ + public static final byte MAP = 11; + + /** + * List / Map entry
+ * In list directly followed by entry value. In map followed by (string) key + * and the entry value. + */ + public static final byte ENTRY = 12; + + /** End of List / Map */ + public static final byte END = 13; + +} diff --git a/src/com/porcupine/ion/Ionizable.java b/src/com/porcupine/ion/Ionizable.java new file mode 100644 index 0000000..7a5f3c0 --- /dev/null +++ b/src/com/porcupine/ion/Ionizable.java @@ -0,0 +1,41 @@ +package com.porcupine.ion; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + +/** + * Object that can be saved to and loaded from Ion file.
+ * All classes implementing Ionizable must be registered to {@link Ion} using + * Ion.registerIonizable(obj.class). + * + * @author MightyPork + */ +public interface Ionizable { + /** + * Load data from the input stream. Mark has already been read, begin + * reading right after it. + * + * @param in input stream + * @throws IOException at IO error + */ + public void ionRead(InputStream in) throws IOException; + + /** + * Store data to output stream. mark has already been written, begin right + * after it. + * + * @param out Output stream + * @throws IOException at IO error + */ + public void ionWrite(OutputStream out) throws IOException; + + /** + * Get Ion mark byte. + * + * @return Ion mark byte. + */ + public byte ionMark(); +} diff --git a/src/com/porcupine/ion/IonizableOptional.java b/src/com/porcupine/ion/IonizableOptional.java new file mode 100644 index 0000000..ef70f46 --- /dev/null +++ b/src/com/porcupine/ion/IonizableOptional.java @@ -0,0 +1,16 @@ +package com.porcupine.ion; + + +/** + * Optional ionizable + * + * @author MightyPork + */ +public interface IonizableOptional extends Ionizable { + /** + * Get if this ionizable should be saved to a list + * + * @return should save + */ + public boolean ionShouldSave(); +} diff --git a/src/com/porcupine/ion/StreamUtils.java b/src/com/porcupine/ion/StreamUtils.java new file mode 100644 index 0000000..a773180 --- /dev/null +++ b/src/com/porcupine/ion/StreamUtils.java @@ -0,0 +1,208 @@ +package com.porcupine.ion; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; + + +/** + * Utilities to store and load objects to streams. + * + * @author MightyPork + */ + +@SuppressWarnings("javadoc") +public class StreamUtils { + + private static ByteBuffer bi = ByteBuffer.allocate(Integer.SIZE / 8); + private static ByteBuffer bd = ByteBuffer.allocate(Double.SIZE / 8); + private static ByteBuffer bf = ByteBuffer.allocate(Float.SIZE / 8); + private static ByteBuffer bc = ByteBuffer.allocate(Character.SIZE / 8); + private static ByteBuffer bl = ByteBuffer.allocate(Long.SIZE / 8); + private static ByteBuffer bs = ByteBuffer.allocate(Short.SIZE / 8); + + private static byte[] ai = new byte[Integer.SIZE / 8]; + private static byte[] ad = new byte[Double.SIZE / 8]; + private static byte[] af = new byte[Float.SIZE / 8]; + private static byte[] ac = new byte[Character.SIZE / 8]; + private static byte[] al = new byte[Long.SIZE / 8]; + private static byte[] as = new byte[Short.SIZE / 8]; + + // CONVERSIONS + + private static byte[] convBool(boolean bool) { + return new byte[] { (byte) (bool ? 1 : 0) }; + } + + private static byte[] convByte(byte num) { + return new byte[] { num }; + } + + private static byte[] convChar(char num) { + bc.clear(); + bc.putChar(num); + return bc.array(); + } + + private static byte[] convShort(short num) { + bs.clear(); + bs.putShort(num); + return bs.array(); + } + + private static byte[] convInt(int num) { + bi.clear(); + bi.putInt(num); + return bi.array(); + } + + private static byte[] convLong(long num) { + bl.clear(); + bl.putLong(num); + return bl.array(); + } + + private static byte[] convFloat(float num) { + bf.clear(); + bf.putFloat(num); + return bf.array(); + } + + private static byte[] convDouble(double num) { + bd.clear(); + bd.putDouble(num); + return bd.array(); + } + + private static byte[] convString(String str) { + char[] chars = str.toCharArray(); + + ByteBuffer bstr = ByteBuffer.allocate((Character.SIZE / 8) * chars.length + (Character.SIZE / 8)); + for (char c : chars) { + bstr.putChar(c); + } + + bstr.putChar((char) 0); + + return bstr.array(); + } + + private static byte[] convString_b(String str) { + char[] chars = str.toCharArray(); + ByteBuffer bstr = ByteBuffer.allocate((Byte.SIZE / 8) * chars.length + 1); + for (char c : chars) { + bstr.put((byte) c); + } + bstr.put((byte) 0); + + return bstr.array(); + } + + public static void writeBoolean(OutputStream out, boolean num) throws IOException { + out.write(convBool(num)); + } + + public static void writeByte(OutputStream out, byte num) throws IOException { + out.write(convByte(num)); + } + + public static void writeChar(OutputStream out, char num) throws IOException { + out.write(convChar(num)); + } + + public static void writeShort(OutputStream out, short num) throws IOException { + out.write(convShort(num)); + } + + public static void writeInt(OutputStream out, int num) throws IOException { + out.write(convInt(num)); + } + + public static void writeLong(OutputStream out, long num) throws IOException { + out.write(convLong(num)); + } + + public static void writeFloat(OutputStream out, float num) throws IOException { + out.write(convFloat(num)); + } + + public static void writeDouble(OutputStream out, double num) throws IOException { + out.write(convDouble(num)); + } + + public static void writeString(OutputStream out, String str) throws IOException { + out.write(convString(str)); + } + + public static void writeStringBytes(OutputStream out, String str) throws IOException { + out.write(convString_b(str)); + } + + + // READING + + public static boolean readBoolean(InputStream in) throws IOException { + return in.read() > 0; + } + + public static byte readByte(InputStream in) throws IOException { + return (byte) in.read(); + } + + public static char readChar(InputStream in) throws IOException { + in.read(ac, 0, ac.length); + ByteBuffer buf = ByteBuffer.wrap(ac); + return buf.getChar(); + } + + public static short readShort(InputStream in) throws IOException { + in.read(as, 0, as.length); + ByteBuffer buf = ByteBuffer.wrap(as); + return buf.getShort(); + } + + public static long readLong(InputStream in) throws IOException { + in.read(al, 0, al.length); + ByteBuffer buf = ByteBuffer.wrap(al); + return buf.getLong(); + } + + public static int readInt(InputStream in) throws IOException { + in.read(ai, 0, ai.length); + ByteBuffer buf = ByteBuffer.wrap(ai); + return buf.getInt(); + } + + public static float readFloat(InputStream in) throws IOException { + in.read(af, 0, af.length); + ByteBuffer buf = ByteBuffer.wrap(af); + return buf.getFloat(); + } + + public static double readDouble(InputStream in) throws IOException { + in.read(ad, 0, ad.length); + ByteBuffer buf = ByteBuffer.wrap(ad); + return buf.getDouble(); + } + + public static String readString(InputStream in) throws IOException { + String s = ""; + char c; + while ((c = readChar(in)) > 0) { + s += c; + } + return s; + } + + public static String readStringBytes(InputStream in) throws IOException { + String s = ""; + byte b; + while ((b = readByte(in)) > 0) { + s += (char) b; + } + return s; + } + +} diff --git a/src/com/porcupine/math/Calc.java b/src/com/porcupine/math/Calc.java new file mode 100644 index 0000000..34f2846 --- /dev/null +++ b/src/com/porcupine/math/Calc.java @@ -0,0 +1,804 @@ +package com.porcupine.math; + + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.lwjgl.BufferUtils; + +import com.porcupine.coord.Coord; +import com.porcupine.coord.Vec; + + +/** + * Math helper + * + * @author MightyPork + */ +public class Calc { + + /** Square root of two */ + public static final double SQ2 = 1.41421356237; + + /** + * Get distance from 2D line to 2D point [X,Y] + * + * @param lineDirVec line directional vector + * @param linePoint point of line + * @param point point coordinate + * @return distance + */ + public static double linePointDist(Vec lineDirVec, Coord linePoint, Coord point) { + // line point L[lx,ly] + double lx = linePoint.x; + double ly = linePoint.y; + + // line equation ax+by+c=0 + double a = -lineDirVec.y; + double b = lineDirVec.x; + double c = -a * lx - b * ly; + + // checked point P[x,y] + double x = point.x; + double y = point.y; + + // distance + return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b); + } + + /** + * Get distance from 2D line to 2D point [X,Z] + * + * @param lineDirVec line directional vector + * @param linePoint point of line + * @param point point coordinate + * @return distance + */ + public static double linePointDistXZ(Vec lineDirVec, Coord linePoint, Coord point) { + return linePointDist(new Vec(lineDirVec.x, lineDirVec.z), new Coord(linePoint.x, linePoint.z), new Coord(point.x, point.z)); + } + + /** + * Get longest side of a right-angled triangle + * + * @param a side a (opposite) + * @param b side b (adjacent) + * @return longest side (hypotenuse) + */ + public static double pythC(double a, double b) { + return Math.sqrt(square(a) + square(b)); + } + + /** + * Get adjacent side of a right-angled triangle + * + * @param a side a (opposite) + * @param c side c (hypotenuse) + * @return side b (adjacent) + */ + public static double pythB(double a, double c) { + return Math.sqrt(square(c) - square(a)); + } + + /** + * Get opposite side of a right-angled triangle + * + * @param b side b (adjacent) + * @param c side c (hypotenuse) + * @return side a (opposite) + */ + public static double pythA(double b, double c) { + return Math.sqrt(square(c) - square(b)); + } + + private static class Angles { + + public static double delta(double alpha, double beta, double a360) { + + while (Math.abs(alpha - beta) > a360 / 2D) { + alpha = norm(alpha + a360 / 2D, a360); + beta = norm(beta + a360 / 2D, a360); + } + + return beta - alpha; + } + + public static double norm(double angle, double a360) { + while (angle < 0) + angle += a360; + while (angle > a360) + angle -= a360; + return angle; + } + } + + /** + * Calc subclass with buffer utils. + * + * @author MightyPork + */ + public static class Buffers { + + /** + * Create java.nio.FloatBuffer of given floats, and flip it. + * + * @param obj floats or float array + * @return float buffer + */ + public static FloatBuffer mkFillBuff(float... obj) { + return (FloatBuffer) BufferUtils.createFloatBuffer(obj.length).put(obj).flip(); + } + + /** + * Fill java.nio.FloatBuffer with floats or float array + * + * @param buff + * @param obj + */ + public static void fill(FloatBuffer buff, float... obj) { + buff.put(obj); + buff.flip(); + } + + /** + * Create new java.nio.FloatBuffer of given length + * + * @param count elements + * @return the new java.nio.FloatBuffer + */ + public static FloatBuffer alloc(int count) { + return BufferUtils.createFloatBuffer(count); + } + + } + + /** + * Angle calculations for degrees. + * + * @author MightyPork + */ + public static class Deg { + /** 180° in degrees */ + public static final double a180 = 180; + /** 270° in degrees */ + public static final double a270 = 270; + /** 360° in degrees */ + public static final double a360 = 360; + /** 45° in degrees */ + public static final double a45 = 45; + /** 90° in degrees */ + public static final double a90 = 90; + + /** + * Subtract two angles alpha - beta + * + * @param alpha first angle + * @param beta second angle + * @return (alpha - beta) in degrees + */ + public static double delta(double alpha, double beta) { + return Angles.delta(alpha, beta, a360); + } + + /** + * Difference of two angles (absolute value of delta) + * + * @param alpha first angle + * @param beta second angle + * @return difference in radians + */ + public static double diff(double alpha, double beta) { + return Math.abs(Angles.delta(alpha, beta, a360)); + } + + /** + * Cosinus in degrees + * + * @param deg angle in degrees + * @return cosinus + */ + public static double cos(double deg) { + return Math.cos(toRad(deg)); + } + + /** + * Sinus in degrees + * + * @param deg angle in degrees + * @return sinus + */ + public static double sin(double deg) { + return Math.sin(toRad(deg)); + } + + /** + * Tangents in degrees + * + * @param deg angle in degrees + * @return tangents + */ + public static double tan(double deg) { + return Math.tan(toRad(deg)); + } + + /** + * Angle normalized to 0-360 range + * + * @param angle angle to normalize + * @return normalized angle + */ + public static double norm(double angle) { + return Angles.norm(angle, a360); + } + + /** + * Convert to radians + * + * @param deg degrees + * @return radians + */ + public static double toRad(double deg) { + return Math.toRadians(deg); + } + + /** + * Round angle to 0,45,90,135... + * + * @param deg angle in deg. to round + * @param x rounding increment (45 - round to 0,45,90...) + * @return rounded + */ + public static int roundX(double deg, double x) { + double half = x / 2d; + deg += half; + deg = norm(deg); + int times = (int) Math.floor(deg / x); + double a = times * x; + if (a == 360) a = 0; + return (int) Math.round(a); + } + + /** + * Round angle to 0,45,90,135... + * + * @param deg angle in deg. to round + * @return rounded + */ + public static int round45(double deg) { + return roundX(deg, 45); + } + + /** + * Round angle to 0,90,180,270 + * + * @param deg angle in deg. to round + * @return rounded + */ + public static int round90(double deg) { + return roundX(deg, 90); + } + + /** + * Round angle to 0,15,30,45,60,75,90... + * + * @param deg angle in deg to round + * @return rounded + */ + public static int round15(double deg) { + return roundX(deg, 15); + } + } + + /** + * Angle calculations for radians. + * + * @author MightyPork + */ + public static class Rad { + /** 180° in radians */ + public static final double a180 = Math.PI; + /** 270° in radians */ + public static final double a270 = Math.PI * 1.5D; + /** 360° in radians */ + public static final double a360 = Math.PI * 2D; + /** 45° in radians */ + public static final double a45 = Math.PI / 4D; + /** 90° in radians */ + public static final double a90 = Math.PI / 2D; + + /** + * Subtract two angles alpha - beta + * + * @param alpha first angle + * @param beta second angle + * @return (alpha - beta) in radians + */ + public static double delta(double alpha, double beta) { + return Angles.delta(alpha, beta, a360); + } + + /** + * Difference of two angles (absolute value of delta) + * + * @param alpha first angle + * @param beta second angle + * @return difference in radians + */ + public static double diff(double alpha, double beta) { + return Math.abs(Angles.delta(alpha, beta, a360)); + } + + /** + * Cos + * + * @param rad angle in rads + * @return cos + */ + public static double cos(double rad) { + return Math.cos(rad); + } + + /** + * Sin + * + * @param rad angle in rads + * @return sin + */ + public static double sin(double rad) { + return Math.sin(rad); + } + + /** + * Tan + * + * @param rad angle in rads + * @return tan + */ + public static double tan(double rad) { + return Math.tan(rad); + } + + /** + * Angle normalized to 0-2*PI range + * + * @param angle angle to normalize + * @return normalized angle + */ + public static double norm(double angle) { + return Angles.norm(angle, a360); + } + + /** + * Convert to degrees + * + * @param rad radians + * @return degrees + */ + public static double toDeg(double rad) { + return Math.toDegrees(rad); + } + } + + private static Random rand = new Random(); + + + /** + * Get volume of a sphere + * + * @param radius sphere radius + * @return volume in cubic units + */ + public static double sphereGetVolume(double radius) { + return (4D / 3D) * Math.PI * cube(radius); + } + + /** + * Get radius of a sphere + * + * @param volume sphere volume + * @return radius in units + */ + public static double sphereGetRadius(double volume) { + return Math.cbrt((3D * volume) / (4 * Math.PI)); + } + + /** + * Get surface of a circle + * + * @param radius circle radius + * @return volume in square units + */ + public static double circleGetSurface(double radius) { + return Math.PI * square(radius); + } + + /** + * Get radius of a circle + * + * @param surface circle volume + * @return radius in units + */ + public static double circleGetRadius(double surface) { + return Math.sqrt(surface / Math.PI); + } + + /** + * Check if objects are equal (for equals function) + * + * @param a + * @param b + * @return are equal + */ + public static boolean areObjectsEqual(Object a, Object b) { + return a == null ? b == null : a.equals(b); + } + + /** + * Private clamping helper. + * + * @param number number to be clamped + * @param min min value + * @param max max value + * @return clamped double + */ + private static double clamp_double(Number number, Number min, Number max) { + double n = number.doubleValue(); + double mind = min.doubleValue(); + double maxd = max.doubleValue(); + if (n > maxd) n = maxd; + if (n < mind) n = mind; + return n; + } + + /** + * Private clamping helper. + * + * @param number number to be clamped + * @param min min value + * @return clamped double + */ + private static double clamp_double(Number number, Number min) { + double n = number.doubleValue(); + double mind = min.doubleValue(); + if (n < mind) n = mind; + return n; + } + + /** + * Clamp number to min and max bounds, inclusive.
+ * DOUBLE version + * + * @param number clamped number + * @param min minimal allowed value + * @param max maximal allowed value + * @return result + */ + public static double clampd(Number number, Number min, Number max) { + return clamp_double(number, min, max); + } + + /** + * Clamp number to min and max bounds, inclusive.
+ * FLOAT version + * + * @param number clamped number + * @param min minimal allowed value + * @param max maximal allowed value + * @return result + */ + public static float clampf(Number number, Number min, Number max) { + return (float) clamp_double(number, min, max); + } + + /** + * Clamp number to min and max bounds, inclusive.
+ * INTEGER version + * + * @param number clamped number + * @param min minimal allowed value + * @param max maximal allowed value + * @return result + */ + public static int clampi(Number number, Number min, Number max) { + return (int) Math.round(clamp_double(number, min, max)); + } + + /** + * Clamp number to min and max bounds, inclusive.
+ * INTEGER version + * + * @param number clamped number + * @param range range + * @return result + */ + public static int clampi(Number number, Range range) { + return (int) Math.round(clamp_double(number, range.getMin(), range.getMax())); + } + + /** + * Clamp number to min and max bounds, inclusive.
+ * DOUBLE version + * + * @param number clamped number + * @param range range + * @return result + */ + public static double clampd(Number number, Range range) { + return clamp_double(number, range.getMin(), range.getMax()); + } + + /** + * Clamp number to min and max bounds, inclusive.
+ * FLOAT version + * + * @param number clamped number + * @param range range + * @return result + */ + public static float clampf(Number number, Range range) { + return (float) clamp_double(number, range.getMin(), range.getMax()); + } + + /** + * Clamp number to min and infinite bounds, inclusive.
+ * DOUBLE version + * + * @param number clamped number + * @param min minimal allowed value + * @return result + */ + public static double clampd(Number number, Number min) { + return clamp_double(number, min); + } + + /** + * Clamp number to min and infinite bounds, inclusive.
+ * FLOAT version + * + * @param number clamped number + * @param min minimal allowed value + * @return result + */ + public static float clampf(Number number, Number min) { + return (float) clamp_double(number, min); + } + + /** + * Clamp number to min and infinite bounds, inclusive.
+ * INTEGER version + * + * @param number clamped number + * @param min minimal allowed value + * @return result + */ + public static int clampi(Number number, Number min) { + return (int) Math.round(clamp_double(number, min)); + } + + /** + * Get class simple name + * + * @param obj object + * @return simple name + */ + public static String className(Object obj) { + if (obj == null) return "NULL"; + return obj.getClass().getSimpleName(); + } + + /** + * Cube a double + * + * @param a squared double + * @return square + */ + public static double cube(double a) { + return a * a * a; + } + + /** + * Convert double to string, remove the mess at the end. + * + * @param d double + * @return string + */ + public static String doubleToString(double d) { + String s = Double.toString(d); + s = s.replaceAll("([0-9]+\\.[0-9]+)00+[0-9]+", "$1"); + s = s.replaceAll("0+$", ""); + s = s.replaceAll("\\.$", ""); + return s; + } + + /** + * Convert float to string, remove the mess at the end. + * + * @param f float + * @return string + */ + public static String floatToString(float f) { + String s = Float.toString(f); + s = s.replaceAll("([0-9]+\\.[0-9]+)00+[0-9]+", "$1"); + s = s.replaceAll("0+$", ""); + s = s.replaceAll("\\.$", ""); + return s; + } + + /** + * Check if number is in range + * + * @param number checked + * @param left lower end + * @param right upper end + * @return is in range + */ + public static boolean inRange(double number, double left, double right) { + return number >= left && number <= right; + } + + /** + * Get number from A to B at delta time (tween A to B) + * + * @param last last number + * @param now new number + * @param dtime delta time + * @return current number to render + */ + public static double interpolate(double last, double now, double dtime) { + return last + (now - last) * dtime; + } + + /** + * Get angle [degrees] from A to B at delta time (tween A to B) + * + * @param last last angle + * @param now new angle + * @param delta delta time + * @return current angle to render + */ + public static double interpolateDeg(double last, double now, double delta) { + return Deg.norm(last + Deg.delta(now, last) * delta); + } + + /** + * Get highest number of a list + * + * @param numbers numbers + * @return lowest + */ + public static double max(double... numbers) { + double highest = numbers[0]; + for (double num : numbers) { + if (num > highest) highest = num; + } + return highest; + } + + /** + * Get highest number of a list + * + * @param numbers numbers + * @return lowest + */ + public static float max(float... numbers) { + float highest = numbers[0]; + for (float num : numbers) { + if (num > highest) highest = num; + } + return highest; + } + + /** + * Get highest number of a list + * + * @param numbers numbers + * @return lowest + */ + public static int max(int... numbers) { + int highest = numbers[0]; + for (int num : numbers) { + if (num > highest) highest = num; + } + return highest; + } + + /** + * Get lowest number of a list + * + * @param numbers numbers + * @return lowest + */ + public static double min(double... numbers) { + double lowest = numbers[0]; + for (double num : numbers) { + if (num < lowest) lowest = num; + } + return lowest; + } + + /** + * Get lowest number of a list + * + * @param numbers numbers + * @return lowest + */ + public static float min(float... numbers) { + float lowest = numbers[0]; + for (float num : numbers) { + if (num < lowest) lowest = num; + } + return lowest; + } + + /** + * Get lowest number of a list + * + * @param numbers numbers + * @return lowest + */ + public static int min(int... numbers) { + int lowest = numbers[0]; + for (int num : numbers) { + if (num < lowest) lowest = num; + } + return lowest; + } + + /** + * Split comma separated list of integers. + * + * @param list String containing the list. + * @return array of integers or null. + */ + public static List parseIntList(String list) { + if (list == null) { + return null; + } + String[] parts = list.split(","); + + ArrayList intList = new ArrayList(); + + for (String part : parts) { + try { + intList.add(Integer.parseInt(part)); + } catch (NumberFormatException e) {} + } + + return intList; + + } + + /** + * Pick random element from a given list. + * + * @param list list of choices + * @return picked element + */ + public static Object pick(List list) { + if (list.size() == 0) return null; + return list.get(rand.nextInt(list.size())); + } + + /** + * Square a double + * + * @param a squared double + * @return square + */ + public static double square(double a) { + return a * a; + } + + /** + * Signum. + * + * @param number + * @return sign, -1,0,1 + */ + public static int sgn(double number) { + return number > 0 ? 1 : number < 0 ? -1 : 0; + } + +} diff --git a/src/com/porcupine/math/Polar.java b/src/com/porcupine/math/Polar.java new file mode 100644 index 0000000..b1b202d --- /dev/null +++ b/src/com/porcupine/math/Polar.java @@ -0,0 +1,91 @@ +package com.porcupine.math; + + +import com.porcupine.coord.Coord; + + +/** + * Polar coordinate + * + * @author MightyPork + */ +public class Polar { + /** angle in radians */ + public double angle = 0; + /** distance in units */ + public double distance = 0; + + /** + * @param angle angle in radians + * @param distance distance from origin + */ + public Polar(double angle, double distance) { + this.angle = angle; + this.distance = distance; + } + + /** + * Make polar from coord + * + * @param coord coord + * @return polar + */ + public static Polar fromCoord(Coord coord) { + return new Polar(Math.atan2(coord.y, coord.x), Math.sqrt(Calc.square(coord.x) + Calc.square(coord.y))); + } + + /** + * Make polar from coords + * + * @param x x coord + * @param y y coord + * @return polar + */ + public static Polar fromCoord(double x, double y) { + return Polar.fromCoord(new Coord(x, y)); + } + + /** + * Make polar from coords + * + * @param x x coord + * @param z z coord + * @return polar + */ + public static Polar fromCoordXZ(double x, double z) { + return Polar.fromCoordXZ(new Coord(x, 0, z)); + } + + /** + * Get coord from polar + * + * @return coord + */ + public Coord toCoord() { + return new Coord(distance * Math.cos(angle), distance * Math.sin(angle)); + } + + /** + * Get X,0,Y coord from polar + * + * @return coord + */ + public Coord toCoordXZ() { + return new Coord(distance * Math.cos(angle), 0, distance * Math.sin(angle)); + } + + @Override + public String toString() { + return "Polar(theta=" + angle + ", r=" + distance + ")"; + } + + /** + * Build polar from X,Z instead of X,Y + * + * @param coord cpprd with X,Z + * @return polar + */ + public static Polar fromCoordXZ(Coord coord) { + return fromCoord(coord.x, coord.z); + } +} diff --git a/src/com/porcupine/math/PolarDeg.java b/src/com/porcupine/math/PolarDeg.java new file mode 100644 index 0000000..34c2d18 --- /dev/null +++ b/src/com/porcupine/math/PolarDeg.java @@ -0,0 +1,95 @@ +package com.porcupine.math; + + +import com.porcupine.coord.Coord; +import com.porcupine.math.Calc.Deg; +import com.porcupine.math.Calc.Rad; + + +/** + * Polar coordinate in degrees + * + * @author MightyPork + */ +public class PolarDeg { + /** angle in degrees */ + public double angle = 0; + /** distance in units */ + public double distance = 0; + + /** + * Polar coordinate in degrees + * + * @param angle angle in degrees + * @param distance distance from origin + */ + public PolarDeg(double angle, double distance) { + this.angle = angle; + this.distance = distance; + } + + /** + * Make polar from coord + * + * @param coord coord + * @return polar + */ + public static PolarDeg fromCoord(Coord coord) { + return new PolarDeg(Rad.toDeg(Math.atan2(coord.y, coord.x)), Math.sqrt(Calc.square(coord.x) + Calc.square(coord.y))); + } + + /** + * Make polar from coords + * + * @param x x coord + * @param y y coord + * @return polar + */ + public static PolarDeg fromCoord(double x, double y) { + return PolarDeg.fromCoord(new Coord(x, y)); + } + + /** + * Make polar from coords + * + * @param x x coord + * @param z y coord + * @return polar + */ + public static PolarDeg fromCoordXZ(double x, double z) { + return PolarDeg.fromCoordXZ(new Coord(x, 0, z)); + } + + /** + * Get coord from polar + * + * @return coord + */ + public Coord toCoord() { + return new Coord(distance * Math.cos(Deg.toRad(angle)), distance * Math.sin(Deg.toRad(angle))); + } + + /** + * Get X,0,Y coord from polar + * + * @return coord + */ + public Coord toCoordXZ() { + return new Coord(distance * Math.cos(Deg.toRad(angle)), 0, distance * Math.sin(Deg.toRad(angle))); + } + + @Override + public String toString() { + return "Polar(theta=" + angle + ", r=" + distance + ")"; + } + + /** + * Build polar from X,Z instead of X,Y + * + * @param coord cpprd with X,Z + * @return polar + */ + public static PolarDeg fromCoordXZ(Coord coord) { + return fromCoord(coord.x, coord.z); + } +} diff --git a/src/com/porcupine/math/Range.java b/src/com/porcupine/math/Range.java new file mode 100644 index 0000000..5900f0c --- /dev/null +++ b/src/com/porcupine/math/Range.java @@ -0,0 +1,174 @@ +package com.porcupine.math; + + +import java.util.Random; + + +/** + * Numeric range, able to generate random numbers and give min/max values. + * + * @author MightyPork + */ +public class Range { + private double min = 0; + private double max = 1; + + private static Random rand = new Random(); + + /** + * Implicit range constructor 0-1 + */ + public Range() {} + + + /** + * Create new range + * + * @param min min number + * @param max max number + */ + public Range(double min, double max) { + if (min > max) { + double t = min; + min = max; + max = t; + } + this.min = min; + this.max = max; + } + + /** + * Create new range + * + * @param minmax min = max number + */ + public Range(double minmax) { + this.min = minmax; + this.max = minmax; + } + + /** + * Get random integer from range + * + * @return random int + */ + public int randInt() { + return (int) (Math.round(min) + rand.nextInt((int) (Math.round(max) - Math.round(min)) + 1)); + } + + /** + * Get random double from this range + * + * @return random double + */ + public double randDouble() { + return min + rand.nextDouble() * (max - min); + } + + /** + * Get min + * + * @return min number + */ + public double getMin() { + return min; + } + + /** + * Get max + * + * @return max number + */ + public double getMax() { + return max; + } + + /** + * Get min + * + * @return min number + */ + public int getMinI() { + return (int) min; + } + + /** + * Get max + * + * @return max number + */ + public int getMaxI() { + return (int) max; + } + + /** + * Set min + * + * @param min min value + */ + public void setMin(double min) { + this.min = min; + } + + /** + * Set max + * + * @param max max value + */ + public void setMax(double max) { + this.max = max; + } + + @Override + public String toString() { + return "Range(" + min + ";" + max + ")"; + } + + + /** + * Get identical copy + * + * @return copy + */ + public Range copy() { + return new Range(min, max); + } + + + /** + * Set to value of other range + * + * @param other copied range + */ + public void setTo(Range other) { + if (other == null) return; + min = other.min; + max = other.max; + + if (min > max) { + double t = min; + min = max; + max = t; + } + } + + + /** + * Set to min-max values + * + * @param min min value + * @param max max value + */ + public void setTo(double min, double max) { + + if (min > max) { + double t = min; + min = max; + max = t; + } + + this.min = min; + this.max = max; + } + +} diff --git a/src/com/porcupine/mutable/AbstractMutable.java b/src/com/porcupine/mutable/AbstractMutable.java new file mode 100644 index 0000000..aea5e2f --- /dev/null +++ b/src/com/porcupine/mutable/AbstractMutable.java @@ -0,0 +1,52 @@ +package com.porcupine.mutable; + + +/** + * Mutable object + * + * @author MightyPork + * @param type + */ +public abstract class AbstractMutable { + /** The wrapped value */ + public T o = getDefault(); + + /** + * Implicint constructor + */ + public AbstractMutable() {} + + /** + * new mutable object + * + * @param o value + */ + public AbstractMutable(T o) { + this.o = o; + } + + /** + * Get the wrapped value + * + * @return value + */ + public T get() { + return o; + } + + /** + * Set value + * + * @param o new value to set + */ + public void set(T o) { + this.o = o; + } + + /** + * Get default value + * + * @return default value + */ + protected abstract T getDefault(); +} diff --git a/src/com/porcupine/mutable/MBoolean.java b/src/com/porcupine/mutable/MBoolean.java new file mode 100644 index 0000000..46fc99d --- /dev/null +++ b/src/com/porcupine/mutable/MBoolean.java @@ -0,0 +1,28 @@ +package com.porcupine.mutable; + + +/** + * Mutable boolean + * + * @author MightyPork + */ +public class MBoolean extends AbstractMutable { + /** + * Mutable boolean + * + * @param o value + */ + public MBoolean(Boolean o) { + super(o); + } + + /** + * Imp.c. + */ + public MBoolean() {} + + @Override + protected Boolean getDefault() { + return false; + } +} diff --git a/src/com/porcupine/mutable/MDouble.java b/src/com/porcupine/mutable/MDouble.java new file mode 100644 index 0000000..cbaf818 --- /dev/null +++ b/src/com/porcupine/mutable/MDouble.java @@ -0,0 +1,28 @@ +package com.porcupine.mutable; + + +/** + * Mutable double + * + * @author MightyPork + */ +public class MDouble extends AbstractMutable { + /** + * Mutable double + * + * @param o value + */ + public MDouble(Double o) { + super(o); + } + + /** + * Imp.c. + */ + public MDouble() {} + + @Override + protected Double getDefault() { + return 0d; + } +} diff --git a/src/com/porcupine/mutable/MFloat.java b/src/com/porcupine/mutable/MFloat.java new file mode 100644 index 0000000..41b015a --- /dev/null +++ b/src/com/porcupine/mutable/MFloat.java @@ -0,0 +1,29 @@ +package com.porcupine.mutable; + + +/** + * Mutable float + * + * @author MightyPork + */ +public class MFloat extends AbstractMutable { + /** + * Mutable float + * + * @param o value + */ + public MFloat(Float o) { + super(o); + } + + + /** + * Imp.c. + */ + public MFloat() {} + + @Override + protected Float getDefault() { + return 0f; + } +} diff --git a/src/com/porcupine/mutable/MInt.java b/src/com/porcupine/mutable/MInt.java new file mode 100644 index 0000000..f30a2d7 --- /dev/null +++ b/src/com/porcupine/mutable/MInt.java @@ -0,0 +1,28 @@ +package com.porcupine.mutable; + + +/** + * Mutable integer + * + * @author MightyPork + */ +public class MInt extends AbstractMutable { + /** + * Mutable int + * + * @param o value + */ + public MInt(Integer o) { + super(o); + } + + /** + * Imp.c. + */ + public MInt() {} + + @Override + protected Integer getDefault() { + return 0; + } +} diff --git a/src/com/porcupine/mutable/MString.java b/src/com/porcupine/mutable/MString.java new file mode 100644 index 0000000..45bfa61 --- /dev/null +++ b/src/com/porcupine/mutable/MString.java @@ -0,0 +1,28 @@ +package com.porcupine.mutable; + + +/** + * Mutable string + * + * @author MightyPork + */ +public class MString extends AbstractMutable { + /** + * Mutable string + * + * @param o value + */ + public MString(String o) { + super(o); + } + + /** + * Imp.c. + */ + public MString() {} + + @Override + protected String getDefault() { + return ""; + } +} diff --git a/src/com/porcupine/struct/Struct2.java b/src/com/porcupine/struct/Struct2.java new file mode 100644 index 0000000..26b5d86 --- /dev/null +++ b/src/com/porcupine/struct/Struct2.java @@ -0,0 +1,132 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 2 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + */ +public class Struct2 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * Make structure of 2 objects + * + * @param objA 1st object + * @param objB 2nd object + */ + public Struct2(T1 objA, T2 objB) { + a = objA; + b = objB; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct2 t = (Struct2) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "}"; + } + +} diff --git a/src/com/porcupine/struct/Struct3.java b/src/com/porcupine/struct/Struct3.java new file mode 100644 index 0000000..331d4a1 --- /dev/null +++ b/src/com/porcupine/struct/Struct3.java @@ -0,0 +1,172 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 3 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + * @param 3rd object class + */ +public class Struct3 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * 3rd object + */ + public T3 c; + + /** + * Make structure of 3 objects + * + * @param objA 1st object + * @param objB 2nd object + * @param objC 3rd object + */ + public Struct3(T1 objA, T2 objB, T3 objC) { + a = objA; + b = objB; + c = objC; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 3rd object + */ + public T3 getC() { + return c; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + /** + * @return 3rd object + */ + public T3 get3() { + return c; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void setC(T3 obj) { + c = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void set3(T3 obj) { + c = obj; + } + + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct3 t = (Struct3) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b) && Calc.areObjectsEqual(c, t.c); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + hash += (c == null ? 0 : c.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "," + c + "}"; + } + +} diff --git a/src/com/porcupine/struct/Struct4.java b/src/com/porcupine/struct/Struct4.java new file mode 100644 index 0000000..6ea6ede --- /dev/null +++ b/src/com/porcupine/struct/Struct4.java @@ -0,0 +1,213 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 4 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + * @param 3rd object class + * @param 4th object class + */ +public class Struct4 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * 3rd object + */ + public T3 c; + + /** + * 4th object + */ + public T4 d; + + /** + * Make structure of 4 objects + * + * @param objA 1st object + * @param objB 2nd object + * @param objC 3rd object + * @param objD 4th object + */ + public Struct4(T1 objA, T2 objB, T3 objC, T4 objD) { + a = objA; + b = objB; + c = objC; + d = objD; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 3rd object + */ + public T3 getC() { + return c; + } + + /** + * @return 4th object + */ + public T4 getD() { + return d; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + /** + * @return 3rd object + */ + public T3 get3() { + return c; + } + + /** + * @return 4th object + */ + public T4 get4() { + return d; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void setC(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void setD(T4 obj) { + d = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void set3(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void set4(T4 obj) { + d = obj; + } + + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct4 t = (Struct4) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b) && Calc.areObjectsEqual(c, t.c) && Calc.areObjectsEqual(d, t.d); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + hash += (c == null ? 0 : c.hashCode()); + hash += (d == null ? 0 : d.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "," + c + "," + d + "}"; + } + +} diff --git a/src/com/porcupine/struct/Struct5.java b/src/com/porcupine/struct/Struct5.java new file mode 100644 index 0000000..790c76d --- /dev/null +++ b/src/com/porcupine/struct/Struct5.java @@ -0,0 +1,256 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 5 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + * @param 3rd object class + * @param 4th object class + * @param 5th object class + */ +public class Struct5 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * 3rd object + */ + public T3 c; + + /** + * 4th object + */ + public T4 d; + + /** + * 5th object + */ + public T5 e; + + /** + * Make structure of 4 objects + * + * @param objA 1st object + * @param objB 2nd object + * @param objC 3rd object + * @param objD 4th object + * @param objE 5th object + */ + public Struct5(T1 objA, T2 objB, T3 objC, T4 objD, T5 objE) { + a = objA; + b = objB; + c = objC; + d = objD; + e = objE; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 3rd object + */ + public T3 getC() { + return c; + } + + /** + * @return 4th object + */ + public T4 getD() { + return d; + } + + /** + * @return 5th object + */ + public T5 getE() { + return e; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + /** + * @return 3rd object + */ + public T3 get3() { + return c; + } + + /** + * @return 4th object + */ + public T4 get4() { + return d; + } + + /** + * @return 5th object + */ + public T5 get5() { + return e; + } + + + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void setC(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void setD(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void setE(T5 obj) { + e = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void set3(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void set4(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void set5(T5 obj) { + e = obj; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct5 t = (Struct5) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b) && Calc.areObjectsEqual(c, t.c) && Calc.areObjectsEqual(d, t.d) + && Calc.areObjectsEqual(e, t.e); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + hash += (c == null ? 0 : c.hashCode()); + hash += (d == null ? 0 : d.hashCode()); + hash += (e == null ? 0 : e.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "," + c + "," + d + "," + e + "}"; + } + +} diff --git a/src/com/porcupine/struct/Struct6.java b/src/com/porcupine/struct/Struct6.java new file mode 100644 index 0000000..33f17a5 --- /dev/null +++ b/src/com/porcupine/struct/Struct6.java @@ -0,0 +1,295 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 6 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + * @param 3rd object class + * @param 4th object class + * @param 5th object class + * @param 6th object class + */ +public class Struct6 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * 3rd object + */ + public T3 c; + + /** + * 4th object + */ + public T4 d; + + /** + * 5th object + */ + public T5 e; + + /** + * 6th object + */ + public T6 f; + + /** + * Make structure of 4 objects + * + * @param objA 1st object + * @param objB 2nd object + * @param objC 3rd object + * @param objD 4th object + * @param objE 5th object + * @param objF 6th object + */ + public Struct6(T1 objA, T2 objB, T3 objC, T4 objD, T5 objE, T6 objF) { + a = objA; + b = objB; + c = objC; + d = objD; + e = objE; + f = objF; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 3rd object + */ + public T3 getC() { + return c; + } + + /** + * @return 4th object + */ + public T4 getD() { + return d; + } + + /** + * @return 5th object + */ + public T5 getE() { + return e; + } + + /** + * @return 6th object + */ + public T6 getF() { + return f; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + /** + * @return 3rd object + */ + public T3 get3() { + return c; + } + + /** + * @return 4th object + */ + public T4 get4() { + return d; + } + + /** + * @return 5th object + */ + public T5 get5() { + return e; + } + + /** + * @return 6th object + */ + public T6 get6() { + return f; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void setC(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void setD(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void setE(T5 obj) { + e = obj; + } + + /** + * Set 6th object + * + * @param obj 6th object + */ + public void setF(T6 obj) { + f = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void set3(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void set4(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void set5(T5 obj) { + e = obj; + } + + /** + * Set 6th object + * + * @param obj 6th object + */ + public void set6(T6 obj) { + f = obj; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct6 t = (Struct6) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b) && Calc.areObjectsEqual(c, t.c) && Calc.areObjectsEqual(d, t.d) + && Calc.areObjectsEqual(e, t.e) && Calc.areObjectsEqual(f, t.f); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + hash += (c == null ? 0 : c.hashCode()); + hash += (d == null ? 0 : d.hashCode()); + hash += (e == null ? 0 : e.hashCode()); + hash += (f == null ? 0 : f.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "," + c + "," + d + "," + e + "," + f + "}"; + } + +} diff --git a/src/com/porcupine/struct/Struct7.java b/src/com/porcupine/struct/Struct7.java new file mode 100644 index 0000000..6be3a48 --- /dev/null +++ b/src/com/porcupine/struct/Struct7.java @@ -0,0 +1,336 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 7 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + * @param 3rd object class + * @param 4th object class + * @param 5th object class + * @param 6th object class + * @param 7th object class + */ +public class Struct7 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * 3rd object + */ + public T3 c; + + /** + * 4th object + */ + public T4 d; + + /** + * 5th object + */ + public T5 e; + + /** + * 6th object + */ + public T6 f; + + /** + * 7th object + */ + public T7 g; + + /** + * Make structure of 4 objects + * + * @param objA 1st object + * @param objB 2nd object + * @param objC 3rd object + * @param objD 4th object + * @param objE 5th object + * @param objF 6th object + * @param objG 7th object + */ + public Struct7(T1 objA, T2 objB, T3 objC, T4 objD, T5 objE, T6 objF, T7 objG) { + a = objA; + b = objB; + c = objC; + d = objD; + e = objE; + f = objF; + g = objG; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 3rd object + */ + public T3 getC() { + return c; + } + + /** + * @return 4th object + */ + public T4 getD() { + return d; + } + + /** + * @return 5th object + */ + public T5 getE() { + return e; + } + + /** + * @return 6th object + */ + public T6 getF() { + return f; + } + + /** + * @return 7th object + */ + public T7 getG() { + return g; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + /** + * @return 3rd object + */ + public T3 get3() { + return c; + } + + /** + * @return 4th object + */ + public T4 get4() { + return d; + } + + /** + * @return 5th object + */ + public T5 get5() { + return e; + } + + /** + * @return 6th object + */ + public T6 get6() { + return f; + } + + /** + * @return 7th object + */ + public T7 get7() { + return g; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void setC(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void setD(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void setE(T5 obj) { + e = obj; + } + + /** + * Set 6th object + * + * @param obj 6th object + */ + public void setF(T6 obj) { + f = obj; + } + + /** + * Set 7th object + * + * @param obj 6th object + */ + public void setG(T7 obj) { + g = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void set3(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void set4(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void set5(T5 obj) { + e = obj; + } + + /** + * Set 6th object + * + * @param obj 6th object + */ + public void set6(T6 obj) { + f = obj; + } + + /** + * Set 7th object + * + * @param obj 6th object + */ + public void set7(T7 obj) { + g = obj; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct7 t = (Struct7) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b) && Calc.areObjectsEqual(c, t.c) && Calc.areObjectsEqual(d, t.d) + && Calc.areObjectsEqual(e, t.e) && Calc.areObjectsEqual(f, t.f) && Calc.areObjectsEqual(g, t.g); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + hash += (c == null ? 0 : c.hashCode()); + hash += (d == null ? 0 : d.hashCode()); + hash += (e == null ? 0 : e.hashCode()); + hash += (f == null ? 0 : f.hashCode()); + hash += (g == null ? 0 : g.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "," + c + "," + d + "," + e + "," + f + "," + g + "}"; + } + +} diff --git a/src/com/porcupine/struct/Struct8.java b/src/com/porcupine/struct/Struct8.java new file mode 100644 index 0000000..dd9ad56 --- /dev/null +++ b/src/com/porcupine/struct/Struct8.java @@ -0,0 +1,377 @@ +package com.porcupine.struct; + + +import com.porcupine.math.Calc; + + +/** + * Structure of 7 objects. + * + * @author MightyPork + * @copy (c) 2012 + * @param 1st object class + * @param 2nd object class + * @param 3rd object class + * @param 4th object class + * @param 5th object class + * @param 6th object class + * @param 7th object class + * @param 8th object class + */ +public class Struct8 { + /** + * 1st object + */ + public T1 a; + + /** + * 2nd object + */ + public T2 b; + + /** + * 3rd object + */ + public T3 c; + + /** + * 4th object + */ + public T4 d; + + /** + * 5th object + */ + public T5 e; + + /** + * 6th object + */ + public T6 f; + + /** + * 7th object + */ + public T7 g; + + /** + * 8th object + */ + public T8 h; + + /** + * Make structure of 4 objects + * + * @param objA 1st object + * @param objB 2nd object + * @param objC 3rd object + * @param objD 4th object + * @param objE 5th object + * @param objF 6th object + * @param objG 7th object + * @param objH 8th object + */ + public Struct8(T1 objA, T2 objB, T3 objC, T4 objD, T5 objE, T6 objF, T7 objG, T8 objH) { + a = objA; + b = objB; + c = objC; + d = objD; + e = objE; + f = objF; + g = objG; + h = objH; + } + + /** + * @return 1st object + */ + public T1 getA() { + return a; + } + + /** + * @return 2nd object + */ + public T2 getB() { + return b; + } + + /** + * @return 3rd object + */ + public T3 getC() { + return c; + } + + /** + * @return 4th object + */ + public T4 getD() { + return d; + } + + /** + * @return 5th object + */ + public T5 getE() { + return e; + } + + /** + * @return 6th object + */ + public T6 getF() { + return f; + } + + /** + * @return 7th object + */ + public T7 getG() { + return g; + } + + /** + * @return 8th object + */ + public T8 getH() { + return h; + } + + /** + * @return 1st object + */ + public T1 get1() { + return a; + } + + /** + * @return 2nd object + */ + public T2 get2() { + return b; + } + + /** + * @return 3rd object + */ + public T3 get3() { + return c; + } + + /** + * @return 4th object + */ + public T4 get4() { + return d; + } + + /** + * @return 5th object + */ + public T5 get5() { + return e; + } + + /** + * @return 6th object + */ + public T6 get6() { + return f; + } + + /** + * @return 7th object + */ + public T7 get7() { + return g; + } + + /** + * @return 8th object + */ + public T8 get8() { + return h; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void setA(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void setB(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void setC(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void setD(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void setE(T5 obj) { + e = obj; + } + + /** + * Set 6th object + * + * @param obj 6th object + */ + public void setF(T6 obj) { + f = obj; + } + + /** + * Set 7th object + * + * @param obj 6th object + */ + public void setG(T7 obj) { + g = obj; + } + + /** + * Set 8th object + * + * @param obj 6th object + */ + public void setH(T8 obj) { + h = obj; + } + + /** + * Set 1st object + * + * @param obj 1st object + */ + public void set1(T1 obj) { + a = obj; + } + + /** + * Set 2nd object + * + * @param obj 2nd object + */ + public void set2(T2 obj) { + b = obj; + } + + /** + * Set 3rd object + * + * @param obj 3rd object + */ + public void set3(T3 obj) { + c = obj; + } + + /** + * Set 4th object + * + * @param obj 4th object + */ + public void set4(T4 obj) { + d = obj; + } + + /** + * Set 5th object + * + * @param obj 5th object + */ + public void set5(T5 obj) { + e = obj; + } + + /** + * Set 6th object + * + * @param obj 6th object + */ + public void set6(T6 obj) { + f = obj; + } + + /** + * Set 7th object + * + * @param obj 6th object + */ + public void set7(T7 obj) { + g = obj; + } + + /** + * Set 8th object + * + * @param obj 6th object + */ + public void set8(T8 obj) { + h = obj; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (!this.getClass().equals(obj.getClass())) { + return false; + } + + Struct8 t = (Struct8) obj; + + return Calc.areObjectsEqual(a, t.a) && Calc.areObjectsEqual(b, t.b) && Calc.areObjectsEqual(c, t.c) && Calc.areObjectsEqual(d, t.d) + && Calc.areObjectsEqual(e, t.e) && Calc.areObjectsEqual(f, t.f) && Calc.areObjectsEqual(g, t.g) && Calc.areObjectsEqual(h, t.h); + + } + + @Override + public int hashCode() { + int hash = 0; + hash += (a == null ? 0 : a.hashCode()); + hash += (b == null ? 0 : b.hashCode()); + hash += (c == null ? 0 : c.hashCode()); + hash += (d == null ? 0 : d.hashCode()); + hash += (e == null ? 0 : e.hashCode()); + hash += (f == null ? 0 : f.hashCode()); + hash += (g == null ? 0 : g.hashCode()); + hash += (h == null ? 0 : h.hashCode()); + return hash; + } + + @Override + public String toString() { + return "STRUCT {" + a + "," + b + "," + c + "," + d + "," + e + "," + f + "," + g + "," + h + "}"; + } + +} diff --git a/src/com/porcupine/time/FpsMeter.java b/src/com/porcupine/time/FpsMeter.java new file mode 100644 index 0000000..1af2de0 --- /dev/null +++ b/src/com/porcupine/time/FpsMeter.java @@ -0,0 +1,54 @@ +package com.porcupine.time; + + +/** + * Class for counting FPS in games.
+ * This class can be used also as a simple frequency meter - output is in Hz. + * + * @author MightyPork + */ +public class FpsMeter { + + private long frames = 0; + private long drops = 0; + private long lastTimeMillis = System.currentTimeMillis(); + private long lastSecFPS = 0; + private long lastSecDrop = 0; + + /** + * @return current second's FPS + */ + public long getFPS() { + return lastSecFPS; + } + + /** + * Notification that frame was rendered + */ + public void frame() { + if (System.currentTimeMillis() - lastTimeMillis > 1000) { + lastSecFPS = frames; + lastSecDrop = drops; + frames = 0; + drops = 0; + lastTimeMillis = System.currentTimeMillis(); + } + frames++; + } + + /** + * Notification that some frames have been dropped + * + * @param dropped dropped frames + */ + public void drop(int dropped) { + drops += dropped; + } + + /** + * @return current second's dropped frames + */ + public long getDropped() { + return lastSecDrop; + } +} diff --git a/src/com/porcupine/time/Timer.java b/src/com/porcupine/time/Timer.java new file mode 100644 index 0000000..b87c9b9 --- /dev/null +++ b/src/com/porcupine/time/Timer.java @@ -0,0 +1,130 @@ +package com.porcupine.time; + + +import com.porcupine.math.Calc; + + +/** + * Precise game timer + */ +public class Timer { + + /** + * Ticks elapsed since last updateTimer().
+ * Used to count how many frames to skip. + */ + public int ticksMissed; + + + /** Speed multiplier. */ + public float timerSpeedMultiplier; + + + /** + * How much of the next tick has already elapsed. + */ + public float renderDeltaTime; + + + /** + * How many update ticks are to be run since last time + * + * @return update ticks needed + */ + public int getTicksMissed() { + return ticksMissed; + } + + /** + * Get render delta time, 0-1 + * + * @return delta time + */ + public double getDeltaTime() { + return renderDeltaTime; + } + + /** + * @return speed multiplier + */ + public double getSpeed() { + return timerSpeedMultiplier; + } + + /** + * Set speed multiplier + * + * @param speed new speed multiplier + */ + public void setSpeed(double speed) { + timerSpeedMultiplier = (float) speed; + } + + + + private float ticksPerSecond; + private double lastUpdateSecs; + private long lastUpdateMillis; + private long lastSyncMillis; + private long syncCounter; + private double timeSyncAdjustment; + + + /** + * init timer + * + * @param ticksPerSecond logic update ticks per second + */ + public Timer(float ticksPerSecond) { + timerSpeedMultiplier = 1.0F; + renderDeltaTime = 0.0F; + timeSyncAdjustment = 1.0D; + this.ticksPerSecond = ticksPerSecond; + + lastUpdateMillis = System.currentTimeMillis(); + lastSyncMillis = System.nanoTime() / 1000000; + } + + /** + * Updates all fields of the Timer using the current time + */ + public void update() { + long l = System.currentTimeMillis(); + long deltaMillis = l - lastUpdateMillis; + long millis = System.nanoTime() / 1000000; + double secs = millis / 1000D; + + if (deltaMillis > 1000L) { + lastUpdateSecs = secs; + } else if (deltaMillis < 0L) { + lastUpdateSecs = secs; + } else { + syncCounter += deltaMillis; + + if (syncCounter > 1000L) { + long d1 = millis - lastSyncMillis; + double d2 = (double) syncCounter / (double) d1; + timeSyncAdjustment += (d2 - timeSyncAdjustment) * 0.2D; + lastSyncMillis = millis; + syncCounter = 0L; + } + + if (syncCounter < 0L) { + lastSyncMillis = millis; + } + } + + lastUpdateMillis = l; + + double delta = (secs - lastUpdateSecs) * timeSyncAdjustment; + lastUpdateSecs = secs; + + delta = Calc.clampd(delta, 0, 1); + + renderDeltaTime += delta * timerSpeedMultiplier * ticksPerSecond; + ticksMissed = (int) renderDeltaTime; + renderDeltaTime -= ticksMissed; + + ticksMissed = Calc.clampi(ticksMissed, 0, 10); + } +} diff --git a/src/com/porcupine/util/FileSuffixFilter.java b/src/com/porcupine/util/FileSuffixFilter.java new file mode 100644 index 0000000..8fe85fd --- /dev/null +++ b/src/com/porcupine/util/FileSuffixFilter.java @@ -0,0 +1,36 @@ +package com.porcupine.util; + + +import java.io.File; +import java.io.FileFilter; + + +/** + * File filter for certain suffixes + * + * @author MightyPork + */ +public class FileSuffixFilter implements FileFilter { + + /** Array of allowed suffixes */ + private String[] suffixes = null; + + /** + * Suffix filter + * + * @param suffixes var-args allowed suffixes, case insensitive + */ + public FileSuffixFilter(String... suffixes) { + this.suffixes = suffixes; + } + + @Override + public boolean accept(File pathname) { + //System.out.println(pathname); + for (String suffix : suffixes) { + return pathname.isFile() && pathname.getName().toLowerCase().trim().endsWith(suffix.toLowerCase().trim()); + } + return false; + } + +} diff --git a/src/com/porcupine/util/FileUtils.java b/src/com/porcupine/util/FileUtils.java new file mode 100644 index 0000000..63c4122 --- /dev/null +++ b/src/com/porcupine/util/FileUtils.java @@ -0,0 +1,182 @@ +package com.porcupine.util; + + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.spritegen.util.Log; + + +/** + * Utilities for filesystem + * + * @author MightyPork + */ +public class FileUtils { + + private enum EnumOS { + linux, solaris, windows, macos, unknown; + } + + /** + * get working directory path ending with slash + * + * @param dirname name of the directory, dot will be added automatically + * @return File path to the folder + */ + public static File getAppDir(String dirname) { + String s = System.getProperty("user.home", "."); + File file; + + switch (getOs()) { + case linux: + case solaris: + file = new File(s, "." + dirname + '/'); + break; + + case windows: + String s1 = System.getenv("APPDATA"); + + if (s1 != null) { + file = new File(s1, "." + dirname + '/'); + } else { + file = new File(s, "." + dirname + '/'); + } + + break; + + case macos: + file = new File(s, "Library/Application Support/" + dirname); + break; + + default: + file = new File(s, dirname + "/"); + break; + } + + if (!file.exists() && !file.mkdirs()) { + throw new RuntimeException((new StringBuilder()).append("The working directory could not be created: ").append(file).toString()); + } else { + return file; + } + } + + private static EnumOS getOs() { + String s = System.getProperty("os.name").toLowerCase(); + + if (s.contains("win")) { + return EnumOS.windows; + } + + if (s.contains("mac")) { + return EnumOS.macos; + } + + if (s.contains("solaris")) { + return EnumOS.solaris; + } + + if (s.contains("sunos")) { + return EnumOS.solaris; + } + + if (s.contains("linux")) { + return EnumOS.linux; + } + + if (s.contains("unix")) { + return EnumOS.linux; + } else { + return EnumOS.unknown; + } + } + + /** + * Get files in a folder (create folder if needed) + * + * @param dir folder + * @param filter file filter + * @return list of files + */ + public static List listFolder(File dir, FileFilter filter) { + try { + dir.mkdir(); + } catch (RuntimeException e) { + Log.e("Error creating folder " + dir, e); + } + + List list = new ArrayList(); + + try { + for (File f : dir.listFiles(filter)) { + list.add(f); + } + } catch (Exception e) { + Log.e("Error listing folder " + dir, e); + } + + return list; + } + + /** + * Get files in a folder (create folder if needed) + * + * @param dir folder + * @return list of files + */ + public static List listFolder(File dir) { + return listFolder(dir, null); + } + + /** + * Remove extension. + * + * @param file file + * @return filename without extension + */ + public static String removeExtension(File file) { + return removeExtension(file.getName()); + } + + /** + * Remove extension. + * + * @param filename + * @return filename without extension + */ + public static String removeExtension(String filename) { + String[] parts = filename.split("[.]"); + String out = ""; + for (int i = 0; i < parts.length - 1; i++) { + out += parts[i]; + } + + return out; + } + + /** + * Read entire file to a string. + * + * @param file file + * @return file contents + * @throws IOException + */ + public static String fileToString(File file) throws IOException { + String result = null; + DataInputStream in = null; + + byte[] buffer = new byte[(int) file.length()]; + in = new DataInputStream(new FileInputStream(file)); + in.readFully(buffer); + result = new String(buffer); + in.close(); + + return result; + } + +} diff --git a/src/com/porcupine/util/PropertyManager.java b/src/com/porcupine/util/PropertyManager.java new file mode 100644 index 0000000..499a3aa --- /dev/null +++ b/src/com/porcupine/util/PropertyManager.java @@ -0,0 +1,1062 @@ +package com.porcupine.util; + + +import java.io.*; +import java.util.*; +import java.util.Map.Entry; + +import org.lwjgl.input.Keyboard; + +import com.porcupine.math.Calc; + + +/** + * Property manager with advanced formatting and value checking.
+ * Methods starting with put are for filling. Most of the others are shortcuts + * to getters. + * + * @author MightyPork + */ +public class PropertyManager { + /** + * Properties stored in file, alphabetically sorted.
+ * Property file is much cleaner than the normal java.util.Properties, + * newlines can be inserted to separate categories, and individual keys can + * have their own inline comments. + * + * @author MightyPork + * @copy (c) 2012 + */ + private static class PC_SortedProperties extends Properties { + + /** A table of hex digits */ + private static final char[] hexDigit_custom = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + /** + * this is here because the original method is private. + * + * @param nibble + * @return hex char. + */ + private static char toHex_custom(int nibble) { + return hexDigit_custom[(nibble & 0xF)]; + } + + private static void writeComments_custom(BufferedWriter bw, String comm) throws IOException { + + String comments = comm.replace("\n\n", "\n \n"); + + int len = comments.length(); + int current = 0; + int last = 0; + char[] uu = new char[6]; + uu[0] = '\\'; + uu[1] = 'u'; + while (current < len) { + char c = comments.charAt(current); + if (c > '\u00ff' || c == '\n' || c == '\r') { + if (last != current) { + bw.write("# " + comments.substring(last, current)); + } + + + + if (c > '\u00ff') { + uu[2] = toHex_custom((c >> 12) & 0xf); + uu[3] = toHex_custom((c >> 8) & 0xf); + uu[4] = toHex_custom((c >> 4) & 0xf); + uu[5] = toHex_custom(c & 0xf); + bw.write(new String(uu)); + } else { + bw.newLine(); + if (c == '\r' && current != len - 1 && comments.charAt(current + 1) == '\n') { + current++; + } + // if (current == len - 1 || (comments.charAt(current + 1) != '#' && comments.charAt(current + 1) != '!')) + // bw.write("#"); + } + last = current + 1; + } + current++; + } + if (last != current) { + bw.write("# " + comments.substring(last, current)); + } + bw.newLine(); + bw.newLine(); + bw.newLine(); + } + + /** Option: put empty line before each comment. */ + public boolean cfgEmptyLineBeforeComment = true; + /** + * Option: Separate sections by newline
+ * Section = string before first dot in key. + */ + public boolean cfgSeparateSectionsByEmptyLine = true; + + private boolean firstEntry = true; + + private Hashtable keyComments = new Hashtable(); + + private String lastSectionBeginning = ""; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public synchronized Enumeration keys() { + Enumeration keysEnum = super.keys(); + Vector keyList = new Vector(); + while (keysEnum.hasMoreElements()) { + keyList.add(keysEnum.nextElement()); + } + Collections.sort(keyList); + return keyList.elements(); + } + + private String saveConvert_custom(String theString, boolean escapeSpace, boolean escapeUnicode) { + + int len = theString.length(); + int bufLen = len * 2; + if (bufLen < 0) { + bufLen = Integer.MAX_VALUE; + } + StringBuffer outBuffer = new StringBuffer(bufLen); + + for (int x = 0; x < len; x++) { + char aChar = theString.charAt(x); + // Handle common case first, selecting largest block that + // avoids the specials below + if ((aChar > 61) && (aChar < 127)) { + if (aChar == '\\') { + outBuffer.append('\\'); + outBuffer.append('\\'); + continue; + } + outBuffer.append(aChar); + continue; + } + switch (aChar) { + case ' ': + if (x == 0 || escapeSpace) { + outBuffer.append('\\'); + } + outBuffer.append(' '); + break; + case '\t': + outBuffer.append('\\'); + outBuffer.append('t'); + break; + case '\n': + outBuffer.append('\\'); + outBuffer.append('n'); + break; + case '\r': + outBuffer.append('\\'); + outBuffer.append('r'); + break; + case '\f': + outBuffer.append('\\'); + outBuffer.append('f'); + break; + case '=': // Fall through + case ':': // Fall through + case '#': // Fall through + case '!': + outBuffer.append('\\'); + outBuffer.append(aChar); + break; + default: + if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode) { + outBuffer.append('\\'); + outBuffer.append('u'); + outBuffer.append(toHex_custom((aChar >> 12) & 0xF)); + outBuffer.append(toHex_custom((aChar >> 8) & 0xF)); + outBuffer.append(toHex_custom((aChar >> 4) & 0xF)); + outBuffer.append(toHex_custom(aChar & 0xF)); + } else { + outBuffer.append(aChar); + } + } + } + return outBuffer.toString(); + } + + /** + * Set additional comment to a key + * + * @param key key for comment + * @param comment the comment + */ + public void setKeyComment(String key, String comment) { + keyComments.put(key, comment); + } + + @Override + public void store(OutputStream out, String comments) throws IOException { + store_custom(new BufferedWriter(new OutputStreamWriter(out, "UTF-8")), comments, false); + } + + @SuppressWarnings("rawtypes") + private void store_custom(BufferedWriter bw, String comments, boolean escUnicode) throws IOException { + if (comments != null) { + writeComments_custom(bw, comments); + } + synchronized (this) { + for (Enumeration e = keys(); e.hasMoreElements();) { + + boolean wasNewLine = false; + + String key = (String) e.nextElement(); + String val = (String) get(key); + key = saveConvert_custom(key, true, escUnicode); + val = saveConvert_custom(val, false, escUnicode); + + if (cfgSeparateSectionsByEmptyLine && !lastSectionBeginning.equals(key.split("[.]")[0])) { + + if (!firstEntry) { + bw.newLine(); + bw.newLine(); + } + + wasNewLine = true; + lastSectionBeginning = key.split("[.]")[0]; + } + + if (keyComments.containsKey(key)) { + String cm = keyComments.get(key); + cm = cm.replace("\r", "\n"); + cm = cm.replace("\r\n", "\n"); + cm = cm.replace("\n\n", "\n \n"); + + String[] cmlines = cm.split("\n"); + + if (!wasNewLine && !firstEntry && cfgEmptyLineBeforeComment) { + bw.newLine(); + } + for (String cmline : cmlines) { + bw.write("# " + cmline); + bw.newLine(); + } + } + + bw.write(key + " = " + val); + bw.newLine(); + + firstEntry = false; + } + } + bw.flush(); + } + } + + /** + * Helper class which loads Properties from UTF-8 file (Properties use + * "ISO-8859-1" by default) + * + * @author Itay Maman + */ + private static class PropertiesLoader { + private static String escapifyStr(String str) { + StringBuilder result = new StringBuilder(); + + int len = str.length(); + for (int x = 0; x < len; x++) { + char ch = str.charAt(x); + if (ch <= 0x007e) { + result.append(ch); + continue; + } + + result.append('\\'); + result.append('u'); + result.append(hexDigit(ch, 12)); + result.append(hexDigit(ch, 8)); + result.append(hexDigit(ch, 4)); + result.append(hexDigit(ch, 0)); + } + return result.toString(); + } + + private static char hexDigit(char ch, int offset) { + int val = (ch >> offset) & 0xF; + if (val <= 9) { + return (char) ('0' + val); + } + + return (char) ('A' + val - 10); + } + + public static PC_SortedProperties loadProperties(PC_SortedProperties props, InputStream is) throws IOException { + return loadProperties(props, is, "utf-8"); + } + + + public static PC_SortedProperties loadProperties(PC_SortedProperties props, InputStream is, String encoding) throws IOException { + StringBuilder sb = new StringBuilder(); + InputStreamReader isr = new InputStreamReader(is, encoding); + while (true) { + int temp = isr.read(); + if (temp < 0) { + break; + } + + char c = (char) temp; + sb.append(c); + } + + String read = sb.toString(); + + String inputString = escapifyStr(read); + byte[] bs = inputString.getBytes("ISO-8859-1"); + ByteArrayInputStream bais = new ByteArrayInputStream(bs); + + PC_SortedProperties ps = props; + ps.load(bais); + return ps; + } + } + + /** + * Property entry in Property manager. + * + * @author MightyPork + * @copy (c) 2012 + */ + private class Property { + public boolean bool = false; + public String entryComment; + public boolean defbool = false; + public double defnum = -1; + + public String defstr = ""; + public String name; + public double num = -1; + public String str = ""; + public PropertyType type; + + /** + * Property + * + * @param key key + * @param default_value default value + * @param entry_type type + * @param entry_comment entry comment + */ + public Property(String key, boolean default_value, PropertyType entry_type, String entry_comment) { + name = key; + defbool = default_value; + type = entry_type; + entryComment = entry_comment; + } + + /** + * Property entry + * + * @param key property key + * @param default_value default value + * @param entry_type property type from enum + * @param entry_comment property comment or null + */ + public Property(String key, double default_value, PropertyType entry_type, String entry_comment) { + name = key; + defnum = default_value; + type = entry_type; + entryComment = entry_comment; + } + + /** + * Property + * + * @param key key + * @param default_value default value + * @param entry_type type + * @param entry_comment entry comment + */ + public Property(String key, String default_value, PropertyType entry_type, String entry_comment) { + name = key; + defstr = default_value; + type = entry_type; + entryComment = entry_comment; + } + + /** + * Get boolean + * + * @return the boolean + */ + public boolean getBoolean() { + return bool; + } + + /** + * Get number + * + * @return the number + */ + public int getInteger() { + return (int) Math.round(num); + } + + /** + * Get number as double + * + * @return the number + */ + public double getDouble() { + return num; + } + + /** + * Get string + * + * @return the string + */ + public String getString() { + return str; + } + + /** + * is this key pressed? + * + * @return pressed state + */ + public boolean isKeyDown() { + return type == PropertyType.KEY && Keyboard.isKeyDown((int) num); + } + + /** + * Is this entry valid? + * + * @return is valid + */ + public boolean isValid() { + if (type == PropertyType.KEY) { + return Keyboard.getKeyName((int) num) != null; + } + if (type == PropertyType.STRING) { + return str != null; + } + if (type == PropertyType.BOOLEAN || type == PropertyType.INT || type == PropertyType.DOUBLE) { + return true; + } + return false; + } + + /** + * Load property value from a file + * + * @param string the string loaded + * @return this entry + */ + public boolean parse(String string) { + if (type == PropertyType.INT) { + if (string == null) { + //Log.finest("* Numeric property \"" + name + "\" not set, setting to default \"" + defnum + "\""); + num = defnum; + return false; + } + try { + num = Integer.parseInt(string.trim()); + } catch (NumberFormatException e) { + //Log.warning("Numeric property \"" + name + "\" has invalid value \"" + string + "\". Falling back to default \"" + defnum + "\""); + num = defnum; + } + } + + if (type == PropertyType.DOUBLE) { + if (string == null) { + //Log.finest("* Numeric property \"" + name + "\" not set, setting to default \"" + defnum + "\""); + num = defnum; + return false; + } + try { + num = Double.parseDouble(string.trim()); + } catch (NumberFormatException e) { + //Log.warning("Numeric property \"" + name + "\" has invalid value \"" + string + "\". Falling back to default \"" + defnum + "\""); + num = defnum; + } + } + + if (type == PropertyType.KEY) { + if (string == null) { + //Log.finest("* Key property \"" + name + "\" not set, setting to default \"" + Keyboard.getKeyName(defnum) + "\""); + num = defnum; + return false; + } + num = Keyboard.getKeyIndex(string); + if (num == Keyboard.KEY_NONE) { + //Log.warning("Key property \"" + name + "\" has invalid value \"" + string + "\". Falling back to default \"" + // + Keyboard.getKeyName(defnum) + "\""); + num = defnum; + } + } + + if (type == PropertyType.STRING) { + if (string == null) { + //Log.finest("* String property \"" + name + "\" not set, setting to default \"" + defstr + "\""); + str = defstr; + return false; + } + this.str = string; + } + + if (type == PropertyType.BOOLEAN) { + if (string == null) { + //Log.finest("* Boolean property \"" + name + "\" not set, setting to default \"" + defbool + "\""); + bool = defbool; + return false; + } + String string2 = string.toLowerCase(); + bool = string2.equals("yes") || string2.equals("true") || string2.equals("on") || string2.equals("enabled") + || string2.equals("enable"); + } + + return true; + } + + /** + * prepare the contents for insertion into Properties + * + * @return the string prepared, or null if type is invalid + */ + @Override + public String toString() { + if (!isValid()) { + if (type == PropertyType.INT|| type == PropertyType.DOUBLE) { + num = defnum; + } + } + if (type == PropertyType.INT) { + return Integer.toString((int) num); + } + if (type == PropertyType.DOUBLE) { + return Calc.floatToString((float) num); + } + if (type == PropertyType.STRING) { + return str; + } + if (type == PropertyType.KEY) { + return Keyboard.getKeyName((int) num) == null ? "none" : Keyboard.getKeyName((int) num); + } + if (type == PropertyType.BOOLEAN) { + return bool ? "True" : "False"; + } + return null; + } + + /** + * If this entry is not valid, change it to the dafault value. + */ + public void validate() { + if (!isValid()) { + if (type == PropertyType.KEY) { + //Log.warning("Key property \"" + name + "\" has invalid value (unknown key name). Falling back to default value \"" + // + Keyboard.getKeyName(defnum) + "\""); + num = defnum; + } + if (type == PropertyType.STRING) { + //Log.warning("String property \"" + name + "\" has invalid value (NULL). Falling back to default value \"" + defstr + "\""); + str = defstr; + } + } + } + } + + /** + * Property type enum. + * + * @author MightyPork + * @copy (c) 2012 + */ + private enum PropertyType { + BOOLEAN, INT, KEY, STRING, DOUBLE; + } + + /** + * Option to put newline before inline comments + */ + private boolean cfgNewlineBeforeComments = true; + /** Disable entry validation */ + private boolean cfgNoValidate = true; + + /** + * Option to put newline between sections.
+ * Sections are detected by text before first dot in identifier. + */ + private boolean cfgSeparateSections = true; + + /** + * Disables enter-leave logging. + */ + private boolean cfgSilent = false; + + private String comment = ""; + + private TreeMap entries; + + + private String filename; + + private TreeMap keyRename; + + private PC_SortedProperties pr = new PC_SortedProperties(); + + private TreeMap setValues; + + /** + * Create property manager from file path and an initial comment. + * + * @param filename file with the props + * @param comment the initial comment. Use \n in it if you want. + */ + public PropertyManager(String filename, String comment) { + this.filename = filename; + this.entries = new TreeMap(); + this.setValues = new TreeMap(); + this.keyRename = new TreeMap(); + this.comment = comment; + } + + /** + * Load, fix and write to file. + */ + public void apply() { + + if (!cfgSilent) { + //Log.finest("Loading configuration from file \"" + filename + "\""); + } + + boolean needsSave = false; + try { + + new File((new File(filename)).getParent()).mkdirs(); + + pr = PropertiesLoader.loadProperties(pr, new FileInputStream(filename)); + + } catch (IOException e) { + needsSave = true; + pr = new PC_SortedProperties(); + } + + pr.cfgSeparateSectionsByEmptyLine = cfgSeparateSections; + pr.cfgEmptyLineBeforeComment = cfgNewlineBeforeComments; + + ArrayList keyList = new ArrayList(); + + // rename keys + for (Entry entry : keyRename.entrySet()) { + if (pr.getProperty(entry.getKey()) == null) { + continue; + } + pr.setProperty(entry.getValue(), pr.getProperty(entry.getKey())); + pr.remove(entry.getKey()); + needsSave = true; + } + + // set the override values into the freshly loaded properties file + for (Entry entry : setValues.entrySet()) { + pr.setProperty(entry.getKey(), entry.getValue()); + needsSave = true; + } + + + // validate entries one by one, replace with default when needed + for (Property entry : entries.values()) { + + keyList.add(entry.name); + + String propOrig = pr.getProperty(entry.name); + if (!entry.parse(propOrig)) needsSave = true; + if (!cfgNoValidate) { + entry.validate(); + } + + if (entry.entryComment != null) { + pr.setKeyComment(entry.name, entry.entryComment); + } + + if (propOrig == null || !entry.toString().equals(propOrig)) { + + pr.setProperty(entry.name, entry.toString()); + + needsSave = true; + } + } + + // removed unused props + for (String propname : pr.keySet().toArray(new String[pr.size()])) { + + if (!keyList.contains(propname)) { + pr.remove(propname); + //Log.finest("* Removing unused property \"" + propname + "\" from config file " + filename); + needsSave = true; + } + + } + + // save if needed + if (needsSave) { + try { + //Log.finest("* Saving modified property file " + filename); + pr.store(new FileOutputStream(filename), comment); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + if (!cfgSilent) { + //Log.finest("Configuration loaded."); + } + + setValues.clear(); + keyRename.clear(); + } + + /** + * Get boolean property + * + * @param n key + * @return the boolean found, or false + */ + public Boolean bool(String n) { + return getBoolean(n); + } + + /** + * @param newlineBeforeComments put newline before comments + */ + public void cfgNewlineBeforeComments(boolean newlineBeforeComments) { + this.cfgNewlineBeforeComments = newlineBeforeComments; + } + + /** + * @param separateSections do separate sections by newline + */ + public void cfgSeparateSections(boolean separateSections) { + this.cfgSeparateSections = separateSections; + } + + /** + * @param silent the cfgSilent to set + */ + public void cfgSilent(boolean silent) { + this.cfgSilent = silent; + } + + /** + * @param validate enable validation + */ + public void enableValidation(boolean validate) { + this.cfgNoValidate = !validate; + } + + /** + * Get boolean property + * + * @param n key + * @return the boolean found, or false + */ + public Boolean flag(String n) { + return getBoolean(n); + } + + /** + * Get a property entry (rarely used) + * + * @param n key + * @return the entry + */ + private Property get(String n) { + try { + return entries.get(n); + } catch (Throwable t) { + return null; + } + } + + /** + * Get boolean property + * + * @param n key + * @return the boolean found, or false + */ + public Boolean getBoolean(String n) { + try { + return entries.get(n).getBoolean(); + } catch (Throwable t) { + return false; + } + } + + /** + * Get numeric property + * + * @param n key + * @return the int found, or null + */ + public Integer getInt(String n) { + return getInteger(n); + } + + /** + * Get numeric property + * + * @param n key + * @return the int found, or null + */ + public Integer getInteger(String n) { + try { + return get(n).getInteger(); + } catch (Throwable t) { + return -1; + } + } + + /** + * Get numeric property as double + * + * @param n key + * @return the double found, or null + */ + public Double getDouble(String n) { + try { + return get(n).getDouble(); + } catch (Throwable t) { + return -1D; + } + } + + /** + * Get numeric property + * + * @param n key + * @return the int found, or null + */ + public Integer getNum(String n) { + return getInteger(n); + } + + /** + * Get string property + * + * @param n key + * @return the string found, or null + */ + public String getString(String n) { + try { + return get(n).getString(); + } catch (Throwable t) { + return null; + } + } + + /** + * Get numeric property + * + * @param n key + * @return the int found, or null + */ + public Integer integer(String n) { + try { + return get(n).getInteger(); + } catch (Throwable t) { + return -1; + } + } + + /** + * Is the key pressed? (works only for properties of type KEY) + * + * @param n key of the key property + * @return is pressed + */ + public Boolean isKeyDown(String n) { + try { + return entries.get(n).isKeyDown(); + } catch (Throwable t) { + return false; + } + } + + /** + * Get numeric property + * + * @param n key + * @return the int found, or null + */ + public Integer num(String n) { + return getInteger(n); + } + + /** + * Add a boolean property + * + * @param n key + * @param d default value + */ + public void putBoolean(String n, boolean d) { + entries.put(n, new Property(n, d, PropertyType.BOOLEAN, null)); + return; + } + + /** + * Add a boolean property + * + * @param n key + * @param d default value + * @param comment the in-file comment + */ + public void putBoolean(String n, boolean d, String comment) { + entries.put(n, new Property(n, d, PropertyType.BOOLEAN, comment)); + return; + } + + /** + * Add a numeric property (double) + * + * @param n key + * @param d default value + */ + public void putDouble(String n, int d) { + entries.put(n, new Property(n, d, PropertyType.DOUBLE, null)); + return; + } + + /** + * Add a numeric property (double) + * + * @param n key + * @param d default value + * @param comment the in-file comment + */ + public void putDouble(String n, int d, String comment) { + entries.put(n, new Property(n, d, PropertyType.DOUBLE, comment)); + return; + } + + /** + * Add a numeric property + * + * @param n key + * @param d default value + */ + public void putInteger(String n, int d) { + entries.put(n, new Property(n, d, PropertyType.INT, null)); + return; + } + + /** + * Add a numeric property + * + * @param n key + * @param d default value + * @param comment the in-file comment + */ + public void putInteger(String n, int d, String comment) { + entries.put(n, new Property(n, d, PropertyType.INT, comment)); + return; + } + + /** + * Add a numeric property + * + * @param n key + * @param d default value + */ + public void putKey(String n, int d) { + entries.put(n, new Property(n, d, PropertyType.KEY, null)); + return; + } + + /** + * Add a numeric property + * + * @param n key + * @param d default value + * @param comment the in-file comment + */ + public void putKey(String n, int d, String comment) { + entries.put(n, new Property(n, d, PropertyType.KEY, comment)); + return; + } + + /** + * Add a string property + * + * @param n key + * @param d default value + */ + public void putString(String n, String d) { + entries.put(n, new Property(n, d, PropertyType.STRING, null)); + return; + } + + /** + * Add a string property + * + * @param n key + * @param d default value + * @param comment the in-file comment + */ + public void putString(String n, String d, String comment) { + entries.put(n, new Property(n, d, PropertyType.STRING, comment)); + return; + } + + + + /** + * Rename key before doing "apply"; value is preserved + * + * @param oldKey old key + * @param newKey new key + */ + public void renameKey(String oldKey, String newKey) { + keyRename.put(oldKey, newKey); + return; + } + + + + /** + * Set value saved to certain key; use to save runtime-changed configuration + * values. + * + * @param key key + * @param value the saved value + */ + public void setValue(String key, Object value) { + setValues.put(key, value.toString()); + return; + } + + /** + * Get string property + * + * @param n key + * @return the string found, or null + */ + public String str(String n) { + try { + return get(n).getString(); + } catch (Throwable t) { + return null; + } + } + + + + /** + * Get string property + * + * @param n key + * @return the string found, or null + */ + public String string(String n) { + try { + return get(n).getString(); + } catch (Throwable t) { + return null; + } + } +} \ No newline at end of file diff --git a/src/com/porcupine/util/StringUtils.java b/src/com/porcupine/util/StringUtils.java new file mode 100644 index 0000000..bfa1000 --- /dev/null +++ b/src/com/porcupine/util/StringUtils.java @@ -0,0 +1,104 @@ +package com.porcupine.util; + + +/** + * General purpose string utilities + * + * @author MightyPork + */ +public class StringUtils { + + /** + * Get if string is in array + * + * @param needle checked string + * @param case_sensitive case sensitive comparision + * @param haystack array of possible values + * @return is in array + */ + public static boolean isInArray(String needle, boolean case_sensitive, String... haystack) { + if (case_sensitive) { + for (String s : haystack) { + if (needle.equals(s)) return true; + } + return false; + } else { + for (String s : haystack) { + if (needle.equalsIgnoreCase(s)) return true; + } + return false; + } + } + + /** + * Repeat a string + * + * @param repeated string + * @param count + * @return output + */ + public static String repeat(String repeated, int count) { + String s = ""; + for (int i = 0; i < count; i++) + s += repeated; + return s; + } + + /** + * convert string to a same-length sequence of # marks + * + * @param password password + * @return encoded + */ + public static String passwordify(String password) { + return passwordify(password, "#"); + } + + + /** + * convert string to a same-length sequence of chars + * + * @param password password + * @param replacing character used in output + * @return encoded + */ + public static String passwordify(String password, String replacing) { + return repeat(replacing, password.length()); + } + + /** + * Get ordinal version of numbers (1 = 1st, 5 = 5th etc.) + * + * @param number number + * @return ordinal, string + */ + public static String numberToOrdinal(int number) { + if (number % 100 < 4 || number % 100 > 13) { + if (number % 10 == 1) return number + "st"; + if (number % 10 == 2) return number + "nd"; + if (number % 10 == 3) return number + "rd"; + } + return number + "th"; + } + + /** + * Format number with thousands separated by a dot. + * + * @param number number + * @return string 12.004.225 + */ + public static String formatInt(long number) { + String num = number + ""; + String out = ""; + String dot = "."; + int cnt = 1; + for (int i = num.length() - 1; i >= 0; i--) { + out = num.charAt(i) + out; + if (cnt % 3 == 0 && i > 0) out = dot + out; + cnt++; + } + + return out; + } + +} diff --git a/src/com/porcupine/util/VarargsParser.java b/src/com/porcupine/util/VarargsParser.java new file mode 100644 index 0000000..54d1e46 --- /dev/null +++ b/src/com/porcupine/util/VarargsParser.java @@ -0,0 +1,51 @@ +package com.porcupine.util; + + +import java.util.LinkedHashMap; + + +/** + * Varargs parser
+ * Converts an array of repeated "key, value" pairs to a LinkedHashMap.
+ * example: + * + *
+ * Object[] array = { "one", 1, "two", 4, "three", 9, "four", 16 };
+ * Map<String, Integer> args = new VarargsParser<String, Integer>().parse(array);
+ * 
+ * + * @author MightyPork + * @param Type for Map keys + * @param Type for Map values + */ +public class VarargsParser { + /** + * Parse array of vararg key, value pairs to a LinkedHashMap. + * + * @param args varargs + * @return LinkedHashMap + * @throws ClassCastException in case of incompatible type in the array + * @throws IllegalArgumentException in case of invalid array length (odd) + */ + @SuppressWarnings("unchecked") + public LinkedHashMap parse(Object... args) throws ClassCastException, IllegalArgumentException { + LinkedHashMap attrs = new LinkedHashMap(); + + if (args.length % 2 != 0) { + throw new IllegalArgumentException("Odd number of elements in varargs map!"); + } + + K key = null; + for (Object o : args) { + if (key == null) { + if (o == null) throw new RuntimeException("Key cannot be NULL in varargs map."); + key = (K) o; + } else { + attrs.put(key, (V) o); + key = null; + } + } + + return attrs; + } +} diff --git a/src/net/spritegen/App.java b/src/net/spritegen/App.java new file mode 100644 index 0000000..0beb6eb --- /dev/null +++ b/src/net/spritegen/App.java @@ -0,0 +1,368 @@ +package net.spritegen; + + +import static org.lwjgl.opengl.GL11.*; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.swing.*; + +import net.spritegen.gui.Screen; +import net.spritegen.gui.ScreenSprites; +import net.spritegen.util.Log; +import net.spritegen.util.Utils; + +import org.lwjgl.LWJGLException; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.openal.AL; +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.DisplayMode; +import org.lwjgl.opengl.PixelFormat; + +import com.porcupine.coord.Coord; +import com.porcupine.time.FpsMeter; +import com.porcupine.time.Timer; +import com.porcupine.util.FileUtils; + + + +/** + * SECTOR main class + * + * @author MightyPork + */ +public class App { + + /** instance */ + public static App inst; + + /** current screen */ + public static Screen screen = null; + + public static String[] args; + + /** + * @param args + */ + public static void main(String[] args) { + + App.args = args; + + inst = new App(); + try { + inst.start(); + } catch (Throwable t) { + showCrashReport(t); + } + + } + + /** + * Show crash report dialog with error stack trace. + * + * @param error + */ + public static void showCrashReport(Throwable error) { + + + Log.e(error); + + try { + inst.deinit(); + } catch (Throwable t) {} + + JFrame f = new JFrame("SpriteGen has crashed!"); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + f.getContentPane().setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS)); + + + StringWriter sw = new StringWriter(); + error.printStackTrace(new PrintWriter(sw)); + String exceptionAsString = sw.toString(); + + String errorLogAsString = "Not found."; + String wholeLogAsString = "Not found."; + + try { + wholeLogAsString = FileUtils.fileToString(Utils.getGameSubfolder(Constants.FILE_LOG)); + } catch (Exception e) { + e.printStackTrace(); + } + + try { + errorLogAsString = FileUtils.fileToString(Utils.getGameSubfolder(Constants.FILE_LOG_E)); + } catch (Exception e) { + e.printStackTrace(); + } + + String txt = ""; + txt = ""; + txt += "SPRITE-GEN HAS CRASHED!\n"; + txt += "\n"; + txt += "Please report it to MightyPork:\n"; + txt += "\tE-mail: ondra@ondrovo.com\n"; + txt += "\tTwitter: #MightyPork (post log via pastebin.com)\n"; + txt += "\n"; + txt += "\n"; + txt += "\n"; + txt += "### STACK TRACE ###\n"; + txt += "\n"; + txt += exceptionAsString + "\n"; + txt += "\n"; + txt += "\n"; + txt += "### ERROR LOG ###\n"; + txt += "\n"; + txt += errorLogAsString + "\n"; + txt += "\n"; + txt += "\n"; + txt += "### FULL LOG ###\n"; + txt += "\n"; + txt += wholeLogAsString + "\n"; + + + // Create Scrolling Text Area in Swing + JTextArea ta = new JTextArea(txt, 20, 70); + ta.setFont(new Font("Courier", 0, 16)); + ta.setMargin(new Insets(10, 10, 10, 10)); + ta.setEditable(false); + ta.setLineWrap(false); + JScrollPane sbrText = new JScrollPane(ta); + sbrText.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10), BorderFactory.createEtchedBorder())); + sbrText.setWheelScrollingEnabled(true); + sbrText.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + sbrText.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + + + // Create Quit Button + JButton btnQuit = new JButton("Quit"); + btnQuit.setAlignmentX(Component.CENTER_ALIGNMENT); + + btnQuit.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); + buttonPane.add(btnQuit); + + + f.getContentPane().add(sbrText); + f.getContentPane().add(buttonPane); + + // Close when the close button is clicked + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + + + //Display Frame + f.pack(); // Adjusts frame to size of components + + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); + f.setLocation((dim.width - f.getWidth()) / 2, (dim.height - f.getHeight()) / 2); + + f.setVisible(true); + + while (true) {} + } + + public static File modelFile; + + public static File modelDir; + + public static SetupLoader cfg; + + + + private void deinit() { + Display.destroy(); + Mouse.destroy(); + Keyboard.destroy(); + AL.destroy(); + } + + /** + * Quit to OS + */ + public void exit() { + deinit(); + System.exit(0); + } + + /** + * Get current screen + * + * @return screen + */ + public Screen getScreen() { + return screen; + } + + /** + * Get screen size + * + * @return size + */ + public Coord getSize() { + return new Coord(Display.getWidth(), Display.getHeight()); + } + +// INIT + + private void init() throws LWJGLException { + + Log.setPrintToStdout(true); + + if (args.length == 0) { + System.out.println("Args: folder/model.obj\n" + + "SpriteGen operates in .spritegen folder.\n" + + "There is a folder \".spritegen/models\", which contains subfolders with your models.\n" + + "\n" + + "Spritesheet settings are found in \"models/modelDir/config.ini\". This file will\n" + + "be generated while creating first spritesheet from that folder.\n" + + "\n" + + "Output PNG image will be saved in \"models/modelDir/out\".\n" + + "\n" + + "Example usage: java -jar spritegen.jar turtle/turtle.obj"); + } + + File dir = Utils.getGameSubfolder("models"); + dir.mkdirs(); + + if (args.length == 0) { + exit(); + return; + } + + modelFile = Utils.getGameSubfolder("models/" + args[0]); + + modelDir = modelFile.getParentFile(); + File out = new File(modelDir,"out"); + out.mkdirs(); + + cfg = new SetupLoader(modelDir); + Log.i("Output image size: " + cfg.img_size + "x" + cfg.img_size); + + // init display + Display.setDisplayMode(new DisplayMode(ScreenSprites.FRAME_SIZE, ScreenSprites.FRAME_SIZE)); + Display.setResizable(false); + Display.setVSyncEnabled(true); + Display.setTitle(Constants.TITLEBAR); + + int samples = cfg.samples; + while (true) { + try { + Display.create(new PixelFormat().withSamples(samples).withAlphaBits(4)); + Log.i("Created display with " + samples + "x multisampling."); + break; + } catch (LWJGLException e) { + Log.w("Failed to create display with " + samples + "x multisampling, trying " + samples / 2 + "x."); + if (samples >= 2) { + samples /= 2; + } else if (samples == 1) { + samples = 0; + } else if (samples == 0) { + Log.e("Could not create display.", e); + exit(); + } + } + } + + Mouse.create(); + Keyboard.create(); + Keyboard.enableRepeatEvents(false); + + StaticInitializer.initOnStartup(); + } + + private void start() throws LWJGLException { + + Log.enable(true); + Log.setPrintToStdout(true); + + init(); + mainLoop(); + deinit(); + } + +// INIT END + + +// UPDATE LOOP + + /** fps meter */ + public FpsMeter fpsMeter; + + /** timer */ + public Timer timer; + + private int timerAfterResize = 0; + + private void mainLoop() { + screen = new ScreenSprites(); + + screen.init(); + + timer = new Timer(Constants.FPS_UPDATE); + fpsMeter = new FpsMeter(); + + while (!Display.isCloseRequested()) { + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + int j = timer.ticksMissed; + + if (j > 1) fpsMeter.drop(j - 1); + timer.update(); + + for (int i = 0; i < j; i++) { + screen.update(); + } + + fpsMeter.frame(); + float delta = timer.renderDeltaTime; + screen.render(delta); + Display.update(); + + try { + Display.sync(Constants.FPS_RENDER); + } catch (Throwable t) { + Log.e("Your graphics card driver does not support fullscreen properly.", t); + } + } + } + +// UPDATE LOOP END + + /** + * Replace screen + * + * @param newScreen new screen + */ + public void replaceScreen(Screen newScreen) { + screen = newScreen; + screen.init(); + } + + /** + * Replace screen, don't init it + * + * @param newScreen new screen + */ + public void replaceScreenNoInit(Screen newScreen) { + screen = newScreen; + } +} diff --git a/src/net/spritegen/Constants.java b/src/net/spritegen/Constants.java new file mode 100644 index 0000000..472e9da --- /dev/null +++ b/src/net/spritegen/Constants.java @@ -0,0 +1,57 @@ +package net.spritegen; + + +import net.spritegen.gui.ScreenSprites; + +import com.porcupine.coord.Coord; + + +/** + * Sector constants + * + * @author MightyPork + */ +@SuppressWarnings("javadoc") +public class Constants { + + // STRINGS + public static final String TITLEBAR = "SpriteGen"; + + // FILES+DIRS + public static final String APP_DIR = "spritegen"; + + public static final String FILE_LOG = "Runtime.log"; + public static final String FILE_LOG_E = "Error.log"; + + // TIMING + public static final int FPS_UPDATE = 55; + public static final double SPEED_MUL = 100D / FPS_UPDATE; + + public static final int FPS_RENDER = 200; // max + + +// // INITIAL WINDOW SIZE (later loaded from config file) +// public static final int WINDOW_SIZE_X = ScreenSprites.FRAME_SIZE; //1024; FIXME +// public static final int WINDOW_SIZE_Y = ScreenSprites.FRAME_SIZE; //768; FIXME + + +// +// // LIGHT +// public static final float LIGHT_AMBIENT = 1F; +// public static final float LIGHT_SPECULAR = 0.5F; +// public static final float LIGHT_DIFFUSE = 1F; +// public static final Coord LIGHT_POS = new Coord(0, 3, 3); +// public static final float LIGHT_ATTR = 1; +// +// public static final float SCENE_MAT_AMBIENT = 1F; +// public static final float SCENE_MAT_SPECULAR = 1F; +// public static final float SCENE_MAT_DIFFUSE = 1F; + + // CAMERA & SCENE + public static final Coord CAM_POS = new Coord(0, 0, 5); + public static final Coord CAM_LOOKAT = new Coord(0, 0, 0); + public static final float CAM_ANGLE = 45; + public static final double CAM_NEAR = 0.1; + public static final double FOG_START = 80; + public static final double CAM_FAR = 100; +} diff --git a/src/net/spritegen/SetupLoader.java b/src/net/spritegen/SetupLoader.java new file mode 100644 index 0000000..6ea04d7 --- /dev/null +++ b/src/net/spritegen/SetupLoader.java @@ -0,0 +1,90 @@ +package net.spritegen; + +import java.io.File; + +import net.spritegen.util.Utils; + +import com.porcupine.coord.Coord; +import com.porcupine.util.PropertyManager; + +public class SetupLoader { + + public PropertyManager cfg; + + public int img_size; + + public int samples; + public double render_wobble_y; + public double render_wobble_z; + public double render_rotate_x; + public double renmder_move_y; + public double render_move_x; + public double render_scale; + + public Coord light_pos; + public double light_attr; + public double light_diffuse; + public double light_specular; + public double light_ambient; + + public double mat_diffuse; + public double mat_specular; + public double mat_ambient; + + public SetupLoader(File dir) { + dir.mkdirs(); + File file = new File(dir,"config.ini"); + + cfg = new PropertyManager(file.getAbsolutePath(), "Spritesheet setup file"); + + cfg.putInteger("output.size", 512, "Output image size"); + cfg.putDouble("render.walk.wobble_x_angle_max", 6, "Maximal wobble angle for walking (rotate around Y)"); + cfg.putDouble("render.walk.wobble_z_angle_max", 0, "Maximal wobble angle for walking (rotate around Z)"); + cfg.putDouble("render.rotate_x", 60, "Rotate around X axis to get 2D or 2.5D perspective"); + cfg.putDouble("render.move_y", 0, "Y offset (for centering)"); + cfg.putDouble("render.move_x", 0, "X move (for centering)"); + cfg.putDouble("render.scale", 1, "Render scale"); + cfg.putInteger("render.multisampling", 4, "Multisampling (smoothing) level, values: 0,1,2,4,8"); + + cfg.putDouble("render.material.ambient", 1, "Material property: ambient"); + cfg.putDouble("render.material.specular", 1, "Material property: specular"); + cfg.putDouble("render.material.diffuse", 1, "Material property: diffuse"); + + cfg.putDouble("render.light.ambient", 1, "Light property: ambient"); + cfg.putDouble("render.light.specular", 1, "Light property: specular"); + cfg.putDouble("render.light.diffuse", 1, "Light property: diffuse"); + cfg.putDouble("render.light.attribute", 1, "Light property: attribute"); + + cfg.putDouble("render.light.x", 0, "Light pos: X"); + cfg.putDouble("render.light.y", 3, "Light pos: Y"); + cfg.putDouble("render.light.z", 3, "Light pos: Z"); + + cfg.apply(); + + + img_size = cfg.getInt("output.size"); + + render_wobble_y = cfg.getDouble("render.walk.wobble_x_angle_max"); + render_wobble_z = cfg.getDouble("render.walk.wobble_z_angle_max"); + render_rotate_x = cfg.getDouble("render.rotate_x"); + renmder_move_y = cfg.getDouble("render.move_y"); + render_move_x = cfg.getDouble("render.move_x"); + render_scale = cfg.getDouble("render.scale"); + samples = cfg.getInt("render.multisampling"); + + mat_ambient = cfg.getDouble("render.material.ambient"); + mat_specular = cfg.getDouble("render.material.specular"); + mat_diffuse = cfg.getDouble("render.material.diffuse"); + + light_ambient = cfg.getDouble("render.light.ambient"); + light_specular = cfg.getDouble("render.light.specular"); + light_diffuse = cfg.getDouble("render.light.diffuse"); + light_attr = cfg.getDouble("render.light.attribute"); + + light_pos = new Coord(cfg.getDouble("render.light.x"), + cfg.getDouble("render.light.y"), + cfg.getDouble("render.light.z")); + + } + +} diff --git a/src/net/spritegen/StaticInitializer.java b/src/net/spritegen/StaticInitializer.java new file mode 100644 index 0000000..94cd465 --- /dev/null +++ b/src/net/spritegen/StaticInitializer.java @@ -0,0 +1,28 @@ +package net.spritegen; + + +import com.mykaruga.models.Models; + + +/** + * Initialization utility, initializing all the static stuff that is needed + * before starting main loop. + * + * @author MightyPork + */ +public class StaticInitializer { + + /** + * Init static things and start threads.
+ * This is called on startup, even before the splash screen. + */ + public static void initOnStartup() { + Models.load(); + } + + /** + * Initialize all. + */ + public static void initPostLoad() {} + +} diff --git a/src/net/spritegen/gui/Screen.java b/src/net/spritegen/gui/Screen.java new file mode 100644 index 0000000..4bc69f3 --- /dev/null +++ b/src/net/spritegen/gui/Screen.java @@ -0,0 +1,101 @@ +package net.spritegen.gui; + + +import static org.lwjgl.opengl.GL11.*; + +import java.util.Random; + +import net.spritegen.App; + +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import com.porcupine.coord.Coord; +import com.porcupine.coord.Vec; + + +/** + * Screen class.
+ * Screen animates 3D world, while contained panels render 2D overlays, process + * inputs and run the game logic. + * + * @author MightyPork + */ +public abstract class Screen{ + + /** application instance, for easier calls */ + public App app = App.inst; + + /** RNG */ + public Random rand = new Random(); + + + /** + * handle window resize. + */ + public void onWindowResize() { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + Coord s = app.getSize(); + + glViewport(0, 0, s.xi(), s.yi()); + + glOrtho(0, s.x, 0, s.y, -1000, 1000); + + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + } + + /** + * Initialize screen + */ + public void init() { + onWindowResize(); + + initScreen(); + + // SETUP LIGHTS + + glDisable(GL_LIGHTING); + + // OTHER SETTINGS + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClearDepth(1f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_NORMALIZE); + + glShadeModel(GL_SMOOTH); + glDisable(GL_TEXTURE_2D); + + } + + /** + * Here you can initialize the screen. + */ + public abstract void initScreen(); + + /** + * Update tick + */ + public void update() {} + + /** + * Render screen + * + * @param delta delta time (position between two update ticks, to allow + * super-smooth animations) + */ + public void render(double delta) {} + +} diff --git a/src/net/spritegen/gui/ScreenSprites.java b/src/net/spritegen/gui/ScreenSprites.java new file mode 100644 index 0000000..781ae5c --- /dev/null +++ b/src/net/spritegen/gui/ScreenSprites.java @@ -0,0 +1,375 @@ +package net.spritegen.gui; + + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +import javax.imageio.ImageIO; + +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.Display; + +import net.spritegen.App; +import net.spritegen.Constants; +import net.spritegen.util.Log; +import net.spritegen.util.Utils; + +import com.mykaruga.models.Models; +import com.porcupine.color.RGB; +import com.porcupine.coord.Coord; +import com.porcupine.math.Calc.Buffers; + +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.util.glu.GLU.*; + + + +/** + * Splash screen + * + * @author MightyPork + */ +public class ScreenSprites extends Screen { + + private static int SHEET_SIZE = App.cfg.img_size; + public static int FRAME_SIZE = App.cfg.img_size/16; + private static double WALK_WOBBLE_Y = App.cfg.render_wobble_y; + private static double WALK_WOBBLE_Z = App.cfg.render_wobble_z; + + + private BufferedImage image; + + @Override + public void initScreen() { + + String format = "PNG"; + image = new BufferedImage(SHEET_SIZE, SHEET_SIZE, BufferedImage.TYPE_INT_RGB); + + } + + private void captureSpriteFrame(int xPos, int yPos) { + + glReadBuffer(GL_FRONT); + int width = Display.getDisplayMode().getWidth(); + int height = Display.getDisplayMode().getHeight(); + int bpp = 4; // Assuming a 32-bit display with a byte each for red, green, blue, and alpha. + ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bpp); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + // convert to a buffered image + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int i = (x + (width * y)) * bpp; + int r = buffer.get(i) & 0xFF; + int g = buffer.get(i + 1) & 0xFF; + int b = buffer.get(i + 2) & 0xFF; + try { + image.setRGB(x + xPos * FRAME_SIZE, (height - (y + 1)) + yPos * FRAME_SIZE, (0xFF << 24) | (r << 16) | (g << 8) | b); + }catch(ArrayIndexOutOfBoundsException e) { + Log.w("X,Y="+x+","+y+"; TILE POS: "+xPos+","+yPos); + throw e; + } + } + } + + } + + private void saveSpritesheet() { + + File file; + + int i = 0; + + while(true) { + file = new File(App.modelDir, "out/spritesheet"+(i==0?"":"-"+i)+".png"); + if(!file.exists()) break; + i++; + } + + // save to disk + try { + ImageIO.write(image, "PNG", file); + } catch (IOException e) { + Log.e("Failed to save screenshot.", e); + } + } + + private int timer0 = 0; + private int timer = 0; + + @Override + public void render(double delta) { + timer0++; + if(timer0<5) return; + timer++; + + int frame = timer/6; + boolean capture = (timer+3)%6==0; + + int MODE = 1; + + if(MODE==0) { + + // walking + if(frame < 8) { + renderTurtle(90+Math.sin(((frame-(0*8D))/4D)*3.1415D)*WALK_WOBBLE_Y, Math.sin(((frame)/4D)*3.1415D)*WALK_WOBBLE_Z); + if(capture) { + captureSpriteFrame(frame-8*0, 0); + } + } + + + if(frame >= 8 && frame < 8*2) { + renderTurtle(180+Math.sin(((frame-(1*8D))/4D)*3.1415D)*WALK_WOBBLE_Y, Math.sin(((frame)/4D)*3.1415D)*WALK_WOBBLE_Z); + if(capture) { + captureSpriteFrame(frame-8*1, 1); + } + } + + if(frame >= 8*2 && frame < 8*3) { + renderTurtle(270+Math.sin(((frame-(2*8D))/4D)*3.1415D)*WALK_WOBBLE_Y, Math.sin(((frame)/4D)*3.1415D)*WALK_WOBBLE_Z); + if(capture) { + captureSpriteFrame(frame-8*2, 2); + } + } + + if(frame >= 8*3 && frame < 8*4) { + renderTurtle(0+Math.sin(((frame-(3*8D))/4D)*3.1415D)*WALK_WOBBLE_Y, Math.sin(((frame)/4D)*3.1415D)*WALK_WOBBLE_Z); + if(capture) { + captureSpriteFrame(frame-8*3, 3); + } + } + + + // rotate + if(frame >= 8*4 && frame < 8*5) { + renderTurtle(90+11.25D*(frame-(4*8D)), 0); + if(capture) { + captureSpriteFrame(frame-8*4, 4); + } + } + + if(frame >= 8*5 && frame < 8*6) { + renderTurtle(180+11.25D*(frame-(5*8D)), 0); + if(capture) { + captureSpriteFrame(frame-8*5, 5); + } + } + + if(frame >= 8*6 && frame < 8*7) { + renderTurtle(270+11.25D*(frame-(6*8D)), 0); + if(capture) { + captureSpriteFrame(frame-8*6, 6); + } + } + + if(frame >= 8*7 && frame < 8*8) { + renderTurtle(0+11.25D*(frame-(7*8D)), 0); + if(capture) { + captureSpriteFrame(frame-8*7, 7); + } + } + + if(frame >= 8*8) { + saveSpritesheet(); + App.inst.exit(); + } + + }else if(MODE==1) { + + int ROW = 16; + + for(int i=0; i<4; i++) { + if(frame >= ROW*i && frame < ROW*(i+1)) { + renderTurtle(90*(i+1)+Math.sin(((frame-(i*ROW))/(ROW/2D))*3.1415D)*WALK_WOBBLE_Y, Math.sin(((frame)/(ROW/2D))*3.1415D)*WALK_WOBBLE_Z); + if(capture) { + captureSpriteFrame(frame-ROW*i, i); + } + } + } + + double ANGLE_ROW = 45D; + double ANGLE_STEP = 45D/ROW; + + + for(int i=0, row = 4; i<360; i+=ANGLE_ROW, row++) { + int angle = 90 + i; + if(angle >= 360) angle -= 360; + + if(frame >= ROW*row && frame < ROW*(row+1)) { + renderTurtle(angle+ANGLE_STEP*(frame-(row*ROW)), 0); + if(capture) { + captureSpriteFrame(frame-ROW*row, row); + } + } + } + + + if(frame >= 16*12) { + saveSpritesheet(); + App.inst.exit(); + } + }else if(MODE==2) { + + int ROW = 16; + + double ANGLE_ROW = 90D; + double ANGLE_STEP = 90D/ROW; + + + for(int i=0, row = 0; i<360; i+=ANGLE_ROW, row++) { + int angle = 90 + i; + if(angle >= 360) angle -= 360; + + if(frame >= ROW*row && frame < ROW*(row+1)) { + renderTurtle(angle+ANGLE_STEP*(frame-(row*ROW)), 0); + if(capture) { + captureSpriteFrame(frame-ROW*row, row); + } + } + } + + + if(frame >= 16*8) { + saveSpritesheet(); + App.inst.exit(); + } + } + } + + private void clearScreen() { + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + private void renderTurtle(double direction, double wobble) { + glPushMatrix(); + + double scale = App.cfg.render_scale; + + glScaled(scale, scale, scale); + glTranslated(App.cfg.render_move_x, App.cfg.renmder_move_y, 0); + + // perspective + glRotated(App.cfg.render_rotate_x, 1, 0, 0); + + // direction + glRotated(direction, 0, 1, 0); + + // wobble + glRotated(wobble, 0, 0, 1); + + Models.turtle.render(); + glPopMatrix(); + } + + + /** + * Enable fog with given parameters + * + * @param fogStart distance from which the fog grows denser + * @param fogEnd distance at which the fog is densest + * @param fogDensity relative fog density, 1.0 default, 0.3 recommended + * @param fogOpacity fog opacity, 1.0 default + * @param fogColor fog color + * @param bgColor screen background color + * @param fogType fog type: GL_LINEAR, GL_EXP, GL_EXP2 + */ + protected final void setupFog(double fogStart, double fogEnd, double fogDensity, double fogOpacity, RGB fogColor, RGB bgColor, int fogType) { + // bg + glClearColor((float) bgColor.r, (float) bgColor.g, (float) bgColor.b, 1.0F); + //fog +// glFogf(GL_FOG_START, (float) fogStart); +// glFogf(GL_FOG_END, (float) fogEnd); +// glFogi(GL_FOG_MODE, fogType); +// glFog(GL_FOG_COLOR, Buffers.mkFillBuff((float) fogColor.r, (float) fogColor.g, (float) fogColor.b, (float) fogOpacity)); +// glFogf(GL_FOG_DENSITY, (float) fogDensity); +// glHint(GL_FOG_HINT, GL_NICEST); + + } + + + /** + * Set up camera + * + * @param eyePos position of the observing eye + * @param centerPos point the eye is looking at + * @param viewAngle viewing angle (FOV) + * @param zNear nearest visible objects (Z axis) + * @param zFar farthest visible objects (Z axis) + */ + protected final void setupCamera(Coord eyePos, Coord centerPos, double viewAngle, double zNear, double zFar) { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + // set up perspective + + Coord s = app.getSize(); + gluPerspective((float) viewAngle, (float) s.x / (float) s.y, (float) zNear, (float) zFar); + gluLookAt((float) eyePos.x, (float) eyePos.y, (float) eyePos.z, (float) centerPos.x, (float) centerPos.y, (float) centerPos.z, 0F, 1F, 0F); + + glViewport(0, 0, s.xi(), s.yi()); + + // back to modelview matrix + glMatrixMode(GL_MODELVIEW); + } + + @Override + public void init() { + super.init(); + + initScreen(); + + setupCamera(Constants.CAM_POS, Constants.CAM_LOOKAT, Constants.CAM_ANGLE, Constants.CAM_NEAR, Constants.CAM_FAR); + setupFog(Constants.FOG_START, Constants.CAM_FAR, 1.0, 1.0, new RGB(0, 0, 0), new RGB(0, 0, 0), GL_LINEAR); + + + // SETUP LIGHTS + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + float spec = (float) App.cfg.light_specular; + float amb = (float) App.cfg.light_ambient; + float diff = (float) App.cfg.light_diffuse; + Coord pos = App.cfg.light_pos; + + FloatBuffer buff = Buffers.alloc(4); + Buffers.fill(buff, amb, amb, amb, 1.0f); + glLight(GL_LIGHT0, GL_AMBIENT, buff); + + buff.clear(); + Buffers.fill(buff, diff, diff, diff, 1.0f); + glLight(GL_LIGHT0, GL_DIFFUSE, buff); + + buff.clear(); + Buffers.fill(buff, spec, spec, spec, 1.0f); + glLight(GL_LIGHT0, GL_SPECULAR, buff); + + buff.clear(); + Buffers.fill(buff, (float) pos.x, (float) pos.y, (float) pos.z, (float)App.cfg.light_attr); + glLight(GL_LIGHT0, GL_POSITION, buff); //Position The Light + + + // OTHER SETTINGS + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClearDepth(1f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + + glShadeModel(GL_SMOOTH); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glEnable(GL_TEXTURE_2D); + } + +} diff --git a/src/net/spritegen/textures/TextureManager.java b/src/net/spritegen/textures/TextureManager.java new file mode 100644 index 0000000..e30dbf2 --- /dev/null +++ b/src/net/spritegen/textures/TextureManager.java @@ -0,0 +1,75 @@ +package net.spritegen.textures; + + +import static org.lwjgl.opengl.GL11.*; + +import java.io.IOException; + +import net.spritegen.Constants; +import net.spritegen.util.Log; + +import org.newdawn.slick.opengl.Texture; +import org.newdawn.slick.opengl.TextureLoader; +import org.newdawn.slick.util.ResourceLoader; + + +/** + * Texture manager + * + * @author MightyPork + */ +public class TextureManager { + + private static Texture lastBinded = null; + + /** + * Load texture + * + * @param resourcePath + * @return the loaded texture + */ + public static Texture load(String resourcePath) { + try { + + String ext = resourcePath.substring(resourcePath.length() - 4); + + Texture texture = TextureLoader.getTexture(ext.toUpperCase(), ResourceLoader.getResourceAsStream(resourcePath)); + + if (texture != null) { + + Log.f2("Texture " + resourcePath + " loaded."); + + return texture; + } + + Log.w("Texture " + resourcePath + " could not be loaded."); + return null; + } catch (IOException e) { + Log.e("Loading of texture " + resourcePath + " failed.", e); + throw new RuntimeException(e); + } + + } + + /** + * Bind texture + * + * @param texture the texture + * @throws RuntimeException if not loaded yet + */ + public static void bind(Texture texture) throws RuntimeException { + if (texture != lastBinded) { + glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, texture.getTextureID()); + lastBinded = texture; + } + } + + /** + * Unbind all + */ + public static void unbind() { + glBindTexture(GL_TEXTURE_2D, 0); + lastBinded = null; + } +} diff --git a/src/net/spritegen/util/Log.java b/src/net/spritegen/util/Log.java new file mode 100644 index 0000000..4d3a790 --- /dev/null +++ b/src/net/spritegen/util/Log.java @@ -0,0 +1,341 @@ +package net.spritegen.util; + + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.logging.FileHandler; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import net.spritegen.Constants; + + +/** + * Sector static logger class. + * + * @author MightyPork + * @copy (c) 2012 + */ +public class Log { + /** + * Global PowerCraft's logger. + */ + private static final Logger logger = Logger.getLogger("Sector"); + private static final Logger loggerError = Logger.getLogger("SectorErr"); + /** Logging enabled */ + public static boolean loggingEnabled = true; + /** Stdout printing enabled */ + public static boolean printToStdout = false; + + static { + try { + FileHandler handler1 = new FileHandler(Utils.getGameSubfolder(Constants.FILE_LOG).getPath()); + handler1.setFormatter(new LogFormatter(true)); + logger.addHandler(handler1); + + FileHandler handler2 = new FileHandler(Utils.getGameSubfolder(Constants.FILE_LOG_E).getPath()); + handler2.setFormatter(new LogFormatter(false)); + loggerError.addHandler(handler2); + + loggingEnabled = true; + } catch (Exception e) { + e.printStackTrace(); + } + + logger.setUseParentHandlers(false); + logger.setLevel(Level.ALL); + logger.info("Main logger initialized."); + logger.info((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")).format(new Date())); + + loggerError.setUseParentHandlers(false); + loggerError.setLevel(Level.ALL); + loggerError.info("Error logger initialized."); + loggerError.info((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")).format(new Date())); + + org.newdawn.slick.util.Log.setVerbose(false); + } + + /** + * Enable logging. + * + * @param flag do enable logging + */ + public static void enable(boolean flag) { + loggingEnabled = flag; + } + + + + /** + * Enable debug mode - log also printed to stdout. + * + * @param printToStdout + */ + public static void setPrintToStdout(boolean printToStdout) { + Log.printToStdout = printToStdout; + } + + /** + * Log INFO message + * + * @param msg message + */ + private static void info(String msg) { + if (!loggingEnabled) { + return; + } + logger.log(Level.INFO, msg); + } + + /** + * Log FINE (important) message + * + * @param msg message + */ + private static void fine(String msg) { + if (!loggingEnabled) { + return; + } + logger.log(Level.FINE, msg); + } + + /** + * Log FINER (loss important) message + * + * @param msg message + */ + private static void finer(String msg) { + if (!loggingEnabled) { + return; + } + logger.log(Level.FINER, msg); + } + + /** + * Log FINEST (least important) message + * + * @param msg message + */ + private static void finest(String msg) { + if (!loggingEnabled) { + return; + } + logger.log(Level.FINEST, msg); + } + + /** + * Log WARNING message + * + * @param msg message + */ + private static void warning(String msg) { + if (!loggingEnabled) { + return; + } + logger.log(Level.WARNING, msg); + loggerError.log(Level.WARNING, msg); + } + + /** + * Log FINE message + * + * @param msg message + */ + public static void f1(String msg) { + fine(msg); + } + + /** + * Log FINER message + * + * @param msg message + */ + public static void f2(String msg) { + finer(msg); + } + + /** + * Log FINEST message + * + * @param msg message + */ + public static void f3(String msg) { + finest(msg); + } + + /** + * Log INFO message + * + * @param msg message + */ + public static void i(String msg) { + info(msg); + } + + + /** + * Log WARNING message (less severe than ERROR) + * + * @param msg message + */ + public static void w(String msg) { + warning(msg); + } + + /** + * Log SEVERE (critical warning) message + * + * @param msg message + */ + private static void severe(String msg) { + loggerError.log(Level.SEVERE, msg); + if (!loggingEnabled) { + return; + } + logger.log(Level.SEVERE, msg); + } + + /** + * Log ERROR message + * + * @param msg message + */ + public static void e(String msg) { + severe(msg); + } + + /** + * Log THROWING message + * + * @param msg message + * @param thrown thrown exception + */ + public static void e(String msg, Throwable thrown) { + loggerError.log(Level.SEVERE, msg + "\n" + getStackTrace(thrown)); + if (!loggingEnabled) { + return; + } + logger.log(Level.SEVERE, msg + "\n" + getStackTrace(thrown)); + } + + /** + * Log exception thrown + * + * @param thrown thrown exception + */ + public static void e(Throwable thrown) { + loggerError.log(Level.SEVERE, getStackTrace(thrown)); + if (!loggingEnabled) { + return; + } + logger.log(Level.SEVERE, getStackTrace(thrown)); + } + + /** + * Get stack trace from throwable + * + * @param t + * @return trace + */ + private static String getStackTrace(Throwable t) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw, true); + t.printStackTrace(pw); + pw.flush(); + sw.flush(); + return sw.toString(); + } + + + /** + * PowerCraft Log file formatter. + * + * @author MightyPork + * @copy (c) 2012 + */ + private static class LogFormatter extends Formatter { + + /** Newline string constant */ + private static final String nl = System.getProperty("line.separator"); + private boolean sysout; + + public LogFormatter(boolean sysout) { + this.sysout = sysout; + } + + @Override + public String format(LogRecord record) { + + StringBuffer buf = new StringBuffer(180); + + if (record.getMessage().equals("\n")) { + return nl; + } + + if (record.getMessage().charAt(0) == '\n') { + buf.append(nl); + record.setMessage(record.getMessage().substring(1)); + } + + Level level = record.getLevel(); + String trail = "[ ? ]"; + if (level == Level.FINE) { + trail = "[ # ] "; + } + if (level == Level.FINER) { + trail = "[ - ] "; + } + if (level == Level.FINEST) { + trail = "[ ] "; + } + if (level == Level.INFO) { + trail = "[ i ] "; + } + if (level == Level.SEVERE) { + trail = "[!E!] "; + } + if (level == Level.WARNING) { + trail = "[!W!] "; + } + + record.setMessage(record.getMessage().replaceAll("\n", nl + trail)); + + buf.append(trail); + buf.append(formatMessage(record)); + + buf.append(nl); + + Throwable throwable = record.getThrown(); + if (throwable != null) { + + buf.append("at "); + buf.append(record.getSourceClassName()); + buf.append('.'); + buf.append(record.getSourceMethodName()); + buf.append(nl); + + StringWriter sink = new StringWriter(); + throwable.printStackTrace(new PrintWriter(sink, true)); + buf.append(sink.toString()); + + buf.append(nl); + } + + if (Log.printToStdout && sysout) { + if (level == Level.FINE || level == Level.FINER || level == Level.FINEST || level == Level.INFO) { + System.out.print(buf.toString()); + } else if (level == Level.SEVERE || level == Level.WARNING) { + System.err.print(buf.toString()); + } + } + + return buf.toString(); + } + } + + +} diff --git a/src/net/spritegen/util/ObjParser.java b/src/net/spritegen/util/ObjParser.java new file mode 100644 index 0000000..ff72cd4 --- /dev/null +++ b/src/net/spritegen/util/ObjParser.java @@ -0,0 +1,322 @@ +package net.spritegen.util; + + +import com.porcupine.coord.Coord; +import com.porcupine.coord.CoordI; +import com.porcupine.math.Range; + + +/** + * Utility for converting Object to data types; Can also convert strings to data + * types. + * + * @author MightyPork + */ +public class ObjParser { + + /** + * Get INTEGER + * + * @param o object + * @param def default value + * @return integer + */ + public static int getInteger(Object o, Integer def) { + try { + if (o == null) return def; + if (o instanceof String) return (int) Math.round(Double.parseDouble((String) o)); + if (o instanceof Number) return ((Number) o).intValue(); + if (o instanceof Range) return ((Range) o).randInt(); + if (o instanceof Boolean) return ((Boolean) o) ? 1 : 0; + } catch (NumberFormatException e) {} + Log.w("Object cast error - cannot cast " + o + " to Integer."); + return def; + } + + /** + * Get DOUBLE + * + * @param o object + * @param def default value + * @return double + */ + public static double getDouble(Object o, Double def) { + return getDoubleImpl(o, def); + } + + /** + * Get DOUBLE + * + * @param o object + * @param def default value + * @return double + */ + public static double getDouble(Object o, double def) { + return getDoubleImpl(o, def); + } + + private static double getDoubleImpl(Object o, Double def) { + try { + if (o == null) return def; + if (o instanceof String) return Double.parseDouble((String) o); + if (o instanceof Number) return ((Number) o).doubleValue(); + if (o instanceof Range) return ((Range) o).randDouble(); + if (o instanceof Boolean) return ((Boolean) o) ? 1 : 0; + } catch (NumberFormatException e) {} + Log.w("Object cast error - cannot cast " + o + " to Double."); + return def; + } + + /** + * Get FLOAT + * + * @param o object + * @param def default value + * @return float + */ + public static double getFloat(Object o, Float def) { + try { + if (o == null) return def; + if (o instanceof Number) return ((Number) o).floatValue(); + } catch (NumberFormatException e) {} + Log.w("Object cast error - cannot cast " + o + " to Float."); + return def; + } + + /** + * Get BOOLEAN + * + * @param o object + * @param def default value + * @return boolean + */ + public static boolean getBoolean(Object o, Boolean def) { + if (o == null) return def; + + if (o instanceof String) { + String s = ((String) o).trim().toLowerCase(); + if (s.equals("0")) return false; + if (s.equals("1")) return true; + try { + double n = Double.parseDouble(s); + return n != 0; + } catch (NumberFormatException e) {} + + if (s.equals("true")) return true; + if (s.equals("yes")) return true; + if (s.equals("enabled")) return true; + + if (s.equals("false")) return false; + if (s.equals("no")) return false; + if (s.equals("disabled")) return true; + } + + if (o instanceof Boolean) return ((Boolean) o).booleanValue(); + if (o instanceof Number) return ((Number) o).intValue() != 0; + Log.w("Object cast error - cannot cast " + o + " to Boolean."); + return def; + } + + /** + * Get STRING + * + * @param o object + * @param def default value + * @return String + */ + public static String getString(Object o, String def) { + if (o == null) return def; + if (o instanceof String) return ((String) o); +// Log.w("Object cast error - cannot cast " + o + " to String."); + return o.toString(); + } + + /** + * Get AI_COORD
+ * Converts special constants to magic coordinate instances. + * + * @param o object + * @param def default value + * @return AiCoord + */ + public static Coord getCoord(Object o, Coord def) { + try { + + if (o == null) return def; + if (o instanceof String) { + String s = ((String) o).trim().toUpperCase(); + + // colon to semicolon + s = s.replace(':', ';'); + // comma to semicolon + s = s.replace(',', ';'); + // remove brackets if any + s = s.replaceAll("[\\(\\[\\{\\)\\]\\}]", ""); + String[] parts = s.split("[;]"); + return new Coord(Double.parseDouble(parts[0].trim()), Double.parseDouble(parts[1].trim())); + } + if (o instanceof Coord) return new Coord((Coord) o); + if (o instanceof CoordI) return ((CoordI) o).toCoord(); + } catch (NumberFormatException e) {} + Log.w("Object cast error - cannot cast " + o + " to AiCoord."); + return def; //new AiCoord(0, 0, EAiCoordSpecialType.BASIC); + } + + + /** + * Get RANGE + * + * @param o object + * @param def default value + * @return AiCoord + */ + public static Range getRange(Object o, Range def) { + try { + if (o == null) return def; + if (o instanceof Number) return new Range(((Number) o).doubleValue(), ((Number) o).doubleValue()); + if (o instanceof String) { + String s = ((String) o).trim(); + + // colon to semicolon + s = s.replace(',', ':'); + // comma to dot. + s = s.replace(';', ':'); + // dash + s = s.replaceAll("([0-9])\\s?[\\-]", "$1:"); + // remove brackets if any + s = s.replaceAll("[\\(\\[\\{\\)\\]\\}]", ""); + String[] parts = s.split("[:]"); + if (parts.length == 2) return new Range(Double.parseDouble(parts[0].trim()), Double.parseDouble(parts[1].trim())); + return new Range(Double.parseDouble(parts[0].trim()), Double.parseDouble(parts[0].trim())); + + } + if (o instanceof Range) return (Range) o; + } catch (NumberFormatException e) {} + Log.w("Object cast error - cannot cast " + o + " to AiRange."); + return def; + } + + + /** + * Get INTEGER + * + * @param o object + * @return integer + */ + public static int getInteger(Object o) { + return getInteger(o, 0); + } + + /** + * Get DOUBLE + * + * @param o object + * @return double + */ + public static double getDouble(Object o) { + return getDouble(o, 0d); + } + + + /** + * Get FLOAT + * + * @param o object + * @return float + */ + public static double getFloat(Object o) { + return getFloat(o, 0f); + } + + /** + * Get BOOLEAN + * + * @param o object + * @return boolean + */ + public static boolean getBoolean(Object o) { + return getBoolean(o, false); + } + + /** + * Get STRING + * + * @param o object + * @return String + */ + public static String getString(Object o) { + return getString(o, ""); + } + + /** + * Get AI_COORD (if special string constant is present instead, build coord + * of it) + * + * @param o object + * @return AiCoord + */ + public static Coord getCoord(Object o) { + return getCoord(o, Coord.ZERO.copy()); + } + + + /** + * Get RANGE + * + * @param o object + * @return AiCoord + */ + public static Range getRange(Object o) { + return getRange(o, new Range()); + } + +// /** +// * Get if object is a NUMBER +// * +// * @param o object +// * @return is number +// */ +// public static boolean isNum(Object o) { +// return o instanceof Number; +// } +// +// /** +// * Get if object is a BOOLEAN +// * +// * @param o object +// * @return is boolean +// */ +// public static boolean isBool(Object o) { +// return o instanceof Boolean; +// } +// +// /** +// * Get if object is a STRING +// * +// * @param o object +// * @return is string +// */ +// public static boolean isString(Object o) { +// return o instanceof String; +// } +// +// /** +// * Get if object is a Coord (any) +// * +// * @param o object +// * @return is coord +// */ +// public static boolean isCoord(Object o) { +// return o instanceof Coord || o instanceof AiCoord || o instanceof CoordI; +// } +// +// /** +// * Get if object is a AiRange +// * +// * @param o object +// * @return is range +// */ +// public static boolean isRange(Object o) { +// return o instanceof AiRange; +// } +} diff --git a/src/net/spritegen/util/RenderUtils.java b/src/net/spritegen/util/RenderUtils.java new file mode 100644 index 0000000..aa81ab0 --- /dev/null +++ b/src/net/spritegen/util/RenderUtils.java @@ -0,0 +1,491 @@ +package net.spritegen.util; + + +import static org.lwjgl.opengl.GL11.*; + +import org.newdawn.slick.opengl.Texture; + +import com.porcupine.color.HSV; +import com.porcupine.color.RGB; +import com.porcupine.coord.Coord; +import com.porcupine.coord.Rect; + + +/** + * Render utilities + * + * @author MightyPork + */ +public class RenderUtils { + + /** + * Render quad 2D + * + * @param min min coord + * @param max max coord + */ + public static void quadCoord(Coord min, Coord max) { + quadCoord(min.x, min.y, max.x, max.y); + } + + /** + * Render quad with absolute coords (from screen bottom) + * + * @param left left x + * @param bottom bottom y + * @param right right x + * @param top top y + */ + public static void quadCoord(double left, double bottom, double right, double top) { + glBegin(GL_QUADS); + glVertex2d(left, top); + glVertex2d(right, top); + glVertex2d(right, bottom); + glVertex2d(left, bottom); + glEnd(); + } + + /** + * Render quad with coloured border + * + * @param min min + * @param max max + * @param border border width + * @param borderColor border color + * @param insideColor filling color + */ + public static void quadCoordBorder(Coord min, Coord max, double border, RGB borderColor, RGB insideColor) { + quadCoordBorder(min.x, min.y, max.x, max.y, border, borderColor, insideColor); + } + + /** + * Render quad with coloured border + * + * @param minX min x + * @param minY min y + * @param maxX max x + * @param maxY max y + * @param border border width + * @param borderColor border color + * @param insideColor filling color + */ + public static void quadCoordBorder(double minX, double minY, double maxX, double maxY, double border, RGB borderColor, RGB insideColor) { + double bdr = border; + + RenderUtils.setColor(borderColor); + + //@formatter:off + RenderUtils.quadCoord(minX, minY, minX + bdr, maxY); + RenderUtils.quadCoord(maxX - bdr, minY, maxX, maxY); + RenderUtils.quadCoord(minX + bdr, maxY - bdr, maxX - bdr, maxY); + RenderUtils.quadCoord(minX + bdr, minY, maxX - bdr, minY + bdr); + //@formatter:on + + if (insideColor != null) { + RenderUtils.setColor(insideColor); + RenderUtils.quadCoord(minX + bdr, minY + bdr, maxX - bdr, maxY - bdr); + } + } + + /** + * Render quad 2D with gradient horizontal + * + * @param min min coord + * @param max max coord + * @param colorLeft color left + * @param colorRight color right + */ + public static void quadCoordGradH(Coord min, Coord max, RGB colorLeft, RGB colorRight) { + quadCoordGradH(min.x, min.y, max.x, max.y, colorLeft, colorRight); + } + + /** + * Render quad 2D with gradient horizontal + * + * @param minX units from left + * @param minY units from bottom + * @param maxX quad width + * @param maxY quad height + * @param colorLeft color left + * @param colorRight color right + */ + public static void quadCoordGradH(double minX, double minY, double maxX, double maxY, RGB colorLeft, RGB colorRight) { + glBegin(GL_QUADS); + setColor(colorLeft); + glVertex2d(minX, maxY); + setColor(colorRight); + glVertex2d(maxX, maxY); + + setColor(colorRight); + glVertex2d(maxX, minY); + setColor(colorLeft); + glVertex2d(minX, minY); + glEnd(); + } + + /** + * Render quad 2D with gradient horizontal + * + * @param min min coord + * @param max max coord + * @param colorOuter color outer + * @param colorMiddle color inner + */ + public static void quadCoordGradHBilinear(Coord min, Coord max, RGB colorOuter, RGB colorMiddle) { + quadCoordGradHBilinear(min.x, min.y, max.x, max.y, colorOuter, colorMiddle); + } + + /** + * Render quad 2D with gradient horizontal + * + * @param minX min x + * @param minY min y + * @param maxX max x + * @param maxY max y + * @param colorOuter color outer + * @param colorMiddle color inner + */ + public static void quadCoordGradHBilinear(double minX, double minY, double maxX, double maxY, RGB colorOuter, RGB colorMiddle) { + glBegin(GL_QUADS); + setColor(colorOuter); + glVertex2d(minX, maxY); + setColor(colorMiddle); + glVertex2d((minX + maxX) / 2, maxY); + + setColor(colorMiddle); + glVertex2d((minX + maxX) / 2, minY); + setColor(colorOuter); + glVertex2d(minX, minY); + + + setColor(colorMiddle); + glVertex2d((minX + maxX) / 2, maxY); + setColor(colorOuter); + glVertex2d(maxX, maxY); + + setColor(colorOuter); + glVertex2d(maxX, minY); + setColor(colorMiddle); + glVertex2d((minX + maxX) / 2, minY); + glEnd(); + } + + /** + * Render quad 2D with gradient vertical + * + * @param min min coord + * @param max max coord + * @param colorTop top color + * @param colorBottom bottom color + */ + public static void quadCoordGradV(Coord min, Coord max, RGB colorTop, RGB colorBottom) { + quadCoordGradV(min.x, min.y, max.x, max.y, colorTop, colorBottom); + } + + /** + * Render quad 2D with gradient vertical + * + * @param minX min X + * @param minY min Y + * @param maxX max X + * @param maxY max Y + * @param colorTop top color + * @param colorBottom bottom color + */ + public static void quadCoordGradV(double minX, double minY, double maxX, double maxY, RGB colorTop, RGB colorBottom) { + glBegin(GL_QUADS); + + setColor(colorTop); + glVertex2d(minX, maxY); + glVertex2d(maxX, maxY); + + setColor(colorBottom); + glVertex2d(maxX, minY); + glVertex2d(minX, minY); + glEnd(); + } + + /** + * Render quad 2D with gradient vertical + * + * @param min min coord + * @param max max coord + * @param colorOuter outer color + * @param colorMiddle middle color + */ + public static void quadCoordGradVBilinear(Coord min, Coord max, RGB colorOuter, RGB colorMiddle) { + quadCoordGradVBilinear(min.x, min.y, max.x, max.y, colorOuter, colorMiddle); + } + + /** + * Render quad 2D with gradient vertical + * + * @param minX min X + * @param minY min Y + * @param maxX max X + * @param maxY max Y + * @param colorOuter outer color + * @param colorMiddle middle color + */ + public static void quadCoordGradVBilinear(double minX, double minY, double maxX, double maxY, RGB colorOuter, RGB colorMiddle) { + glBegin(GL_QUADS); + + setColor(colorOuter); + glVertex2d(minX, maxY); + glVertex2d(maxX, maxY); + + setColor(colorMiddle); + glVertex2d(maxX, (maxY + minY) / 2); + glVertex2d(minX, (maxY + minY) / 2); + + setColor(colorMiddle); + glVertex2d(minX, (maxY + minY) / 2); + glVertex2d(maxX, (maxY + minY) / 2); + + setColor(colorOuter); + glVertex2d(maxX, minY); + glVertex2d(minX, minY); + + glEnd(); + } + + /** + * Render quad with coloured border with outset effect + * + * @param min min coord + * @param max max coord + * @param border border width + * @param fill fill color + * @param inset true for inset, false for outset + */ + public static void quadCoordOutset(Coord min, Coord max, double border, RGB fill, boolean inset) { + quadCoordOutset(min.x, min.y, max.x, max.y, border, fill, inset); + } + + /** + * Render quad with coloured border with outset effect + * + * @param minX left X + * @param minY bottom Y + * @param maxX right X + * @param maxY top Y + * @param border border width + * @param fill fill color + * @param inset true for inset, false for outset + */ + public static void quadCoordOutset(double minX, double minY, double maxX, double maxY, double border, RGB fill, boolean inset) { + HSV hsv = fill.toHSV(); + HSV h; + + h = hsv.copy(); + h.s *= 0.6; + RGB a = h.toRGB(); + + h = fill.toHSV(); + h.v *= 0.6; + RGB b = h.toRGB(); + + RGB leftTopC, rightBottomC; + + if (!inset) { + leftTopC = a; + rightBottomC = b; + } else { + leftTopC = b; + rightBottomC = a; + } + + double bdr = border; + + RenderUtils.setColor(leftTopC); + + // left + top + glBegin(GL_QUADS); + glVertex2d(minX, minY); + glVertex2d(minX + bdr, minY + bdr); + glVertex2d(minX + bdr, maxY - bdr); + glVertex2d(minX, maxY); + + glVertex2d(minX, maxY); + glVertex2d(minX + bdr, maxY - bdr); + glVertex2d(maxX - bdr, maxY - bdr); + glVertex2d(maxX, maxY); + glEnd(); + + + RenderUtils.setColor(rightBottomC); + + // right + bottom + glBegin(GL_QUADS); + glVertex2d(maxX, minY); + glVertex2d(maxX, maxY); + glVertex2d(maxX - bdr, maxY - bdr); + glVertex2d(maxX - bdr, minY + bdr); + + glVertex2d(minX, minY); + glVertex2d(maxX, minY); + glVertex2d(maxX - bdr, minY + bdr); + glVertex2d(minX + bdr, minY + bdr); + glEnd(); + + RenderUtils.setColor(fill); + RenderUtils.quadCoord(minX + bdr, minY + bdr, maxX - bdr, maxY - bdr); + } + + /** + * Render quad 2D + * + * @param rect rectangle + */ + public static void quadRect(Rect rect) { + quadCoord(rect.getMin(), rect.getMax()); + } + + /** + * Render quad 2D + * + * @param rect rectangle + * @param color draw color + */ + public static void quadRect(Rect rect, RGB color) { + setColor(color); + quadCoord(rect.getMin(), rect.getMax()); + } + + + /** + * Render quad with coloured border + * + * @param rect rect + * @param border border width + * @param borderColor border color + * @param insideColor filling color + */ + public static void quadBorder(Rect rect, double border, RGB borderColor, RGB insideColor) { + quadCoordBorder(rect.getMin(), rect.getMax(), border, borderColor, insideColor); + } + + /** + * Render quad 2D with gradient horizontal + * + * @param rect rect + * @param colorLeft color left + * @param colorRight color right + */ + public static void quadGradH(Rect rect, RGB colorLeft, RGB colorRight) { + quadCoordGradH(rect.getMin(), rect.getMax(), colorLeft, colorRight); + } + + /** + * Render quad 2D with gradient horizontal + * + * @param rect rect + * @param colorOuter color outer + * @param colorMiddle color inner + */ + public static void quadGradHBilinear(Rect rect, RGB colorOuter, RGB colorMiddle) { + quadCoordGradHBilinear(rect.getMin(), rect.getMax(), colorOuter, colorMiddle); + } + + + + /** + * Render quad 2D with gradient vertical + * + * @param rect rect + * @param colorTop top color + * @param colorBottom bottom color + */ + public static void quadGradV(Rect rect, RGB colorTop, RGB colorBottom) { + quadCoordGradV(rect.getMin(), rect.getMax(), colorTop, colorBottom); + } + + /** + * Render quad 2D with gradient vertical + * + * @param rect rect + * @param colorOuter outer color + * @param colorMiddle middle color + */ + public static void quadGradVBilinear(Rect rect, RGB colorOuter, RGB colorMiddle) { + quadCoordGradVBilinear(rect.getMin(), rect.getMax(), colorOuter, colorMiddle); + } + + /** + * Render quad with coloured border with outset effect + * + * @param rect rectangle + * @param border border width + * @param fill fill color + * @param inset true for inset, false for outset + */ + public static void quadRectOutset(Rect rect, double border, RGB fill, boolean inset) { + quadCoordOutset(rect.getMin(), rect.getMax(), border, fill, inset); + } + + + /** + * Render textured rect (texture must be binded already) + * + * @param quad rectangle (px) + * @param textureCoords texture coords (0-1) + */ + public static void quadTexturedAbs(Rect quad, Rect textureCoords) { + double left = quad.x1(); + double bottom = quad.y2(); + double right = quad.x2(); + double top = quad.y1(); + + double tleft = textureCoords.x1(); + double tbottom = textureCoords.y1(); + double tright = textureCoords.x2(); + double ttop = textureCoords.y2(); + + glBegin(GL_QUADS); + glTexCoord2d(tleft, ttop); + glVertex2d(left, top); + glTexCoord2d(tright, ttop); + glVertex2d(right, top); + glTexCoord2d(tright, tbottom); + glVertex2d(right, bottom); + glTexCoord2d(tleft, tbottom); + glVertex2d(left, bottom); + glEnd(); + } + + /** + * Render quad 2D + * + * @param left units from left + * @param bottom units from bottom + * @param width quad width + * @param height quad height + */ + public static void quadSize(double left, double bottom, double width, double height) { + glBegin(GL_QUADS); + glVertex2d(left, bottom + height); + glVertex2d(left + width, bottom + height); + glVertex2d(left + width, bottom); + glVertex2d(left, bottom); + glEnd(); + } + + + /** + * Bing GL color + * + * @param color RGB color + */ + public static void setColor(RGB color) { + if (color != null) glColor4d(color.r, color.g, color.b, color.a); + } + + /** + * Translate with coord + * + * @param coord coord + */ + public static void translate(Coord coord) { + glTranslated(coord.x, coord.y, coord.z); + } +} diff --git a/src/net/spritegen/util/Utils.java b/src/net/spritegen/util/Utils.java new file mode 100644 index 0000000..53de2e7 --- /dev/null +++ b/src/net/spritegen/util/Utils.java @@ -0,0 +1,71 @@ +package net.spritegen.util; + + +import java.io.File; + +import net.spritegen.Constants; + +import com.porcupine.coord.Coord; +import com.porcupine.coord.Vec; +import com.porcupine.math.Calc.Rad; +import com.porcupine.math.Polar; +import com.porcupine.util.FileUtils; + + +/** + * Sector's utils class + * + * @author MightyPork + */ +public class Utils { + + + private static File gameDir; + + /** + * 2D angle of observer to point + * + * @param observer point of observer + * @param point point of target + * @param lookVec look vector of observer + * @return angle + */ + public static double observerAngleToCoord(Coord observer, Coord point, Vec lookVec) { + Vec dist = observer.vecTo(point); + + Polar point_p = Polar.fromCoord(dist.x, dist.z); + Polar look_p = Polar.fromCoord(lookVec.x, lookVec.z); + + return Rad.toDeg(Rad.diff(point_p.angle, look_p.angle)); + } + + /** + * Get working directory ending with slash. + * + * @return directory path file + */ + public static File getGameFolder() { + if (gameDir == null) { + gameDir = FileUtils.getAppDir(Constants.APP_DIR); + } + + return gameDir; + } + + /** + * Get subfolder of game dir + * + * @param subfolderName sibfolder name + * @return the file object + */ + public static File getGameSubfolder(String subfolderName) { + return new File(getGameFolder(), subfolderName); + } + + public static Object fallback(Object... options) { + for (Object o : options) { + if (o != null) return o; + } + return null; // error + } +}