From 579e3bb5df1347320bc2c402ab486a8c13e379c6 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 17 Feb 2017 17:32:44 -0600 Subject: [PATCH] Initial commit. --- .gitignore | 1 + A1/.gitignore | 1 + A1/A1.zip | Bin 0 -> 133118 bytes A1/CMakeLists.txt | 34 + A1/README.txt | 7 + A1/resources/bunny.obj | 7474 +++++++++++++++++ A1/resources/sphere.obj | 204 + A1/resources/teapot.obj | 5049 +++++++++++ A1/resources/tri.obj | 4 + A1/resources/tri2.obj | 8 + A1/shadow8t4.zip | Bin 0 -> 30291 bytes A1/shadow8t4/shadow8t4/CMakeLists.txt | 34 + A1/shadow8t4/shadow8t4/README.txt | 7 + A1/shadow8t4/shadow8t4/src/Image.cpp | 61 + A1/shadow8t4/shadow8t4/src/Image.h | 25 + A1/shadow8t4/shadow8t4/src/Triangle.cpp | 45 + A1/shadow8t4/shadow8t4/src/Triangle.h | 34 + A1/shadow8t4/shadow8t4/src/main.cpp | 347 + A1/shadow8t4/shadow8t4/src/stb_image_write.h | 1048 +++ A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h | 1922 +++++ A1/src/Image.cpp | 61 + A1/src/Image.h | 25 + A1/src/Triangle.cpp | 45 + A1/src/Triangle.h | 34 + A1/src/main.cpp | 347 + A1/src/stb_image_write.h | 1048 +++ A1/src/tiny_obj_loader.h | 1922 +++++ A2/.gitignore | 1 + A2/CMakeLists.txt | 126 + A2/resources/cube.obj | 29 + A2/resources/frag.glsl | 8 + A2/resources/vert.glsl | 13 + A2/src/Body.h | 43 + A2/src/GLSL.cpp | 152 + A2/src/GLSL.h | 40 + A2/src/MatrixStack.cpp | 114 + A2/src/MatrixStack.h | 50 + A2/src/Program.cpp | 126 + A2/src/Program.h | 44 + A2/src/Shape.cpp | 135 + A2/src/Shape.h | 36 + A2/src/main.cpp | 187 + A2/src/tiny_obj_loader.h | 1922 +++++ L00(old)/.gitignore | 1 + L00(old)/CMakeLists.txt | 118 + L00(old)/resources/simple_frag.glsl | 11 + L00(old)/resources/simple_vert.glsl | 12 + L00(old)/resources/teapot.obj | 5049 +++++++++++ L00(old)/src/GLSL.cpp | 152 + L00(old)/src/GLSL.h | 40 + L00(old)/src/MatrixStack.cpp | 114 + L00(old)/src/MatrixStack.h | 50 + L00(old)/src/Program.cpp | 126 + L00(old)/src/Program.h | 44 + L00(old)/src/Shape.cpp | 135 + L00(old)/src/Shape.h | 36 + L00(old)/src/main.cpp | 152 + L00(old)/src/tiny_obj_loader.h | 1922 +++++ L00.zip | Bin 0 -> 58868 bytes L00/.gitignore | 1 + L00/CMakeLists.txt | 118 + L00/resources/simple_frag.glsl | 11 + L00/resources/simple_vert.glsl | 12 + L00/resources/teapot.obj | 5049 +++++++++++ L00/src/GLSL.cpp | 152 + L00/src/GLSL.h | 40 + L00/src/MatrixStack.cpp | 114 + L00/src/MatrixStack.h | 50 + L00/src/Program.cpp | 126 + L00/src/Program.h | 44 + L00/src/Shape.cpp | 135 + L00/src/Shape.h | 36 + L00/src/main.cpp | 152 + L00/src/tiny_obj_loader.h | 1922 +++++ L01.zip | Bin 0 -> 14255 bytes L01/.gitignore | 1 + L01/CMakeLists.txt | 34 + L01/src/Image.cpp | 87 + L01/src/Image.h | 40 + L01/src/main.cpp | 87 + L01/src/stb_image_write.h | 1048 +++ L01/src/triangle.cpp | 33 + L01/src/triangle.h | 23 + L02/.gitignore | 1 + L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake | 68 + L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake | 69 + .../3.7.2/CMakeDetermineCompilerABI_C.bin | Bin 0 -> 8616 bytes .../3.7.2/CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 8632 bytes L02/CMakeFiles/3.7.2/CMakeSystem.cmake | 15 + .../3.7.2/CompilerIdC/CMakeCCompilerId.c | 561 ++ L02/CMakeFiles/3.7.2/CompilerIdC/a.out | Bin 0 -> 8776 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 533 ++ L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out | Bin 0 -> 8784 bytes .../CMakeDirectoryInformation.cmake | 16 + L02/CMakeFiles/CMakeOutput.log | 544 ++ L02/CMakeFiles/L02.dir/CXX.includecache | 52 + L02/CMakeFiles/L02.dir/DependInfo.cmake | 21 + L02/CMakeFiles/L02.dir/build.make | 140 + L02/CMakeFiles/L02.dir/cmake_clean.cmake | 11 + L02/CMakeFiles/L02.dir/depend.internal | 10 + L02/CMakeFiles/L02.dir/depend.make | 10 + L02/CMakeFiles/L02.dir/flags.make | 10 + L02/CMakeFiles/L02.dir/link.txt | 1 + L02/CMakeFiles/L02.dir/progress.make | 4 + L02/CMakeFiles/L02.dir/src/Image.cpp.o | Bin 0 -> 81608 bytes L02/CMakeFiles/L02.dir/src/main.cpp.o | Bin 0 -> 64144 bytes L02/CMakeFiles/Makefile.cmake | 45 + L02/CMakeFiles/Makefile2 | 108 + L02/CMakeFiles/TargetDirectories.txt | 3 + L02/CMakeFiles/cmake.check_cache | 1 + L02/CMakeFiles/feature_tests.bin | Bin 0 -> 12672 bytes L02/CMakeFiles/feature_tests.c | 34 + L02/CMakeFiles/feature_tests.cxx | 405 + L02/CMakeFiles/progress.marks | 1 + L02/CMakeLists.txt | 34 + L02/src/Image.cpp | 87 + L02/src/Image.h | 43 + L02/src/main.cpp | 146 + L02/src/stb_image_write.h | 1048 +++ L03.zip | Bin 0 -> 20758 bytes L03/.gitignore | 1 + L03/CMakeLists.txt | 126 + L03/resources/cube.obj | 29 + L03/resources/frag.glsl | 8 + L03/resources/vert.glsl | 13 + L03/src/GLSL.cpp | 152 + L03/src/GLSL.h | 40 + L03/src/main.cpp | 449 + L03/src/tiny_obj_loader.h | 1922 +++++ L04.zip | Bin 0 -> 21810 bytes L04/.gitignore | 1 + L04/CMakeLists.txt | 126 + L04/resources/cube.obj | 29 + L04/resources/frag.glsl | 8 + L04/resources/vert.glsl | 13 + L04/src/GLSL.cpp | 152 + L04/src/GLSL.h | 40 + L04/src/MatrixStack.cpp | 114 + L04/src/MatrixStack.h | 50 + L04/src/Program.cpp | 126 + L04/src/Program.h | 44 + L04/src/Shape.cpp | 135 + L04/src/Shape.h | 36 + L04/src/main.cpp | 347 + L04/src/tiny_obj_loader.h | 1922 +++++ 145 files changed, 49994 insertions(+) create mode 100644 .gitignore create mode 100644 A1/.gitignore create mode 100644 A1/A1.zip create mode 100644 A1/CMakeLists.txt create mode 100644 A1/README.txt create mode 100644 A1/resources/bunny.obj create mode 100644 A1/resources/sphere.obj create mode 100644 A1/resources/teapot.obj create mode 100644 A1/resources/tri.obj create mode 100644 A1/resources/tri2.obj create mode 100644 A1/shadow8t4.zip create mode 100644 A1/shadow8t4/shadow8t4/CMakeLists.txt create mode 100644 A1/shadow8t4/shadow8t4/README.txt create mode 100644 A1/shadow8t4/shadow8t4/src/Image.cpp create mode 100644 A1/shadow8t4/shadow8t4/src/Image.h create mode 100644 A1/shadow8t4/shadow8t4/src/Triangle.cpp create mode 100644 A1/shadow8t4/shadow8t4/src/Triangle.h create mode 100644 A1/shadow8t4/shadow8t4/src/main.cpp create mode 100644 A1/shadow8t4/shadow8t4/src/stb_image_write.h create mode 100644 A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h create mode 100644 A1/src/Image.cpp create mode 100644 A1/src/Image.h create mode 100644 A1/src/Triangle.cpp create mode 100644 A1/src/Triangle.h create mode 100644 A1/src/main.cpp create mode 100644 A1/src/stb_image_write.h create mode 100644 A1/src/tiny_obj_loader.h create mode 100644 A2/.gitignore create mode 100644 A2/CMakeLists.txt create mode 100644 A2/resources/cube.obj create mode 100644 A2/resources/frag.glsl create mode 100644 A2/resources/vert.glsl create mode 100644 A2/src/Body.h create mode 100644 A2/src/GLSL.cpp create mode 100644 A2/src/GLSL.h create mode 100644 A2/src/MatrixStack.cpp create mode 100644 A2/src/MatrixStack.h create mode 100644 A2/src/Program.cpp create mode 100644 A2/src/Program.h create mode 100644 A2/src/Shape.cpp create mode 100644 A2/src/Shape.h create mode 100644 A2/src/main.cpp create mode 100644 A2/src/tiny_obj_loader.h create mode 100644 L00(old)/.gitignore create mode 100644 L00(old)/CMakeLists.txt create mode 100644 L00(old)/resources/simple_frag.glsl create mode 100644 L00(old)/resources/simple_vert.glsl create mode 100644 L00(old)/resources/teapot.obj create mode 100644 L00(old)/src/GLSL.cpp create mode 100644 L00(old)/src/GLSL.h create mode 100644 L00(old)/src/MatrixStack.cpp create mode 100644 L00(old)/src/MatrixStack.h create mode 100644 L00(old)/src/Program.cpp create mode 100644 L00(old)/src/Program.h create mode 100644 L00(old)/src/Shape.cpp create mode 100644 L00(old)/src/Shape.h create mode 100644 L00(old)/src/main.cpp create mode 100644 L00(old)/src/tiny_obj_loader.h create mode 100644 L00.zip create mode 100644 L00/.gitignore create mode 100644 L00/CMakeLists.txt create mode 100644 L00/resources/simple_frag.glsl create mode 100644 L00/resources/simple_vert.glsl create mode 100644 L00/resources/teapot.obj create mode 100644 L00/src/GLSL.cpp create mode 100644 L00/src/GLSL.h create mode 100644 L00/src/MatrixStack.cpp create mode 100644 L00/src/MatrixStack.h create mode 100644 L00/src/Program.cpp create mode 100644 L00/src/Program.h create mode 100644 L00/src/Shape.cpp create mode 100644 L00/src/Shape.h create mode 100644 L00/src/main.cpp create mode 100644 L00/src/tiny_obj_loader.h create mode 100644 L01.zip create mode 100644 L01/.gitignore create mode 100644 L01/CMakeLists.txt create mode 100644 L01/src/Image.cpp create mode 100644 L01/src/Image.h create mode 100644 L01/src/main.cpp create mode 100644 L01/src/stb_image_write.h create mode 100644 L01/src/triangle.cpp create mode 100644 L01/src/triangle.h create mode 100644 L02/.gitignore create mode 100644 L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake create mode 100644 L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake create mode 100755 L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_C.bin create mode 100755 L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_CXX.bin create mode 100644 L02/CMakeFiles/3.7.2/CMakeSystem.cmake create mode 100644 L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c create mode 100755 L02/CMakeFiles/3.7.2/CompilerIdC/a.out create mode 100644 L02/CMakeFiles/3.7.2/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100755 L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out create mode 100644 L02/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 L02/CMakeFiles/CMakeOutput.log create mode 100644 L02/CMakeFiles/L02.dir/CXX.includecache create mode 100644 L02/CMakeFiles/L02.dir/DependInfo.cmake create mode 100644 L02/CMakeFiles/L02.dir/build.make create mode 100644 L02/CMakeFiles/L02.dir/cmake_clean.cmake create mode 100644 L02/CMakeFiles/L02.dir/depend.internal create mode 100644 L02/CMakeFiles/L02.dir/depend.make create mode 100644 L02/CMakeFiles/L02.dir/flags.make create mode 100644 L02/CMakeFiles/L02.dir/link.txt create mode 100644 L02/CMakeFiles/L02.dir/progress.make create mode 100644 L02/CMakeFiles/L02.dir/src/Image.cpp.o create mode 100644 L02/CMakeFiles/L02.dir/src/main.cpp.o create mode 100644 L02/CMakeFiles/Makefile.cmake create mode 100644 L02/CMakeFiles/Makefile2 create mode 100644 L02/CMakeFiles/TargetDirectories.txt create mode 100644 L02/CMakeFiles/cmake.check_cache create mode 100755 L02/CMakeFiles/feature_tests.bin create mode 100644 L02/CMakeFiles/feature_tests.c create mode 100644 L02/CMakeFiles/feature_tests.cxx create mode 100644 L02/CMakeFiles/progress.marks create mode 100644 L02/CMakeLists.txt create mode 100644 L02/src/Image.cpp create mode 100644 L02/src/Image.h create mode 100644 L02/src/main.cpp create mode 100644 L02/src/stb_image_write.h create mode 100644 L03.zip create mode 100644 L03/.gitignore create mode 100644 L03/CMakeLists.txt create mode 100644 L03/resources/cube.obj create mode 100644 L03/resources/frag.glsl create mode 100644 L03/resources/vert.glsl create mode 100644 L03/src/GLSL.cpp create mode 100644 L03/src/GLSL.h create mode 100644 L03/src/main.cpp create mode 100644 L03/src/tiny_obj_loader.h create mode 100644 L04.zip create mode 100644 L04/.gitignore create mode 100644 L04/CMakeLists.txt create mode 100644 L04/resources/cube.obj create mode 100644 L04/resources/frag.glsl create mode 100644 L04/resources/vert.glsl create mode 100644 L04/src/GLSL.cpp create mode 100644 L04/src/GLSL.h create mode 100644 L04/src/MatrixStack.cpp create mode 100644 L04/src/MatrixStack.h create mode 100644 L04/src/Program.cpp create mode 100644 L04/src/Program.h create mode 100644 L04/src/Shape.cpp create mode 100644 L04/src/Shape.h create mode 100644 L04/src/main.cpp create mode 100644 L04/src/tiny_obj_loader.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52369be --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +libraries/ diff --git a/A1/.gitignore b/A1/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/A1/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/A1/A1.zip b/A1/A1.zip new file mode 100644 index 0000000000000000000000000000000000000000..e18e089f05b4dc4d1f003cc74a28f0ab8cfb30f4 GIT binary patch literal 133118 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 jEc;*u7Lnv7lj@*#_ua^iB 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 aGYm^ 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 literal 0 HcmV?d00001 diff --git a/A1/CMakeLists.txt b/A1/CMakeLists.txt new file mode 100644 index 0000000..5deaf8f --- /dev/null +++ b/A1/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(A1) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/A1/README.txt b/A1/README.txt new file mode 100644 index 0000000..2f808ed --- /dev/null +++ b/A1/README.txt @@ -0,0 +1,7 @@ +1) Alexander Huddleston + +2) The last coloring mode goes from blue to green, top to bottom respectively. + +3) http://www.mathopenref.com/coordtrianglearea.html + +4) This was written and compiled on Arch Linux on a 64-bit machine. There should not be any errors when run on another machine, but I am making note here just in case. diff --git a/A1/resources/bunny.obj b/A1/resources/bunny.obj new file mode 100644 index 0000000..18abc08 --- /dev/null +++ b/A1/resources/bunny.obj @@ -0,0 +1,7474 @@ +# OBJ file format with ext .obj +# vertex count = 2503 +# face count = 4968 +v -3.4101800e-003 1.3031957e-001 2.1754370e-002 +v -8.1719160e-002 1.5250145e-001 2.9656090e-002 +v -3.0543480e-002 1.2477885e-001 1.0983400e-003 +v -2.4901590e-002 1.1211138e-001 3.7560240e-002 +v -1.8405680e-002 1.7843055e-001 -2.4219580e-002 +v 1.9067940e-002 1.2144925e-001 3.1968440e-002 +v 6.0412000e-003 1.2494359e-001 3.2652890e-002 +v -1.3469030e-002 1.6299355e-001 -1.2000020e-002 +v -3.4393240e-002 1.7236688e-001 -9.8213000e-004 +v -8.4314160e-002 1.0957263e-001 3.7097300e-003 +v -4.2233540e-002 1.7211574e-001 -4.1799800e-003 +v -6.3308390e-002 1.5660615e-001 -1.3838790e-002 +v -7.6903950e-002 1.6708033e-001 -2.6931360e-002 +v -7.2253920e-002 1.1539550e-001 5.1670300e-002 +v 1.2981330e-002 1.1366375e-001 3.8302950e-002 +v -3.7857280e-002 1.7010102e-001 1.4236000e-003 +v 4.8689400e-003 3.7962370e-002 4.5867630e-002 +v -5.7180550e-002 4.0918830e-002 4.6301340e-002 +v -4.5209070e-002 3.8839100e-002 4.4503770e-002 +v -3.3761490e-002 1.2617876e-001 1.7132300e-003 +v -5.0242270e-002 1.5773747e-001 9.3944500e-003 +v -2.1216950e-002 1.5887938e-001 -4.6923700e-003 +v -5.6472950e-002 1.5778406e-001 8.1786500e-003 +v -5.2802060e-002 4.1319860e-002 4.6169800e-002 +v -4.9960340e-002 4.3101950e-002 4.4462650e-002 +v -2.9748750e-002 3.6539860e-002 5.2493310e-002 +v -3.5438900e-003 4.2659770e-002 4.7541530e-002 +v 4.9304900e-003 4.1982660e-002 4.5723390e-002 +v -3.9088180e-002 1.6872020e-001 -1.1924680e-002 +v -5.6901000e-002 4.5437000e-002 4.3236960e-002 +v -4.1244880e-002 4.3098890e-002 4.2129560e-002 +v -2.6471980e-002 4.5034530e-002 5.1219460e-002 +v -2.1866970e-002 4.4022930e-002 5.3243800e-002 +v -3.6996250e-002 1.6899301e-001 1.3256300e-003 +v -6.7216590e-002 1.6171340e-001 -1.3733710e-002 +v 4.9760060e-002 7.0235220e-002 2.3732020e-002 +v -4.9186640e-002 4.6411230e-002 4.1170040e-002 +v -4.4590380e-002 4.3797990e-002 4.2685460e-002 +v -4.3686470e-002 4.7154500e-002 4.0286310e-002 +v -2.2491950e-002 4.6513620e-002 5.1885310e-002 +v -6.5174200e-003 4.5036200e-002 4.7502780e-002 +v 3.7699000e-004 4.4935790e-002 4.6519930e-002 +v 3.4023920e-002 1.1353879e-001 2.4595280e-002 +v -2.6467900e-002 1.8104250e-001 -8.0811700e-003 +v -1.7533470e-002 4.7964250e-002 4.8829630e-002 +v -7.0012600e-003 4.6416520e-002 4.7485540e-002 +v 5.9862300e-003 4.6689140e-002 4.9073620e-002 +v 9.1007200e-003 4.8474490e-002 4.9353190e-002 +v -3.5453700e-002 1.1244769e-001 3.5055410e-002 +v -7.5983200e-002 1.3820800e-001 4.9216580e-002 +v 3.4838440e-002 4.3153410e-002 2.8954310e-002 +v -5.2655550e-002 4.8494220e-002 3.8731190e-002 +v -4.7378940e-002 4.8456670e-002 3.9126790e-002 +v -3.8933750e-002 4.6364270e-002 4.0364780e-002 +v -2.6468940e-002 4.7816430e-002 4.9322590e-002 +v -2.2365790e-002 4.8073650e-002 5.0126500e-002 +v -1.3373430e-002 4.7892410e-002 4.7883850e-002 +v -1.2193490e-002 4.9470300e-002 4.9484490e-002 +v -6.3364000e-004 4.7193060e-002 4.9136900e-002 +v 2.0656800e-003 5.0104680e-002 5.2290220e-002 +v -2.2749270e-002 4.9883880e-002 4.6605520e-002 +v -1.8002080e-002 4.9917850e-002 4.6947970e-002 +v -7.8036800e-003 5.0169310e-002 5.0988650e-002 +v -2.6843800e-003 5.1247420e-002 5.3186790e-002 +v -6.3875650e-002 1.6140094e-001 -2.0064210e-002 +v 3.2434000e-002 4.5333970e-002 3.0316760e-002 +v -8.8064570e-002 1.2496764e-001 5.7412000e-004 +v -4.1503710e-002 1.6748512e-001 3.2765900e-003 +v -6.4457010e-002 1.5342891e-001 -5.1180400e-003 +v -3.4303190e-002 5.0520150e-002 3.8286020e-002 +v -2.2949400e-002 5.1020650e-002 4.3926450e-002 +v -1.4354710e-002 5.4428200e-002 5.0710310e-002 +v 1.3773100e-003 5.2302710e-002 5.3149010e-002 +v 3.6285000e-003 5.3198640e-002 5.3422710e-002 +v 8.0723800e-003 5.1574140e-002 5.1773560e-002 +v -7.2665890e-002 1.3005582e-001 5.1668200e-002 +v 3.7992780e-002 4.9793200e-002 3.1902020e-002 +v 3.8497260e-002 4.8062400e-002 3.1737450e-002 +v 2.1503510e-002 1.2563988e-001 2.1252620e-002 +v -7.6481330e-002 1.4827412e-001 -8.9376200e-003 +v -8.7240410e-002 1.1967213e-001 -1.7813000e-004 +v -4.3719960e-002 1.6822738e-001 2.3425000e-003 +v -4.0652200e-002 1.2266506e-001 2.6290300e-002 +v -4.6686180e-002 5.4570720e-002 3.7587370e-002 +v -4.4071750e-002 5.1058250e-002 3.8977810e-002 +v -3.8144110e-002 5.0599600e-002 3.9302160e-002 +v -1.9875770e-002 5.1607710e-002 4.6142000e-002 +v -1.6911250e-002 5.1843550e-002 4.8459320e-002 +v -1.6249190e-002 5.4292110e-002 5.0306940e-002 +v -1.0446540e-002 5.3685970e-002 5.1958610e-002 +v -4.3090900e-003 5.4467500e-002 5.3908250e-002 +v 7.8152700e-003 5.5050680e-002 5.2750250e-002 +v 3.7955090e-002 1.0488710e-001 -3.2031800e-003 +v -7.9003790e-002 1.2850550e-001 5.3149340e-002 +v -7.9778990e-002 1.3448894e-001 5.0990290e-002 +v -5.9129700e-002 1.5039712e-001 3.4489540e-002 +v -6.5691790e-002 1.4961818e-001 3.8160980e-002 +v -3.1951660e-002 1.2518394e-001 1.9400580e-002 +v -6.9372590e-002 1.6061775e-001 -9.1905000e-003 +v -4.5225500e-002 1.2935459e-001 2.0377520e-002 +v -4.1879110e-002 5.6164390e-002 3.9796700e-002 +v -3.0614840e-002 5.4412650e-002 3.6694290e-002 +v -2.4787600e-002 5.2606220e-002 4.0839760e-002 +v -2.1588860e-002 5.6836920e-002 4.5467040e-002 +v -2.4264000e-004 5.4536020e-002 5.4641200e-002 +v -8.0900510e-002 1.2558713e-001 5.2155370e-002 +v -2.9996210e-002 1.7811137e-001 -5.2358200e-003 +v 3.5515390e-002 5.0449570e-002 3.1439830e-002 +v 4.3315550e-002 5.2145550e-002 3.2492110e-002 +v -6.3938540e-002 1.5262699e-001 3.4481070e-002 +v -4.4489440e-002 6.1077710e-002 3.9545320e-002 +v -3.8979900e-002 5.7996270e-002 4.0151390e-002 +v -7.9087730e-002 1.7044488e-001 -4.1373170e-002 +v -4.6247300e-003 5.7759650e-002 5.3990710e-002 +v -1.4985500e-003 5.5925480e-002 5.4630800e-002 +v 5.1981700e-003 5.7017990e-002 5.3423530e-002 +v 3.0920000e-005 1.2315746e-001 3.4749660e-002 +v 3.3568300e-002 1.1523716e-001 2.1798410e-002 +v 3.8686300e-002 5.6450590e-002 3.1188930e-002 +v -3.4385780e-002 5.4096000e-002 3.8060290e-002 +v -8.5308300e-003 6.0159420e-002 5.5308950e-002 +v -4.4024000e-004 5.8343410e-002 5.4483410e-002 +v -9.1078730e-002 1.1506037e-001 4.0141810e-002 +v 4.0775480e-002 5.4557490e-002 3.2014740e-002 +v 4.5636880e-002 5.7402620e-002 3.1992220e-002 +v 2.0358850e-002 1.2448747e-001 2.5906340e-002 +v -1.4169700e-002 1.2767892e-001 1.3080500e-003 +v -1.1987590e-002 5.7493210e-002 5.2752420e-002 +v 3.2514500e-003 5.9828640e-002 5.5464300e-002 +v -1.2395240e-002 1.2264726e-001 3.3588280e-002 +v 1.3813780e-002 1.2322188e-001 3.2502590e-002 +v -7.7004310e-002 1.5521281e-001 2.4534770e-002 +v -2.8001360e-002 6.1075420e-002 3.7471210e-002 +v -8.5480000e-004 6.0593520e-002 5.5824810e-002 +v -3.8050200e-002 1.1527068e-001 3.3178540e-002 +v -1.6231340e-002 1.2382942e-001 2.9576990e-002 +v -2.5373550e-002 1.5840012e-001 -1.4801300e-003 +v -6.7818590e-002 1.5454353e-001 3.0233720e-002 +v -4.3082600e-003 6.1418570e-002 5.5688490e-002 +v -3.1958900e-003 1.1912518e-001 3.8349580e-002 +v -6.4292400e-003 1.2201090e-001 3.5740890e-002 +v 4.2312960e-002 5.9099150e-002 3.0848420e-002 +v 4.8510010e-002 6.1780760e-002 3.0347250e-002 +v 5.0412290e-002 6.0312610e-002 3.0245060e-002 +v -3.9185590e-002 6.3074530e-002 4.1382890e-002 +v -3.4448660e-002 6.0780500e-002 3.9543990e-002 +v -1.4746030e-002 6.5583910e-002 5.3730860e-002 +v 2.6645200e-003 6.2700010e-002 5.6525210e-002 +v -1.3991610e-002 1.1962575e-001 3.6251540e-002 +v 1.9659170e-002 1.1236219e-001 3.7545270e-002 +v -3.2597160e-002 1.7498725e-001 -2.5953100e-003 +v -2.1513900e-003 9.9437380e-002 4.9849750e-002 +v -5.6001390e-002 6.1830670e-002 2.7931150e-002 +v -5.4707260e-002 6.3461570e-002 3.1670590e-002 +v -5.1307940e-002 6.0521660e-002 3.1434930e-002 +v -4.1979320e-002 6.9629980e-002 4.1824930e-002 +v -3.0272490e-002 6.2474660e-002 3.7982220e-002 +v -1.1387860e-002 6.4742460e-002 5.4918000e-002 +v 6.9544900e-003 6.4700130e-002 5.5599150e-002 +v 4.3015090e-002 9.7690960e-002 1.0258300e-003 +v 4.0635900e-002 6.1574860e-002 2.9841250e-002 +v 4.6183560e-002 6.1910110e-002 3.0223400e-002 +v 3.7552960e-002 1.0685291e-001 2.6303470e-002 +v -7.8640730e-002 1.6387238e-001 -2.8387790e-002 +v -6.1996240e-002 1.4761484e-001 -4.3256800e-003 +v -5.7499800e-003 6.5488980e-002 5.6173390e-002 +v 2.5369000e-004 6.5741170e-002 5.6569260e-002 +v -2.0542550e-002 1.1979518e-001 3.3003670e-002 +v 4.3155900e-003 1.2782561e-001 2.8646880e-002 +v -4.6549580e-002 6.7652130e-002 3.9635790e-002 +v -1.7420580e-002 6.9659490e-002 5.4089530e-002 +v -1.5242190e-002 7.0909900e-002 5.5004790e-002 +v -1.0282890e-002 6.8926360e-002 5.5289610e-002 +v -1.1289000e-004 6.9288200e-002 5.6579790e-002 +v -3.6309330e-002 1.1876943e-001 3.0674020e-002 +v -7.0325800e-002 6.3367770e-002 1.9809180e-002 +v 4.3023100e-002 6.3795810e-002 2.8039210e-002 +v 4.2831110e-002 8.5556040e-002 2.7873760e-002 +v 1.6981600e-002 1.2715003e-001 2.2931490e-002 +v -4.2121490e-002 1.2825104e-001 1.0751500e-003 +v 1.6329230e-002 1.2251895e-001 3.1375390e-002 +v -8.1264160e-002 1.5381172e-001 2.5897830e-002 +v -3.2257870e-002 8.8192600e-002 -2.5130960e-002 +v -1.3774950e-002 7.0887950e-002 5.4695630e-002 +v 5.2929600e-003 6.8006030e-002 5.5670490e-002 +v 7.6962500e-003 7.2375600e-002 5.6062150e-002 +v 3.4830600e-003 1.2002635e-001 3.6911950e-002 +v 6.6532500e-003 1.1673563e-001 3.8716340e-002 +v 4.6086570e-002 6.6473930e-002 2.6808990e-002 +v 5.2327290e-002 6.4327070e-002 2.8281890e-002 +v -6.1897630e-002 1.2297065e-001 -8.7725500e-003 +v -6.3934700e-003 1.0524472e-001 -2.2841900e-002 +v -3.5218330e-002 6.8559830e-002 4.1381470e-002 +v -3.2689880e-002 6.7729720e-002 4.0124390e-002 +v -2.9245440e-002 6.9551520e-002 3.9369010e-002 +v -5.0024500e-003 6.9655000e-002 5.6892510e-002 +v 1.6573960e-002 1.1890153e-001 3.5042300e-002 +v -8.9385100e-002 9.9024040e-002 1.7521830e-002 +v 4.5719230e-002 6.9489400e-002 2.3549340e-002 +v 5.4537210e-002 6.8796720e-002 2.4517690e-002 +v -4.4989450e-002 7.1577330e-002 4.1929250e-002 +v -4.2439400e-003 1.2914902e-001 2.5829230e-002 +v -7.3880090e-002 1.2091638e-001 5.3395800e-002 +v -7.4033870e-002 1.4406894e-001 4.4994970e-002 +v 5.0400010e-002 6.7292480e-002 2.6851470e-002 +v -5.4056890e-002 1.5671602e-001 -2.4865900e-003 +v 2.6148110e-002 1.2014725e-001 2.7308010e-002 +v -1.0736490e-002 1.2990285e-001 1.0993790e-002 +v -4.5078840e-002 8.7261130e-002 -2.1865520e-002 +v -3.8340900e-002 6.8843770e-002 4.1846470e-002 +v -2.9255580e-002 7.5169210e-002 4.1186430e-002 +v -4.7311210e-002 1.6296037e-001 6.0740300e-003 +v -1.1866030e-002 7.3183750e-002 5.6250050e-002 +v -6.3734600e-003 7.2184340e-002 5.7972980e-002 +v -2.9935300e-003 7.2186440e-002 5.8167190e-002 +v -2.5781060e-002 9.3778180e-002 -2.8388220e-002 +v -1.6692560e-002 1.1568553e-001 3.7853150e-002 +v -8.4123410e-002 1.0832050e-001 2.4730980e-002 +v -7.4294080e-002 1.6356850e-001 -1.5534220e-002 +v -9.4297150e-002 1.2617744e-001 1.9224650e-002 +v -3.5207090e-002 1.2505219e-001 2.1635690e-002 +v -4.9495940e-002 7.3436340e-002 4.1673570e-002 +v -3.3064160e-002 7.6654840e-002 4.1277900e-002 +v -7.3157300e-003 7.3919590e-002 5.7971690e-002 +v 2.1850000e-005 7.3496040e-002 5.7696650e-002 +v 4.1934400e-003 7.2915170e-002 5.6298730e-002 +v -7.7256080e-002 1.4565854e-001 4.3122930e-002 +v 4.1073260e-002 8.8724320e-002 -9.7879400e-003 +v 3.7418710e-002 1.0850822e-001 3.3973000e-004 +v -5.5111380e-002 7.4687840e-002 4.1939740e-002 +v -4.2740230e-002 7.6995340e-002 4.2804080e-002 +v -6.8531190e-002 1.5630045e-001 2.0997710e-002 +v -9.9440200e-003 7.6343100e-002 5.7388560e-002 +v -3.2479200e-003 7.5710690e-002 5.8714640e-002 +v 1.3414380e-002 9.3073740e-002 5.1467750e-002 +v -7.3504440e-002 9.3883340e-002 -1.4751720e-002 +v -7.4471830e-002 1.3507476e-001 5.0688900e-002 +v -2.5851310e-002 1.2182948e-001 2.6079670e-002 +v -3.4022940e-002 1.7597076e-001 -3.7271600e-003 +v -7.5405850e-002 1.6839072e-001 -2.6792980e-002 +v -3.6658410e-002 7.5087300e-002 4.2006940e-002 +v -1.7795480e-002 7.7486190e-002 5.6087240e-002 +v -1.1378660e-002 7.9877150e-002 5.7698880e-002 +v -1.0415000e-004 7.6881950e-002 5.8190740e-002 +v 2.7381400e-003 7.9105680e-002 5.6719190e-002 +v 5.5681200e-003 7.6397140e-002 5.6327220e-002 +v -6.1895860e-002 1.5424247e-001 -1.9018600e-002 +v -7.2646960e-002 1.4098943e-001 4.6976640e-002 +v 1.5799740e-002 1.2901416e-001 1.3236870e-002 +v -1.1703420e-002 9.7355720e-002 5.1592080e-002 +v -5.8922160e-002 7.7545490e-002 4.2961390e-002 +v -5.3121320e-002 7.7912430e-002 4.3334920e-002 +v -5.0745740e-002 7.6148400e-002 4.3137630e-002 +v -4.7401820e-002 7.5550340e-002 4.2630140e-002 +v -4.5055620e-002 7.8796280e-002 4.2341310e-002 +v -3.9517650e-002 7.8127780e-002 4.2918620e-002 +v -1.5245570e-002 8.2940770e-002 5.6934590e-002 +v -1.4557790e-002 7.6582160e-002 5.6493250e-002 +v -5.9406000e-003 7.9038240e-002 5.7969830e-002 +v 3.7176540e-002 1.1064404e-001 1.8811330e-002 +v 2.3929700e-003 1.3162713e-001 1.1955100e-002 +v -9.3644210e-002 1.1789378e-001 1.8662080e-002 +v -6.3939810e-002 7.8621830e-002 4.2083520e-002 +v -4.5376460e-002 8.2383550e-002 4.3282120e-002 +v -3.6505460e-002 8.1152260e-002 4.3162320e-002 +v -3.3244340e-002 8.2266590e-002 4.1852180e-002 +v -3.0800650e-002 8.0068420e-002 4.1798070e-002 +v -2.0578500e-003 8.0998290e-002 5.7553840e-002 +v 8.1848100e-003 8.0756170e-002 5.5374510e-002 +v -1.2953370e-002 1.1593580e-001 3.8920230e-002 +v -7.8081470e-002 1.2351940e-001 5.2136990e-002 +v -2.6580930e-002 1.5567694e-001 -4.1963400e-003 +v -8.2471600e-002 1.1624130e-001 -2.3236300e-003 +v -2.7538480e-002 7.9964780e-002 4.7697210e-002 +v 1.2556400e-003 8.3845570e-002 5.7446440e-002 +v 6.1508300e-003 8.3406240e-002 5.6463500e-002 +v -6.2433240e-002 8.4035270e-002 4.4203120e-002 +v -5.9867170e-002 8.0540510e-002 4.3277090e-002 +v -5.5238340e-002 8.1999450e-002 4.4984770e-002 +v -5.4000400e-002 8.0568410e-002 4.4601460e-002 +v -5.0027020e-002 8.1311330e-002 4.4264180e-002 +v -4.1996120e-002 8.1083670e-002 4.2456150e-002 +v -3.9357940e-002 8.3631380e-002 4.3502350e-002 +v -8.6161480e-002 1.0838594e-001 1.8244920e-002 +v -8.6723010e-002 9.9917250e-002 3.5537100e-003 +v -2.2413700e-002 8.3283520e-002 5.5590700e-002 +v -1.6993180e-002 8.2555820e-002 5.7523880e-002 +v -1.2406010e-002 8.5222570e-002 5.7267780e-002 +v -7.4442100e-003 1.1693417e-001 3.9283850e-002 +v -2.1452000e-003 1.1143287e-001 4.2436620e-002 +v -7.5718220e-002 1.2522734e-001 5.3087330e-002 +v -7.7056660e-002 1.3193469e-001 5.2462430e-002 +v -6.1121040e-002 1.5569660e-001 2.2517050e-002 +v -3.7538540e-002 1.2744127e-001 1.5320870e-002 +v -2.0516700e-003 1.0093469e-001 4.5625920e-002 +v -6.4992150e-002 8.4550900e-002 4.4120060e-002 +v -5.7861950e-002 8.3944360e-002 4.4186030e-002 +v -4.5681080e-002 8.4988010e-002 4.4159500e-002 +v -3.5022640e-002 8.2888160e-002 4.2912760e-002 +v -2.9982010e-002 8.5402300e-002 4.3745080e-002 +v -8.8892260e-002 9.9209100e-002 9.5703200e-003 +v -1.9135300e-002 8.3474800e-002 5.7217390e-002 +v -8.3489710e-002 1.0724729e-001 7.5790000e-004 +v -7.0112800e-002 1.1790350e-001 5.2714160e-002 +v -3.5526320e-002 1.7595563e-001 -4.8676200e-003 +v -7.0831390e-002 1.2254425e-001 5.3274880e-002 +v 4.5133810e-002 9.3630690e-002 6.2336800e-003 +v -5.3616700e-002 8.5346850e-002 4.5332470e-002 +v -4.9000840e-002 8.6221680e-002 4.5352040e-002 +v -3.6744880e-002 8.6083690e-002 4.3612890e-002 +v -1.0872600e-002 8.8826770e-002 5.6665490e-002 +v -3.8450200e-003 8.4787810e-002 5.7197980e-002 +v -4.9020070e-002 1.1771293e-001 3.1581430e-002 +v -4.2914400e-002 1.1835991e-001 3.0645040e-002 +v -5.7684530e-002 1.5561695e-001 1.2983110e-002 +v -2.5411730e-002 1.2472533e-001 1.2886000e-004 +v 1.9012230e-002 1.2736197e-001 1.7786580e-002 +v -5.9498600e-002 8.8845470e-002 4.5109290e-002 +v -5.6931050e-002 8.8101500e-002 4.4692930e-002 +v 3.5765600e-003 1.3138981e-001 7.2086000e-003 +v -1.6683350e-002 8.7266690e-002 5.6741190e-002 +v -8.4980800e-003 8.3990470e-002 5.7605220e-002 +v 3.5078200e-003 8.6339520e-002 5.7048320e-002 +v -2.8398700e-002 1.8070650e-001 -7.8469500e-003 +v -7.6565830e-002 1.1674037e-001 5.1489350e-002 +v 1.7869430e-002 9.0898610e-002 4.8712940e-002 +v -4.0342100e-002 1.1669551e-001 3.2460200e-002 +v 5.9105700e-003 1.3140929e-001 1.6823750e-002 +v -8.5777550e-002 9.1701370e-002 -4.6970000e-005 +v -5.0372230e-002 8.8844660e-002 4.5188000e-002 +v -4.4434130e-002 8.7654530e-002 4.3477620e-002 +v -4.2056390e-002 8.6711520e-002 4.2534630e-002 +v -3.3058460e-002 8.6185500e-002 4.2560350e-002 +v -2.9241910e-002 9.0453360e-002 4.4236610e-002 +v -6.8964100e-003 8.4432910e-002 5.7168580e-002 +v -6.6210600e-003 9.0415250e-002 5.6879750e-002 +v -1.2439100e-003 8.9093200e-002 5.6552120e-002 +v 9.4076000e-003 9.0328050e-002 5.4214140e-002 +v 4.0194810e-002 1.0231597e-001 -2.0048600e-003 +v -8.6227130e-002 1.1466841e-001 2.2102000e-003 +v -8.9495490e-002 9.5632430e-002 1.4234810e-002 +v -6.7132160e-002 1.5709447e-001 -6.2032000e-003 +v -5.2935640e-002 9.0913520e-002 4.4568870e-002 +v -3.6744910e-002 8.8886950e-002 4.3312050e-002 +v -1.3626110e-002 8.9787930e-002 5.6674380e-002 +v 2.3337130e-002 1.2353449e-001 2.4874140e-002 +v -3.7053790e-002 1.2715094e-001 3.5474000e-004 +v -7.3696690e-002 1.5613015e-001 1.4359790e-002 +v -6.5592380e-002 9.1042400e-002 4.4092080e-002 +v -5.8997380e-002 9.2030670e-002 4.5335270e-002 +v -3.3238910e-002 8.8573580e-002 4.3697040e-002 +v -3.1834990e-002 9.0722970e-002 4.4173460e-002 +v -2.0022170e-002 8.8032110e-002 5.5589350e-002 +v -1.1213830e-002 9.2366370e-002 5.6105260e-002 +v 3.9108440e-002 1.0829072e-001 1.3142330e-002 +v 2.8675700e-002 1.1959600e-001 2.4545910e-002 +v -6.8940210e-002 1.5652777e-001 -1.9716000e-003 +v -6.2615110e-002 9.1126880e-002 4.5090730e-002 +v 3.0444560e-002 1.1886441e-001 2.0821750e-002 +v -1.5241090e-002 9.1821720e-002 5.5817230e-002 +v -5.6221700e-003 9.3235010e-002 5.5893630e-002 +v 4.7989900e-003 9.1654840e-002 5.4715170e-002 +v -6.8282400e-002 9.2376840e-002 4.2388730e-002 +v -5.5623730e-002 9.2187420e-002 4.5054970e-002 +v -5.1901030e-002 9.5457620e-002 4.3937650e-002 +v -4.8809030e-002 9.1083890e-002 4.4456690e-002 +v -4.5411560e-002 9.1002130e-002 4.3252770e-002 +v -4.4514550e-002 9.4860420e-002 4.2972490e-002 +v -3.9430320e-002 8.9597620e-002 4.3177890e-002 +v -3.5642240e-002 9.2617410e-002 4.4238490e-002 +v -1.2246000e-004 9.3201160e-002 5.5398380e-002 +v 9.5104600e-003 9.5483870e-002 5.0910600e-002 +v 2.1441660e-002 9.1354960e-002 4.8043360e-002 +v -8.9830300e-003 1.6926449e-001 -2.2683480e-002 +v -7.3019050e-002 1.5602104e-001 2.2419340e-002 +v -6.4760430e-002 1.5311588e-001 -2.0371200e-003 +v -6.9368510e-002 9.5242790e-002 4.2129000e-002 +v -6.0117140e-002 9.5552910e-002 4.4183820e-002 +v -2.9241690e-002 9.4290440e-002 4.4821190e-002 +v -2.6561430e-002 9.3289510e-002 4.4975420e-002 +v -1.4394030e-002 9.4587640e-002 5.3993500e-002 +v -8.8691600e-003 9.5400260e-002 5.4445980e-002 +v -1.2188700e-003 9.6201750e-002 5.3815910e-002 +v 4.0479000e-003 9.5817360e-002 5.2936770e-002 +v -4.6019400e-003 1.2428544e-001 3.3471960e-002 +v -7.8436460e-002 1.3928013e-001 4.8329360e-002 +v 1.0774610e-002 1.3079162e-001 1.4341740e-002 +v -5.6623730e-002 9.6322170e-002 4.3667910e-002 +v -3.6298870e-002 9.5695620e-002 4.3580310e-002 +v -2.4379930e-002 9.5866450e-002 4.4434530e-002 +v 1.0915500e-002 1.2633629e-001 2.9857020e-002 +v -5.8622700e-003 9.7350210e-002 5.2743650e-002 +v 1.6973450e-002 9.7106620e-002 4.7440920e-002 +v -6.7231980e-002 9.9173950e-002 4.1593880e-002 +v -5.4994210e-002 9.9640820e-002 4.2955230e-002 +v -4.8617990e-002 9.6452700e-002 4.4183060e-002 +v -5.5369000e-002 1.5442476e-001 1.6160650e-002 +v -9.4243550e-002 1.2207432e-001 2.3568470e-002 +v 1.3242990e-002 9.6738240e-002 4.8750160e-002 +v 2.0639290e-002 9.6602480e-002 4.6971000e-002 +v 7.3429700e-003 1.2098188e-001 3.5973430e-002 +v -1.3493870e-002 1.2882438e-001 5.9690700e-003 +v -2.0110640e-002 1.2504545e-001 2.3588310e-002 +v -6.9438450e-002 1.6479930e-001 -1.7218700e-002 +v -6.4028050e-002 9.7838670e-002 4.2565330e-002 +v -5.1996350e-002 9.9707850e-002 4.2716590e-002 +v -4.3990880e-002 9.9425460e-002 4.2383430e-002 +v -3.9738250e-002 1.0215357e-001 4.0574410e-002 +v -3.5931490e-002 9.9809950e-002 4.2335800e-002 +v -3.0867600e-002 9.6914680e-002 4.4651400e-002 +v -2.8342070e-002 9.7782680e-002 4.3761280e-002 +v -2.5622580e-002 9.8713420e-002 4.4210890e-002 +v -8.5236620e-002 1.1077356e-001 2.4537670e-002 +v 7.1936000e-003 9.8859470e-002 4.8419510e-002 +v 9.6509200e-003 1.0108782e-001 4.7373080e-002 +v 1.3487100e-002 1.0076420e-001 4.7454290e-002 +v 7.7389800e-003 1.3147500e-001 1.1682970e-002 +v 8.0905000e-004 1.1633319e-001 4.0167560e-002 +v -7.2652570e-002 1.6567918e-001 -1.8212480e-002 +v -5.6009400e-003 1.3076674e-001 1.0516060e-002 +v -2.6303720e-002 1.2518875e-001 1.7392980e-002 +v -4.7590430e-002 1.0081180e-001 4.2349150e-002 +v -4.1460830e-002 9.8544800e-002 4.1778620e-002 +v -3.3582070e-002 1.0383908e-001 4.0737990e-002 +v -2.2870240e-002 1.0284737e-001 4.3544750e-002 +v -2.2361970e-002 9.8207610e-002 4.4765940e-002 +v -1.8870510e-002 9.8973200e-002 4.4489280e-002 +v -7.1433690e-002 7.7573520e-002 3.8060760e-002 +v -7.3001150e-002 1.1826712e-001 5.3034590e-002 +v -6.8466430e-002 1.3498146e-001 -8.3359800e-003 +v -7.4683810e-002 1.0786100e-001 -9.0477100e-003 +v -6.4958960e-002 1.5852021e-001 -1.2595320e-002 +v -7.8931700e-002 1.5093057e-001 3.5151900e-002 +v -7.4113550e-002 9.9442520e-002 3.8337710e-002 +v -7.0456930e-002 1.0098777e-001 3.9794060e-002 +v -5.9058760e-002 1.0041260e-001 4.2725130e-002 +v -4.9187330e-002 1.0452012e-001 4.0301390e-002 +v -2.9151180e-002 1.0197369e-001 4.2633060e-002 +v -1.1599720e-002 1.0107813e-001 4.4191660e-002 +v 5.1450400e-003 1.0163906e-001 4.5423010e-002 +v -5.1495700e-002 1.0496738e-001 4.0347210e-002 +v -2.0218210e-002 1.0214391e-001 4.3701160e-002 +v 4.2515900e-003 1.0523743e-001 4.2563550e-002 +v 1.6832800e-002 1.0337487e-001 4.5287270e-002 +v -2.5661080e-002 1.2562669e-001 4.5537500e-003 +v -7.2141950e-002 1.0536685e-001 3.7523210e-002 +v -6.4984570e-002 1.0371550e-001 4.0647810e-002 +v -6.0652480e-002 1.0467197e-001 4.0906390e-002 +v -5.5308980e-002 1.0365394e-001 4.1516690e-002 +v -4.4243240e-002 1.0431726e-001 4.1339990e-002 +v -1.5513340e-002 1.0436131e-001 4.2919420e-002 +v -7.6323200e-003 1.0304531e-001 4.3710640e-002 +v -7.8046900e-003 1.0516619e-001 4.3825460e-002 +v 9.7163200e-003 1.0523506e-001 4.3603830e-002 +v 3.0300390e-002 1.1553645e-001 2.8685010e-002 +v -4.7496910e-002 1.0635662e-001 4.0165640e-002 +v -3.8978950e-002 1.0683037e-001 3.8247660e-002 +v -2.5869310e-002 1.0426705e-001 4.2207540e-002 +v -1.8057930e-002 1.0503919e-001 4.2802830e-002 +v -1.5180030e-002 1.0807750e-001 4.2350430e-002 +v -3.8981500e-003 1.0566175e-001 4.4047190e-002 +v 2.6820000e-005 1.0446731e-001 4.3775910e-002 +v 1.1978350e-002 1.0403629e-001 4.5396310e-002 +v 1.5004970e-002 1.0726898e-001 4.1811990e-002 +v 2.6488060e-002 1.2230287e-001 2.0398110e-002 +v -3.6225630e-002 1.0634244e-001 3.8644860e-002 +v -2.1126780e-002 1.0932290e-001 4.0715320e-002 +v -1.2819810e-002 1.0457100e-001 4.3465690e-002 +v 5.2847900e-003 1.0943666e-001 4.1674980e-002 +v 8.9403700e-003 1.0710645e-001 4.1243400e-002 +v -5.1839670e-002 1.6062039e-001 7.1421300e-003 +v -5.4201370e-002 1.1451730e-001 3.4843990e-002 +v 1.3226250e-002 1.2958070e-001 1.9689610e-002 +v -6.9382410e-002 1.0865787e-001 3.7507800e-002 +v -6.7691040e-002 1.0734145e-001 3.8018440e-002 +v -6.3782400e-002 1.1037270e-001 3.7579790e-002 +v -5.0749390e-002 1.0928682e-001 3.8297580e-002 +v -9.3936200e-003 1.0742813e-001 4.3454570e-002 +v 1.1760100e-003 1.0932531e-001 4.2662800e-002 +v 9.8020300e-003 1.1003994e-001 3.9945400e-002 +v 2.0131290e-002 1.0732778e-001 4.0323840e-002 +v -2.7872800e-003 1.0577531e-001 -2.2459030e-002 +v -5.4996890e-002 1.0774199e-001 3.9424590e-002 +v -4.5966740e-002 1.0905146e-001 3.8754110e-002 +v -4.2324540e-002 1.0737278e-001 3.9456440e-002 +v -3.2161240e-002 1.0896504e-001 3.8102720e-002 +v -3.0770180e-002 1.1597313e-001 3.2858800e-002 +v -1.1608610e-002 1.0983707e-001 4.2475330e-002 +v -2.9428320e-002 9.3166620e-002 -2.4931860e-002 +v -8.0043570e-002 9.2080160e-002 -9.4198200e-003 +v -4.9797430e-002 1.1342104e-001 3.5117920e-002 +v -4.3723850e-002 1.6191369e-001 5.7713400e-003 +v -5.7981740e-002 1.0943152e-001 3.7997640e-002 +v -4.1491180e-002 1.1224766e-001 3.5873450e-002 +v -2.4929830e-002 1.1592775e-001 3.4094730e-002 +v -2.0881690e-002 1.1409528e-001 3.7872990e-002 +v -7.5519700e-003 1.1183813e-001 4.2039690e-002 +v 3.7667200e-003 1.1240547e-001 4.1494710e-002 +v -6.2829620e-002 1.5189480e-001 -9.2373400e-003 +v -5.9195950e-002 1.1320797e-001 3.6234680e-002 +v -5.1079080e-002 9.3892810e-002 -2.1761690e-002 +v -7.3945370e-002 8.4374880e-002 -1.5154490e-002 +v -7.2146240e-002 1.3486431e-001 -7.7592200e-003 +v -1.9408870e-002 1.7041104e-001 -2.0994830e-002 +v -5.5530450e-002 1.4905531e-001 -1.9602100e-003 +v 1.6688460e-002 3.6976600e-002 4.3000600e-002 +v -5.2277330e-002 1.1775075e-001 3.3769460e-002 +v -6.9201380e-002 9.3039200e-002 -1.6486120e-002 +v 2.6579210e-002 1.1702438e-001 3.0867940e-002 +v -2.3574310e-002 3.7036910e-002 5.4144750e-002 +v -7.3775100e-003 3.8988430e-002 4.8929450e-002 +v 1.3234660e-002 3.8453060e-002 4.4501470e-002 +v 1.9487350e-002 4.0809290e-002 4.2641060e-002 +v -6.3953930e-002 1.4694729e-001 3.8484200e-002 +v -4.9579470e-002 3.6096540e-002 4.5955360e-002 +v -4.3323650e-002 3.6286400e-002 4.4042360e-002 +v -2.9047200e-002 1.2556338e-001 7.7617700e-003 +v -1.7343100e-003 3.9476800e-002 4.7262900e-002 +v -3.1358130e-002 1.5362199e-001 -4.6738900e-003 +v 2.5822000e-003 1.0747582e-001 -2.0606030e-002 +v -5.6802300e-002 1.4514674e-001 3.1740300e-002 +v -5.6464330e-002 3.7683110e-002 4.6819640e-002 +v -5.0964750e-002 3.8312290e-002 4.6286140e-002 +v -5.0980410e-002 1.3486613e-001 2.7585000e-002 +v -2.5647410e-002 3.8860730e-002 5.4161390e-002 +v -2.2542110e-002 4.0615780e-002 5.3986030e-002 +v -1.7618010e-002 3.8911170e-002 5.2403440e-002 +v -1.9711750e-002 1.6829145e-001 -1.3020960e-002 +v 2.3780070e-002 9.5222940e-002 4.6347330e-002 +v 1.4744290e-002 4.2716950e-002 4.4510310e-002 +v 2.1691360e-002 4.0161530e-002 4.0846450e-002 +v -6.4067240e-002 9.0172190e-002 -1.8855520e-002 +v 2.0319150e-002 1.0041961e-001 4.5760520e-002 +v -3.6425000e-002 9.3630690e-002 -2.3534630e-002 +v -1.4981170e-002 4.2571420e-002 5.1404530e-002 +v -5.7335340e-002 1.2340101e-001 4.0231470e-002 +v -5.4172560e-002 1.2337919e-001 3.7576440e-002 +v 2.2625210e-002 4.3621680e-002 4.0904580e-002 +v 2.8810520e-002 4.3352290e-002 3.2157720e-002 +v -4.2764160e-002 1.5727487e-001 5.2016200e-003 +v 9.2231900e-003 4.4125090e-002 4.5057440e-002 +v 1.5048210e-002 4.5755840e-002 4.3793870e-002 +v -6.3757290e-002 1.0251144e-001 -1.7484400e-002 +v -3.4070430e-002 1.6148975e-001 -1.3786960e-002 +v -8.2191500e-002 7.5610200e-002 1.6542620e-002 +v -6.6299420e-002 1.2337119e-001 5.0615920e-002 +v -1.5510100e-002 4.5283110e-002 5.0653040e-002 +v 1.8928020e-002 4.4249610e-002 4.3009830e-002 +v 2.5821800e-002 4.6326610e-002 3.8277230e-002 +v 2.7268700e-002 4.4547790e-002 3.6152520e-002 +v -4.5301340e-002 1.5695057e-001 7.2036900e-003 +v 2.3855760e-002 1.0616625e-001 3.9378080e-002 +v 2.1632670e-002 4.8127270e-002 4.0694430e-002 +v 4.3785360e-002 4.8803700e-002 3.1343420e-002 +v 4.8074790e-002 4.8969960e-002 2.8165490e-002 +v 5.2663090e-002 4.7673620e-002 2.1201270e-002 +v -5.2722450e-002 4.4722850e-002 4.4143250e-002 +v -3.0071610e-002 1.7258324e-001 -6.3597700e-003 +v -3.4508050e-002 1.5447469e-001 1.6504600e-003 +v 1.0629710e-002 4.6711810e-002 4.6472020e-002 +v 1.6743440e-002 4.8439000e-002 4.3678630e-002 +v 2.8827050e-002 9.2133370e-002 4.3920090e-002 +v -5.9937100e-002 1.2726188e-001 4.0771270e-002 +v -3.6752090e-002 1.5802075e-001 4.1862000e-003 +v -3.7885390e-002 1.6199719e-001 2.4686000e-004 +v -2.2047790e-002 1.8348586e-001 -1.2094990e-002 +v -2.4364620e-002 1.8096836e-001 -9.8312000e-003 +v -4.4882280e-002 1.5052959e-001 7.6451700e-003 +v 2.6996760e-002 5.1317780e-002 3.8752040e-002 +v 4.7735750e-002 5.2751040e-002 3.0797290e-002 +v 5.1703790e-002 4.8857380e-002 2.4147970e-002 +v -6.7504360e-002 1.1424088e-001 4.8036050e-002 +v -1.6257520e-002 1.6031250e-001 -9.6926000e-003 +v -6.3926300e-002 1.6792441e-001 -4.0730420e-002 +v -4.1665290e-002 1.4996141e-001 4.5405000e-003 +v -3.5203230e-002 1.6493551e-001 -2.6810000e-003 +v 4.1318770e-002 9.9496740e-002 2.4275750e-002 +v 1.4055220e-002 5.2523910e-002 4.8593880e-002 +v 1.9421220e-002 5.1321300e-002 4.4798910e-002 +v 2.3677990e-002 5.1474390e-002 4.1053270e-002 +v 3.4258130e-002 5.1930810e-002 3.2757880e-002 +v 5.5957340e-002 5.3147410e-002 2.3197720e-002 +v -3.9937960e-002 1.4922850e-001 1.6017200e-003 +v -4.6988800e-002 1.2600802e-001 2.6985500e-002 +v -2.7708370e-002 9.0081290e-002 -3.1911460e-002 +v 1.9204630e-002 5.5166510e-002 4.7722150e-002 +v 2.1886000e-002 5.3927560e-002 4.5102460e-002 +v 3.1286270e-002 5.2863840e-002 3.6913620e-002 +v 4.6661160e-002 5.4719230e-002 3.1976810e-002 +v 5.1823730e-002 5.3276700e-002 2.7927010e-002 +v -2.9264880e-002 1.6140418e-001 -2.1039500e-003 +v -6.8700770e-002 1.4463537e-001 4.3041630e-002 +v -5.6070060e-002 1.5000706e-001 2.9867640e-002 +v 4.4717850e-002 9.4802660e-002 1.2024710e-002 +v -4.1804090e-002 1.5582081e-001 6.4548200e-003 +v -6.8369340e-002 1.2289287e-001 5.2437860e-002 +v -6.4114810e-002 9.5509880e-002 -1.8114610e-002 +v -1.8383130e-002 1.8543664e-001 -1.7136370e-002 +v 1.1745400e-002 5.6678340e-002 5.1914060e-002 +v -5.9375360e-002 1.1998238e-001 4.0548240e-002 +v 5.9092080e-002 5.7956980e-002 2.0270120e-002 +v 4.3547740e-002 9.7389400e-002 1.7314650e-002 +v -2.6291780e-002 1.5963381e-001 -5.1845000e-004 +v 1.4904780e-002 5.6350380e-002 4.9522780e-002 +v 2.4286200e-002 5.4958580e-002 4.3086850e-002 +v 2.8952610e-002 5.6125250e-002 4.0388970e-002 +v -4.9507770e-002 1.2949500e-001 3.0259270e-002 +v 4.0824790e-002 9.5170220e-002 2.8657920e-002 +v 1.7774800e-002 5.8243780e-002 4.8864720e-002 +v 3.3573840e-002 5.8515260e-002 3.8310990e-002 +v 3.6385040e-002 5.6996480e-002 3.3601460e-002 +v -6.4205010e-002 1.2243894e-001 4.8008340e-002 +v -6.5424500e-002 1.4011279e-001 4.1308960e-002 +v 5.0801340e-002 5.7308080e-002 3.0001390e-002 +v 5.6671750e-002 5.6970820e-002 2.4291920e-002 +v -4.9349930e-002 1.4913519e-001 1.1274060e-002 +v -6.9760570e-002 1.3442855e-001 4.8265220e-002 +v 1.9537060e-002 6.0003780e-002 4.8576140e-002 +v 2.7013910e-002 5.9952790e-002 4.3454420e-002 +v 5.7679430e-002 6.1392970e-002 2.4201790e-002 +v -5.6916540e-002 1.2623512e-001 3.9426610e-002 +v 2.3469280e-002 1.1656262e-001 3.3537270e-002 +v -5.8298640e-002 1.3885500e-001 3.2937460e-002 +v 6.4598400e-003 6.0297430e-002 5.4780030e-002 +v 1.0406020e-002 5.9162400e-002 5.2484370e-002 +v 2.3183950e-002 5.8654360e-002 4.5871060e-002 +v 3.3040360e-002 6.1773840e-002 3.9781440e-002 +v -6.4348220e-002 1.2628088e-001 4.6650200e-002 +v -5.7031440e-002 1.1562007e-001 3.6494880e-002 +v 5.4451560e-002 5.8342890e-002 2.7653010e-002 +v -3.0134400e-002 1.7011322e-001 -7.3591600e-003 +v -3.7077100e-002 1.5986369e-001 1.6096500e-003 +v -5.6032760e-002 1.3731083e-001 3.1970590e-002 +v -6.7676470e-002 1.4150325e-001 4.3868140e-002 +v 9.9911700e-003 6.2735270e-002 5.4009240e-002 +v 1.4521510e-002 6.1382890e-002 5.0500900e-002 +v 3.0051740e-002 6.2169610e-002 4.1545810e-002 +v 3.7519170e-002 6.1062710e-002 3.4366020e-002 +v 5.3944010e-002 6.1391550e-002 2.8268530e-002 +v 5.9119900e-002 6.3128810e-002 2.1561830e-002 +v -2.4366390e-002 1.7693266e-001 -1.1719630e-002 +v -1.3253420e-002 1.6627152e-001 -1.4120370e-002 +v 3.9218740e-002 1.0669250e-001 2.0450190e-002 +v -1.7968980e-002 1.8078031e-001 -1.8103430e-002 +v 2.1902390e-002 6.0875970e-002 4.7282360e-002 +v 3.5341750e-002 6.1630030e-002 3.7606020e-002 +v -6.2145620e-002 1.3599775e-001 3.6700970e-002 +v 5.6820620e-002 6.3691150e-002 2.5286090e-002 +v -3.2800040e-002 1.5948699e-001 2.1962800e-003 +v 1.1212140e-002 6.6584120e-002 5.3982180e-002 +v 1.2919590e-002 6.4203580e-002 5.2441150e-002 +v 2.0126950e-002 6.3851330e-002 4.7919660e-002 +v 3.5971760e-002 6.6669610e-002 3.7781400e-002 +v 3.9906940e-002 6.4361260e-002 3.1686660e-002 +v -6.6702350e-002 1.3210600e-001 4.5480940e-002 +v -4.1601430e-002 1.5978000e-001 3.5374700e-003 +v 3.3044580e-002 1.0766252e-001 3.1916150e-002 +v 2.4672100e-002 6.3694500e-002 4.5204640e-002 +v 2.6108660e-002 6.8007640e-002 4.3902690e-002 +v 3.3363940e-002 6.7054760e-002 3.9729480e-002 +v 4.2915790e-002 6.6707700e-002 2.6994720e-002 +v 5.4714960e-002 6.4697160e-002 2.6979680e-002 +v -1.6530940e-002 1.6325000e-001 -9.2475200e-003 +v -1.7891600e-002 1.6113800e-001 -6.7072700e-003 +v 4.1118120e-002 9.7491260e-002 -3.9756700e-003 +v 2.3386770e-002 7.0075990e-002 4.7012620e-002 +v 3.8102900e-002 6.5678440e-002 3.5132520e-002 +v 1.0145240e-002 1.2221678e-001 3.4718950e-002 +v 5.8392410e-002 6.6741240e-002 2.1979460e-002 +v 3.8302050e-002 8.4549140e-002 -1.4478830e-002 +v 3.4126440e-002 9.7053980e-002 3.7590390e-002 +v -3.1355740e-002 1.5809888e-001 1.9128800e-003 +v -5.8259510e-002 1.4099493e-001 3.2440640e-002 +v -6.6817230e-002 1.1951525e-001 5.1490220e-002 +v -6.8090040e-002 1.1647050e-001 5.1151230e-002 +v 1.6568300e-002 6.6269890e-002 5.1009890e-002 +v 2.9362870e-002 6.6509780e-002 4.2289380e-002 +v 3.7027180e-002 9.3949630e-002 -1.1674040e-002 +v 5.6412730e-002 6.7659930e-002 2.3969320e-002 +v -6.1295740e-002 1.4519988e-001 3.7137830e-002 +v 8.3873000e-003 1.1336223e-001 3.9792610e-002 +v 1.1807030e-002 7.0920980e-002 5.4240490e-002 +v 2.9741730e-002 7.0647100e-002 4.1653890e-002 +v 3.6294410e-002 7.1220700e-002 3.7114610e-002 +v 3.9899680e-002 7.0294820e-002 3.2720020e-002 +v -6.2763130e-002 1.3778012e-001 3.6678590e-002 +v -1.5815440e-002 1.7504938e-001 -1.8654160e-002 +v -9.2268990e-002 1.1475156e-001 1.7017380e-002 +v -9.4964000e-004 1.0141111e-001 4.4290070e-002 +v -6.3712920e-002 1.1274250e-001 3.8006760e-002 +v -6.1096020e-002 1.1701650e-001 3.9654020e-002 +v 2.0991870e-002 6.9335450e-002 4.9003540e-002 +v 2.5658530e-002 7.0550460e-002 4.4539930e-002 +v 3.2978560e-002 7.3500690e-002 4.0486510e-002 +v 4.2156130e-002 6.9717580e-002 2.8318230e-002 +v -5.5516860e-002 1.2956070e-001 3.6598450e-002 +v -4.0802290e-002 1.6436059e-001 3.7448800e-003 +v -6.2546500e-003 1.0121650e-001 4.4322030e-002 +v -1.0986820e-002 1.6621199e-001 -1.6047550e-002 +v -3.0351420e-002 1.6448158e-001 -5.3291400e-003 +v 2.6110920e-002 1.0088990e-001 4.1733260e-002 +v -6.5599940e-002 1.1329504e-001 4.2318710e-002 +v 2.8814660e-002 9.6712680e-002 4.2257700e-002 +v 1.5263280e-002 7.1571940e-002 5.2717390e-002 +v 2.8982400e-002 7.4088480e-002 4.3447240e-002 +v 4.4872540e-002 7.5516710e-002 2.3155250e-002 +v -7.8225230e-002 1.4962481e-001 -2.5019400e-003 +v -4.6094940e-002 1.5296850e-001 9.0029700e-003 +v -5.2369030e-002 1.4682913e-001 1.8934650e-002 +v -2.1592100e-002 1.5763440e-001 -6.8623600e-003 +v 1.7176770e-002 7.3066230e-002 5.1826600e-002 +v 2.2687500e-002 7.5149180e-002 4.9312500e-002 +v 3.5472040e-002 7.3076670e-002 3.8482270e-002 +v -8.9480840e-002 1.3839976e-001 2.5061450e-002 +v -5.3216730e-002 1.3221978e-001 3.2978380e-002 +v -3.7776780e-002 1.5551947e-001 4.3700800e-003 +v -9.0549380e-002 1.3511875e-001 2.1680550e-002 +v -6.3366580e-002 1.3037076e-001 4.1669940e-002 +v 1.4074270e-002 7.6651720e-002 5.4221350e-002 +v 1.8109790e-002 7.5806590e-002 5.2488260e-002 +v 4.2209940e-002 7.8861480e-002 2.9187200e-002 +v -5.2115930e-002 1.4179906e-001 2.0510310e-002 +v 2.9063090e-002 1.1149602e-001 3.3805790e-002 +v -5.4731460e-002 1.4267229e-001 2.8980480e-002 +v 2.5903640e-002 7.5536040e-002 4.6416650e-002 +v 3.1298760e-002 7.5907440e-002 4.2699060e-002 +v 3.8446170e-002 7.5649430e-002 3.5050640e-002 +v 4.6351670e-002 7.4079520e-002 1.8354320e-002 +v -4.7656560e-002 1.3077525e-001 2.5523570e-002 +v -1.1447430e-002 1.7131059e-001 -1.9602980e-002 +v -3.6647240e-002 1.6640131e-001 -2.8167000e-004 +v -4.6653530e-002 1.5917824e-001 7.8019000e-003 +v -4.5569890e-002 1.4663612e-001 5.6514200e-003 +v 4.1438880e-002 9.2365100e-002 -7.4587000e-003 +v -6.4287420e-002 1.3463625e-001 3.9945640e-002 +v -6.1128890e-002 1.3178328e-001 3.8915910e-002 +v -4.7843540e-002 1.2215063e-001 2.8833160e-002 +v -4.9536830e-002 1.2491344e-001 3.1778440e-002 +v -7.1135380e-002 1.3817656e-001 4.7853960e-002 +v 1.0113870e-002 7.6468110e-002 5.5256790e-002 +v 1.7897450e-002 7.9516550e-002 5.2759530e-002 +v 2.1740850e-002 8.0250650e-002 5.0425390e-002 +v 2.5271590e-002 7.8724920e-002 4.8026570e-002 +v 3.0885040e-002 7.8999480e-002 4.3388770e-002 +v -6.2441930e-002 1.4084781e-001 3.6965840e-002 +v -6.2165060e-002 1.5666850e-001 -1.7837760e-002 +v 2.0657260e-002 1.0416830e-001 4.3004680e-002 +v -6.3602800e-002 1.1571453e-001 4.2572290e-002 +v 1.4424020e-002 8.0085500e-002 5.3755600e-002 +v 2.8779340e-002 8.2553250e-002 4.4527350e-002 +v 4.4450130e-002 8.1846900e-002 2.4552920e-002 +v 4.5541990e-002 8.3338380e-002 1.9700850e-002 +v -4.9665810e-002 1.2063801e-001 3.2163270e-002 +v -2.9177290e-002 1.7619959e-001 -5.6241100e-003 +v -5.8203130e-002 1.3270975e-001 3.6918680e-002 +v 3.8997050e-002 9.7088220e-002 -7.7799300e-003 +v -5.4725800e-002 1.2071262e-001 3.7451450e-002 +v 1.3189120e-002 8.4211180e-002 5.3065830e-002 +v -1.9926300e-002 1.6489742e-001 -9.9900200e-003 +v 2.0153130e-002 1.1849719e-001 3.4271250e-002 +v -5.5859940e-002 1.1774313e-001 3.7253480e-002 +v 1.8045260e-002 8.3623160e-002 5.1285840e-002 +v -6.3757130e-002 1.5912175e-001 -5.0155730e-002 +v -1.8527620e-002 1.7653197e-001 -1.7043540e-002 +v 2.8734400e-002 1.0360053e-001 3.8035240e-002 +v 4.1414010e-002 1.0284216e-001 1.6578920e-002 +v 2.4411730e-002 9.8016880e-002 4.4687400e-002 +v 2.0925180e-002 8.6311430e-002 4.9433120e-002 +v 3.0445010e-002 8.4959560e-002 4.3011090e-002 +v 3.3030090e-002 8.3781640e-002 4.1636930e-002 +v 3.6975090e-002 7.9876480e-002 3.7198390e-002 +v -7.7721460e-002 1.1355888e-001 4.8155990e-002 +v 2.9250000e-002 1.0651935e-001 3.6590330e-002 +v -5.3078180e-002 1.3754688e-001 2.8266470e-002 +v -6.2990590e-002 1.1999459e-001 4.5235530e-002 +v -6.5398320e-002 1.1751956e-001 4.8735570e-002 +v 3.3373910e-002 1.1227890e-001 2.7788130e-002 +v 3.8413590e-002 8.7489930e-002 3.5185850e-002 +v -6.1945930e-002 1.6479234e-001 -5.6647670e-002 +v -2.2876480e-002 1.7392813e-001 -1.3431140e-002 +v 4.3766230e-002 8.8390020e-002 -3.5708800e-003 +v 3.9291530e-002 1.0125969e-001 2.7550520e-002 +v 1.0936230e-002 8.6027290e-002 5.4732670e-002 +v 2.4108720e-002 8.4492600e-002 4.8292310e-002 +v 3.6758390e-002 9.9195470e-002 3.2837670e-002 +v -5.1941640e-002 1.2565987e-001 3.4587860e-002 +v -3.1582110e-002 1.6641850e-001 -5.7320000e-003 +v 7.6405900e-003 8.6427230e-002 5.6117850e-002 +v 1.6771020e-002 8.8644690e-002 5.0522960e-002 +v 3.4404610e-002 8.6932850e-002 4.0574270e-002 +v 3.6143820e-002 8.4439200e-002 3.7936930e-002 +v 4.1258830e-002 1.0361081e-001 2.6760600e-003 +v 2.4766140e-002 1.1081111e-001 3.6728360e-002 +v -2.2601590e-002 1.6250449e-001 -6.0717000e-003 +v -1.2893670e-002 1.7879041e-001 -2.2624750e-002 +v -2.4939150e-002 1.7031135e-001 -1.1329700e-002 +v -4.8468630e-002 1.4559606e-001 8.3661500e-003 +v 1.2534490e-002 8.9593930e-002 5.3394630e-002 +v 2.5872860e-002 8.8482290e-002 4.6655260e-002 +v 3.2756470e-002 8.8969130e-002 4.2215450e-002 +v -2.3343620e-002 1.6103450e-001 -3.1862400e-003 +v -9.2594970e-002 1.1943826e-001 2.6802950e-002 +v -7.4314840e-002 1.3761738e-001 -6.6698800e-003 +v -9.2499230e-002 1.2131500e-001 2.9256200e-002 +v -7.7378260e-002 1.5764266e-001 -1.4133650e-002 +v -9.2907340e-002 1.2307021e-001 3.6523230e-002 +v 2.8423340e-002 8.8011080e-002 4.4234200e-002 +v 3.5251680e-002 9.0836820e-002 3.9183920e-002 +v 1.5760560e-002 9.3203560e-002 4.9939310e-002 +v 3.8785530e-002 9.4954300e-002 3.2520220e-002 +v -6.1511220e-002 1.2373565e-001 4.3062680e-002 +v -6.8145120e-002 1.2748676e-001 5.0148970e-002 +v -2.0616710e-002 1.8237588e-001 -1.4299100e-002 +v 1.5137190e-002 1.1571495e-001 3.7031980e-002 +v -5.0718270e-002 1.5276300e-001 1.1816680e-002 +v 3.0168690e-002 1.0048686e-001 3.9404710e-002 +v -8.7426500e-002 9.5469530e-002 4.0312400e-003 +v -6.0010390e-002 1.4284463e-001 3.5449690e-002 +v -5.8603310e-002 1.4637237e-001 3.3808800e-002 +v 3.2411650e-002 9.3736150e-002 4.0890240e-002 +v -7.5917780e-002 1.4997690e-001 -1.6842050e-002 +v 1.8596570e-002 3.5293940e-002 -8.6782200e-003 +v 1.7209800e-002 3.5259400e-002 -1.4685160e-002 +v 4.4326540e-002 9.0818120e-002 2.2097520e-002 +v 3.8335910e-002 3.8830830e-002 3.0938100e-003 +v 2.2192920e-002 3.6775320e-002 -2.0919300e-003 +v 1.9636020e-002 3.8234010e-002 -1.2507670e-002 +v 2.3682120e-002 3.9762540e-002 3.7148760e-002 +v 4.6693280e-002 4.2465320e-002 6.5649500e-003 +v 2.1621110e-002 3.7657240e-002 -4.7021600e-003 +v 1.6638610e-002 3.8196090e-002 -1.9884930e-002 +v -9.0253980e-002 1.1366307e-001 3.7720210e-002 +v -9.0593870e-002 1.1373094e-001 1.0276770e-002 +v -6.2541690e-002 1.7679461e-001 -5.7821820e-002 +v -1.1091940e-002 1.7992082e-001 -2.5996430e-002 +v -6.2263130e-002 1.5219935e-001 -2.2578880e-002 +v -4.2276760e-002 9.4982570e-002 -2.2562420e-002 +v 4.3293410e-002 4.1864140e-002 2.0634400e-003 +v 4.3779590e-002 4.4530720e-002 -1.2622500e-003 +v 2.1696990e-002 4.0427270e-002 -9.4629500e-003 +v -1.1183700e-002 1.6450000e-001 -1.6151690e-002 +v -6.2372570e-002 1.5313041e-001 -2.8997120e-002 +v -9.2489300e-003 1.7725850e-001 -2.8270200e-002 +v 4.1477400e-002 8.5509410e-002 -9.1575000e-003 +v -8.1268710e-002 1.0879438e-001 2.9440660e-002 +v 4.9575680e-002 4.3815900e-002 1.4582960e-002 +v 5.2987960e-002 4.7747690e-002 5.0420000e-003 +v 2.1977540e-002 4.2855330e-002 -1.4536230e-002 +v 1.8505700e-002 3.8294100e-002 -1.7136500e-002 +v -3.5100500e-002 1.5203437e-001 -1.3279000e-004 +v 4.8749130e-002 4.5265000e-002 2.3023500e-003 +v 3.1912900e-002 9.9870060e-002 -1.4620980e-002 +v -1.4222520e-002 1.6167426e-001 -1.3349060e-002 +v -4.8663640e-002 1.3638523e-001 6.8063900e-003 +v -9.5837200e-003 1.7426102e-001 -2.8390760e-002 +v 5.2801850e-002 4.6539940e-002 1.0427720e-002 +v 5.1433800e-002 4.8485200e-002 1.0401000e-003 +v 2.3911240e-002 9.8021670e-002 -2.0807290e-002 +v 2.4567060e-002 4.4130110e-002 -1.0820840e-002 +v 2.0356810e-002 4.3662400e-002 -2.0456280e-002 +v -2.1882420e-002 1.1087418e-001 -1.9695320e-002 +v -5.3831800e-002 1.4981693e-001 2.5066610e-002 +v 5.4114210e-002 4.7773090e-002 1.7484000e-002 +v 5.6730570e-002 5.0515740e-002 1.0627080e-002 +v 4.5941820e-002 4.8138820e-002 -3.8715700e-003 +v -8.3817760e-002 1.1109094e-001 2.8524490e-002 +v 2.9207770e-002 4.7450250e-002 -8.5081800e-003 +v 2.8454920e-002 4.8067390e-002 -1.2847240e-002 +v 2.6637260e-002 4.7607100e-002 -1.6427740e-002 +v 2.2040110e-002 4.4992500e-002 -1.7528500e-002 +v 1.9120080e-002 4.7167750e-002 -2.2114680e-002 +v -1.5782200e-002 1.0072957e-001 -2.3724130e-002 +v -6.2514170e-002 1.7213119e-001 -5.2788100e-002 +v -6.2345600e-002 1.4745498e-001 -7.6600200e-003 +v 4.5598180e-002 8.8151720e-002 1.3124070e-002 +v -4.9422610e-002 1.4283525e-001 8.9728300e-003 +v -8.2761860e-002 1.1162341e-001 4.4221460e-002 +v -5.2166220e-002 1.5013661e-001 1.7448750e-002 +v -6.3616740e-002 1.4801371e-001 -2.0170260e-002 +v -5.1492690e-002 1.3796388e-001 2.3662180e-002 +v -6.1517580e-002 1.7517449e-001 -6.0631700e-002 +v 5.6524870e-002 5.0125660e-002 1.5564490e-002 +v 5.5257900e-002 5.1416260e-002 3.2062600e-003 +v 5.0318130e-002 5.2786370e-002 -3.4166300e-003 +v -6.2681950e-002 1.6744086e-001 -4.5713890e-002 +v 5.6520150e-002 5.1179900e-002 1.9940560e-002 +v 5.6907980e-002 5.1578130e-002 7.2538300e-003 +v 5.2854160e-002 5.1898670e-002 -6.2070000e-004 +v -3.8921140e-002 3.3767390e-002 -2.9042560e-002 +v 2.9740700e-002 5.0324690e-002 -1.3990860e-002 +v -6.8796190e-002 3.5117720e-002 -5.2067400e-003 +v 5.8826020e-002 5.5503780e-002 1.8647920e-002 +v -2.6160570e-002 1.2309988e-001 -4.4735500e-003 +v -5.3341960e-002 1.4401200e-001 2.4261390e-002 +v 5.8177390e-002 5.2821320e-002 1.5182420e-002 +v 5.9798140e-002 5.6840180e-002 1.3342730e-002 +v 5.4549870e-002 5.6044630e-002 -6.6158000e-004 +v 2.6775460e-002 5.1423450e-002 -2.0234060e-002 +v -8.6960400e-003 1.7291588e-001 -2.6708770e-002 +v -7.7039560e-002 7.1967020e-002 2.6405070e-002 +v -6.3069890e-002 1.5897471e-001 -4.2951850e-002 +v 3.5706690e-002 5.6083040e-002 -8.9993300e-003 +v 3.2600380e-002 5.3707520e-002 -1.1006150e-002 +v 2.9739960e-002 5.2538430e-002 -1.6224950e-002 +v 5.9238530e-002 5.6362780e-002 9.4530800e-003 +v 5.7421750e-002 5.6012210e-002 4.0245600e-003 +v 2.9062990e-002 5.5210580e-002 -1.8042060e-002 +v -1.7224410e-002 9.5214090e-002 -3.2085300e-002 +v -8.5911380e-002 1.0968787e-001 7.6582400e-003 +v 6.0594930e-002 6.1677210e-002 1.5591560e-002 +v 5.9531640e-002 6.0504600e-002 5.8397000e-003 +v 5.7306470e-002 5.9944620e-002 1.8886400e-003 +v 3.8829380e-002 5.9839830e-002 -6.4252500e-003 +v 3.0662770e-002 5.7300390e-002 -1.6518370e-002 +v -2.7762070e-002 1.2068537e-001 -9.0152900e-003 +v -8.8194590e-002 1.0314633e-001 1.7509020e-002 +v 6.0778800e-002 6.1646560e-002 1.0463990e-002 +v 3.5915080e-002 5.9916380e-002 -1.1966510e-002 +v 2.4251860e-002 5.6457470e-002 -2.4254800e-002 +v -6.1954390e-002 1.6865320e-001 -5.2621160e-002 +v -9.0557930e-002 1.1275994e-001 1.6141030e-002 +v -8.8469220e-002 1.1124294e-001 1.2679160e-002 +v 5.9558010e-002 6.3099260e-002 5.9471000e-003 +v 3.0940440e-002 6.0518080e-002 -1.8132720e-002 +v -9.3575750e-002 1.2474629e-001 2.6213300e-002 +v -9.3189820e-002 1.2019919e-001 3.7913720e-002 +v -9.2296100e-003 1.7314463e-001 -2.4197660e-002 +v -8.1739460e-002 7.6861340e-002 2.3313610e-002 +v -3.6992750e-002 1.5063932e-001 -2.0372300e-003 +v 6.0093570e-002 6.5693450e-002 1.8533320e-002 +v 5.9837240e-002 6.6423180e-002 8.5139400e-003 +v 4.0706180e-002 6.4475310e-002 -5.5920300e-003 +v 3.4745940e-002 6.3261340e-002 -1.4646740e-002 +v -6.1879660e-002 1.6000450e-001 -2.5806250e-002 +v -7.6537810e-002 1.5344875e-001 -1.2898750e-002 +v 3.8111070e-002 6.4811810e-002 -1.1142000e-002 +v 3.1909340e-002 6.4657050e-002 -1.8473410e-002 +v -8.3159350e-002 1.4674277e-001 3.0757900e-003 +v -8.7055900e-002 1.0562761e-001 9.7651100e-003 +v -7.1448330e-002 1.8105301e-001 -5.5478550e-002 +v -8.5632110e-002 1.2461094e-001 -2.7335800e-003 +v 6.0728970e-002 6.5806600e-002 1.3974830e-002 +v 3.9909650e-002 6.8171740e-002 -9.5698200e-003 +v 3.4981790e-002 6.7740790e-002 -1.5683210e-002 +v -9.1822030e-002 1.2747346e-001 3.6458650e-002 +v -6.2425420e-002 1.6366637e-001 -4.9667290e-002 +v -7.1168950e-002 1.4740156e-001 -2.7590940e-002 +v -5.0364760e-002 1.3715763e-001 1.9526100e-003 +v -5.0492650e-002 1.4159899e-001 1.6291740e-002 +v 5.9886670e-002 6.8513050e-002 1.6171610e-002 +v -6.1406990e-002 1.7268822e-001 -5.8265750e-002 +v 2.4990740e-002 6.5897320e-002 -2.3568270e-002 +v -7.4852750e-002 1.4993112e-001 -2.7752940e-002 +v -6.2225690e-002 6.0265200e-002 2.0449290e-002 +v -6.2001940e-002 3.6435020e-002 4.3918940e-002 +v 5.8374570e-002 7.1186410e-002 1.3072740e-002 +v -3.6125040e-002 1.2286688e-001 -8.2927900e-003 +v 2.9216510e-002 6.7850250e-002 -2.0418570e-002 +v -4.1681700e-002 1.2575112e-001 -7.0193300e-003 +v -7.4226550e-002 1.6437012e-001 -3.8240340e-002 +v -9.7845700e-003 1.6928488e-001 -2.4756660e-002 +v -8.9577950e-002 1.2078310e-001 3.5229100e-003 +v -6.2311930e-002 1.6371109e-001 -4.0623990e-002 +v 4.3514770e-002 9.1519890e-002 -2.6468100e-003 +v -4.8434350e-002 1.3754973e-001 1.3244980e-002 +v -8.9313160e-002 1.3653006e-001 3.0458750e-002 +v -7.4230190e-002 1.5652681e-001 -2.5167090e-002 +v 3.7378600e-002 7.3093410e-002 -1.2635370e-002 +v 2.6321810e-002 7.0240650e-002 -2.3878680e-002 +v -4.8023620e-002 1.4426649e-001 4.2498600e-003 +v -9.2019580e-002 1.1611534e-001 3.5842730e-002 +v -7.1305510e-002 7.3899020e-002 3.5969780e-002 +v -6.2059290e-002 1.5697807e-001 -3.3784580e-002 +v -9.7015300e-003 1.6738863e-001 -1.9360250e-002 +v 4.3342140e-002 7.1676120e-002 -2.2304600e-003 +v 4.1772460e-002 6.9568020e-002 -6.1596000e-003 +v 3.3505410e-002 7.2809860e-002 -1.7034800e-002 +v 2.9665000e-002 7.1506830e-002 -2.1282340e-002 +v -2.9460160e-002 1.5550263e-001 -1.1914700e-003 +v -8.6396440e-002 1.0479356e-001 5.9820600e-003 +v -5.4910700e-002 1.4662313e-001 2.8438970e-002 +v 4.4203810e-002 8.5204260e-002 -2.1170500e-003 +v 4.3264350e-002 7.5810540e-002 -3.8843900e-003 +v 1.3096990e-002 9.1126480e-002 -2.9269770e-002 +v -6.7069210e-002 9.1144610e-002 -1.7425950e-002 +v -9.0821680e-002 1.2276896e-001 6.0998500e-003 +v 4.5620000e-002 7.4684430e-002 2.6073900e-003 +v -9.3039800e-002 1.2026416e-001 1.1216820e-002 +v 4.4635590e-002 9.2794290e-002 1.7832070e-002 +v -1.1243390e-002 1.6457514e-001 -1.8240780e-002 +v 4.5511190e-002 8.6953050e-002 3.8865500e-003 +v 4.6252720e-002 7.7373870e-002 6.9140800e-003 +v 4.0281640e-002 7.2637130e-002 -9.2881000e-003 +v 4.3218200e-002 9.9486740e-002 5.0153300e-003 +v -5.1108270e-002 1.4520219e-001 1.4279480e-002 +v 4.4692980e-002 9.2688550e-002 2.2466700e-003 +v 4.3422540e-002 9.1860370e-002 2.4538450e-002 +v 4.0751360e-002 1.0554729e-001 7.5074100e-003 +v -8.5613030e-002 9.6277110e-002 -6.6514000e-004 +v 4.0721470e-002 7.8475530e-002 -8.2130000e-003 +v 3.5538080e-002 7.6062960e-002 -1.4434750e-002 +v -9.2736510e-002 1.2073095e-001 3.2692730e-002 +v -6.2278520e-002 1.5166598e-001 -1.4672730e-002 +v 4.4960220e-002 8.0942630e-002 6.1119000e-004 +v 3.7814740e-002 7.9698150e-002 -1.3289630e-002 +v 3.3864490e-002 7.8656690e-002 -1.7632490e-002 +v -9.1044280e-002 1.4199862e-001 2.1729630e-002 +v -7.4004450e-002 1.7818523e-001 -5.3916320e-002 +v -6.1768650e-002 1.6067957e-001 -3.4046350e-002 +v -4.9747450e-002 1.4112519e-001 5.2937500e-003 +v 4.1065440e-002 9.0460700e-002 2.9888620e-002 +v -7.2916360e-002 6.5057400e-002 1.8794620e-002 +v -9.0949690e-002 1.3895375e-001 1.7371130e-002 +v 4.2879050e-002 1.0093777e-001 9.4753200e-003 +v -7.2455480e-002 1.7610676e-001 -5.3535420e-002 +v -7.5862940e-002 1.5071299e-001 -9.0209000e-003 +v -8.5269820e-002 1.0267793e-001 1.3935600e-003 +v -7.7025570e-002 1.1396763e-001 -4.6168100e-003 +v 4.6280880e-002 7.8702020e-002 1.4786330e-002 +v 4.2106910e-002 8.1533160e-002 -6.6690900e-003 +v 3.6523880e-002 8.1991750e-002 -1.6229590e-002 +v -3.7420220e-002 4.5428500e-002 -2.4226790e-002 +v -8.5148910e-002 1.3965520e-001 2.4808500e-003 +v -6.3313300e-002 1.6503258e-001 -3.2895120e-002 +v -6.1591410e-002 1.5681572e-001 -2.5945630e-002 +v 4.5918540e-002 8.7036220e-002 8.4236300e-003 +v 4.4631140e-002 8.4178380e-002 8.2665000e-004 +v -4.4842870e-002 1.4629393e-001 1.7114800e-003 +v -6.4124180e-002 1.7953625e-001 -5.8730420e-002 +v -6.7070300e-002 1.8072682e-001 -5.6618620e-002 +v -6.4793760e-002 1.7885275e-001 -5.5883250e-002 +v -6.4371030e-002 1.7296209e-001 -4.9225660e-002 +v -7.0381530e-002 1.8071180e-001 -5.3172590e-002 +v -7.5269270e-002 1.5232949e-001 3.4374060e-002 +v -1.6273090e-002 1.2844514e-001 1.6683610e-002 +v -6.2116150e-002 1.5600787e-001 1.8034420e-002 +v -5.6010790e-002 1.5381662e-001 2.5369280e-002 +v -3.7277920e-002 1.7289068e-001 -8.6627000e-004 +v -7.4158700e-002 1.7987275e-001 -5.0794750e-002 +v -7.9039960e-002 1.5537445e-001 1.5141810e-002 +v -7.2505530e-002 1.5459529e-001 2.9588830e-002 +v -6.7738180e-002 1.7728865e-001 -5.0375960e-002 +v -7.5346900e-003 1.0021302e-001 4.7488700e-002 +v -5.9575620e-002 1.5472401e-001 2.6373250e-002 +v -7.7382710e-002 1.5346600e-001 3.0894990e-002 +v -8.1496670e-002 1.5473104e-001 1.9697340e-002 +v -7.2223320e-002 1.5896734e-001 -5.4242300e-003 +v -1.3708500e-002 1.8491150e-001 -2.5549550e-002 +v -4.3465340e-002 1.2451145e-001 2.2518890e-002 +v -6.9103650e-002 1.5559479e-001 1.6370800e-003 +v -7.3748080e-002 1.5539253e-001 2.3491700e-003 +v -6.8192410e-002 1.7439828e-001 -4.5365870e-002 +v -6.0052850e-002 1.5280350e-001 3.2887630e-002 +v -2.3459490e-002 1.2615386e-001 1.6613770e-002 +v -7.2777220e-002 1.7854465e-001 -4.8208800e-002 +v -7.6595580e-002 1.7753227e-001 -4.7118080e-002 +v 1.3906410e-002 1.2790838e-001 2.5110240e-002 +v -8.6367510e-002 1.0906537e-001 1.1980640e-002 +v -3.1358850e-002 1.2140977e-001 2.5971090e-002 +v -4.9104590e-002 1.3666879e-001 1.9314030e-002 +v -4.2930640e-002 1.2928436e-001 9.2700700e-003 +v -6.5320350e-002 1.5390322e-001 9.1386000e-004 +v -3.7606490e-002 1.2422605e-001 2.4313530e-002 +v 9.5078400e-003 1.3041865e-001 2.0715020e-002 +v -1.7976800e-003 1.3117283e-001 1.6360660e-002 +v 3.6231700e-003 1.3076791e-001 2.1168600e-002 +v -9.2674700e-002 1.1701945e-001 1.1889520e-002 +v -6.5739720e-002 1.5565338e-001 2.6017600e-002 +v -8.6561940e-002 1.4249188e-001 8.4326800e-003 +v -7.0731530e-002 1.5569959e-001 6.9058200e-003 +v -8.0840700e-003 1.3030537e-001 1.6872280e-002 +v -4.4286250e-002 1.2606625e-001 2.0795220e-002 +v -7.0222260e-002 1.5143521e-001 3.6718910e-002 +v -1.5210690e-002 1.8463639e-001 -2.2057240e-002 +v -1.7270750e-002 1.8699602e-001 -1.9977570e-002 +v -8.3560950e-002 1.5255943e-001 7.6806700e-003 +v -8.8130280e-002 9.7540510e-002 5.6788000e-003 +v -8.8399240e-002 1.3899000e-001 1.0640660e-002 +v -6.7780550e-002 1.5614453e-001 1.4276320e-002 +v -6.5864600e-003 1.2641717e-001 3.0226390e-002 +v -8.8746180e-002 1.3625578e-001 7.1477800e-003 +v -7.7206730e-002 1.5639950e-001 -1.8972540e-002 +v -9.3176480e-002 1.1821016e-001 2.3362360e-002 +v -2.3506850e-002 1.2672006e-001 1.0996900e-002 +v -6.6546650e-002 1.7171115e-001 -4.2127770e-002 +v -6.9136000e-002 1.7247836e-001 -3.9013330e-002 +v 5.7180270e-002 7.1107690e-002 8.0307600e-003 +v -7.5390870e-002 1.7952824e-001 -5.2402050e-002 +v -3.1828840e-002 1.2639115e-001 1.0013410e-002 +v -8.9888800e-003 1.2952269e-001 2.2026810e-002 +v 3.4325880e-002 1.1193312e-001 -2.2406500e-003 +v -8.1414950e-002 9.7100250e-002 -6.8745800e-003 +v -2.3298830e-002 1.8324307e-001 -1.7923000e-002 +v -6.1641660e-002 1.5582039e-001 1.1099820e-002 +v -8.8826450e-002 9.0483320e-002 2.1204700e-002 +v 5.8373130e-002 6.8067590e-002 5.7247600e-003 +v -4.3045630e-002 1.2785122e-001 1.6842260e-002 +v 3.0835720e-002 1.1554234e-001 -3.1785500e-003 +v -8.8631270e-002 9.4881200e-002 7.9337600e-003 +v -9.1715140e-002 1.1709957e-001 3.0809400e-002 +v -7.2083780e-002 1.7499844e-001 -4.1930320e-002 +v -6.9540630e-002 1.5308527e-001 3.3865720e-002 +v 6.0078690e-002 6.8129260e-002 1.1454500e-002 +v -4.0081060e-002 1.2628381e-001 1.9607250e-002 +v 3.2819930e-002 1.1655625e-001 4.4458600e-003 +v -7.2823220e-002 1.4510601e-001 -1.5654680e-002 +v -8.5270210e-002 1.0551770e-001 2.3290940e-002 +v -7.6051320e-002 1.1103825e-001 -6.2722100e-003 +v -8.6537730e-002 1.5154801e-001 2.5875370e-002 +v 5.5888480e-002 7.2579250e-002 1.0669650e-002 +v -5.4642360e-002 1.5522963e-001 1.2612400e-002 +v 3.6729960e-002 1.1116756e-001 3.8670600e-003 +v 3.1501870e-002 1.1725172e-001 1.6855100e-003 +v -7.8751550e-002 9.5240290e-002 -1.0600670e-002 +v -8.9408160e-002 1.4352815e-001 3.0924750e-002 +v -2.0891130e-002 1.8595338e-001 -1.5037360e-002 +v -7.0863560e-002 1.6136525e-001 -9.7324600e-003 +v -7.0919760e-002 1.7136688e-001 -3.2763750e-002 +v -3.0771290e-002 1.2564075e-001 1.6594770e-002 +v -5.4454180e-002 1.5297699e-001 2.2505190e-002 +v -1.5539500e-003 1.2754717e-001 2.9232870e-002 +v 2.9130550e-002 1.2027445e-001 6.1117500e-003 +v 2.5725940e-002 1.2122705e-001 -3.6150000e-005 +v -8.9318970e-002 9.9546980e-002 1.3418110e-002 +v -7.5429500e-002 1.7095605e-001 -3.2879890e-002 +v -2.8596020e-002 1.1901156e-001 2.9888170e-002 +v 2.1069780e-002 1.2497756e-001 1.0998100e-003 +v -9.2240760e-002 1.1816838e-001 4.1201730e-002 +v 2.4094600e-003 1.0016785e-001 4.6938070e-002 +v -5.6627620e-002 1.5270606e-001 2.9629030e-002 +v -5.7264800e-002 1.5506250e-001 1.9322430e-002 +v -3.6452070e-002 1.2199869e-001 2.7670650e-002 +v -7.4108160e-002 1.7355729e-001 -3.7986840e-002 +v 5.1537130e-002 7.3496690e-002 1.2698700e-002 +v -6.6096040e-002 1.5532529e-001 7.1561800e-003 +v 3.6102000e-002 1.1266103e-001 1.0491780e-002 +v 1.6715210e-002 1.2689851e-001 2.2331000e-004 +v -8.0767920e-002 1.4301400e-001 -1.5312800e-003 +v -9.1757600e-002 1.4334588e-001 1.7790710e-002 +v -8.6824940e-002 1.5280775e-001 1.5521450e-002 +v -6.5808100e-002 1.6764344e-001 -3.0558670e-002 +v -7.8217340e-002 1.6873975e-001 -3.3564250e-002 +v -7.2567060e-002 1.4753230e-001 4.1714090e-002 +v 5.8439960e-002 7.0200810e-002 1.7779620e-002 +v 5.6847560e-002 7.2017160e-002 1.7139380e-002 +v 5.4919390e-002 7.3161610e-002 1.5223590e-002 +v 4.7446900e-002 7.3691410e-002 1.2430020e-002 +v 1.2319360e-002 1.2903768e-001 1.3336200e-003 +v -7.9790640e-002 1.0351662e-001 -6.6275400e-003 +v -7.6655210e-002 1.5509766e-001 7.9686300e-003 +v 2.1747320e-002 1.2118456e-001 3.0878810e-002 +v -7.5260490e-002 1.4938613e-001 3.9175980e-002 +v -2.5919610e-002 1.8272826e-001 -1.3541090e-002 +v -6.7983790e-002 1.6974781e-001 -3.1627490e-002 +v 1.6831110e-002 1.2487146e-001 2.8425580e-002 +v 5.4016490e-002 7.2883850e-002 1.8678010e-002 +v 5.0522750e-002 7.3397910e-002 1.6166890e-002 +v -5.9582440e-002 1.5623338e-001 7.9209900e-003 +v 2.5343500e-002 1.2374750e-001 9.9818800e-003 +v 1.9262750e-002 1.2689390e-001 5.5552100e-003 +v -9.0758520e-002 1.4223375e-001 2.6008130e-002 +v -4.6548490e-002 1.3320769e-001 1.6889630e-002 +v -2.4106950e-002 1.8380887e-001 -1.1544760e-002 +v 8.6784400e-003 1.2894574e-001 2.6156880e-002 +v 2.4919200e-003 1.2983563e-001 2.4847110e-002 +v 5.7345150e-002 6.9482720e-002 2.1153510e-002 +v -8.5329840e-002 1.5339912e-001 2.0378290e-002 +v 3.2877320e-002 1.1691463e-001 9.2957500e-003 +v 2.4246630e-002 1.2377758e-001 4.8764500e-003 +v -4.7765650e-002 1.3301969e-001 2.2874020e-002 +v -6.3541830e-002 1.6332115e-001 -2.5912990e-002 +v -6.6605200e-002 1.6477375e-001 -2.0670760e-002 +v -6.8504220e-002 1.6732018e-001 -2.3959570e-002 +v -7.2759160e-002 1.6965906e-001 -2.7013420e-002 +v 4.8206850e-002 7.2698580e-002 1.6994630e-002 +v -2.7383180e-002 1.2324257e-001 2.1658860e-002 +v -4.5077500e-002 1.3124443e-001 1.1145770e-002 +v 2.9253150e-002 1.2057701e-001 1.2299330e-002 +v 1.3677610e-002 1.2967262e-001 6.9327400e-003 +v 8.4210900e-003 1.3090986e-001 6.2754400e-003 +v 9.6836000e-004 1.3064303e-001 2.5865900e-003 +v 3.0802000e-003 9.8307360e-002 5.0535640e-002 +v -5.2420170e-002 1.5310101e-001 1.2927370e-002 +v -7.0359720e-002 1.6906988e-001 -2.6144260e-002 +v 5.4359390e-002 7.1467260e-002 2.1381250e-002 +v 4.5161440e-002 7.1030380e-002 2.2530690e-002 +v 1.9320440e-002 1.2738348e-001 1.1296310e-002 +v -9.3281210e-002 1.2691094e-001 1.3505010e-002 +v -8.7405060e-002 1.0593990e-001 1.3645920e-002 +v -2.2851640e-002 9.0635040e-002 5.2280460e-002 +v -6.2099370e-002 1.5406697e-001 3.0837360e-002 +v -4.5851560e-002 1.2072981e-001 2.7665040e-002 +v 5.0781670e-002 7.2155170e-002 2.0680180e-002 +v -8.9607270e-002 1.3971105e-001 2.9308560e-002 +v -5.3323050e-002 1.5273520e-001 1.6213860e-002 +v -1.5227080e-002 1.2784878e-001 2.1545200e-002 +v 3.3663540e-002 1.1574212e-001 1.7181290e-002 +v 2.4000260e-002 1.2468761e-001 1.5517930e-002 +v -8.4166840e-002 9.7756820e-002 -3.2761900e-003 +v -3.6223590e-002 1.2777519e-001 9.8501500e-003 +v -3.9189580e-002 1.2828193e-001 5.0346300e-003 +v -3.3674050e-002 1.7774449e-001 -8.1799500e-003 +v -7.4488620e-002 1.5649443e-001 -2.5954600e-003 +v -4.6755620e-002 1.3284294e-001 8.1212800e-003 +v -8.4970410e-002 1.5322309e-001 1.2654460e-002 +v -1.0866210e-002 1.2691699e-001 2.7575440e-002 +v -3.1074000e-003 1.3072898e-001 5.6428500e-003 +v -8.8760540e-002 9.7037440e-002 2.1079040e-002 +v -6.4811320e-002 3.4530640e-002 1.5508440e-002 +v -6.4300260e-002 3.5086450e-002 2.4272050e-002 +v -6.6727020e-002 3.5895770e-002 3.3849430e-002 +v 1.9838510e-002 9.6518890e-002 -2.2785880e-002 +v -3.8670510e-002 1.6070199e-001 -1.2357760e-002 +v -7.6890090e-002 1.3041906e-001 -6.9570100e-003 +v -7.2539730e-002 3.5399270e-002 7.0298800e-003 +v -6.9209050e-002 3.5454810e-002 1.2042140e-002 +v -6.4160810e-002 3.5900770e-002 1.7687570e-002 +v -6.6804150e-002 3.7377740e-002 3.3296290e-002 +v -6.2928350e-002 3.9061660e-002 4.2707680e-002 +v -7.1752230e-002 3.6789350e-002 8.6966700e-003 +v -6.5171380e-002 3.7289500e-002 2.5953770e-002 +v -6.6392030e-002 3.7712350e-002 2.9621950e-002 +v -6.4558720e-002 3.9639900e-002 3.9411530e-002 +v -6.0145790e-002 4.1202050e-002 4.4293830e-002 +v -6.0318430e-002 3.8442990e-002 4.5245950e-002 +v -3.6756310e-002 8.8663360e-002 -2.3868800e-002 +v -3.9494750e-002 3.7551570e-002 4.2870900e-002 +v -7.2016030e-002 3.7572700e-002 3.9789400e-003 +v -7.1693630e-002 3.9461000e-002 6.0145000e-003 +v -7.1165950e-002 3.9366310e-002 8.1142100e-003 +v -6.9000300e-002 3.8467710e-002 1.0768900e-002 +v -6.7253420e-002 3.8142160e-002 1.3533960e-002 +v -6.1125670e-002 3.7790050e-002 1.9710900e-002 +v -3.9179680e-002 4.2406740e-002 4.1476070e-002 +v -3.5145960e-002 3.8585920e-002 4.7732690e-002 +v -2.8950940e-002 3.9285940e-002 5.3309090e-002 +v -1.8223900e-002 9.7494570e-002 4.6847940e-002 +v -6.6916260e-002 1.2278907e-001 -8.9077400e-003 +v -6.3754640e-002 3.8250120e-002 1.6593500e-002 +v -6.4415760e-002 4.1283840e-002 2.8243480e-002 +v -8.5856340e-002 9.7025390e-002 2.7414960e-002 +v -3.7501130e-002 4.0221900e-002 4.4296550e-002 +v -3.4333970e-002 4.0923630e-002 4.8425810e-002 +v -3.1172890e-002 4.0294330e-002 5.1312460e-002 +v -6.9997320e-002 4.2073080e-002 6.6897800e-003 +v -8.0379330e-002 9.7800660e-002 3.3645750e-002 +v -2.6273160e-002 7.7631160e-002 4.8356180e-002 +v -3.7501450e-002 4.2736690e-002 4.2988400e-002 +v -2.6177500e-002 4.2498930e-002 5.3315220e-002 +v -6.9637250e-002 4.1881270e-002 3.1825800e-003 +v -6.7156510e-002 4.1972860e-002 1.0240940e-002 +v -8.7405510e-002 1.0205209e-001 2.2020360e-002 +v -2.3944380e-002 7.8800140e-002 5.3534730e-002 +v -6.0902360e-002 4.3429500e-002 4.2678530e-002 +v -3.1217880e-002 4.3847510e-002 4.9780920e-002 +v -7.5729440e-002 1.0354026e-001 3.6070970e-002 +v -6.2425320e-002 4.1885720e-002 1.4646770e-002 +v -6.1051660e-002 4.4392230e-002 1.2421940e-002 +v 2.5855060e-002 8.9610660e-002 -2.2701840e-002 +v -7.7644960e-002 8.2214940e-002 3.5797660e-002 +v -6.0381270e-002 4.5921420e-002 4.0088740e-002 +v -2.4982010e-002 8.1777650e-002 5.3421060e-002 +v -3.4453850e-002 4.4563960e-002 4.5422990e-002 +v -2.9842910e-002 4.6782280e-002 4.7746920e-002 +v -1.5119580e-002 9.9930020e-002 4.4500270e-002 +v -6.7306470e-002 4.4176830e-002 7.5958300e-003 +v -5.7852990e-002 4.6444500e-002 1.1062610e-002 +v -5.1815260e-002 1.6392582e-001 1.7488800e-003 +v -5.5174130e-002 4.8383880e-002 3.8517780e-002 +v -7.8849150e-002 1.1867375e-001 5.0622870e-002 +v -2.7229070e-002 8.7991480e-002 4.7909730e-002 +v -7.5536880e-002 1.5977062e-001 -1.0438650e-002 +v -3.6151280e-002 4.6505140e-002 4.0740900e-002 +v -2.5439220e-002 9.0677870e-002 4.8852330e-002 +v -8.0050370e-002 1.1670406e-001 4.8762460e-002 +v -5.2513640e-002 4.7577880e-002 1.4858440e-002 +v -3.2043560e-002 5.0461830e-002 3.9341520e-002 +v -3.1487770e-002 4.6930210e-002 4.5253210e-002 +v -2.0321500e-002 9.3999570e-002 5.1588540e-002 +v -7.2145040e-002 9.1556450e-002 4.1494780e-002 +v -5.3644200e-002 4.9358170e-002 1.2201850e-002 +v -8.2403890e-002 1.2186563e-001 4.9365030e-002 +v -4.9754420e-002 4.9738300e-002 3.7037110e-002 +v -3.2332060e-002 4.8672840e-002 4.2523960e-002 +v -2.3122950e-002 9.4515900e-002 4.7358870e-002 +v -8.6347140e-002 9.1722090e-002 2.6811080e-002 +v -5.7713110e-002 4.8717820e-002 7.2765100e-003 +v -8.6970360e-002 8.8912090e-002 2.4879860e-002 +v -9.2237750e-002 1.2488519e-001 4.0786530e-002 +v -1.5862800e-002 9.7021620e-002 5.0139360e-002 +v -2.7720040e-002 5.0502090e-002 4.3340720e-002 +v -8.5918770e-002 1.4263412e-001 3.9849810e-002 +v -7.5097360e-002 9.0073560e-002 3.9581000e-002 +v -8.9430840e-002 1.4730552e-001 2.7694960e-002 +v -5.3288350e-002 5.1925760e-002 1.1730350e-002 +v -5.0168720e-002 5.3462260e-002 1.6255440e-002 +v -8.5986050e-002 1.4670902e-001 3.4827030e-002 +v -6.9937250e-002 8.6076860e-002 4.2175690e-002 +v -5.0399320e-002 5.1831330e-002 3.4037400e-002 +v -8.3298980e-002 1.4960772e-001 3.3740890e-002 +v -2.9174820e-002 5.2264530e-002 3.7637320e-002 +v -8.8763730e-002 1.1944938e-001 4.6560090e-002 +v -7.7693460e-002 1.7367969e-001 -4.1478670e-002 +v -8.3418140e-002 9.4127440e-002 3.0898450e-002 +v -5.6067510e-002 5.3470630e-002 7.3718200e-003 +v -7.8935630e-002 1.4817228e-001 3.9463070e-002 +v -6.7902770e-002 8.7817230e-002 4.3526990e-002 +v -4.4111240e-002 9.2883990e-002 -2.2373210e-002 +v -8.6605100e-002 1.3226807e-001 4.6783020e-002 +v -9.2654280e-002 1.2084025e-001 4.1629650e-002 +v -5.0887310e-002 5.2727900e-002 1.4455790e-002 +v -4.9763410e-002 5.6241200e-002 3.3624250e-002 +v -8.9771330e-002 1.2904861e-001 4.3022990e-002 +v -2.8054240e-002 5.4551030e-002 3.6786850e-002 +v -2.5867080e-002 5.6689210e-002 3.9182240e-002 +v -8.3702200e-002 1.2226381e-001 -3.7301400e-003 +v -8.1455470e-002 1.3012213e-001 5.2117660e-002 +v -5.1458550e-002 5.5878150e-002 1.5900350e-002 +v -7.8597700e-002 1.7441574e-001 -4.6607580e-002 +v -5.2909820e-002 5.7043070e-002 2.0988410e-002 +v -5.2978500e-002 5.9553770e-002 2.6211920e-002 +v -5.2130640e-002 5.6302970e-002 2.6672460e-002 +v -4.7714500e-002 6.1944520e-002 3.6705820e-002 +v -8.3539790e-002 8.1169560e-002 2.7014070e-002 +v -1.8340000e-002 5.7489970e-002 4.9763020e-002 +v -8.0069810e-002 9.0586130e-002 3.4593070e-002 +v -8.3812250e-002 8.6337700e-002 2.9223270e-002 +v -5.5436650e-002 5.9420250e-002 2.3018970e-002 +v -8.2227680e-002 1.4513771e-001 4.0600080e-002 +v -2.4187580e-002 7.2269150e-002 4.7681090e-002 +v -2.5353150e-002 6.2567200e-002 4.0642170e-002 +v -9.1132110e-002 1.2282100e-001 4.4115160e-002 +v -4.6076290e-002 1.6819719e-001 7.3744000e-004 +v -8.7829280e-002 1.4351461e-001 3.5707670e-002 +v -8.6990640e-002 1.3812326e-001 4.2316550e-002 +v -1.5715900e-002 6.0822970e-002 5.2365440e-002 +v -8.3803580e-002 1.2561100e-001 5.0440490e-002 +v -6.2786680e-002 1.1274190e-001 -1.3605440e-002 +v -8.1033840e-002 8.4698180e-002 3.3106400e-002 +v -8.8563540e-002 1.1624535e-001 4.5392840e-002 +v -2.0268380e-002 6.2266810e-002 4.8212120e-002 +v -1.2619630e-002 6.1635030e-002 5.4424080e-002 +v -7.0491190e-002 8.1818160e-002 4.0609890e-002 +v -8.3882520e-002 1.3331465e-001 4.9113540e-002 +v -5.6560350e-002 4.8355540e-002 3.6607050e-002 +v 9.9444900e-003 1.0919723e-001 -1.9472810e-002 +v -5.5928250e-002 3.5917310e-002 4.6376100e-002 +v -7.6003260e-002 1.6361344e-001 -1.8021110e-002 +v -8.3798850e-002 1.0290691e-001 2.8038330e-002 +v -8.8252110e-002 1.2692730e-001 4.6141300e-002 +v -7.9126720e-002 1.0619883e-001 3.2050700e-002 +v -8.8206230e-002 9.4485700e-002 2.3744010e-002 +v -8.9110330e-002 1.3851394e-001 3.7658780e-002 +v -1.9321360e-002 9.2123890e-002 5.3820650e-002 +v -5.8265630e-002 9.0926390e-002 -2.0948690e-002 +v -2.7046310e-002 6.7014450e-002 3.9672140e-002 +v -2.1416300e-002 1.7977662e-001 -2.1732520e-002 +v -7.8240000e-003 1.0924112e-001 -2.2185670e-002 +v -2.3988340e-002 8.5995590e-002 5.3716430e-002 +v -6.0483580e-002 1.5567975e-001 4.3343800e-003 +v -8.6389150e-002 1.2168475e-001 4.8412440e-002 +v -7.4084360e-002 1.4987744e-001 -3.2610050e-002 +v -2.0580600e-002 7.9572500e-002 5.6013880e-002 +v -8.3837500e-002 1.3927865e-001 4.4893850e-002 +v -2.2933960e-002 3.5632910e-002 5.2865490e-002 +v -8.6153620e-002 1.2735612e-001 4.8563960e-002 +v -6.5728590e-002 1.0709818e-001 -1.4317670e-002 +v -2.1481090e-002 7.4194460e-002 5.2857680e-002 +v -7.6423900e-002 1.5736285e-001 -9.0354600e-003 +v -7.7216010e-002 8.5594880e-002 3.7420770e-002 +v -8.4150830e-002 1.2955013e-001 5.0483700e-002 +v -8.1221440e-002 8.1003250e-002 3.1255840e-002 +v -8.1704000e-002 1.0167226e-001 3.0939660e-002 +v -8.6252730e-002 1.0106846e-001 2.5413770e-002 +v -8.0944970e-002 1.3903572e-001 4.7359080e-002 +v -7.8908350e-002 9.4830900e-002 3.5435500e-002 +v -7.3440160e-002 9.5412600e-002 4.0210650e-002 +v -5.2675780e-002 8.8220740e-002 -2.1886300e-002 +v -7.6440670e-002 7.7511060e-002 3.3748300e-002 +v -2.1791140e-002 1.0658035e-001 -2.2327000e-002 +v -8.8360940e-002 1.4996706e-001 2.6044170e-002 +v -2.4078870e-002 6.7906700e-002 4.5178370e-002 +v -2.0018090e-002 6.7569300e-002 5.1565340e-002 +v -8.3577750e-002 1.2052625e-001 4.9177500e-002 +v -1.4655950e-002 1.7456543e-001 -2.5972690e-002 +v -2.7395940e-002 8.4108300e-002 4.8745680e-002 +v -4.1933580e-002 8.8463400e-002 -2.2126350e-002 +v -3.1693900e-002 1.0261265e-001 -2.2352310e-002 +v -2.7890200e-002 1.0440703e-001 -2.2830920e-002 +v -7.3790400e-002 1.2016662e-001 -7.8851200e-003 +v -4.6124160e-002 1.0506369e-001 -2.0457580e-002 +v -2.7412650e-002 7.3269450e-002 4.2641380e-002 +v -4.5532880e-002 3.4736480e-002 -2.1363200e-002 +v -4.4993030e-002 3.9017010e-002 -2.1097830e-002 +v -4.6462610e-002 3.6800270e-002 -1.7778710e-002 +v -8.8366460e-002 1.1361863e-001 5.8227800e-003 +v 5.1746240e-002 7.2897250e-002 9.0647400e-003 +v -7.0385250e-002 3.7450300e-002 -9.3190000e-004 +v -6.0923170e-002 3.8621820e-002 2.2468850e-002 +v -7.7696720e-002 1.7027889e-001 -4.3117910e-002 +v -4.3793210e-002 1.6955506e-001 -7.3026400e-003 +v -7.7587180e-002 1.7717875e-001 -5.0221090e-002 +v -4.0541880e-002 3.8886010e-002 -2.7364950e-002 +v -4.4215850e-002 3.6131460e-002 -2.4252210e-002 +v -6.6634880e-002 4.0430310e-002 -5.0180700e-003 +v -6.9242120e-002 4.1474050e-002 1.9289000e-004 +v -7.5640690e-002 1.5930400e-001 -2.6908460e-002 +v -6.3087030e-002 3.9614170e-002 2.5181560e-002 +v -7.2303020e-002 1.5186699e-001 -4.1544310e-002 +v -4.1051490e-002 4.1528620e-002 -2.4061000e-002 +v -4.6990580e-002 3.8892380e-002 -1.4016920e-002 +v -8.9559690e-002 1.2851666e-001 4.5457500e-003 +v -7.6987340e-002 1.5369375e-001 -2.2970800e-003 +v -7.0121670e-002 1.6882633e-001 -5.1173650e-002 +v -6.4792610e-002 4.1724530e-002 3.1616900e-002 +v -4.2148060e-002 1.2409627e-001 -9.5602500e-003 +v -4.8069700e-002 1.2493027e-001 -8.4076400e-003 +v -4.2150480e-002 4.3343970e-002 -2.1508710e-002 +v -6.7315160e-002 4.4034000e-002 1.5741800e-003 +v -7.3386640e-002 1.5463418e-001 -2.9943830e-002 +v -5.5352770e-002 4.2936210e-002 1.9135490e-002 +v -6.0067770e-002 4.1419500e-002 2.2953280e-002 +v -6.5488460e-002 4.0937780e-002 3.5315470e-002 +v -8.0066400e-002 1.5039650e-001 6.0518000e-004 +v -4.4031300e-002 4.1949070e-002 -1.7993960e-002 +v -4.5186510e-002 4.2453420e-002 -1.4193620e-002 +v -8.3109430e-002 1.0265445e-001 -3.2933400e-003 +v -6.5472800e-002 4.5627570e-002 4.5575400e-003 +v -7.5427730e-002 1.5201213e-001 -1.4393690e-002 +v -5.4473420e-002 4.5937510e-002 2.3612600e-002 +v -6.2464100e-002 4.3722000e-002 2.8493310e-002 +v -6.2832600e-002 4.5182750e-002 3.4622890e-002 +v -6.3538130e-002 4.3524020e-002 3.7974010e-002 +v -6.0255260e-002 4.4749620e-002 -4.1316200e-003 +v -6.3242050e-002 4.5549700e-002 4.8428000e-004 +v -6.2249430e-002 4.6540050e-002 7.1903500e-003 +v -9.1003650e-002 1.4885725e-001 2.1507030e-002 +v -5.7094130e-002 4.5996540e-002 2.6865280e-002 +v -5.7276490e-002 4.7299580e-002 2.9889950e-002 +v -3.9519900e-002 1.7385855e-001 -7.5752600e-003 +v -8.9641110e-002 1.3841920e-001 3.4141800e-002 +v -9.2601430e-002 1.3018652e-001 2.5183580e-002 +v -9.2280860e-002 1.2762053e-001 2.9751670e-002 +v -3.3957310e-002 4.1025060e-002 -2.9660250e-002 +v -9.0199540e-002 1.1657506e-001 5.6754900e-003 +v -5.8515890e-002 4.7731310e-002 2.1246000e-004 +v -7.1723560e-002 1.4617438e-001 -2.1567820e-002 +v -5.2389820e-002 4.5449130e-002 1.7686300e-002 +v -5.9414350e-002 4.7277990e-002 3.4172420e-002 +v -5.7520620e-002 1.5877600e-001 4.1621200e-003 +v -8.0959140e-002 1.0926674e-001 -2.0189900e-003 +v -5.1904000e-002 4.6100060e-002 1.9421290e-002 +v -5.1830050e-002 4.8568730e-002 2.1647030e-002 +v -7.7650400e-002 1.5658012e-001 -1.6599150e-002 +v -3.7416450e-002 4.7682130e-002 -1.7147280e-002 +v -7.8876110e-002 1.5347012e-001 3.9875800e-003 +v -5.7635420e-002 5.0425540e-002 4.6108400e-003 +v -5.2625440e-002 5.0434620e-002 2.9046740e-002 +v -5.2998720e-002 4.9169020e-002 3.3967600e-002 +v -7.3502600e-002 1.6871934e-001 -4.4791800e-002 +v -5.4420720e-002 4.7836520e-002 -5.9186900e-003 +v -5.2312740e-002 5.1085350e-002 2.4485690e-002 +v -7.9129930e-002 1.6736568e-001 -3.5506230e-002 +v 9.4115700e-003 1.2350285e-001 -9.8291000e-003 +v -3.2715700e-002 1.0896631e-001 -1.8941410e-002 +v -3.1133380e-002 4.9607260e-002 -1.9406940e-002 +v 4.5997330e-002 6.9814450e-002 3.0143300e-003 +v 3.3525460e-002 1.0966209e-001 -6.9894800e-003 +v -5.5047160e-002 5.2767560e-002 -3.9461300e-003 +v -5.6897890e-002 4.9655570e-002 -1.5319000e-003 +v -5.0290500e-002 4.9098930e-002 1.7164780e-002 +v -5.0595170e-002 4.9923270e-002 1.9174130e-002 +v -5.1887420e-002 5.3324670e-002 2.8705560e-002 +v -6.7684480e-002 1.6533627e-001 -5.5466400e-002 +v -3.0271440e-002 5.2106080e-002 -1.7676140e-002 +v -9.1087300e-003 1.1141669e-001 -2.0543230e-002 +v -5.7069360e-002 5.4424380e-002 2.3395500e-003 +v -3.2748380e-002 1.7759875e-001 -1.1627470e-002 +v -2.9009580e-002 5.1265290e-002 -2.2175780e-002 +v -3.1383130e-002 5.1791310e-002 -1.3886800e-002 +v -5.5673960e-002 5.6983850e-002 -3.3510400e-003 +v -5.0916050e-002 5.3813610e-002 1.9753140e-002 +v -8.8875380e-002 1.5169443e-001 2.0086580e-002 +v -7.7153050e-002 1.7378676e-001 -4.7867620e-002 +v -7.8577770e-002 1.6420639e-001 -3.1825860e-002 +v -2.7545910e-002 5.4021570e-002 -2.5147390e-002 +v -5.4463660e-002 5.5357450e-002 1.0326840e-002 +v -8.7041410e-002 1.3058932e-001 9.1161000e-004 +v -9.0009340e-002 1.3278082e-001 5.9220600e-003 +v -9.2232620e-002 1.3195400e-001 1.5430650e-002 +v -4.8639980e-002 1.6472475e-001 -5.0591500e-003 +v -5.4066480e-002 5.9959350e-002 -7.5992200e-003 +v -5.7434090e-002 5.7683500e-002 8.7259700e-003 +v -8.6794730e-002 1.3850688e-001 4.5575900e-003 +v -9.2989530e-002 1.3092307e-001 1.9919290e-002 +v -9.1282030e-002 1.3311897e-001 2.4688630e-002 +v 2.1815020e-002 1.1770533e-001 -1.0015300e-002 +v -2.9647120e-002 5.8104260e-002 -2.1311320e-002 +v -3.1289530e-002 5.5208570e-002 -1.4387840e-002 +v -5.9002160e-002 5.9234620e-002 2.6140800e-003 +v -9.0241700e-002 1.3575994e-001 1.4149160e-002 +v -6.1569420e-002 1.7084875e-001 -6.1679170e-002 +v -6.6070180e-002 1.6557822e-001 -5.8644080e-002 +v -2.4539930e-002 1.8005865e-001 -1.8726950e-002 +v -1.6131750e-002 1.8298848e-001 -2.6037190e-002 +v -3.0809390e-002 5.6998040e-002 -1.7835020e-002 +v 1.0464280e-002 9.6180450e-002 -2.5898970e-002 +v -5.7491630e-002 5.9530160e-002 -1.0786100e-003 +v -8.9146460e-002 1.3650500e-001 2.5952780e-002 +v 4.3714500e-003 1.0391901e-001 -2.1515100e-002 +v -9.0377040e-002 1.3252490e-001 3.1082650e-002 +v -9.0795450e-002 1.3855232e-001 2.0562560e-002 +v -9.4237710e-002 1.2615419e-001 2.2201450e-002 +v -9.0336910e-002 1.3119830e-001 3.8138790e-002 +v -4.5082610e-002 1.2218447e-001 -1.1569430e-002 +v 1.1348010e-002 9.8243750e-002 -2.3024250e-002 +v -3.9227920e-002 9.9184630e-002 -2.1912720e-002 +v -6.5509530e-002 1.5857325e-001 -5.5600270e-002 +v -7.7409510e-002 1.6260515e-001 -2.0754580e-002 +v -4.8580010e-002 1.6689211e-001 -2.5256100e-003 +v -7.6922910e-002 1.5351394e-001 -9.0785600e-003 +v -6.7750580e-002 1.5734825e-001 -5.3982110e-002 +v 5.2906410e-002 6.5230450e-002 -5.1112000e-004 +v -2.9054820e-002 6.1084120e-002 -2.4918230e-002 +v -3.1066920e-002 6.5058860e-002 -2.2751080e-002 +v 2.4249720e-002 1.0266151e-001 -1.8313830e-002 +v -5.5473660e-002 1.6050213e-001 1.3763500e-003 +v -6.6642850e-002 1.6040875e-001 -5.6842680e-002 +v -7.8200320e-002 1.6073213e-001 -2.3999690e-002 +v -1.8320680e-002 1.1968625e-001 -1.1110660e-002 +v 2.1712970e-002 1.0956342e-001 -1.5081090e-002 +v -6.8382640e-002 1.5980248e-001 -5.4208800e-002 +v -2.5445620e-002 6.0208550e-002 -3.0864700e-002 +v -2.6540330e-002 6.5084000e-002 -3.1664870e-002 +v -2.8425710e-002 6.2199610e-002 -2.7938500e-002 +v -3.2605750e-002 6.1264600e-002 -1.5453010e-002 +v -7.0872290e-002 1.1611638e-001 -7.9563700e-003 +v -6.9780530e-002 1.5938570e-001 -4.9418240e-002 +v -3.0324870e-002 6.7694720e-002 -2.7654950e-002 +v -3.2977370e-002 6.6365180e-002 -1.8385530e-002 +v 1.3533490e-002 1.0255388e-001 -2.1579310e-002 +v 4.4408530e-002 6.9758860e-002 9.4765000e-004 +v -2.1999000e-003 1.1215881e-001 -1.9658660e-002 +v -7.2028500e-002 6.7046610e-002 -7.2256000e-004 +v -7.8699630e-002 1.7313910e-001 -4.2720470e-002 +v -8.3211970e-002 1.5072131e-001 4.2128500e-003 +v -8.7439060e-002 1.3374875e-001 2.3974700e-003 +v 2.6348020e-002 8.4562230e-002 -2.3151710e-002 +v -7.4901490e-002 7.0419350e-002 -2.2854300e-003 +v -5.4576350e-002 9.1562950e-002 -2.2098700e-002 +v -7.3242520e-002 1.5231332e-001 -3.5703520e-002 +v -7.4550960e-002 1.7218738e-001 -4.7551010e-002 +v -2.8680680e-002 6.8283500e-002 -3.0610160e-002 +v 1.7372900e-002 1.0246037e-001 -2.1487700e-002 +v -8.1257430e-002 7.3025200e-002 7.1020400e-003 +v -7.4982300e-002 1.5407794e-001 -1.8974470e-002 +v -9.1556500e-002 1.3196262e-001 1.0638150e-002 +v -8.2448000e-004 9.5165120e-002 -3.2056320e-002 +v -7.7618830e-002 7.3999130e-002 -5.3263500e-003 +v -7.9858790e-002 7.2755040e-002 3.0420200e-003 +v -8.1627470e-002 7.3470610e-002 1.1161690e-002 +v -7.3679290e-002 1.4785987e-001 -2.0236290e-002 +v -9.1309820e-002 1.4848588e-001 1.6270070e-002 +v -9.0850140e-002 1.4625613e-001 1.4809050e-002 +v -6.8543890e-002 1.7513008e-001 -5.7187900e-002 +v -2.7253960e-002 1.0747453e-001 -2.1279680e-002 +v 2.1443580e-002 1.2273826e-001 -2.9316700e-003 +v -7.9061200e-002 7.3724300e-002 -8.4521000e-004 +v -8.2063500e-002 7.5993670e-002 1.7615500e-003 +v -8.3736580e-002 7.6771840e-002 8.9586000e-003 +v -9.0205720e-002 1.4947775e-001 1.3035090e-002 +v 8.4818000e-004 1.1670025e-001 -1.7337090e-002 +v -7.4577550e-002 1.5164041e-001 -2.8647990e-002 +v -2.9087460e-002 7.2924630e-002 -3.3354470e-002 +v -3.1184020e-002 7.3989530e-002 -3.0339870e-002 +v -3.2606620e-002 7.1955620e-002 -2.4866580e-002 +v -8.0575990e-002 7.6607800e-002 -2.9879400e-003 +v -8.9491020e-002 1.4392581e-001 1.2488490e-002 +v -7.7388410e-002 1.4656426e-001 -4.3543000e-003 +v -7.2896160e-002 1.5834962e-001 -3.4109420e-002 +v 7.1346500e-003 1.1468229e-001 -1.8345640e-002 +v -3.4502610e-002 7.6130020e-002 -2.2373150e-002 +v -8.3890740e-002 8.0789530e-002 2.2951400e-003 +v -8.3740480e-002 7.7240270e-002 4.6673300e-003 +v -8.6204620e-002 8.0930750e-002 1.0535420e-002 +v -8.6061500e-002 7.9931100e-002 1.4440780e-002 +v -8.1542760e-002 7.7950660e-002 2.6727280e-002 +v 2.6666170e-002 1.1268609e-001 -1.0509540e-002 +v -7.6041430e-002 1.5663068e-001 -2.1420480e-002 +v -9.0012110e-002 1.5083344e-001 1.5752740e-002 +v -7.1156510e-002 1.6335125e-001 -4.5360530e-002 +v -3.3210960e-002 7.6873190e-002 -2.7708380e-002 +v -7.3263090e-002 7.9983830e-002 -1.3749940e-002 +v -7.9285950e-002 8.0048830e-002 -7.0125500e-003 +v -8.6034510e-002 8.2645720e-002 1.9542680e-002 +v -8.4335410e-002 8.0729950e-002 2.2180460e-002 +v -7.1351460e-002 1.5727092e-001 -4.2183090e-002 +v -7.3548450e-002 1.6120822e-001 -3.5288420e-002 +v 1.6732620e-002 1.0991230e-001 -1.7020040e-002 +v -3.0978770e-002 7.7020860e-002 -3.2816490e-002 +v -6.2359240e-002 1.7544824e-001 -6.1485990e-002 +v -1.7587870e-002 1.1491318e-001 -1.7205040e-002 +v -8.2354050e-002 8.0876320e-002 -2.4038900e-003 +v -7.8578910e-002 1.4050129e-001 -4.6031000e-003 +v -2.8931080e-002 7.9247620e-002 -3.5049800e-002 +v -3.1225710e-002 8.0413100e-002 -3.2182320e-002 +v -3.3258680e-002 7.9621670e-002 -2.7146060e-002 +v -4.4697400e-002 1.1791537e-001 -1.4725860e-002 +v -7.9723740e-002 8.4226660e-002 -8.7608600e-003 +v -8.5042160e-002 8.3817830e-002 -7.7640000e-005 +v -8.6776400e-002 8.4344860e-002 1.2419030e-002 +v -8.6674670e-002 8.2665010e-002 1.5174340e-002 +v -8.5106250e-002 8.5176580e-002 2.5679440e-002 +v -7.6975760e-002 8.2935940e-002 -1.1450630e-002 +v -8.2776390e-002 8.3430890e-002 -4.3687000e-003 +v -8.6180440e-002 8.2572150e-002 6.3639000e-003 +v -9.1160820e-002 1.4144362e-001 1.5673910e-002 +v -7.4638800e-002 1.4398484e-001 -7.1504600e-003 +v -8.3448500e-002 1.3393299e-001 -1.6873200e-003 +v -7.5804700e-002 1.5134475e-001 -1.9881200e-002 +v -7.4924140e-002 1.5273013e-001 -1.9397440e-002 +v -5.2314440e-002 1.2159646e-001 -1.0798060e-002 +v -3.0734050e-002 8.5427560e-002 -3.0506670e-002 +v -3.2590560e-002 8.1942660e-002 -2.9100210e-002 +v -8.6454830e-002 8.6940490e-002 9.1667000e-004 +v -1.2501820e-002 1.0634409e-001 -2.2360190e-002 +v -8.8585880e-002 1.4605869e-001 9.8780000e-003 +v -8.5609750e-002 1.4712513e-001 6.5981100e-003 +v -8.7511210e-002 1.5061504e-001 1.0152460e-002 +v -6.0113540e-002 3.5550440e-002 4.4907580e-002 +v -8.8284200e-002 8.6869110e-002 8.1029200e-003 +v -8.8812560e-002 8.7765490e-002 1.4226540e-002 +v -8.8001070e-002 8.6626430e-002 1.5466680e-002 +v -8.6991110e-002 8.6444700e-002 2.2420950e-002 +v -7.4609990e-002 1.4727815e-001 -1.4172380e-002 +v -3.4707910e-002 8.4035880e-002 -2.4302260e-002 +v -8.4964900e-002 8.9962540e-002 -3.0068000e-003 +v -8.8091450e-002 8.7741580e-002 4.8489900e-003 +v -9.1490470e-002 1.4543178e-001 2.2277220e-002 +v -9.4380420e-002 1.2183919e-001 1.7904340e-002 +v -2.9164530e-002 8.5393440e-002 -3.3666780e-002 +v -3.0557790e-002 8.8625920e-002 -2.7550670e-002 +v -7.7770550e-002 8.7844840e-002 -1.1694810e-002 +v -8.0728260e-002 8.8204150e-002 -7.8003100e-003 +v -8.3272540e-002 8.9476690e-002 -5.6502900e-003 +v -8.9398710e-002 8.9539000e-002 1.1645550e-002 +v -8.9698390e-002 1.3971257e-001 1.3774760e-002 +v -7.7134890e-002 1.5151225e-001 -5.5823000e-003 +v -5.1121410e-002 1.6374125e-001 -2.6640500e-003 +v -8.6442960e-002 1.2767438e-001 -1.4864100e-003 +v -6.9605590e-002 1.5490763e-001 -5.0188670e-002 +v -8.7265180e-002 9.2110030e-002 4.2059000e-003 +v -8.9086250e-002 9.2377120e-002 1.0569860e-002 +v -8.9612340e-002 9.1599880e-002 1.7812280e-002 +v -8.2732460e-002 1.4196856e-001 1.2529100e-003 +v -7.2618370e-002 1.4368135e-001 -1.0987100e-002 +v -7.7677230e-002 1.6610992e-001 -3.6777320e-002 +v -1.5078060e-002 9.3863440e-002 -3.4317310e-002 +v -7.1057280e-002 1.5476885e-001 -4.5778530e-002 +v -9.2331920e-002 1.2523886e-001 9.1589500e-003 +v -7.6046700e-002 9.1037250e-002 -1.3643150e-002 +v -8.2942810e-002 9.3291700e-002 -6.1856300e-003 +v -1.0411170e-002 9.4592340e-002 -3.3784850e-002 +v -2.9331140e-002 1.1476230e-001 -1.5844640e-002 +v -3.7218250e-002 1.1594244e-001 -1.5173050e-002 +v -1.2429920e-002 1.0286006e-001 -2.3822480e-002 +v 6.6509600e-003 8.8144500e-002 -3.2945810e-002 +v -6.4119900e-003 9.2876210e-002 -3.4817640e-002 +v 1.5800150e-002 1.1996558e-001 -1.1415630e-002 +v 2.9102740e-002 1.0247506e-001 -1.5768380e-002 +v 4.2080690e-002 6.3480630e-002 -2.5405300e-003 +v 2.8723120e-002 9.7943220e-002 -1.7497350e-002 +v -1.9987640e-002 1.0278313e-001 -2.3392920e-002 +v 3.3748350e-002 8.3644140e-002 -1.8630450e-002 +v -1.8685680e-002 1.8689625e-001 -2.0248700e-002 +v 6.4154900e-003 1.1790181e-001 -1.6282740e-002 +v 5.6305210e-002 6.7769910e-002 2.6525000e-003 +v -5.3608300e-003 1.1289400e-001 -1.9613290e-002 +v 4.5769430e-002 6.4628800e-002 -1.2166100e-003 +v -1.0090870e-002 9.8229650e-002 -2.7731360e-002 +v -6.0458520e-002 1.1755645e-001 -1.1354580e-002 +v 1.2933940e-002 1.1887250e-001 -1.3979370e-002 +v 1.5235680e-002 9.4977900e-002 -2.4437140e-002 +v -3.0892950e-002 4.7409030e-002 -2.4954000e-002 +v -1.7766190e-002 1.8572344e-001 -2.3049280e-002 +v -1.3034890e-002 1.1002855e-001 -2.0161170e-002 +v -7.1206550e-002 3.8608570e-002 7.7218000e-004 +v 1.7904800e-002 1.0627709e-001 -1.7729250e-002 +v -3.3623490e-002 1.1840428e-001 -1.1927480e-002 +v -4.9906840e-002 1.1788332e-001 -1.4402480e-002 +v -6.6878100e-003 1.1747209e-001 -1.5359280e-002 +v -1.5451470e-002 1.8597600e-001 -2.4795870e-002 +v -3.0603900e-002 3.8038460e-002 -3.0123840e-002 +v -1.3220270e-002 1.8397188e-001 -2.7519460e-002 +v -4.7859450e-002 1.1162729e-001 -1.7482120e-002 +v -1.3098990e-002 9.0776040e-002 -3.6659270e-002 +v -6.3117340e-002 1.5425437e-001 2.9730400e-003 +v -5.5139750e-002 1.1051601e-001 -1.7672740e-002 +v -1.1096770e-002 1.8202324e-001 -2.8042450e-002 +v -2.6568900e-002 3.4695830e-002 -2.9113750e-002 +v -6.6396600e-003 1.0222209e-001 -2.3519320e-002 +v -5.6996400e-002 1.5741713e-001 6.0244000e-004 +v 1.9076550e-002 9.1870620e-002 -2.4890230e-002 +v 1.3473090e-002 1.2429893e-001 -6.8361400e-003 +v -2.1730490e-002 9.8410960e-002 -2.4306850e-002 +v -1.7142170e-002 9.8057460e-002 -2.4924330e-002 +v -5.8698110e-002 1.5137318e-001 -6.5801000e-004 +v 3.5641100e-003 1.2764883e-001 -4.4672400e-003 +v -8.5369800e-003 9.9921220e-002 -2.4351070e-002 +v -1.2171980e-002 1.8125102e-001 -2.9061170e-002 +v -6.1113980e-002 1.5305212e-001 9.9983000e-004 +v -2.9570620e-002 1.1713871e-001 -1.3675530e-002 +v 3.0530110e-002 1.1221207e-001 -8.1860600e-003 +v -3.1714100e-002 3.5111530e-002 -3.0658990e-002 +v -1.3691130e-002 1.7914707e-001 -2.8126410e-002 +v 1.1620840e-002 1.1548972e-001 -1.6385680e-002 +v -6.1993570e-002 1.5028063e-001 -1.6297100e-003 +v 3.6684020e-002 1.0099570e-001 -9.8485900e-003 +v 4.8512670e-002 7.1798180e-002 6.0005000e-003 +v -4.6583000e-004 1.1983662e-001 -1.3610580e-002 +v 1.6747170e-002 9.0113950e-002 -2.7127190e-002 +v 6.9832400e-003 9.7730080e-002 -2.4800310e-002 +v -4.3226830e-002 4.6263570e-002 -1.1771730e-002 +v -8.3562500e-003 1.1373600e-001 -1.8239810e-002 +v -1.2354410e-002 1.1556773e-001 -1.6486930e-002 +v 4.6834470e-002 7.4354100e-002 1.0139500e-002 +v 2.5319170e-002 1.0931725e-001 -1.3579660e-002 +v -4.2459500e-002 1.1392482e-001 -1.6188050e-002 +v 5.7744640e-002 6.4158440e-002 2.6277600e-003 +v -5.9710530e-002 3.6535780e-002 -9.4949000e-003 +v -3.2078400e-003 1.0962100e-001 -2.1523850e-002 +v 2.7020740e-002 6.1345700e-002 -2.2292060e-002 +v 7.1030200e-003 1.0191162e-001 -2.1230990e-002 +v -3.8225680e-002 1.2465525e-001 -7.3257400e-003 +v 2.5941540e-002 1.1576352e-001 -8.2193900e-003 +v -6.1297960e-002 3.3900220e-002 -9.3216600e-003 +v -5.9466670e-002 1.4743956e-001 -1.8885400e-003 +v 1.0506610e-002 1.0087700e-001 -2.2109510e-002 +v 3.3081340e-002 1.0273382e-001 -1.2787210e-002 +v 1.2517840e-002 1.0475378e-001 -1.9915960e-002 +v 2.3087990e-002 9.3998720e-002 -2.2210680e-002 +v 3.1555430e-002 9.2484730e-002 -1.8204280e-002 +v 6.2723100e-003 9.9910370e-002 -2.2296890e-002 +v -4.0917240e-002 4.6121780e-002 -1.7942580e-002 +v 3.5407360e-002 9.8188850e-002 -1.2008970e-002 +v 9.4135900e-003 1.2121902e-001 -1.2937780e-002 +v 5.3735190e-002 7.2027350e-002 6.8010000e-003 +v 2.5620340e-002 1.1880719e-001 -5.0330800e-003 +v -3.8150260e-002 4.2466610e-002 -2.6893990e-002 +v -2.8212410e-002 1.1116862e-001 -1.8001930e-002 +v -6.0253590e-002 1.4339100e-001 -3.7906300e-003 +v 1.9016880e-002 1.0401450e-001 -1.9333120e-002 +v 7.5446700e-003 9.1682150e-002 -3.1643140e-002 +v -7.0760800e-003 1.2240119e-001 -1.1364410e-002 +v -1.9047500e-002 9.6562130e-002 -2.7579900e-002 +v -1.6953390e-002 1.0669256e-001 -2.2002990e-002 +v -6.7307000e-004 1.0119875e-001 -2.2857770e-002 +v -9.0179300e-003 1.2528031e-001 -7.7912000e-003 +v -6.8136180e-002 1.8006113e-001 -5.8816050e-002 +v -2.3600190e-002 1.1513818e-001 -1.5577390e-002 +v -5.9831220e-002 4.2842260e-002 -6.6469100e-003 +v 5.3124070e-002 5.9012380e-002 -2.8853800e-003 +v -3.6931840e-002 3.7107370e-002 -2.9714170e-002 +v -5.6215140e-002 1.4139213e-001 -2.8027300e-003 +v 3.6695880e-002 1.0372844e-001 -7.9621500e-003 +v -3.5885070e-002 1.2040038e-001 -1.0640470e-002 +v -9.3569500e-003 8.5423730e-002 -3.8112540e-002 +v -6.0127340e-002 1.2041391e-001 -9.3791100e-003 +v -3.9842790e-002 1.2156113e-001 -1.1570310e-002 +v 2.8322200e-002 1.0847957e-001 -1.2623390e-002 +v -1.8733500e-003 1.1593910e-001 -1.7169430e-002 +v 3.8648150e-002 9.0153340e-002 -1.2549680e-002 +v -1.7359200e-003 9.2244170e-002 -3.4310460e-002 +v 5.0000820e-002 6.1612070e-002 -3.4649900e-003 +v 5.5858960e-002 6.2910170e-002 6.9037000e-004 +v 2.0461520e-002 1.1515372e-001 -1.3103780e-002 +v -1.5165840e-002 1.1798075e-001 -1.4465520e-002 +v -7.0859540e-002 7.1510150e-002 3.3895100e-002 +v 2.2674030e-002 8.6606050e-002 -2.4925490e-002 +v 3.5358840e-002 8.7438890e-002 -1.7109050e-002 +v 1.8400920e-002 1.2145507e-001 -7.6804200e-003 +v -2.5425900e-002 4.1421010e-002 -2.9204830e-002 +v -8.2085100e-003 9.6777440e-002 -3.0809780e-002 +v -5.6810660e-002 3.3873940e-002 -1.1166310e-002 +v -3.4588640e-002 4.4744960e-002 -2.7122900e-002 +v -4.0251680e-002 1.1827531e-001 -1.3674080e-002 +v 1.6387020e-002 1.1402346e-001 -1.5496900e-002 +v 4.2635280e-002 6.0797460e-002 -3.4583700e-003 +v -5.0687200e-002 3.5935870e-002 -1.2380790e-002 +v 7.3446800e-003 9.4509570e-002 -2.9683220e-002 +v -1.9706700e-002 9.2917340e-002 -3.4636880e-002 +v -1.2083040e-002 1.2219229e-001 -9.7120900e-003 +v 4.8805930e-002 6.8457810e-002 1.6952900e-003 +v -3.0869700e-003 9.8402500e-002 -2.7403170e-002 +v -5.3198790e-002 1.3672896e-001 -1.6580500e-003 +v -4.7290060e-002 1.3055355e-001 1.6909100e-003 +v 4.4651700e-003 1.2044039e-001 -1.3931400e-002 +v -2.3850100e-003 1.2290534e-001 -1.0382460e-002 +v -2.4833330e-002 9.5858030e-002 -2.5162110e-002 +v -4.2296900e-002 3.6291920e-002 -2.7253600e-002 +v -5.4388260e-002 1.3404922e-001 -3.9920400e-003 +v -5.0539380e-002 1.3336659e-001 -1.0872200e-003 +v 2.6040300e-003 9.6942660e-002 -2.8407060e-002 +v -7.8163100e-003 1.2821209e-001 -1.9430400e-003 +v 6.5111700e-003 1.3002517e-001 9.2881000e-004 +v 3.4742860e-002 9.2274140e-002 -1.5654590e-002 +v -6.7787700e-002 1.8088887e-001 -5.8191050e-002 +v -3.3715410e-002 1.1151566e-001 -1.8078440e-002 +v 4.4630400e-003 1.2427294e-001 -9.4291400e-003 +v -2.3370170e-002 9.3392760e-002 -3.2031820e-002 +v -4.8982070e-002 1.2980647e-001 -1.3229400e-003 +v -7.8164000e-004 1.2822918e-001 -3.2490000e-003 +v 2.4960400e-003 8.9857600e-002 -3.3628450e-002 +v 7.4553300e-003 1.1196790e-001 -1.9554260e-002 +v 2.8791140e-002 9.1157340e-002 -2.0370210e-002 +v -5.3590150e-002 1.2437450e-001 -7.3470400e-003 +v -4.7743630e-002 1.2064432e-001 -1.2812990e-002 +v -1.9616230e-002 1.2109197e-001 -9.5487700e-003 +v -6.5047370e-002 1.7999148e-001 -5.9758600e-002 +v -5.1704160e-002 3.7620360e-002 -1.1763450e-002 +v -5.2124270e-002 1.2929832e-001 -4.1187000e-003 +v -4.5334450e-002 1.2891494e-001 1.5819100e-003 +v -3.0471200e-003 1.2919453e-001 -1.0688000e-003 +v 7.2129600e-003 1.2721957e-001 -5.2073700e-003 +v 1.1669320e-002 1.2720154e-001 -3.1850900e-003 +v 5.3056400e-002 6.9708830e-002 3.1291400e-003 +v -6.3021150e-002 1.7810951e-001 -6.0393570e-002 +v 2.8204800e-002 6.4391270e-002 -2.0698040e-002 +v 3.4400180e-002 1.0503000e-001 -1.0224920e-002 +v 3.0975190e-002 1.0790250e-001 -1.1058430e-002 +v -4.8984390e-002 1.1480518e-001 -1.5966690e-002 +v -3.2821710e-002 1.2300500e-001 -5.9088300e-003 +v -5.0792860e-002 1.2716487e-001 -4.8183200e-003 +v -3.5301670e-002 1.2547815e-001 -3.1542800e-003 +v 5.6455250e-002 6.9951490e-002 4.9191700e-003 +v -1.6240450e-002 1.2512177e-001 -3.6499700e-003 +v -1.6970400e-002 1.1119793e-001 -1.9586410e-002 +v -5.4088120e-002 3.9781210e-002 -1.0544680e-002 +v -3.4190490e-002 4.7514010e-002 -2.2301500e-002 +v 1.3699090e-002 9.3914220e-002 -2.6427690e-002 +v 8.8000000e-004 9.9234930e-002 -2.4355670e-002 +v -4.6459460e-002 1.2723953e-001 -4.8843300e-003 +v -4.1735500e-002 1.2687599e-001 -4.1742000e-003 +v -2.1000480e-002 1.2313643e-001 -6.1190100e-003 +v -1.2130450e-002 1.2572568e-001 -5.2007900e-003 +v -4.3822400e-003 1.2640753e-001 -6.9495200e-003 +v 1.4085700e-003 3.4781990e-002 -2.3265200e-002 +v -1.4846200e-002 3.5070930e-002 -2.6071900e-002 +v -2.1399500e-002 3.4795120e-002 -2.7958820e-002 +v 1.2009220e-002 3.5961900e-002 -2.1735750e-002 +v 3.8249200e-003 3.6129220e-002 -2.3878090e-002 +v -5.1139560e-002 9.6617580e-002 -2.2095120e-002 +v -5.4813320e-002 9.8102480e-002 -2.1425370e-002 +v -2.7597040e-002 1.6979824e-001 -1.8170420e-002 +v 1.3359870e-002 3.9377410e-002 -2.2496330e-002 +v 4.3919300e-003 3.8674430e-002 -2.4170290e-002 +v -6.8478200e-003 3.6444540e-002 -2.5177120e-002 +v -1.3280260e-002 3.7699590e-002 -2.6391810e-002 +v -4.7672760e-002 3.6116650e-002 -1.3301210e-002 +v -4.5590120e-002 1.0853826e-001 -1.8796680e-002 +v -5.0095670e-002 1.0990925e-001 -1.8504510e-002 +v -6.5766640e-002 3.6469550e-002 -7.2073000e-003 +v -2.3455840e-002 1.6824727e-001 -1.8822880e-002 +v -4.5918000e-003 3.8404570e-002 -2.5412870e-002 +v -2.4954130e-002 3.7441060e-002 -2.9152720e-002 +v 2.9007770e-002 3.7358220e-002 -2.7474000e-004 +v -7.9468800e-003 4.1489920e-002 -2.5911270e-002 +v -1.6803800e-002 3.9753810e-002 -2.7565350e-002 +v -6.5156150e-002 1.4034537e-001 -7.6848600e-003 +v -4.7080100e-002 4.0700690e-002 -1.1869830e-002 +v -6.8470630e-002 3.7477700e-002 -4.9557400e-003 +v 3.7326850e-002 4.0209510e-002 -8.5850000e-004 +v 3.5349870e-002 4.1257050e-002 -2.8075100e-003 +v 5.1820700e-003 4.1536320e-002 -2.4065670e-002 +v 1.8660660e-002 1.0030784e-001 -2.2127290e-002 +v -6.0510780e-002 1.0748450e-001 -1.7042300e-002 +v -6.2374340e-002 4.0146090e-002 -7.4040200e-003 +v 2.5456950e-002 3.9483890e-002 -4.0251400e-003 +v -2.2828000e-004 4.3394940e-002 -2.5124420e-002 +v -8.1088400e-003 4.3439060e-002 -2.6140070e-002 +v -1.7362450e-002 4.3237420e-002 -2.7665190e-002 +v -2.6416670e-002 4.4674020e-002 -2.8209740e-002 +v 3.8064500e-003 1.0944331e-001 -2.0203790e-002 +v -5.8232370e-002 9.5690400e-002 -2.0616030e-002 +v -6.6122370e-002 4.2341260e-002 -2.7538800e-003 +v -6.0959920e-002 9.4173040e-002 -1.9015670e-002 +v 3.1352250e-002 4.2649280e-002 -4.6745000e-003 +v -3.3540900e-002 3.6342620e-002 4.9089960e-002 +v 1.7252780e-002 4.4335610e-002 -2.3067190e-002 +v 1.0637660e-002 4.4161560e-002 -2.4926170e-002 +v 4.3843100e-003 4.5806710e-002 -2.6788990e-002 +v -8.2506400e-003 4.5148720e-002 -2.8441070e-002 +v -1.5748410e-002 4.5043860e-002 -2.7877790e-002 +v 2.8990330e-002 4.4697850e-002 -6.1863000e-003 +v 8.1686400e-003 4.5053030e-002 -2.5178740e-002 +v -9.6291000e-004 4.5378230e-002 -2.7308280e-002 +v -1.7033400e-003 4.7819200e-002 -2.9928930e-002 +v -3.1535830e-002 4.4740410e-002 -2.8079410e-002 +v -3.3619650e-002 1.5691468e-001 -1.1024870e-002 +v -5.0751180e-002 4.3109620e-002 -1.0018680e-002 +v 3.6890890e-002 4.7353200e-002 -6.1057100e-003 +v 2.4975630e-002 4.2644580e-002 -7.0169900e-003 +v 2.4562420e-002 4.8369560e-002 -1.9672760e-002 +v 1.3964040e-002 4.5579170e-002 -2.4706510e-002 +v 1.3376130e-002 4.8630300e-002 -2.6551500e-002 +v 3.7308900e-003 4.8127990e-002 -2.9025970e-002 +v -8.7947000e-003 4.7056850e-002 -2.9881630e-002 +v -1.3753770e-002 5.1865060e-002 -3.2243480e-002 +v -2.1200840e-002 4.6657090e-002 -2.7951320e-002 +v 3.9693540e-002 4.5658580e-002 -4.5274100e-003 +v 3.3627400e-002 4.8717730e-002 -6.3904600e-003 +v -6.5352120e-002 9.9294570e-002 -1.6820150e-002 +v 1.2868100e-003 5.0383670e-002 -3.0357440e-002 +v -8.1797500e-003 4.9845800e-002 -3.1071390e-002 +v -1.7184350e-002 4.8210500e-002 -2.9741930e-002 +v -2.6049450e-002 4.7692500e-002 -2.6149500e-002 +v -8.4747010e-002 1.1078350e-001 3.9488380e-002 +v -5.1316870e-002 4.8270690e-002 -7.9310500e-003 +v -8.2506510e-002 1.2765487e-001 -4.6796400e-003 +v 3.8663690e-002 5.1696670e-002 -6.6910200e-003 +v -7.5643160e-002 9.9440450e-002 -1.1927610e-002 +v 2.0284470e-002 5.1349190e-002 -2.4895380e-002 +v 5.9436000e-003 5.0976660e-002 -2.9119360e-002 +v -2.5528290e-002 5.1472710e-002 -2.6884680e-002 +v -3.5562670e-002 4.9399890e-002 -1.2865040e-002 +v -4.2818980e-002 1.6220182e-001 -1.0337510e-002 +v -6.5593600e-002 1.7665711e-001 -6.0504730e-002 +v -3.4151080e-002 1.7442797e-001 -1.3312550e-002 +v 4.3673180e-002 5.0162230e-002 -5.9843500e-003 +v -5.0342410e-002 1.5546197e-001 -5.1927700e-003 +v 2.5464180e-002 5.4029700e-002 -2.1691010e-002 +v 1.0149790e-002 4.9258540e-002 -2.7750590e-002 +v -2.2043190e-002 5.3612020e-002 -3.0135610e-002 +v -3.2875520e-002 5.1677630e-002 -1.0888650e-002 +v -3.7613820e-002 4.9534770e-002 -1.1626140e-002 +v -4.0750630e-002 4.9285110e-002 -1.1286200e-002 +v -4.6385170e-002 4.7490850e-002 -1.0085980e-002 +v 4.4473170e-002 5.3293010e-002 -6.3327900e-003 +v 3.3205620e-002 5.1020650e-002 -7.2382500e-003 +v 1.5678350e-002 5.1169270e-002 -2.6397810e-002 +v 6.8341700e-003 5.5010170e-002 -3.0561130e-002 +v 2.1424700e-003 5.5502800e-002 -3.1334400e-002 +v 5.9285000e-004 5.2867950e-002 -3.0513830e-002 +v -3.6481400e-003 5.1869000e-002 -3.1457940e-002 +v -9.4245600e-003 5.5399220e-002 -3.3653980e-002 +v -1.9302150e-002 5.8224770e-002 -3.3919700e-002 +v -6.1084270e-002 1.3386190e-001 -7.2248900e-003 +v -4.3309760e-002 5.5656840e-002 -1.1402110e-002 +v -6.1080540e-002 1.6833773e-001 -5.9192060e-002 +v 4.7574690e-002 5.2943630e-002 -5.1300300e-003 +v -3.7403030e-002 1.1150775e-001 -1.8243310e-002 +v 1.9972490e-002 5.4409710e-002 -2.7108230e-002 +v 5.3974800e-003 5.8382570e-002 -3.0903760e-002 +v -1.0603590e-002 5.3602910e-002 -3.3403350e-002 +v -3.4998290e-002 5.2331560e-002 -1.0347380e-002 +v -4.6471230e-002 5.1304340e-002 -9.8299800e-003 +v -6.7945360e-002 1.1493603e-001 -9.5107300e-003 +v -7.1048210e-002 1.5161088e-001 -4.4679270e-002 +v -5.8903800e-003 3.4790620e-002 -2.4224470e-002 +v 1.6842140e-002 5.5555670e-002 -2.8284560e-002 +v 1.0711040e-002 5.4687610e-002 -2.9767520e-002 +v -1.1826800e-003 5.9492420e-002 -3.3360920e-002 +v -5.2325900e-003 5.5688960e-002 -3.2840220e-002 +v -5.1705830e-002 5.2470760e-002 -7.4047200e-003 +v -5.2626360e-002 6.0043760e-002 -8.9566900e-003 +v -7.2598590e-002 9.7762720e-002 -1.4434510e-002 +v 4.4331260e-002 5.5818010e-002 -6.0362700e-003 +v 3.8463400e-002 5.4934820e-002 -6.1822500e-003 +v 3.8838620e-002 5.7808260e-002 -5.2584800e-003 +v -9.2015400e-003 5.9510130e-002 -3.4437110e-002 +v -3.5262560e-002 5.5284900e-002 -1.0545060e-002 +v -3.8336450e-002 5.4503540e-002 -1.0905320e-002 +v -1.7727540e-002 3.6289540e-002 5.2222250e-002 +v 5.0006490e-002 5.8095800e-002 -4.6211800e-003 +v 4.6133970e-002 5.9278810e-002 -4.7769600e-003 +v 1.5110300e-002 5.9819840e-002 -2.8645750e-002 +v 1.0312380e-002 5.7586530e-002 -2.9995250e-002 +v -6.1353400e-003 6.0256790e-002 -3.4695830e-002 +v -1.2318220e-002 5.9396390e-002 -3.5268510e-002 +v -1.4466910e-002 6.3136020e-002 -3.6865870e-002 +v -4.6650260e-002 5.9840950e-002 -1.2135840e-002 +v -5.6572080e-002 1.2480275e-001 -7.1885700e-003 +v -7.9237500e-002 1.2055419e-001 -5.6744800e-003 +v -7.9334790e-002 1.2560650e-001 -6.1175900e-003 +v 2.2340000e-002 5.8492230e-002 -2.6014120e-002 +v 7.6270400e-003 6.2098330e-002 -3.1135840e-002 +v 3.3101700e-003 6.0456840e-002 -3.2481070e-002 +v -1.6811880e-002 6.1275230e-002 -3.5929330e-002 +v -3.2491910e-002 5.7196350e-002 -1.2104730e-002 +v -3.4108240e-002 6.1466560e-002 -1.3053130e-002 +v -3.3896980e-002 5.7025330e-002 -1.1047570e-002 +v -3.8623580e-002 5.8303290e-002 -1.1505750e-002 +v -4.5008400e-002 6.2723940e-002 -1.3390450e-002 +v -5.6896010e-002 1.3398739e-001 -5.6270700e-003 +v -4.4853890e-002 1.5746031e-001 -8.6731600e-003 +v -7.8609550e-002 6.9656870e-002 1.1810740e-002 +v -2.3730020e-002 1.0186156e-001 -2.3836400e-002 +v -2.8122930e-002 9.9322390e-002 -2.3580130e-002 +v -5.0076720e-002 1.4997652e-001 -3.6419700e-003 +v -3.3048420e-002 9.5958590e-002 -2.3426460e-002 +v 1.9520390e-002 6.2064770e-002 -2.7292470e-002 +v -3.8864710e-002 1.0333987e-001 -2.0641400e-002 +v -4.8952940e-002 5.6281090e-002 -1.0220880e-002 +v -5.3993040e-002 1.4498656e-001 -1.1093400e-003 +v -4.5530560e-002 9.8510850e-002 -2.1729510e-002 +v -5.0910960e-002 1.0074570e-001 -2.1619430e-002 +v 2.3245830e-002 6.2792530e-002 -2.5047990e-002 +v 9.7412800e-003 6.3181400e-002 -3.1141370e-002 +v -8.6614000e-004 6.4559630e-002 -3.4490930e-002 +v -8.5264000e-003 6.4001730e-002 -3.5850480e-002 +v -4.8451500e-002 6.4794120e-002 -1.3029910e-002 +v -5.2325160e-002 1.0614813e-001 -1.9271240e-002 +v -5.5265350e-002 1.0216682e-001 -1.9897100e-002 +v -5.9042010e-002 9.9032210e-002 -1.9222950e-002 +v -5.7846760e-002 1.0433496e-001 -1.8525740e-002 +v -2.7113460e-002 1.7332156e-001 -1.8538890e-002 +v 2.2832000e-002 6.7082570e-002 -2.6297510e-002 +v 1.4519060e-002 6.4595540e-002 -2.9855690e-002 +v 1.1471330e-002 6.7581440e-002 -3.0901170e-002 +v -1.7739360e-002 6.6260830e-002 -3.7657310e-002 +v -6.5059750e-002 1.3452104e-001 -8.0899900e-003 +v -7.5829320e-002 1.4244605e-001 -5.8090000e-003 +v -4.1362350e-002 6.1637330e-002 -1.2813770e-002 +v -5.6147890e-002 6.1921550e-002 -5.7541100e-003 +v -6.2126110e-002 6.2845360e-002 -4.5202600e-003 +v -3.7292480e-002 1.6449057e-001 -1.3627050e-002 +v -1.9818920e-002 1.6509494e-001 -1.7608980e-002 +v 6.2881100e-003 6.5416350e-002 -3.2563040e-002 +v -5.9250500e-003 6.9515630e-002 -3.5933480e-002 +v -1.0538630e-002 6.7999180e-002 -3.6517060e-002 +v -3.5385700e-002 6.6817430e-002 -1.5434860e-002 +v -5.3994500e-002 6.4638700e-002 -9.3254900e-003 +v -6.3852310e-002 6.5572310e-002 -6.9393300e-003 +v -6.3920880e-002 1.2774242e-001 -8.5494600e-003 +v -2.6940700e-002 3.6184050e-002 5.3351850e-002 +v 1.9618650e-002 6.7007390e-002 -2.8356120e-002 +v 1.2275180e-002 6.9933940e-002 -3.1553160e-002 +v 5.4265100e-003 6.8247960e-002 -3.2730520e-002 +v -4.4084200e-003 6.6619200e-002 -3.4870250e-002 +v -2.1911350e-002 6.7144790e-002 -3.6535750e-002 +v -4.5643150e-002 1.5466949e-001 -7.2969400e-003 +v -5.1673460e-002 6.6850660e-002 -1.2120350e-002 +v -5.8105180e-002 6.6465950e-002 -1.0044340e-002 +v -5.6992260e-002 1.4311862e-001 -2.2403000e-003 +v -8.0651110e-002 1.3119854e-001 -4.4397800e-003 +v -5.6544310e-002 1.2850938e-001 -6.2014700e-003 +v 1.7758080e-002 7.0138540e-002 -2.9404680e-002 +v 6.4980500e-003 7.0791870e-002 -3.3525310e-002 +v 7.5831000e-004 7.0434460e-002 -3.4462560e-002 +v -1.3235950e-002 6.9292820e-002 -3.7917490e-002 +v -6.7390780e-002 1.1889688e-001 -8.7301400e-003 +v -3.8119520e-002 6.4162310e-002 -1.3829140e-002 +v 1.8527400e-003 1.1303356e-001 -1.9794270e-002 +v -7.5950810e-002 6.8170610e-002 1.8117970e-002 +v -1.0001990e-002 7.2671480e-002 -3.7661370e-002 +v -1.7976070e-002 7.0613770e-002 -3.8443880e-002 +v -2.3035990e-002 7.2778460e-002 -3.8072640e-002 +v -2.6120100e-002 7.1177480e-002 -3.5451530e-002 +v -6.8535420e-002 1.3929375e-001 -7.8046600e-003 +v -3.5263040e-002 7.1067650e-002 -1.8011860e-002 +v -4.1558180e-002 6.9774010e-002 -1.6774100e-002 +v -5.2831730e-002 7.0298920e-002 -1.4864960e-002 +v -6.6978850e-002 6.7638980e-002 -6.8094400e-003 +v -1.0244470e-002 1.7895826e-001 -2.9538870e-002 +v -7.5272650e-002 1.2680098e-001 -8.0241700e-003 +v -8.7359900e-002 1.1248315e-001 4.2049490e-002 +v 8.7503000e-003 7.4301560e-002 -3.3398210e-002 +v -6.4249520e-002 1.6045024e-001 -5.7041470e-002 +v -4.4354010e-002 7.3372220e-002 -1.7874430e-002 +v -4.5762580e-002 6.9445320e-002 -1.5928780e-002 +v -4.7957440e-002 7.2542990e-002 -1.6106990e-002 +v -5.7822630e-002 6.9538010e-002 -1.4416470e-002 +v -7.2071600e-002 7.1538150e-002 -7.4714400e-003 +v 2.5472930e-002 7.4094500e-002 -2.4938540e-002 +v 1.5719730e-002 7.3756350e-002 -2.9747770e-002 +v 4.8214000e-003 7.3763980e-002 -3.4552450e-002 +v -2.2528600e-003 7.3921320e-002 -3.5887190e-002 +v -7.3834900e-003 7.4799620e-002 -3.7223830e-002 +v -2.0225340e-002 7.7095190e-002 -3.9044290e-002 +v -3.4016180e-002 7.2101270e-002 -2.0823150e-002 +v -3.8493370e-002 7.2839870e-002 -1.7502230e-002 +v -6.4392550e-002 7.3116330e-002 -1.5335340e-002 +v -6.4480660e-002 7.0187350e-002 -1.2261750e-002 +v -2.3854330e-002 1.6164528e-001 -1.4504190e-002 +v 2.2104450e-002 7.2692600e-002 -2.6900140e-002 +v 1.5532370e-002 7.6586960e-002 -2.9606940e-002 +v 1.1574050e-002 7.4860570e-002 -3.1383860e-002 +v -1.4731560e-002 7.7640750e-002 -3.8490670e-002 +v -1.6018820e-002 7.4288800e-002 -3.8864420e-002 +v -5.1103620e-002 7.3071950e-002 -1.6243060e-002 +v -5.7989540e-002 7.4017880e-002 -1.7522320e-002 +v -6.9608380e-002 7.2322890e-002 -1.0934430e-002 +v -7.5996110e-002 1.1714132e-001 -6.5577200e-003 +v -3.7987660e-002 1.0751453e-001 -1.9975760e-002 +v 1.0696210e-002 7.9889200e-002 -3.2009580e-002 +v -5.3433400e-003 7.8264580e-002 -3.7476940e-002 +v -2.6081990e-002 7.6191290e-002 -3.6780200e-002 +v -3.9161040e-002 1.5718885e-001 -1.0580510e-002 +v -6.5609880e-002 7.5860010e-002 -1.6750060e-002 +v -7.0177600e-002 7.5663330e-002 -1.3839210e-002 +v -7.4291360e-002 7.4808360e-002 -9.3537900e-003 +v -6.3428890e-002 1.7185387e-001 -6.1412170e-002 +v 3.0684890e-002 7.5726870e-002 -2.0778090e-002 +v 1.9305010e-002 7.9017870e-002 -2.7743990e-002 +v -8.5992100e-003 7.9338730e-002 -3.7905180e-002 +v -2.3200110e-002 7.6568500e-002 -3.8386500e-002 +v -3.8117820e-002 7.6390120e-002 -1.8644360e-002 +v -4.4231130e-002 7.7664130e-002 -1.9026580e-002 +v -5.1025500e-002 7.5705070e-002 -1.8186900e-002 +v -7.0595130e-002 1.2994832e-001 -8.7629200e-003 +v 2.8147660e-002 7.8785370e-002 -2.2432450e-002 +v 7.6016000e-003 7.9435920e-002 -3.3714560e-002 +v 4.9502400e-003 7.8027250e-002 -3.4409750e-002 +v -1.5858350e-002 8.1165550e-002 -3.9185590e-002 +v -1.8502080e-002 8.3343870e-002 -3.9010720e-002 +v -7.9739350e-002 1.3606854e-001 -4.1482100e-003 +v -3.0980180e-002 1.6634656e-001 -1.6241160e-002 +v -3.5749800e-002 7.7248350e-002 -1.9374020e-002 +v -4.8944740e-002 7.9086360e-002 -1.9575700e-002 +v -5.5065860e-002 7.8089190e-002 -1.9755480e-002 +v 2.3706000e-002 8.0240410e-002 -2.5450120e-002 +v 1.2254110e-002 8.3456700e-002 -3.0771580e-002 +v 1.8549900e-003 8.4692790e-002 -3.4838500e-002 +v -2.0857000e-004 7.8941410e-002 -3.5782080e-002 +v -4.2710000e-004 8.2947370e-002 -3.6380660e-002 +v -4.4101600e-003 8.2794510e-002 -3.7467250e-002 +v -3.3202320e-002 1.0578320e-001 -2.0647590e-002 +v -3.9206970e-002 8.1536380e-002 -2.0571000e-002 +v -6.0355410e-002 7.9766610e-002 -1.9375540e-002 +v -4.1771830e-002 1.0396706e-001 -2.0832940e-002 +v -1.1204010e-002 8.2713320e-002 -3.8489610e-002 +v -2.3181500e-002 8.1686990e-002 -3.8329160e-002 +v -2.7233190e-002 8.0570950e-002 -3.6620670e-002 +v -3.5470180e-002 8.0196070e-002 -2.2325910e-002 +v -4.4864210e-002 8.1997900e-002 -2.0473520e-002 +v -5.0647890e-002 8.2309430e-002 -2.1365890e-002 +v -5.5522610e-002 8.1927600e-002 -2.1353790e-002 +v -8.8089610e-002 1.1135484e-001 1.8516150e-002 +v -7.2036080e-002 1.1107918e-001 4.5361400e-002 +v -3.3359780e-002 1.6986395e-001 -1.5448990e-002 +v -6.6839030e-002 6.2170510e-002 2.1576840e-002 +v 3.0730560e-002 8.1968990e-002 -2.0040460e-002 +v 1.6224320e-002 8.6480380e-002 -2.8952010e-002 +v -6.9855630e-002 1.0027892e-001 -1.4847830e-002 +v -6.3836170e-002 8.1704600e-002 -1.8908860e-002 +v -6.7914820e-002 8.0136290e-002 -1.7128200e-002 +v -4.5752080e-002 1.6340754e-001 -8.1780500e-003 +v 1.1727540e-002 8.8010780e-002 -3.0860110e-002 +v 7.3334800e-003 8.5270000e-002 -3.2829380e-002 +v -3.4356500e-003 8.7017890e-002 -3.6461000e-002 +v -2.6964110e-002 8.4512810e-002 -3.6361740e-002 +v -3.6553370e-002 8.5316190e-002 -2.2576200e-002 +v -3.8791090e-002 8.5232710e-002 -2.1917600e-002 +v -5.7676940e-002 8.6258340e-002 -2.1098320e-002 +v -6.2581810e-002 8.6394530e-002 -1.9169290e-002 +v -7.1395340e-002 1.2468846e-001 -8.5944200e-003 +v 1.4801570e-002 9.9040900e-002 -2.2842920e-002 +v -2.1162860e-002 1.7491852e-001 -2.1977110e-002 +v -1.4824250e-002 8.7288840e-002 -3.8317070e-002 +v -2.3285750e-002 8.9468030e-002 -3.6027250e-002 +v -5.1595650e-002 8.4422070e-002 -2.1600960e-002 +v -6.9481040e-002 8.5656460e-002 -1.7198420e-002 +v -7.0917210e-002 1.0754846e-001 -1.1496630e-002 +v 3.0145320e-002 8.6284000e-002 -2.0408140e-002 +v -5.5578110e-002 1.1567692e-001 -1.4645990e-002 +v -8.0981100e-003 8.9070080e-002 -3.6552200e-002 +v -8.1206310e-002 1.1205088e-001 -8.8299000e-004 +v -1.8772170e-002 8.9838040e-002 -3.6991710e-002 +v -2.1100420e-002 8.6587670e-002 -3.7849050e-002 +v -2.5809910e-002 8.8889590e-002 -3.5082250e-002 +v -4.8984800e-002 9.0731760e-002 -2.1817170e-002 +v -3.5874870e-002 3.4776000e-002 -3.0845200e-002 +v -3.3164390e-002 3.3606540e-002 -2.9721880e-002 +v -2.5964020e-002 3.3487000e-002 -2.6321120e-002 +v -1.6717530e-002 3.3611640e-002 -2.4625420e-002 +v -5.3486300e-003 3.3829010e-002 -2.2600430e-002 +v 6.4843500e-003 3.4293000e-002 -2.0854930e-002 +v 1.3950350e-002 3.4880000e-002 -1.8612870e-002 +v -4.2465980e-002 3.4189100e-002 -2.7260650e-002 +v -3.3241100e-002 3.3578760e-002 -2.6719450e-002 +v 6.2813500e-003 3.4165800e-002 -1.8764230e-002 +v -4.4265790e-002 3.3663660e-002 -2.1914420e-002 +v -2.3671460e-002 3.3630970e-002 -2.3217760e-002 +v -1.1558580e-002 3.3895430e-002 -2.1054260e-002 +v -2.0406400e-003 3.4053940e-002 -1.9331070e-002 +v 1.7323900e-003 3.4459660e-002 -1.6607870e-002 +v -2.7316070e-002 3.3910070e-002 -2.1353750e-002 +v -1.3371080e-002 3.4361580e-002 -1.9023720e-002 +v 9.5887300e-003 3.4207220e-002 -1.5424050e-002 +v -1.4981540e-002 3.5878180e-002 -1.7992380e-002 +v -2.3474300e-003 3.5903130e-002 -1.5929740e-002 +v 2.2544300e-003 3.6411540e-002 -1.4783970e-002 +v -3.5199130e-002 3.3835210e-002 -2.0508290e-002 +v -2.6075450e-002 3.5918600e-002 -1.9405170e-002 +v 8.2740600e-003 3.5645200e-002 -1.2648700e-002 +v 1.0473640e-002 3.4742600e-002 -1.1262870e-002 +v 1.4055380e-002 3.4483430e-002 -1.4495730e-002 +v -3.6970520e-002 3.5680360e-002 -1.5007790e-002 +v -2.4719500e-003 3.8408770e-002 -1.4159030e-002 +v -3.9481890e-002 3.3618220e-002 -2.3612470e-002 +v -4.1091510e-002 3.4006000e-002 -1.1997540e-002 +v -3.1589810e-002 3.5592330e-002 -1.9204150e-002 +v -2.0086310e-002 3.8064450e-002 -1.7220790e-002 +v -1.1113250e-002 3.8290290e-002 -1.5646360e-002 +v 4.4522600e-003 3.7705190e-002 -1.2957650e-002 +v 1.5870480e-002 3.4416230e-002 -2.9666500e-003 +v -4.7872000e-002 3.4136300e-002 -1.5418250e-002 +v -4.7521640e-002 3.3622720e-002 -1.2804590e-002 +v -3.3407340e-002 3.7577040e-002 -1.6158190e-002 +v -2.7851470e-002 3.8404330e-002 -1.7210420e-002 +v -8.5065300e-003 3.9028950e-002 -1.3000800e-002 +v 6.4552500e-003 3.8165190e-002 -1.0164860e-002 +v 7.4147100e-003 3.4659190e-002 -3.0116800e-003 +v 1.1966200e-002 3.4335400e-002 -5.9571300e-003 +v 2.0414820e-002 3.5567580e-002 -3.7806900e-003 +v -1.9288780e-002 3.8762570e-002 -1.4202620e-002 +v -1.1390100e-003 3.9176760e-002 -1.0381370e-002 +v 3.8149200e-003 3.9024470e-002 -8.0827300e-003 +v 7.5208200e-003 3.6733400e-002 -6.7614300e-003 +v 1.9968120e-002 3.4843990e-002 -1.8984900e-003 +v -4.5058400e-002 3.3600490e-002 -1.2527510e-002 +v -3.0754850e-002 3.8639810e-002 -1.4050770e-002 +v -5.1499810e-002 3.3729110e-002 -1.2082510e-002 +v -2.3756860e-002 3.8585750e-002 -1.1093270e-002 +v 3.9734700e-003 3.8208550e-002 -3.7963500e-003 +v 9.5485400e-003 3.4232620e-002 1.7162000e-003 +v 2.9086550e-002 3.5799990e-002 3.5630900e-003 +v -5.5965200e-002 3.3529910e-002 -9.1246200e-003 +v -1.9523510e-002 3.8505210e-002 -4.5434500e-003 +v 1.6363470e-002 3.4394790e-002 2.2948600e-003 +v 2.1324740e-002 3.4624040e-002 5.6444000e-003 +v -3.9670300e-002 3.6174000e-002 -7.3397700e-003 +v -1.4251730e-002 3.8648030e-002 -4.3030400e-003 +v 2.3262300e-003 3.5348200e-002 2.3246000e-003 +v 1.4014300e-002 3.5703800e-002 3.8878900e-003 +v 1.5322800e-002 3.6239700e-002 3.6628500e-003 +v 2.3753130e-002 3.4670710e-002 3.9885300e-003 +v 3.2369180e-002 3.5816010e-002 7.0246300e-003 +v -6.3715900e-002 3.3776930e-002 -8.0065600e-003 +v -6.4266880e-002 3.3562500e-002 -5.1253200e-003 +v -3.8066600e-002 3.8518600e-002 -7.3079600e-003 +v -9.4308800e-003 3.8887690e-002 -7.4848700e-003 +v 3.9677800e-003 3.4200210e-002 4.9754500e-003 +v 9.4292600e-003 3.6030400e-002 4.5275100e-003 +v 2.9859020e-002 3.4980130e-002 9.8349300e-003 +v -5.2730060e-002 3.3497900e-002 -1.8117500e-003 +v -4.1271000e-002 3.3855400e-002 -1.8800800e-003 +v -3.1105000e-003 3.8946190e-002 -2.7793900e-003 +v 6.2194100e-003 3.5134100e-002 6.5492800e-003 +v 2.0897900e-002 3.5937100e-002 8.7849000e-003 +v 3.5606010e-002 3.6526640e-002 9.8155300e-003 +v -6.7078340e-002 3.3840100e-002 -6.1688300e-003 +v -8.1140000e-004 3.7424170e-002 4.7721500e-003 +v 3.1492300e-003 3.4125310e-002 1.1762220e-002 +v 4.9172000e-003 3.3997100e-002 9.1666100e-003 +v 2.5130800e-002 3.4546910e-002 1.1012580e-002 +v 2.8248620e-002 3.5046370e-002 1.6016700e-002 +v -6.7032970e-002 6.5145960e-002 2.7292860e-002 +v -4.6380170e-002 3.3605230e-002 -8.9435000e-004 +v -3.3163400e-002 3.8195400e-002 -5.2520000e-004 +v -3.2074200e-002 3.8323400e-002 -4.2109000e-004 +v -2.1692690e-002 3.8266010e-002 4.5100800e-003 +v 2.3930750e-002 3.4816710e-002 1.7739160e-002 +v 4.2719120e-002 3.9977070e-002 8.9321600e-003 +v -5.8604080e-002 3.3462230e-002 -2.1667000e-004 +v -3.7314400e-002 3.3633000e-002 4.5724700e-003 +v -1.0423990e-002 3.8488570e-002 6.2292700e-003 +v -1.3896900e-003 3.8651360e-002 2.3966500e-003 +v -3.0845000e-004 3.5462480e-002 8.2607200e-003 +v -1.4089000e-003 3.6193080e-002 1.2944550e-002 +v 2.2252900e-002 3.6583300e-002 1.3979700e-002 +v -7.0961830e-002 3.4345730e-002 -7.8374000e-004 +v -6.9066180e-002 3.3717630e-002 -1.9761000e-004 +v -6.4825640e-002 3.3505860e-002 2.8222500e-003 +v -4.7059660e-002 3.3501860e-002 3.5646400e-003 +v -3.6953800e-003 3.8172780e-002 1.3046800e-002 +v 3.3475850e-002 3.6447340e-002 1.6266960e-002 +v 3.7249610e-002 3.7509920e-002 1.4815820e-002 +v -4.5675940e-002 3.3703640e-002 6.4300300e-003 +v -3.8639270e-002 3.3937310e-002 8.5506500e-003 +v -9.5064100e-003 3.8352640e-002 1.5570660e-002 +v 2.1499800e-002 3.5807100e-002 1.8169400e-002 +v 4.4876460e-002 4.1230990e-002 1.6008250e-002 +v -7.2474010e-002 3.6255930e-002 1.5532600e-003 +v -7.1498130e-002 3.4452970e-002 4.2026500e-003 +v -2.7790900e-002 3.8062900e-002 7.9376100e-003 +v -1.6556410e-002 3.8286470e-002 1.0215790e-002 +v 8.1043500e-003 3.4842900e-002 1.8134600e-002 +v 2.3589460e-002 3.5890600e-002 2.5337690e-002 +v 4.1261350e-002 4.0585070e-002 2.0751930e-002 +v -5.1350870e-002 3.3645700e-002 8.0329400e-003 +v -4.7104300e-002 3.5549500e-002 8.0803900e-003 +v -1.4103500e-003 3.6999940e-002 1.6982030e-002 +v 9.1714000e-004 3.4803380e-002 1.5634690e-002 +v 2.8887900e-003 3.4636250e-002 1.8849770e-002 +v 1.3279200e-002 3.4379500e-002 2.1423700e-002 +v 1.4322700e-002 3.4425500e-002 2.1593200e-002 +v 1.7490100e-002 3.4646300e-002 2.2040900e-002 +v 2.9868460e-002 3.6248820e-002 1.9872200e-002 +v -3.9222000e-002 3.6326200e-002 1.0789900e-002 +v -3.0307100e-002 3.3995400e-002 1.4706400e-002 +v 2.0081230e-002 3.5172700e-002 2.8018770e-002 +v 2.4989010e-002 3.8104580e-002 2.9429570e-002 +v 3.3584130e-002 3.8303930e-002 2.2928670e-002 +v 4.9015720e-002 4.4573630e-002 2.0659450e-002 +v -5.8225970e-002 6.6607310e-002 3.5050280e-002 +v -6.7330830e-002 3.3846440e-002 8.7266300e-003 +v -3.4692330e-002 3.3828710e-002 1.2438580e-002 +v -2.9803200e-002 3.4287000e-002 1.6353100e-002 +v 1.7023800e-003 3.6310890e-002 2.1179600e-002 +v 4.5137020e-002 4.4625440e-002 2.5516510e-002 +v -6.8876490e-002 1.1022176e-001 3.9004630e-002 +v -5.7680560e-002 3.3622690e-002 1.4040310e-002 +v -5.3210500e-002 3.3585300e-002 1.3987000e-002 +v -3.5711600e-002 3.5891600e-002 1.5502900e-002 +v -2.8861500e-002 3.5396700e-002 1.7350000e-002 +v -2.6580500e-002 3.7742600e-002 1.5705300e-002 +v -1.0974400e-003 3.8147840e-002 2.0427010e-002 +v 3.5047710e-002 4.0973940e-002 2.6970390e-002 +v -6.9685460e-002 3.4478780e-002 9.7984300e-003 +v -5.4019000e-002 3.3309900e-002 1.5848000e-002 +v 4.4816800e-003 3.7117830e-002 2.4755300e-002 +v 6.6605500e-003 3.5204730e-002 2.4315930e-002 +v 8.3833000e-003 3.4748700e-002 2.4057310e-002 +v 3.8883100e-002 4.1032980e-002 2.4976570e-002 +v -2.6441900e-003 3.8727070e-002 2.5131260e-002 +v 3.2222300e-003 3.8708440e-002 2.5898750e-002 +v 9.0016500e-003 3.6890930e-002 2.8482190e-002 +v 1.3196980e-002 3.4835790e-002 3.1630980e-002 +v 2.2291600e-002 3.7053310e-002 3.3101020e-002 +v 2.8948390e-002 3.9160020e-002 2.7234810e-002 +v -8.7773470e-002 1.1181412e-001 3.7144310e-002 +v -1.7870490e-002 3.8203890e-002 2.0243220e-002 +v 1.0087420e-002 3.7047690e-002 3.0822500e-002 +v 4.2296550e-002 4.5435770e-002 2.9040920e-002 +v -8.4341340e-002 1.1388013e-001 4.6513480e-002 +v -7.3795710e-002 1.0895629e-001 3.9217250e-002 +v -5.1243340e-002 6.4239200e-002 3.4258040e-002 +v -6.1777390e-002 3.4017860e-002 1.6900580e-002 +v -3.6665100e-002 3.5304200e-002 2.3032000e-002 +v -1.4930180e-002 3.8643510e-002 2.9378330e-002 +v -8.0894520e-002 1.0967225e-001 3.7910230e-002 +v -8.9822620e-002 1.1387199e-001 3.2845310e-002 +v -6.9655510e-002 6.8728370e-002 3.1127880e-002 +v -7.8449800e-002 1.0988832e-001 4.2517920e-002 +v -7.5824140e-002 1.0794900e-001 3.7128750e-002 +v -5.5740630e-002 3.4128050e-002 2.6674360e-002 +v -3.8279600e-002 3.5429000e-002 2.4380600e-002 +v -3.5283340e-002 3.4179780e-002 2.2744860e-002 +v -2.5798070e-002 3.7865000e-002 1.9981460e-002 +v 6.9064300e-003 3.9004270e-002 2.9548510e-002 +v 1.5448990e-002 3.4852440e-002 3.6984890e-002 +v 1.9128230e-002 3.5640640e-002 3.6642280e-002 +v -6.3664970e-002 6.6047840e-002 3.1828080e-002 +v 3.9604800e-002 4.4939530e-002 2.9992360e-002 +v -8.0294310e-002 7.1702430e-002 1.5995300e-002 +v -5.4185430e-002 6.7322700e-002 3.6935610e-002 +v -7.3110210e-002 1.4847168e-001 -2.8748470e-002 +v -5.8999980e-002 7.3751550e-002 4.1197080e-002 +v -5.9520730e-002 6.1040260e-002 -2.3753800e-003 +v -6.2791800e-002 3.4596760e-002 2.3505640e-002 +v -4.1895500e-002 3.3668300e-002 2.6940000e-002 +v 8.9808200e-003 3.7639400e-002 3.3900800e-002 +v 8.5287800e-003 3.4888000e-002 3.6265100e-002 +v -8.9803890e-002 1.1498106e-001 4.2771650e-002 +v -6.5545420e-002 7.4430370e-002 3.9168070e-002 +v -6.4644190e-002 6.1723230e-002 2.2552000e-004 +v 5.2496900e-003 3.9507100e-002 3.3271200e-002 +v 2.0250320e-002 3.7033170e-002 3.9327190e-002 +v -6.7006400e-002 6.3292870e-002 -1.7493900e-003 +v -6.4479770e-002 6.0651470e-002 4.2343200e-003 +v -5.7219630e-002 5.7000470e-002 4.9175800e-003 +v -7.4362810e-002 7.2437050e-002 3.1430040e-002 +v -6.2019000e-002 3.4343180e-002 3.1883280e-002 +v -4.6870820e-002 3.4444130e-002 3.0513130e-002 +v -2.0814280e-002 3.8400960e-002 2.7868430e-002 +v 1.6439350e-002 3.5635110e-002 4.1281040e-002 +v -6.9087160e-002 1.1205014e-001 4.5320060e-002 +v -7.1811570e-002 1.4861318e-001 -3.4639490e-002 +v -6.9538770e-002 6.3074750e-002 3.5758200e-003 +v -8.4863890e-002 7.8392100e-002 1.6462010e-002 +v -9.1188780e-002 1.1588893e-001 2.4705540e-002 +v -8.8827760e-002 1.1359169e-001 2.3873640e-002 +v -7.1302830e-002 1.1325363e-001 4.9444530e-002 +v -5.4876950e-002 7.0282330e-002 3.8828200e-002 +v -7.7208880e-002 1.0715887e-001 3.4738290e-002 +v -6.1241780e-002 5.9007440e-002 8.0916600e-003 +v -6.5885650e-002 3.5025080e-002 2.9416520e-002 +v -5.7889430e-002 3.4419570e-002 3.6265760e-002 +v -5.1847710e-002 3.4470270e-002 3.4635180e-002 +v -3.4834600e-002 3.4721400e-002 3.4578200e-002 +v -3.0984700e-002 3.8191900e-002 3.2390100e-002 +v -4.9613100e-003 3.9364900e-002 3.6702200e-002 +v 1.2224170e-002 3.5177480e-002 4.2620580e-002 +v -7.4898220e-002 1.1458863e-001 5.0776480e-002 +v -8.0469100e-002 1.1357963e-001 4.6643440e-002 +v -7.4107560e-002 6.9586030e-002 2.7264400e-002 +v -7.9002620e-002 7.6339320e-002 2.9248090e-002 +v -6.5297080e-002 3.4778970e-002 3.3744340e-002 +v -3.3656400e-002 3.4344100e-002 3.6914100e-002 +v 4.9318500e-003 3.4814800e-002 4.3462110e-002 +v 1.1347440e-002 3.6213020e-002 4.4652280e-002 +v -6.0569260e-002 7.1154540e-002 3.8653760e-002 +v -8.8979470e-002 1.1450869e-001 2.8446030e-002 +v -6.8543520e-002 6.1090480e-002 1.0557760e-002 +v -8.2710960e-002 1.1648975e-001 4.8518530e-002 +v -4.1913210e-002 3.4467720e-002 3.3200040e-002 +v -1.1289800e-002 3.9529200e-002 3.8844100e-002 +v -2.8261900e-003 3.4885340e-002 4.5611410e-002 +v -6.4561210e-002 5.9484140e-002 1.3061680e-002 +v -5.8581440e-002 5.7801460e-002 1.3429540e-002 +v -2.3320000e-002 3.9169500e-002 3.8473300e-002 +v -1.8159900e-002 3.9322300e-002 3.9402900e-002 +v -1.6471400e-002 3.4812800e-002 4.3684700e-002 +v 3.2906600e-003 3.5833470e-002 4.6024610e-002 +v -8.5229630e-002 1.1200712e-001 3.0416940e-002 +v -8.5644730e-002 1.1131719e-001 3.4234780e-002 +v -7.4530360e-002 6.6680690e-002 4.6953300e-003 +v -7.1112970e-002 6.2751470e-002 8.7995500e-003 +v -6.1149380e-002 5.8834410e-002 1.6539440e-002 +v -4.6912270e-002 3.4627180e-002 3.9739710e-002 +v -4.0760350e-002 3.4668230e-002 4.0492530e-002 +v -2.6323100e-002 3.4658000e-002 4.3473500e-002 +v -3.1836600e-003 3.6229910e-002 4.7873100e-002 +v -7.9940490e-002 1.0916678e-001 3.4119800e-002 +v -5.9712170e-002 6.3165280e-002 2.8789180e-002 +v -5.1176600e-002 6.8061880e-002 3.7398330e-002 +v -5.0126580e-002 7.0933150e-002 3.9481010e-002 +v -7.2790130e-002 6.4399880e-002 1.5205950e-002 +v -6.8511230e-002 6.1214650e-002 1.5354080e-002 +v -3.9343210e-002 3.5440180e-002 4.2492560e-002 +v -8.1305900e-003 3.5008350e-002 4.7502400e-002 +v -6.6080670e-002 7.0202740e-002 3.5552860e-002 +v -6.8602600e-002 1.4992277e-001 -4.0051350e-002 +v -7.1722100e-002 6.7023040e-002 2.4959750e-002 +v -7.5115010e-002 6.6557040e-002 1.0244090e-002 +v -6.5146650e-002 3.5945650e-002 3.9775080e-002 +v -3.6898600e-002 3.5924640e-002 4.4794170e-002 +v -9.4780400e-003 3.5977600e-002 4.9434210e-002 +v -8.5175960e-002 1.1706809e-001 4.8139420e-002 +v -6.3366400e-002 6.2790260e-002 2.5647610e-002 +v -6.6633330e-002 6.1001700e-002 1.8101240e-002 +v -5.8167590e-002 5.9985190e-002 2.2606060e-002 +v -6.4212210e-002 3.4992560e-002 3.9401920e-002 +v -5.3425790e-002 3.4560020e-002 4.2782420e-002 +v -1.8031490e-002 3.4859970e-002 4.9264760e-002 +v -1.1440410e-002 3.7640770e-002 5.0275730e-002 +v -7.5165320e-002 1.1154286e-001 4.6707180e-002 +v -7.7168390e-002 6.9826450e-002 5.0605600e-003 +v -7.2801360e-002 6.4382590e-002 1.2089080e-002 +v -7.8022000e-002 7.0995160e-002 2.1322150e-002 +v -6.1263370e-002 3.4690410e-002 4.1994900e-002 +v -5.4403750e-002 3.5007310e-002 4.4874590e-002 +v -4.5754280e-002 3.5206980e-002 4.3518120e-002 +v -3.3832440e-002 3.5168820e-002 4.6957890e-002 +v -2.8657630e-002 3.5083380e-002 5.0549440e-002 +v -1.5306440e-002 3.5246410e-002 5.0133810e-002 +v -6.5283650e-002 1.5592447e-001 -4.9865930e-002 +v -6.6467860e-002 1.4871539e-001 -3.1579300e-002 +v -6.2095980e-002 1.6388324e-001 -5.8385930e-002 +v -6.3274890e-002 1.5245731e-001 -3.2221730e-002 +v -4.3755720e-002 1.4773408e-001 -2.1433200e-003 +v -6.5696940e-002 1.4561631e-001 -1.8974710e-002 +v -6.6713650e-002 1.5358824e-001 -4.9097100e-002 +v -1.0482810e-002 1.6668287e-001 -2.1746090e-002 +v -6.2744510e-002 1.6397531e-001 -5.9398280e-002 +v -7.0413230e-002 1.4129200e-001 -8.4590800e-003 +v -6.1530380e-002 1.4037628e-001 -6.2734700e-003 +v -1.1452460e-002 1.7220633e-001 -2.6844980e-002 +v -6.3731140e-002 1.6577037e-001 -6.0103610e-002 +v -2.8218820e-002 1.5758144e-001 -1.0999490e-002 +v -1.8471270e-002 1.5967716e-001 -1.1169510e-002 +v -6.6700710e-002 1.5236775e-001 -4.5266390e-002 +v -4.9896410e-002 1.4670859e-001 -1.8614200e-003 +v -3.1449640e-002 1.5460463e-001 -7.6802300e-003 +v -6.7447660e-002 1.5507675e-001 -5.1594250e-002 +v -1.0906650e-002 1.7649301e-001 -2.9246300e-002 +v -7.2083600e-002 1.4965550e-001 -3.9265860e-002 +v -6.4230830e-002 1.4877806e-001 -2.5899710e-002 +v -6.3056640e-002 1.4341650e-001 -7.4907700e-003 +v -5.3043350e-002 1.4092550e-001 -4.7408000e-004 +v -3.9269410e-002 1.5205232e-001 -6.6203800e-003 +v -6.4796930e-002 1.5210615e-001 -3.6185520e-002 +v -6.4400320e-002 1.5834400e-001 -5.4256370e-002 +v -6.6178120e-002 1.4218350e-001 -9.3766300e-003 +v -6.7751430e-002 1.4605207e-001 -2.3333300e-002 +v -6.4731580e-002 1.5410067e-001 -4.0464820e-002 +v -2.4265590e-002 1.5687690e-001 -7.8509300e-003 +v -1.5723180e-002 1.6312344e-001 -1.6396570e-002 +v -7.0887660e-002 1.4404618e-001 -1.4908480e-002 +v -4.4341830e-002 1.5113809e-001 -5.6859800e-003 +v -6.2896810e-002 1.4694778e-001 -1.3098620e-002 +v -6.3755400e-002 1.4428875e-001 -1.1395730e-002 +v -6.8214560e-002 1.4390932e-001 -1.4984170e-002 +v -5.0271440e-002 1.4336563e-001 1.5153000e-003 +v -2.8535590e-002 1.6208479e-001 -1.4786030e-002 +v -6.5810700e-002 1.4359119e-001 -1.2585380e-002 +v -5.6179200e-002 1.3774406e-001 -4.0674300e-003 +v -6.8866880e-002 1.4723338e-001 -2.8739870e-002 +v -6.0965420e-002 1.7002113e-001 -6.0839390e-002 +v -1.3895490e-002 1.6787168e-001 -2.1897230e-002 +v -6.9413000e-002 1.5121847e-001 -4.4538540e-002 +v -5.5039800e-002 5.7309700e-002 1.6990900e-002 +f 1069 1647 1578 +f 1058 909 939 +f 421 1176 238 +f 1055 1101 1042 +f 238 1059 1126 +f 1254 30 1261 +f 1065 1071 1 +f 1037 1130 1120 +f 1570 2381 1585 +f 2434 2502 2473 +f 1632 1654 1646 +f 1144 1166 669 +f 1202 1440 305 +f 1071 1090 1 +f 1555 1570 1584 +f 1184 1174 404 +f 65 432 12 +f 1032 1085 574 +f 1789 2207 2223 +f 1154 1118 1184 +f 1141 1086 1154 +f 99 1117 342 +f 404 1174 419 +f 489 2000 1998 +f 1118 1174 1184 +f 1196 403 136 +f 1495 717 1490 +f 1804 402 1207 +f 2272 1398 891 +f 1100 1002 804 +f 1596 1595 2381 +f 208 420 1207 +f 402 208 1207 +f 1455 1935 1925 +f 1176 1059 238 +f 1150 1040 348 +f 1957 1537 2051 +f 1124 1189 939 +f 1804 1207 1823 +f 1381 1300 1109 +f 383 384 1182 +f 1085 1086 1141 +f 1040 1046 132 +f 220 1495 1188 +f 420 261 1207 +f 261 420 1065 +f 1055 1133 1101 +f 1054 421 403 +f 182 1109 2 +f 1181 1207 320 +f 545 1570 1561 +f 35 342 432 +f 1024 574 1141 +f 432 342 12 +f 1489 1081 1547 +f 1181 320 1805 +f 1516 1683 1507 +f 357 1117 1047 +f 1561 1570 1555 +f 1090 1196 1206 +f 1047 1203 1051 +f 1165 202 1121 +f 1099 341 301 +f 1174 240 419 +f 922 921 833 +f 1121 1080 385 +f 815 21 1183 +f 35 99 342 +f 1083 398 262 +f 106 94 1317 +f 94 292 1317 +f 292 95 1317 +f 940 1039 1033 +f 1300 1306 433 +f 21 212 471 +f 1120 1131 1037 +f 833 921 688 +f 1117 357 342 +f 106 271 94 +f 386 227 1375 +f 1130 1044 1053 +f 419 240 219 +f 1255 1244 32 +f 1557 1081 1489 +f 2062 2120 2109 +f 2034 2110 430 +f 23 315 1111 +f 291 94 271 +f 291 292 94 +f 50 386 95 +f 964 734 665 +f 1616 1585 1611 +f 445 1084 402 +f 574 1085 1141 +f 1654 341 1653 +f 220 1188 1640 +f 342 69 12 +f 417 261 328 +f 292 50 95 +f 204 227 386 +f 50 204 386 +f 1276 1471 1311 +f 1206 1196 136 +f 1033 1055 1042 +f 1037 1044 1130 +f 1180 320 417 +f 1121 202 1080 +f 325 203 271 +f 291 76 292 +f 292 237 50 +f 2159 1696 1767 +f 583 929 850 +f 1584 1585 1616 +f 1495 1490 1188 +f 1557 1489 1660 +f 1078 1069 1494 +f 1972 1992 1971 +f 183 1226 2000 +f 325 429 203 +f 292 76 237 +f 1152 227 1143 +f 1488 1412 1489 +f 1638 1646 1653 +f 1947 1869 2468 +f 203 306 291 +f 306 76 291 +f 237 248 50 +f 204 1143 227 +f 2395 14 429 +f 1502 881 2500 +f 1 1090 202 +f 1652 1653 1099 +f 2117 1863 2496 +f 50 248 204 +f 160 792 994 +f 884 888 857 +f 544 2117 2496 +f 1090 1206 202 +f 2463 879 2492 +f 429 306 203 +f 498 188 418 +f 865 884 857 +f 994 998 1014 +f 884 897 888 +f 1795 948 1802 +f 208 1035 1071 +f 1065 1 1066 +f 377 435 1377 +f 304 429 14 +f 304 306 429 +f 73 60 74 +f 248 592 204 +f 846 2264 829 +f 897 912 906 +f 1004 991 992 +f 1422 1421 1233 +f 980 10 303 +f 1058 922 909 +f 2436 2449 2418 +f 394 435 377 +f 435 475 446 +f 475 474 446 +f 336 337 361 +f 338 235 372 +f 624 148 129 +f 812 306 596 +f 1726 992 1019 +f 945 1514 1511 +f 1069 1627 1628 +f 1812 1823 1181 +f 1165 1121 169 +f 447 475 435 +f 2487 2458 901 +f 42 59 46 +f 401 7 187 +f 1010 970 797 +f 1513 220 1640 +f 2474 2491 2462 +f 594 307 1014 +f 398 1513 1640 +f 307 594 1026 +f 545 2381 1570 +f 403 421 238 +f 445 402 127 +f 1611 1631 1616 +f 1805 1180 1148 +f 394 447 435 +f 2341 2413 2376 +f 75 74 60 +f 541 47 42 +f 47 59 42 +f 541 42 28 +f 917 931 1103 +f 897 906 883 +f 2484 2068 779 +f 888 883 857 +f 261 1065 328 +f 363 1307 349 +f 377 363 394 +f 444 747 464 +f 323 338 362 +f 92 116 74 +f 592 634 97 +f 982 1027 1004 +f 1020 982 1004 +f 1084 1054 1035 +f 208 402 1084 +f 421 1119 1176 +f 1207 1181 1823 +f 1179 1187 1160 +f 263 296 1343 +f 1298 296 1307 +f 1307 296 349 +f 405 363 349 +f 405 394 363 +f 405 447 394 +f 362 372 384 +f 338 372 362 +f 983 1004 987 +f 122 134 139 +f 415 440 414 +f 75 92 74 +f 226 186 246 +f 796 787 700 +f 1119 1059 1176 +f 122 114 91 +f 624 129 116 +f 641 558 631 +f 1311 1318 1487 +f 100 1162 1170 +f 1653 341 1099 +f 1316 1983 273 +f 263 277 296 +f 296 358 349 +f 436 447 405 +f 109 554 570 +f 504 1385 2501 +f 115 122 91 +f 2068 2460 779 +f 43 777 163 +f 378 405 349 +f 358 378 349 +f 448 447 436 +f 448 476 447 +f 78 77 108 +f 75 60 47 +f 1764 2481 1795 +f 717 714 1512 +f 1490 717 1501 +f 238 1126 168 +f 1878 1866 826 +f 2025 2360 2367 +f 251 278 263 +f 278 277 263 +f 277 318 296 +f 296 318 358 +f 318 350 358 +f 378 436 405 +f 384 372 1182 +f 454 440 415 +f 987 1004 992 +f 493 476 448 +f 323 788 338 +f 403 238 136 +f 1565 1503 1474 +f 297 277 278 +f 297 318 277 +f 358 350 378 +f 378 388 436 +f 476 493 500 +f 73 105 60 +f 323 337 312 +f 953 1573 2358 +f 142 161 119 +f 454 443 440 +f 1862 1871 1405 +f 297 319 318 +f 560 47 541 +f 170 1323 111 +f 357 1047 1050 +f 1119 98 1059 +f 1838 1877 1900 +f 2359 230 251 +f 350 364 378 +f 449 448 436 +f 449 493 448 +f 185 186 226 +f 443 469 479 +f 874 165 2480 +f 463 444 464 +f 64 105 91 +f 1182 440 1129 +f 1958 1651 2502 +f 1238 2034 191 +f 251 279 278 +f 278 279 297 +f 364 388 378 +f 483 493 449 +f 134 148 139 +f 244 268 259 +f 910 942 930 +f 105 115 91 +f 24 30 18 +f 1132 487 1059 +f 1869 1947 2021 +f 2497 2494 2463 +f 2359 2385 230 +f 230 280 251 +f 251 280 279 +f 279 308 297 +f 297 308 319 +f 319 364 318 +f 364 350 318 +f 388 395 436 +f 436 395 449 +f 493 472 500 +f 122 129 134 +f 125 142 124 +f 373 400 393 +f 24 557 30 +f 2264 2278 2251 +f 1261 30 1269 +f 1730 1862 1877 +f 252 280 230 +f 343 364 319 +f 364 343 388 +f 63 64 91 +f 399 393 416 +f 416 444 463 +f 162 189 142 +f 768 373 326 +f 189 661 177 +f 189 199 661 +f 847 887 864 +f 533 747 444 +f 1744 1022 1418 +f 1170 524 729 +f 121 1342 128 +f 1236 1244 26 +f 280 281 279 +f 281 308 279 +f 343 319 308 +f 343 365 388 +f 388 365 395 +f 365 406 395 +f 406 449 395 +f 483 477 493 +f 477 491 472 +f 493 477 472 +f 78 109 77 +f 166 174 196 +f 481 150 814 +f 63 59 64 +f 326 373 393 +f 643 260 43 +f 230 253 252 +f 449 441 483 +f 441 477 483 +f 415 416 463 +f 226 246 245 +f 464 470 454 +f 323 362 337 +f 52 37 1283 +f 253 281 252 +f 281 280 252 +f 309 308 281 +f 330 343 308 +f 366 365 343 +f 441 449 406 +f 464 814 15 +f 883 906 887 +f 337 362 371 +f 479 498 290 +f 247 746 1003 +f 25 37 557 +f 640 930 669 +f 2486 2499 2459 +f 309 330 308 +f 343 330 366 +f 441 437 477 +f 290 498 418 +f 124 119 108 +f 77 124 108 +f 589 125 109 +f 570 589 109 +f 125 162 142 +f 1045 433 1034 +f 1207 261 320 +f 2004 2474 2495 +f 1215 1228 2285 +f 365 396 406 +f 396 422 406 +f 422 437 441 +f 406 422 441 +f 59 47 60 +f 51 78 66 +f 361 371 383 +f 196 215 214 +f 463 454 415 +f 27 41 535 +f 53 1283 37 +f 84 1299 1283 +f 1805 320 1180 +f 254 253 222 +f 254 281 253 +f 309 366 330 +f 396 365 366 +f 456 477 437 +f 484 491 477 +f 2480 2485 2493 +f 418 188 187 +f 53 85 1283 +f 85 84 1283 +f 420 1071 1065 +f 264 281 254 +f 298 309 281 +f 368 366 367 +f 368 396 366 +f 1639 1564 1139 +f 560 48 47 +f 82 471 212 +f 25 38 37 +f 202 1206 1080 +f 264 298 281 +f 298 331 309 +f 309 331 366 +f 331 367 366 +f 396 368 422 +f 422 456 437 +f 491 1192 313 +f 1699 2064 1710 +f 462 443 479 +f 371 362 384 +f 2502 2476 2464 +f 371 384 383 +f 21 732 212 +f 1571 1629 1627 +f 38 39 53 +f 37 38 53 +f 39 85 53 +f 1173 1184 404 +f 1006 2142 1674 +f 201 255 254 +f 255 264 254 +f 368 407 422 +f 450 456 422 +f 450 484 456 +f 456 484 477 +f 314 1192 491 +f 2027 2501 2489 +f 2475 2471 2488 +f 551 492 732 +f 464 481 814 +f 1081 1494 1547 +f 201 231 255 +f 407 450 422 +f 484 494 491 +f 494 327 491 +f 327 314 491 +f 876 797 995 +f 847 856 829 +f 125 143 162 +f 134 129 148 +f 1564 1571 1627 +f 417 320 261 +f 328 1065 1066 +f 170 156 201 +f 156 231 201 +f 231 282 255 +f 282 264 255 +f 450 485 484 +f 484 485 494 +f 2463 2486 2479 +f 159 185 167 +f 492 68 212 +f 732 492 212 +f 68 82 212 +f 1311 1471 1296 +f 101 156 111 +f 332 264 282 +f 332 298 264 +f 332 331 298 +f 331 332 367 +f 407 423 450 +f 450 423 485 +f 804 1002 1443 +f 2484 779 946 +f 689 443 462 +f 440 689 1129 +f 166 167 174 +f 38 31 39 +f 112 145 101 +f 101 145 156 +f 156 256 231 +f 332 423 368 +f 367 332 368 +f 368 423 407 +f 946 779 920 +f 1432 1261 1449 +f 461 478 453 +f 464 15 470 +f 31 54 39 +f 39 54 85 +f 86 101 85 +f 145 210 156 +f 282 283 332 +f 283 369 332 +f 369 423 332 +f 423 408 485 +f 854 876 965 +f 78 108 66 +f 440 443 689 +f 374 2465 961 +f 929 519 979 +f 54 86 85 +f 156 241 256 +f 256 282 231 +f 256 283 282 +f 389 423 369 +f 389 408 423 +f 408 457 485 +f 457 49 485 +f 485 49 494 +f 494 135 327 +f 175 83 314 +f 1167 1140 1483 +f 196 174 215 +f 697 16 68 +f 1038 82 16 +f 140 117 141 +f 1654 1653 1646 +f 1234 54 31 +f 86 112 101 +f 210 241 156 +f 923 917 911 +f 697 34 16 +f 145 193 210 +f 256 265 283 +f 265 310 283 +f 283 310 369 +f 310 344 369 +f 344 370 369 +f 370 389 369 +f 409 408 389 +f 409 466 408 +f 466 457 408 +f 466 49 457 +f 49 135 494 +f 174 225 215 +f 1014 766 602 +f 826 2220 2215 +f 1078 1494 1081 +f 1273 70 86 +f 120 112 86 +f 146 145 112 +f 146 193 145 +f 265 256 241 +f 223 265 241 +f 486 49 466 +f 175 327 135 +f 105 122 115 +f 480 15 681 +f 225 234 215 +f 731 34 697 +f 86 54 1273 +f 70 120 86 +f 193 241 210 +f 299 310 265 +f 310 333 344 +f 344 351 370 +f 424 466 409 +f 135 49 175 +f 214 215 234 +f 48 75 47 +f 34 9 1038 +f 16 34 1038 +f 203 291 271 +f 9 558 754 +f 1195 397 1120 +f 120 146 112 +f 146 194 193 +f 266 265 223 +f 266 299 265 +f 299 333 310 +f 333 351 344 +f 382 383 392 +f 399 416 415 +f 266 333 299 +f 351 352 370 +f 424 486 466 +f 487 175 49 +f 7 117 187 +f 1182 414 440 +f 41 42 46 +f 290 289 497 +f 2502 2464 2473 +f 372 399 414 +f 1570 1585 1584 +f 1066 1 1165 +f 1 202 1165 +f 120 70 102 +f 157 146 120 +f 194 223 193 +f 223 241 193 +f 352 379 370 +f 370 379 389 +f 410 409 389 +f 2478 1409 1958 +f 806 945 1002 +f 157 194 146 +f 267 266 223 +f 267 333 266 +f 379 410 389 +f 410 438 409 +f 438 424 409 +f 190 205 143 +f 337 371 361 +f 2215 830 826 +f 1631 1646 1638 +f 102 157 120 +f 157 195 194 +f 195 223 194 +f 195 211 223 +f 223 211 267 +f 267 300 333 +f 300 334 351 +f 333 300 351 +f 351 334 352 +f 410 411 438 +f 438 486 424 +f 487 49 486 +f 875 594 989 +f 108 581 66 +f 225 245 244 +f 312 336 335 +f 151 754 107 +f 274 1386 300 +f 352 334 379 +f 923 1729 1096 +f 244 245 268 +f 463 464 454 +f 414 399 415 +f 15 480 470 +f 1647 1069 1078 +f 909 922 833 +f 387 417 328 +f 133 157 102 +f 1314 133 102 +f 133 195 157 +f 1148 1179 1160 +f 1046 1167 182 +f 379 411 410 +f 792 339 229 +f 391 7 668 +f 185 226 174 +f 461 290 497 +f 2027 504 2501 +f 1196 1054 403 +f 728 1019 752 +f 2459 2483 2461 +f 1291 1264 55 +f 133 1356 195 +f 195 1356 211 +f 412 438 411 +f 4 486 438 +f 458 4 438 +f 4 487 486 +f 1720 1572 1771 +f 245 275 268 +f 1869 2021 2059 +f 235 399 372 +f 64 60 105 +f 836 2492 879 +f 1315 133 1314 +f 1331 1382 1356 +f 1310 926 1128 +f 7 1121 117 +f 119 161 611 +f 380 379 334 +f 379 380 411 +f 467 4 458 +f 495 487 4 +f 495 1126 487 +f 416 400 533 +f 479 469 498 +f 74 116 73 +f 478 461 497 +f 393 400 416 +f 61 1291 55 +f 505 1999 2474 +f 1999 2491 2474 +f 199 189 36 +f 1164 1165 169 +f 1179 387 249 +f 390 411 380 +f 411 390 412 +f 458 438 412 +f 495 168 1126 +f 480 469 470 +f 116 122 105 +f 418 187 140 +f 185 174 167 +f 166 148 167 +f 470 469 443 +f 40 55 32 +f 61 71 1291 +f 71 103 1291 +f 1184 1173 1154 +f 634 514 97 +f 425 458 412 +f 917 923 931 +f 2472 2489 853 +f 754 641 567 +f 44 567 1163 +f 454 470 443 +f 40 32 1249 +f 33 40 1249 +f 56 55 40 +f 56 61 55 +f 451 1265 439 +f 1180 417 1179 +f 1099 301 1077 +f 1189 1058 939 +f 1059 221 1132 +f 598 1074 1075 +f 412 426 425 +f 650 186 185 +f 234 244 259 +f 226 245 225 +f 1033 1042 1030 +f 2492 836 247 +f 7 169 1121 +f 1462 1322 1482 +f 425 467 458 +f 496 4 467 +f 1751 2468 2480 +f 290 418 140 +f 326 789 762 +f 142 177 161 +f 165 1751 2480 +f 87 103 71 +f 103 87 104 +f 1180 1179 1148 +f 417 387 1179 +f 2081 2060 2031 +f 1154 1173 1141 +f 181 131 197 +f 442 425 426 +f 614 144 143 +f 876 1010 797 +f 40 45 56 +f 56 45 61 +f 87 71 61 +f 1563 1437 1590 +f 1121 385 117 +f 1148 1160 1137 +f 1449 1459 1439 +f 1028 2462 929 +f 442 459 425 +f 459 467 425 +f 168 495 4 +f 496 168 4 +f 1763 1403 1444 +f 140 187 117 +f 244 234 225 +f 246 740 269 +f 372 414 1182 +f 40 547 45 +f 45 62 61 +f 62 87 61 +f 87 88 104 +f 1084 517 1054 +f 387 328 1064 +f 2467 2497 2485 +f 286 1363 302 +f 205 189 162 +f 290 140 289 +f 214 234 224 +f 393 399 809 +f 315 1131 397 +f 302 321 353 +f 1164 169 391 +f 427 459 442 +f 217 496 467 +f 217 168 496 +f 978 969 2074 +f 361 383 382 +f 269 276 245 +f 1440 11 305 +f 62 88 87 +f 328 1066 1064 +f 1066 1165 1164 +f 242 287 302 +f 1363 242 302 +f 287 321 302 +f 1179 249 1187 +f 983 1020 1004 +f 464 747 481 +f 788 323 276 +f 269 245 246 +f 88 89 1325 +f 171 172 242 +f 360 353 321 +f 360 1354 353 +f 1057 1064 1164 +f 2184 2188 2183 +f 460 459 451 +f 460 467 459 +f 149 168 217 +f 149 136 168 +f 116 129 122 +f 109 124 77 +f 159 167 148 +f 28 42 41 +f 57 88 62 +f 45 57 62 +f 1336 1325 89 +f 89 72 1336 +f 147 172 171 +f 172 258 242 +f 258 257 242 +f 257 287 242 +f 257 321 287 +f 345 360 321 +f 360 381 1354 +f 1069 938 1655 +f 387 473 249 +f 270 217 467 +f 130 136 149 +f 851 847 829 +f 983 987 975 +f 189 177 142 +f 88 72 89 +f 184 258 172 +f 257 288 321 +f 1265 451 459 +f 270 149 217 +f 226 225 174 +f 27 28 41 +f 109 125 124 +f 547 57 45 +f 57 58 88 +f 88 58 72 +f 2476 2484 2458 +f 147 184 172 +f 184 213 258 +f 258 243 257 +f 243 288 257 +f 345 321 288 +f 391 169 7 +f 468 460 451 +f 468 488 460 +f 270 467 460 +f 488 270 460 +f 1206 136 130 +f 481 793 150 +f 143 205 162 +f 142 119 124 +f 58 90 72 +f 90 128 72 +f 147 173 184 +f 173 213 184 +f 213 233 258 +f 258 233 243 +f 354 360 345 +f 354 381 360 +f 1026 991 307 +f 268 312 259 +f 1206 130 1080 +f 116 105 73 +f 139 148 166 +f 275 312 268 +f 188 401 187 +f 2479 2459 2461 +f 58 63 90 +f 1064 1066 1164 +f 1064 473 387 +f 288 311 345 +f 311 354 345 +f 996 994 307 +f 452 468 439 +f 452 478 468 +f 478 488 468 +f 141 130 149 +f 1564 1639 1563 +f 547 41 57 +f 2081 2107 2060 +f 382 381 354 +f 497 270 488 +f 289 149 270 +f 289 141 149 +f 114 122 139 +f 59 60 64 +f 275 323 312 +f 401 668 7 +f 41 46 57 +f 57 46 58 +f 1459 1345 1269 +f 1342 121 158 +f 166 173 158 +f 213 224 233 +f 233 259 243 +f 243 322 288 +f 322 311 288 +f 453 478 452 +f 497 289 270 +f 912 911 906 +f 276 323 275 +f 276 275 245 +f 46 63 58 +f 90 121 128 +f 173 214 213 +f 213 214 224 +f 259 322 243 +f 336 311 322 +f 336 354 311 +f 361 382 354 +f 1043 439 1290 +f 497 488 478 +f 385 130 141 +f 385 1080 130 +f 144 190 143 +f 535 41 547 +f 121 166 158 +f 335 336 322 +f 354 336 361 +f 2004 2481 1764 +f 698 439 1043 +f 289 140 141 +f 923 1096 931 +f 650 185 159 +f 46 59 63 +f 63 91 90 +f 90 114 121 +f 121 139 166 +f 173 196 214 +f 259 335 322 +f 2478 2502 2434 +f 312 337 336 +f 90 91 114 +f 114 139 121 +f 166 196 173 +f 224 234 233 +f 234 259 233 +f 259 312 335 +f 1124 916 1189 +f 542 541 530 +f 462 479 290 +f 269 783 276 +f 813 567 641 +f 276 783 788 +f 82 1038 1333 +f 816 701 703 +f 672 137 603 +f 625 635 624 +f 2457 2439 1973 +f 767 533 529 +f 2468 1869 2480 +f 662 190 639 +f 711 720 719 +f 630 639 614 +f 161 654 638 +f 781 991 982 +f 1227 31 516 +f 648 639 630 +f 630 614 590 +f 2098 544 1899 +f 578 579 586 +f 697 492 551 +f 529 533 400 +f 869 859 870 +f 1732 924 914 +f 1004 1027 991 +f 801 591 603 +f 636 676 651 +f 876 949 965 +f 2207 1789 1859 +f 76 739 237 +f 188 681 15 +f 578 604 599 +f 797 616 995 +f 510 2035 1365 +f 76 812 617 +f 617 739 76 +f 1468 93 1765 +f 596 546 812 +f 1457 1305 1477 +f 760 197 150 +f 671 773 765 +f 586 609 604 +f 591 700 632 +f 476 2312 474 +f 2084 2027 2489 +f 582 590 571 +f 1555 2449 1996 +f 674 546 596 +f 812 655 617 +f 161 177 661 +f 599 604 636 +f 700 787 576 +f 776 675 572 +f 776 674 675 +f 617 634 739 +f 591 632 649 +f 612 546 674 +f 617 655 634 +f 728 752 706 +f 571 2311 2305 +f 775 674 776 +f 775 612 674 +f 612 628 546 +f 546 628 812 +f 812 628 655 +f 620 630 615 +f 620 648 630 +f 667 653 646 +f 810 782 785 +f 150 197 814 +f 534 1517 2000 +f 702 572 2378 +f 748 776 572 +f 655 613 634 +f 911 917 905 +f 648 679 662 +f 727 771 713 +f 750 807 799 +f 639 190 144 +f 662 679 200 +f 702 748 572 +f 775 776 748 +f 628 718 655 +f 626 658 645 +f 791 778 790 +f 612 811 628 +f 613 514 634 +f 1380 1756 1673 +f 570 590 614 +f 720 741 719 +f 1074 795 835 +f 614 639 144 +f 612 775 811 +f 718 735 655 +f 655 735 613 +f 798 338 788 +f 636 652 676 +f 571 590 555 +f 528 730 687 +f 690 702 2312 +f 476 690 2312 +f 811 718 628 +f 721 778 727 +f 748 702 690 +f 735 686 613 +f 1517 2002 2127 +f 654 685 667 +f 569 588 606 +f 513 531 538 +f 538 549 548 +f 549 553 548 +f 550 588 549 +f 1903 869 870 +f 691 775 748 +f 691 600 775 +f 600 811 775 +f 811 563 718 +f 563 736 718 +f 718 736 735 +f 736 647 735 +f 735 647 686 +f 686 745 613 +f 745 514 613 +f 569 606 605 +f 654 667 638 +f 851 857 847 +f 588 569 549 +f 690 691 748 +f 680 514 745 +f 2127 2002 2094 +f 747 701 481 +f 400 373 529 +f 600 536 811 +f 536 563 811 +f 1306 227 1152 +f 522 24 18 +f 523 24 522 +f 865 857 851 +f 2031 2060 1540 +f 767 701 747 +f 618 652 609 +f 652 636 609 +f 573 22 710 +f 642 699 730 +f 1522 1518 2476 +f 500 629 691 +f 690 500 691 +f 691 629 600 +f 780 644 641 +f 579 578 561 +f 131 668 197 +f 197 668 814 +f 789 809 798 +f 622 760 150 +f 621 563 536 +f 673 745 686 +f 673 818 745 +f 818 680 745 +f 680 96 514 +f 2495 2462 1028 +f 1028 583 575 +f 663 794 664 +f 629 761 600 +f 761 757 600 +f 600 757 536 +f 621 696 563 +f 755 736 563 +f 696 755 563 +f 633 736 755 +f 633 647 736 +f 623 686 647 +f 633 623 647 +f 686 623 673 +f 819 680 818 +f 680 819 96 +f 1729 1677 1096 +f 2482 1899 2471 +f 537 536 757 +f 536 537 621 +f 673 819 818 +f 2428 222 230 +f 25 24 523 +f 25 557 24 +f 38 25 19 +f 710 22 272 +f 663 759 794 +f 1120 878 1195 +f 537 696 621 +f 696 633 755 +f 822 2215 2220 +f 97 96 1053 +f 750 784 743 +f 887 905 864 +f 768 784 373 +f 512 513 548 +f 573 664 22 +f 696 715 633 +f 673 521 819 +f 2454 2453 2445 +f 883 887 847 +f 306 812 76 +f 642 528 759 +f 798 809 235 +f 994 792 998 +f 587 626 586 +f 1900 1918 1937 +f 645 652 618 +f 537 786 696 +f 521 593 819 +f 515 19 523 +f 741 749 719 +f 789 326 809 +f 539 581 550 +f 657 777 723 +f 684 713 660 +f 692 712 720 +f 652 666 692 +f 507 761 629 +f 472 507 629 +f 507 757 761 +f 623 633 673 +f 724 521 673 +f 515 516 19 +f 304 675 674 +f 178 778 721 +f 947 1447 2358 +f 626 645 618 +f 586 626 618 +f 784 768 742 +f 753 537 757 +f 537 753 786 +f 724 981 521 +f 521 981 593 +f 979 559 850 +f 637 660 677 +f 787 631 576 +f 141 117 385 +f 809 399 235 +f 641 754 558 +f 542 553 561 +f 742 768 762 +f 444 416 533 +f 528 687 796 +f 813 598 566 +f 1490 1501 1557 +f 753 757 507 +f 786 715 696 +f 633 724 673 +f 2090 2062 2109 +f 646 653 660 +f 660 694 683 +f 677 660 683 +f 1872 839 838 +f 1224 18 30 +f 326 393 809 +f 799 529 373 +f 313 507 472 +f 715 774 633 +f 974 699 841 +f 703 820 816 +f 692 711 676 +f 1014 355 766 +f 875 752 1019 +f 627 646 660 +f 711 692 720 +f 652 692 676 +f 799 373 784 +f 813 566 567 +f 2462 2482 2475 +f 764 644 780 +f 1479 1924 1916 +f 753 738 786 +f 738 607 786 +f 786 607 715 +f 715 524 774 +f 633 774 724 +f 559 979 672 +f 758 798 783 +f 683 694 705 +f 820 703 562 +f 764 687 644 +f 744 743 725 +f 313 753 507 +f 607 524 715 +f 664 801 22 +f 646 627 610 +f 800 820 562 +f 750 769 807 +f 767 747 533 +f 578 586 604 +f 862 593 981 +f 688 2382 1083 +f 306 304 674 +f 738 584 607 +f 168 136 238 +f 773 552 765 +f 2473 2464 2458 +f 773 793 552 +f 626 619 658 +f 1007 1139 1013 +f 562 529 799 +f 744 750 743 +f 659 683 693 +f 677 683 659 +f 313 737 753 +f 753 737 738 +f 607 729 524 +f 27 518 28 +f 553 569 580 +f 657 163 777 +f 580 569 605 +f 789 798 758 +f 769 562 807 +f 820 671 816 +f 638 646 611 +f 1074 598 644 +f 750 799 784 +f 1931 907 898 +f 2483 2487 2461 +f 737 584 738 +f 1439 1438 1431 +f 2098 1213 544 +f 48 578 75 +f 796 631 787 +f 815 732 21 +f 581 588 550 +f 625 636 651 +f 778 1011 810 +f 693 705 725 +f 693 683 705 +f 236 1921 1966 +f 584 729 607 +f 2237 1866 2227 +f 530 541 28 +f 237 739 248 +f 512 530 28 +f 727 778 771 +f 684 727 713 +f 2237 2220 826 +f 542 561 560 +f 528 796 700 +f 808 785 671 +f 739 592 248 +f 895 905 896 +f 740 246 186 +f 272 137 979 +f 770 769 744 +f 712 742 720 +f 1213 2026 544 +f 1888 1235 2438 +f 555 554 2311 +f 737 313 1192 +f 1585 1612 1611 +f 695 721 685 +f 518 17 28 +f 769 770 562 +f 719 749 740 +f 648 669 679 +f 773 657 723 +f 606 637 619 +f 2072 2062 2042 +f 606 619 626 +f 549 569 553 +f 161 638 611 +f 910 917 942 +f 917 1103 942 +f 991 1026 992 +f 979 137 672 +f 785 163 657 +f 710 2488 2472 +f 611 581 119 +f 808 671 820 +f 1820 1900 1870 +f 759 700 591 +f 637 677 619 +f 2494 2490 2463 +f 671 765 816 +f 687 764 780 +f 1019 992 1026 +f 1726 1719 987 +f 713 771 694 +f 51 2355 78 +f 510 526 525 +f 525 526 1249 +f 526 33 1249 +f 2311 554 2335 +f 827 848 840 +f 603 591 649 +f 758 269 740 +f 1595 1612 1586 +f 1694 1048 1699 +f 682 740 186 +f 22 801 603 +f 555 570 554 +f 1053 110 97 +f 615 582 601 +f 814 668 188 +f 725 705 744 +f 528 700 759 +f 640 648 620 +f 703 701 562 +f 886 892 582 +f 631 731 576 +f 1087 1835 1747 +f 882 864 895 +f 956 950 1103 +f 1502 2500 2470 +f 205 190 200 +f 815 878 616 +f 616 878 995 +f 1183 878 815 +f 1601 1827 881 +f 527 535 526 +f 2184 2183 2175 +f 1142 1125 1133 +f 235 338 798 +f 160 339 792 +f 599 92 75 +f 598 1116 566 +f 631 558 731 +f 771 770 744 +f 730 528 642 +f 841 699 642 +f 668 401 188 +f 510 527 526 +f 749 758 740 +f 706 721 695 +f 694 726 705 +f 694 744 726 +f 906 911 905 +f 661 695 161 +f 708 815 616 +f 535 547 33 +f 794 759 591 +f 778 808 790 +f 269 758 783 +f 771 744 694 +f 800 808 820 +f 571 886 582 +f 854 948 1010 +f 906 905 887 +f 625 651 635 +f 2000 1226 534 +f 2140 1504 2016 +f 601 620 615 +f 620 601 640 +f 648 640 669 +f 698 452 439 +f 671 785 657 +f 1561 2356 545 +f 685 653 667 +f 685 727 684 +f 568 616 797 +f 708 732 815 +f 93 229 339 +f 865 851 839 +f 942 1103 950 +f 589 614 125 +f 606 610 627 +f 951 834 873 +f 92 599 625 +f 1878 830 1902 +f 2482 2098 1899 +f 568 708 616 +f 708 551 732 +f 2434 2487 2483 +f 160 964 665 +f 2316 2391 2309 +f 762 758 749 +f 570 614 589 +f 888 897 883 +f 2000 1517 1388 +f 685 721 727 +f 588 610 606 +f 653 685 684 +f 651 650 635 +f 760 1151 6 +f 793 622 150 +f 651 676 650 +f 744 769 750 +f 541 542 560 +f 476 500 690 +f 473 1064 1057 +f 561 578 560 +f 636 625 599 +f 876 995 949 +f 829 856 846 +f 682 704 740 +f 791 790 770 +f 2466 2500 2460 +f 579 587 586 +f 1352 1208 1095 +f 1684 1479 1916 +f 604 609 636 +f 751 721 706 +f 810 608 782 +f 672 603 649 +f 475 447 476 +f 794 591 801 +f 682 186 650 +f 808 800 790 +f 644 598 813 +f 704 719 740 +f 1011 608 810 +f 1192 584 737 +f 687 780 796 +f 2337 474 2312 +f 638 667 646 +f 706 1186 728 +f 733 575 568 +f 595 551 708 +f 595 540 551 +f 1308 501 1852 +f 665 339 160 +f 527 2447 535 +f 558 9 731 +f 723 793 773 +f 660 713 694 +f 693 725 666 +f 562 767 529 +f 550 538 531 +f 2267 2287 2233 +f 996 964 160 +f 2068 2470 2466 +f 704 711 719 +f 741 762 749 +f 605 606 626 +f 548 542 530 +f 995 878 709 +f 1898 1684 1916 +f 778 791 771 +f 782 163 785 +f 789 758 762 +f 857 883 847 +f 733 970 1028 +f 838 829 825 +f 2447 511 535 +f 22 603 137 +f 705 726 744 +f 605 587 580 +f 512 548 530 +f 743 784 742 +f 790 800 770 +f 778 810 808 +f 1014 998 355 +f 708 568 595 +f 656 697 551 +f 540 656 551 +f 143 125 614 +f 1000 1020 983 +f 778 178 1011 +f 676 704 682 +f 637 627 660 +f 606 627 637 +f 701 552 481 +f 808 810 785 +f 590 570 555 +f 716 595 568 +f 2355 2335 554 +f 912 1729 911 +f 1076 1456 1546 +f 697 68 492 +f 676 711 704 +f 839 851 838 +f 1028 575 733 +f 1020 844 982 +f 716 568 575 +f 844 781 982 +f 1238 2156 2034 +f 553 580 561 +f 580 579 561 +f 452 461 453 +f 560 578 48 +f 564 540 595 +f 632 656 540 +f 564 632 540 +f 75 578 599 +f 518 27 535 +f 511 518 535 +f 783 798 788 +f 642 759 663 +f 720 742 741 +f 605 626 587 +f 580 587 579 +f 725 712 666 +f 562 701 767 +f 1729 923 911 +f 712 743 742 +f 619 677 658 +f 161 695 654 +f 770 800 562 +f 2084 2489 2472 +f 575 559 716 +f 716 564 595 +f 654 695 685 +f 843 855 2064 +f 34 731 9 +f 527 510 1973 +f 723 622 793 +f 992 1726 987 +f 693 666 652 +f 2472 853 573 +f 624 159 148 +f 671 657 773 +f 681 188 498 +f 797 970 733 +f 565 656 632 +f 565 697 656 +f 565 731 697 +f 1949 951 920 +f 85 111 84 +f 662 200 190 +f 44 324 754 +f 33 547 40 +f 658 693 652 +f 658 652 645 +f 664 794 801 +f 666 712 692 +f 639 648 662 +f 611 646 610 +f 850 559 575 +f 1447 2490 1106 +f 1972 1955 1935 +f 582 615 590 +f 66 581 539 +f 780 641 631 +f 796 780 631 +f 1049 1192 83 +f 1348 13 1519 +f 799 807 562 +f 581 611 588 +f 687 795 644 +f 663 8 642 +f 1936 1972 1935 +f 650 676 682 +f 615 630 590 +f 730 795 687 +f 742 762 741 +f 548 553 542 +f 1048 1692 1074 +f 658 659 693 +f 37 52 30 +f 611 610 588 +f 649 632 564 +f 565 576 731 +f 2138 922 1058 +f 1204 854 965 +f 725 743 712 +f 644 813 641 +f 660 653 684 +f 771 791 770 +f 644 795 1074 +f 469 480 681 +f 559 672 564 +f 716 559 564 +f 672 649 564 +f 2161 1378 2171 +f 474 475 476 +f 816 765 701 +f 765 552 701 +f 513 538 548 +f 754 324 107 +f 609 586 618 +f 25 523 19 +f 677 659 658 +f 689 452 698 +f 1334 1115 1353 +f 700 565 632 +f 700 576 565 +f 481 552 793 +f 763 901 2458 +f 550 549 538 +f 781 964 996 +f 1596 1634 1595 +f 198 916 1124 +f 198 1124 341 +f 842 973 1025 +f 842 1025 836 +f 1009 1024 934 +f 573 710 2472 +f 1100 971 1002 +f 1501 1081 1557 +f 1225 1219 955 +f 413 2138 284 +f 955 1630 522 +f 341 1124 301 +f 2333 2376 2350 +f 1107 218 284 +f 398 925 1513 +f 1513 1442 1495 +f 1935 1455 1744 +f 1723 1935 1744 +f 825 1872 838 +f 1495 1442 1496 +f 963 1024 1009 +f 1511 1514 966 +f 1775 1729 912 +f 688 262 1067 +f 714 1007 1512 +f 919 1732 914 +f 2319 2331 2304 +f 2400 2407 2391 +f 1674 2164 1780 +f 843 927 899 +f 1660 988 1188 +f 1067 262 1640 +f 1381 1109 1483 +f 1437 1381 1483 +f 2495 1010 948 +f 1514 1289 1313 +f 899 374 961 +f 1438 1430 1422 +f 1634 1095 1632 +f 2487 973 2461 +f 1003 499 874 +f 849 848 827 +f 1430 1462 1453 +f 2496 2084 2471 +f 909 10 980 +f 730 927 835 +f 2031 1540 1536 +f 831 849 2178 +f 881 834 951 +f 1841 1722 1803 +f 1005 670 1020 +f 1021 670 1005 +f 1869 2059 2467 +f 903 902 1939 +f 2476 2502 1651 +f 853 8 573 +f 1850 831 2178 +f 934 746 247 +f 934 65 746 +f 301 285 1077 +f 968 944 977 +f 970 2495 1028 +f 974 2465 374 +f 899 927 374 +f 1882 1898 1916 +f 1613 1634 1596 +f 909 833 1396 +f 2492 247 1003 +f 919 914 1931 +f 1459 1299 1458 +f 1634 1632 1633 +f 844 670 228 +f 2494 2497 2467 +f 901 973 2487 +f 228 1772 734 +f 1701 1709 1666 +f 963 574 1024 +f 847 864 856 +f 1730 1736 2239 +f 870 859 848 +f 2074 2111 2103 +f 1140 1590 1483 +f 927 730 974 +f 2103 978 2074 +f 756 1745 1718 +f 848 859 840 +f 1296 1482 1320 +f 2331 51 66 +f 1067 988 962 +f 1396 833 1445 +f 1001 1005 1000 +f 901 1009 973 +f 1099 1077 817 +f 933 944 936 +f 952 958 1828 +f 988 1660 986 +f 833 1067 1445 +f 1067 1640 988 +f 218 413 284 +f 1843 180 347 +f 1846 1708 1798 +f 2469 2477 855 +f 1006 1021 1005 +f 381 382 250 +f 2369 828 531 +f 968 977 1001 +f 2460 1949 779 +f 1194 1441 1115 +f 1001 1000 968 +f 756 678 1745 +f 963 1009 901 +f 2471 2084 2472 +f 841 642 8 +f 982 991 1027 +f 670 844 1020 +f 1289 1514 945 +f 869 904 890 +f 1161 1115 1639 +f 823 2178 849 +f 746 12 499 +f 263 428 2366 +f 1685 1075 1692 +f 1002 926 806 +f 1799 1755 216 +f 944 968 993 +f 943 944 993 +f 31 38 19 +f 531 828 550 +f 1501 1078 1081 +f 1921 1149 431 +f 936 943 932 +f 1660 1489 1412 +f 301 980 285 +f 903 918 902 +f 869 890 868 +f 890 903 867 +f 1003 746 499 +f 951 1949 2500 +f 990 841 853 +f 1595 1634 1611 +f 374 927 974 +f 836 1025 247 +f 1653 1652 1638 +f 1303 1545 1142 +f 1616 1631 1638 +f 1629 1546 1628 +f 936 932 913 +f 513 506 531 +f 868 890 867 +f 2330 2369 2353 +f 924 918 914 +f 907 914 904 +f 1258 1421 1267 +f 301 939 980 +f 1472 1482 1296 +f 868 867 859 +f 472 491 313 +f 272 519 2488 +f 1471 1472 1296 +f 1025 934 247 +f 1634 1633 1611 +f 2176 1847 2177 +f 1310 1289 806 +f 924 933 918 +f 1969 1968 902 +f 2107 2128 2118 +f 1428 1436 1287 +f 1139 1564 1617 +f 2378 572 2384 +f 853 841 8 +f 2501 961 2465 +f 1221 1240 1408 +f 1069 1578 1627 +f 1006 1005 1001 +f 1617 1564 1578 +f 828 539 550 +f 1791 2168 2160 +f 1829 1718 1739 +f 1968 1939 902 +f 756 1718 665 +f 1998 2000 1388 +f 2451 545 2356 +f 178 997 1011 +f 1275 325 1270 +f 1709 872 1666 +f 2176 1959 1847 +f 944 943 936 +f 2424 518 511 +f 1445 1067 962 +f 2007 952 1828 +f 2052 2061 2081 +f 828 2303 539 +f 835 1699 1048 +f 1709 1706 872 +f 885 574 963 +f 1318 1296 1320 +f 859 867 1902 +f 1452 1448 1421 +f 943 993 976 +f 993 1000 983 +f 854 1010 876 +f 988 986 962 +f 2031 2052 2081 +f 924 1732 1828 +f 965 949 1060 +f 781 228 734 +f 1718 1765 665 +f 943 976 932 +f 1680 1794 1783 +f 1448 1471 1276 +f 1276 1267 1421 +f 1931 914 907 +f 991 781 996 +f 1276 1421 1448 +f 10 909 1396 +f 831 860 849 +f 1523 1762 1774 +f 924 1828 937 +f 307 994 1014 +f 946 963 901 +f 978 2103 977 +f 977 1006 1001 +f 1007 1161 1639 +f 1639 1294 1437 +f 885 1032 574 +f 1294 1381 1437 +f 733 568 797 +f 792 229 1112 +f 119 581 108 +f 843 835 927 +f 1889 860 831 +f 2211 2216 2204 +f 2400 2431 2422 +f 2103 1006 977 +f 840 1902 830 +f 827 840 830 +f 827 830 822 +f 1003 874 2492 +f 1432 1439 1431 +f 781 734 964 +f 1937 1936 1723 +f 918 913 902 +f 958 977 944 +f 1850 2178 2177 +f 1005 1020 1000 +f 991 996 307 +f 1396 1445 340 +f 2179 1763 889 +f 939 909 980 +f 1828 958 937 +f 978 977 958 +f 1590 1571 1563 +f 779 1949 920 +f 1551 1362 1573 +f 2103 2142 1006 +f 920 885 963 +f 946 920 963 +f 1584 1616 1583 +f 1453 1472 1452 +f 1647 1617 1578 +f 1578 1564 1627 +f 1628 938 1069 +f 869 868 859 +f 993 983 976 +f 912 1762 1775 +f 752 751 706 +f 1628 1546 938 +f 844 228 781 +f 840 859 1902 +f 898 907 904 +f 1025 973 1009 +f 663 664 573 +f 763 946 901 +f 898 904 869 +f 2172 889 1763 +f 1128 926 971 +f 860 848 849 +f 904 903 890 +f 2486 2459 2479 +f 577 782 608 +f 933 936 918 +f 2177 1847 1851 +f 665 1765 339 +f 937 958 944 +f 894 981 724 +f 968 1000 993 +f 2192 2195 2205 +f 1652 1099 817 +f 997 608 1011 +f 997 577 608 +f 577 163 782 +f 1112 998 792 +f 2177 1851 1850 +f 1257 1421 1258 +f 951 873 920 +f 822 830 2215 +f 1899 2496 2471 +f 1773 1668 1558 +f 904 914 903 +f 932 1671 913 +f 873 885 920 +f 1013 1617 1647 +f 873 1032 885 +f 894 862 981 +f 2469 855 961 +f 913 1671 1969 +f 2477 2064 855 +f 918 936 913 +f 860 870 848 +f 937 944 933 +f 1501 1013 1647 +f 824 178 751 +f 824 997 178 +f 824 577 997 +f 643 163 577 +f 863 856 882 +f 2128 2153 2134 +f 722 774 880 +f 722 894 774 +f 864 905 895 +f 850 575 583 +f 914 918 903 +f 924 937 933 +f 1501 717 1013 +f 1587 1324 928 +f 717 1512 1013 +f 602 577 824 +f 766 643 577 +f 894 709 862 +f 709 878 862 +f 976 975 932 +f 1324 1596 928 +f 880 524 1060 +f 2434 2459 2499 +f 1324 1613 1596 +f 752 824 751 +f 602 766 577 +f 1014 602 594 +f 1387 1226 2152 +f 2153 1387 2152 +f 669 930 950 +f 1710 1694 1699 +f 768 326 762 +f 582 892 601 +f 974 990 2465 +f 624 116 625 +f 835 795 730 +f 2458 2484 763 +f 989 602 824 +f 2064 2477 1710 +f 976 983 975 +f 949 722 880 +f 996 160 994 +f 2305 863 556 +f 556 863 886 +f 601 910 640 +f 2264 825 829 +f 989 824 752 +f 856 864 882 +f 1595 1586 2381 +f 1627 1629 1628 +f 2174 2180 2173 +f 2128 2134 2118 +f 137 272 22 +f 949 880 1060 +f 995 894 722 +f 894 995 709 +f 894 724 774 +f 886 895 892 +f 640 910 930 +f 871 870 860 +f 846 856 863 +f 1026 875 1019 +f 838 851 829 +f 1024 1171 934 +f 36 189 205 +f 863 882 886 +f 886 882 895 +f 875 1026 594 +f 52 1459 1269 +f 896 917 910 +f 1025 1009 934 +f 949 995 722 +f 2152 1226 1636 +f 895 896 892 +f 892 910 601 +f 942 950 930 +f 875 989 752 +f 594 602 989 +f 766 355 643 +f 355 260 643 +f 905 917 896 +f 965 1060 1162 +f 892 896 910 +f 1101 1052 1042 +f 1029 1031 834 +f 1101 1133 1118 +f 342 357 376 +f 516 515 2454 +f 1656 2494 2467 +f 1056 1303 1133 +f 1120 1130 862 +f 69 342 376 +f 1055 1056 1133 +f 499 69 165 +f 85 101 111 +f 1031 1032 834 +f 200 679 1166 +f 1031 1042 1032 +f 1171 65 934 +f 1822 1204 1177 +f 1096 956 1103 +f 514 96 97 +f 956 1145 1144 +f 1185 1166 1144 +f 1145 1185 1144 +f 1185 200 1166 +f 375 132 1041 +f 1153 1202 305 +f 32 1244 1249 +f 1096 1087 956 +f 554 78 2355 +f 1191 138 110 +f 65 35 432 +f 1087 1110 956 +f 1110 1146 956 +f 956 1146 1145 +f 1146 1156 1145 +f 1145 1156 1185 +f 950 956 1144 +f 2481 2495 948 +f 1156 1193 1185 +f 1050 1047 1051 +f 239 151 107 +f 1185 1193 36 +f 1747 1110 1087 +f 1134 1146 1110 +f 1146 1157 1156 +f 1156 1157 1193 +f 1041 1045 1034 +f 1397 1134 1110 +f 1157 1146 1134 +f 1157 1175 1193 +f 1193 199 36 +f 1090 1035 1196 +f 1456 1150 1051 +f 1175 199 1193 +f 1186 695 199 +f 1186 199 1175 +f 1175 1157 1134 +f 728 1186 1175 +f 197 760 6 +f 1130 593 862 +f 1167 1109 182 +f 1194 1115 1161 +f 2140 1928 1504 +f 921 922 2138 +f 1147 1134 1397 +f 1719 1147 1397 +f 1147 1175 1134 +f 1175 1147 728 +f 341 1654 1208 +f 754 151 9 +f 284 2138 1058 +f 1188 1557 1660 +f 1191 110 1053 +f 916 284 1189 +f 284 1058 1189 +f 2094 1465 2127 +f 1726 1019 1147 +f 1147 1019 728 +f 593 1130 96 +f 239 305 1038 +f 1036 1131 315 +f 397 1131 1120 +f 1053 96 1130 +f 2467 2485 1869 +f 517 1089 421 +f 834 1827 1029 +f 419 1047 1117 +f 1034 433 1306 +f 2239 1862 1730 +f 1453 1462 1472 +f 1408 1422 1399 +f 471 23 1111 +f 1205 1150 1456 +f 1205 1040 1150 +f 1131 1036 293 +f 293 1068 1044 +f 375 1041 138 +f 1205 1140 1046 +f 1040 1205 1046 +f 1140 1167 1046 +f 1104 1049 83 +f 1052 1085 1032 +f 1044 1068 1191 +f 1167 1483 1109 +f 208 1084 1035 +f 1040 132 375 +f 1834 20 3 +f 1050 1051 1070 +f 1133 1125 1174 +f 11 1440 1401 +f 420 208 1071 +f 1135 1079 1094 +f 1086 1101 1118 +f 1029 1030 1031 +f 1200 1061 294 +f 1191 1068 138 +f 1171 1141 65 +f 1141 1172 65 +f 1172 35 65 +f 1172 404 35 +f 404 99 35 +f 221 1104 1063 +f 802 398 1083 +f 20 1089 3 +f 2064 1699 835 +f 1042 1052 1032 +f 1433 1261 1432 +f 1323 2338 155 +f 1076 1205 1456 +f 1088 1402 1056 +f 1150 348 1070 +f 1200 1089 20 +f 1097 1162 100 +f 1032 873 834 +f 21 471 1111 +f 294 1097 1104 +f 1072 100 584 +f 1151 760 622 +f 132 1045 1041 +f 1050 1070 1135 +f 1088 1039 940 +f 650 159 635 +f 100 1170 729 +f 729 584 100 +f 1103 931 1096 +f 925 1443 1513 +f 138 1102 110 +f 1034 1306 1152 +f 1071 1035 1090 +f 100 1072 1097 +f 23 1158 315 +f 1068 375 138 +f 1586 1612 1585 +f 1819 1030 1029 +f 1041 1034 1102 +f 232 375 1068 +f 348 1079 1070 +f 1061 1097 294 +f 1513 1443 1442 +f 1200 294 1119 +f 376 1050 1062 +f 1094 1036 315 +f 1200 1119 1089 +f 1111 1183 21 +f 1044 1191 1053 +f 698 295 689 +f 1079 232 1036 +f 404 1117 99 +f 1495 1496 717 +f 1119 294 98 +f 3 1089 517 +f 1132 1063 83 +f 1132 83 175 +f 132 1046 182 +f 1111 1195 1183 +f 1131 1044 1037 +f 127 402 1804 +f 219 1272 1047 +f 1697 1135 1094 +f 2140 1854 2117 +f 1111 397 1195 +f 1177 1162 1097 +f 1061 1177 1097 +f 717 1509 714 +f 2 1300 433 +f 462 290 461 +f 98 294 221 +f 294 1104 221 +f 714 1161 1007 +f 1073 1152 1143 +f 1697 1094 1360 +f 1223 1423 1218 +f 836 2479 842 +f 1097 1072 1049 +f 348 1040 375 +f 3 517 316 +f 180 1061 1201 +f 348 375 232 +f 1432 1431 1415 +f 220 1513 1495 +f 1104 1097 1049 +f 306 674 596 +f 777 455 723 +f 2170 2151 1641 +f 1047 419 219 +f 1102 1034 1073 +f 1073 1034 1152 +f 1035 1054 1196 +f 1177 1204 1162 +f 746 65 12 +f 751 178 721 +f 1054 517 421 +f 1051 1150 1070 +f 1102 1073 110 +f 998 1136 355 +f 567 566 1163 +f 1111 315 397 +f 1048 1074 835 +f 1158 1094 315 +f 1374 1107 1252 +f 1112 1136 998 +f 472 629 500 +f 355 1136 260 +f 260 118 43 +f 1104 83 1063 +f 376 357 1050 +f 1463 1142 1545 +f 1036 232 293 +f 1030 1042 1031 +f 1079 348 232 +f 221 1063 1132 +f 1094 1079 1036 +f 1076 1629 1205 +f 1136 1197 260 +f 260 1197 118 +f 1204 965 1162 +f 293 232 1068 +f 1590 1205 1629 +f 1205 1590 1140 +f 250 382 392 +f 1296 1318 1311 +f 347 1201 20 +f 1201 1200 20 +f 132 182 1045 +f 1101 1086 1052 +f 1033 1039 1055 +f 138 1041 1102 +f 970 1010 2495 +f 455 777 43 +f 1992 1948 2023 +f 20 1834 347 +f 1072 584 1049 +f 584 1192 1049 +f 182 2 1045 +f 1163 324 44 +f 1360 1094 1158 +f 1450 1360 1158 +f 1091 1112 229 +f 509 723 455 +f 207 509 455 +f 1251 1257 1266 +f 1488 1489 1547 +f 2157 1541 1875 +f 305 107 324 +f 1045 2 433 +f 1070 1079 1135 +f 1136 1168 1197 +f 1197 359 118 +f 118 359 43 +f 359 356 43 +f 356 455 43 +f 356 207 455 +f 1240 1422 1408 +f 1163 1153 324 +f 1201 1061 1200 +f 1052 1086 1085 +f 1024 1141 1171 +f 1112 1105 1136 +f 1050 1135 1062 +f 1105 1168 1136 +f 1168 1178 1197 +f 1197 1178 359 +f 1173 404 1172 +f 465 356 359 +f 1174 1125 240 +f 1240 1431 1422 +f 1098 1113 1105 +f 1112 1098 1105 +f 1105 1178 1168 +f 1178 465 359 +f 1091 1098 1112 +f 1133 1174 1118 +f 98 221 1059 +f 487 1132 175 +f 980 1017 285 +f 465 207 356 +f 180 1201 347 +f 1060 524 1170 +f 445 127 316 +f 1431 1438 1422 +f 498 469 681 +f 940 1807 1759 +f 381 250 1290 +f 1113 1122 1105 +f 1105 1122 1178 +f 1151 509 207 +f 1236 2035 525 +f 1131 293 1044 +f 346 207 465 +f 346 1151 207 +f 1822 1796 1204 +f 1143 204 97 +f 123 1128 971 +f 2153 2152 2134 +f 126 1151 346 +f 517 445 316 +f 1450 1158 23 +f 1458 1462 1430 +f 1129 152 1182 +f 1122 1159 1178 +f 1178 1198 465 +f 79 346 465 +f 126 1155 1151 +f 1151 1155 6 +f 295 1129 689 +f 1073 1143 97 +f 1098 1123 1113 +f 1113 1123 1122 +f 1123 1169 1122 +f 1178 1159 1198 +f 1198 79 465 +f 392 383 152 +f 1822 1061 180 +f 116 92 625 +f 421 1089 1119 +f 1129 295 152 +f 110 1073 97 +f 1173 1172 1141 +f 1122 1169 1159 +f 79 126 346 +f 1155 181 6 +f 971 926 1002 +f 295 1043 152 +f 1039 1088 1056 +f 1428 1266 1436 +f 404 419 1117 +f 836 879 2479 +f 2464 2476 2458 +f 1198 317 79 +f 1124 939 301 +f 44 754 567 +f 1039 1056 1055 +f 1439 1459 1458 +f 1660 1412 986 +f 1169 1160 1159 +f 179 1155 126 +f 1155 131 181 +f 1061 1822 1177 +f 1153 305 324 +f 175 314 327 +f 1160 1187 1159 +f 1159 1187 1198 +f 1198 1187 317 +f 79 179 126 +f 1043 250 392 +f 152 1043 392 +f 96 819 593 +f 1123 1127 1169 +f 317 179 79 +f 1057 1155 179 +f 1155 391 131 +f 131 391 668 +f 2381 1586 1585 +f 12 69 499 +f 262 398 1640 +f 2107 2118 2060 +f 2130 2094 2002 +f 1187 249 317 +f 1155 1057 391 +f 1290 439 1265 +f 305 239 107 +f 1127 1160 1169 +f 317 473 179 +f 473 1057 179 +f 83 1192 314 +f 1043 1290 250 +f 1807 940 1030 +f 517 1084 445 +f 1057 1164 391 +f 2492 2480 2493 +f 163 643 43 +f 1056 1545 1303 +f 1069 1655 1023 +f 249 473 317 +f 1162 1060 1170 +f 1086 1118 1154 +f 82 68 16 +f 1989 1990 1536 +f 1633 1632 1611 +f 1487 2372 1305 +f 1494 1069 1023 +f 1137 1160 1127 +f 669 1166 679 +f 390 1285 426 +f 1955 1972 1971 +f 1219 1223 2437 +f 1254 1261 1223 +f 1319 1545 1056 +f 1320 1328 2443 +f 1261 1433 1223 +f 1219 1254 1223 +f 254 222 2428 +f 1237 1290 1265 +f 1284 1273 1263 +f 1277 1291 1301 +f 1314 102 1301 +f 1280 363 377 +f 1313 1353 1514 +f 468 451 439 +f 1918 1964 1956 +f 2026 29 2140 +f 1354 381 1279 +f 1224 30 1254 +f 147 158 173 +f 1247 1253 274 +f 1271 380 334 +f 2043 2072 2042 +f 274 300 267 +f 1356 1392 211 +f 13 240 1142 +f 1382 1330 1392 +f 1312 1323 155 +f 240 1125 1142 +f 2358 1573 1362 +f 1236 1249 1244 +f 1272 219 1348 +f 1271 1274 380 +f 191 2034 1982 +f 1992 2052 1990 +f 462 452 689 +f 2262 2286 2261 +f 183 489 1642 +f 2485 2480 1869 +f 84 111 1323 +f 1190 353 1354 +f 446 434 435 +f 1336 171 1341 +f 2021 430 2059 +f 862 878 1120 +f 1263 1273 1248 +f 1966 1921 2144 +f 1312 84 1323 +f 240 13 1348 +f 1359 1274 1271 +f 1392 1330 1247 +f 1520 1333 11 +f 1368 1253 1247 +f 1279 1285 1190 +f 2465 990 2489 +f 1272 1519 805 +f 1369 1272 805 +f 1317 95 1344 +f 1242 1248 1234 +f 1368 242 1363 +f 274 1262 1386 +f 532 597 1886 +f 2117 2026 2140 +f 1392 1247 274 +f 2162 508 985 +f 1964 1469 1965 +f 1315 104 1331 +f 1392 1356 1382 +f 128 1342 1336 +f 1285 427 426 +f 1219 1224 1254 +f 1320 1322 1321 +f 1320 1321 1328 +f 153 2443 1328 +f 1321 153 1328 +f 1235 1244 1243 +f 1225 1224 1219 +f 1359 353 1190 +f 1312 1473 1458 +f 1336 1342 147 +f 305 1333 1038 +f 1336 147 171 +f 516 31 19 +f 2479 2461 842 +f 1237 1265 427 +f 1263 1278 1284 +f 881 1827 834 +f 1237 427 1285 +f 1299 1312 1458 +f 1190 1285 1274 +f 1363 286 1253 +f 2330 2303 828 +f 427 442 426 +f 2493 2463 2492 +f 1285 380 1274 +f 522 18 1225 +f 2471 2472 2488 +f 2338 154 1321 +f 1423 1415 1218 +f 1225 18 1224 +f 1253 286 1262 +f 286 353 1359 +f 171 1368 1383 +f 1273 54 1234 +f 1973 2447 527 +f 1322 155 1321 +f 1203 1369 1413 +f 1307 363 1298 +f 1364 1375 1329 +f 1329 227 1306 +f 296 1298 1343 +f 947 2499 1447 +f 1203 1047 1272 +f 1098 1748 1123 +f 1519 1272 1348 +f 1277 70 1273 +f 1282 1337 1361 +f 286 302 353 +f 103 104 1315 +f 1377 435 434 +f 1449 1261 1345 +f 926 1310 806 +f 1263 1248 1242 +f 985 508 597 +f 1415 1222 1218 +f 88 1325 104 +f 170 111 156 +f 1384 1282 1361 +f 274 1253 1262 +f 1371 1317 1344 +f 1371 1366 1337 +f 1345 1459 1449 +f 171 1383 1341 +f 2438 1235 1227 +f 2134 1582 2118 +f 428 1260 1379 +f 1336 1341 1325 +f 1235 1242 1227 +f 1228 1687 2284 +f 1854 2140 2016 +f 1866 1887 1873 +f 1343 1298 1370 +f 1384 1361 2440 +f 171 242 1368 +f 1344 1309 1366 +f 1371 1344 1366 +f 1280 1377 1293 +f 200 1185 205 +f 1330 1383 1368 +f 1255 1264 1263 +f 543 1367 1876 +f 1343 1370 1260 +f 1293 1326 1370 +f 2440 1361 1302 +f 1282 1384 2406 +f 271 1337 1282 +f 170 2338 1323 +f 1528 1503 2470 +f 515 1347 2453 +f 1997 1705 1998 +f 2285 1228 2284 +f 1229 1250 1228 +f 1330 1368 1247 +f 1919 1619 2045 +f 1344 1364 1335 +f 1222 1240 1221 +f 1212 858 1741 +f 2388 1222 1221 +f 1528 2470 2068 +f 501 1308 2171 +f 1295 1311 1487 +f 2116 1619 1655 +f 1220 1229 1228 +f 8 663 573 +f 1343 1260 428 +f 1337 1366 1361 +f 1298 1280 1293 +f 1269 1345 1261 +f 1279 381 1290 +f 1230 1229 1220 +f 1230 1245 1229 +f 1245 1250 1229 +f 1227 1234 31 +f 1302 1361 1350 +f 1245 1266 1428 +f 1992 2023 2052 +f 2482 2471 2475 +f 452 462 461 +f 271 1282 1275 +f 1991 1989 1934 +f 1366 1309 1350 +f 1344 1335 1309 +f 730 699 974 +f 1374 1252 1208 +f 597 508 1912 +f 1363 1253 1368 +f 1386 1271 300 +f 1211 1218 1222 +f 1376 1377 434 +f 2399 2437 1211 +f 1284 1291 1277 +f 1230 1251 1245 +f 1251 1266 1245 +f 1317 1371 1337 +f 1288 1286 1095 +f 1095 1286 1352 +f 1241 1208 1352 +f 1241 1374 1208 +f 1284 1278 1291 +f 211 1392 267 +f 1344 1375 1364 +f 929 583 1028 +f 1361 1366 1350 +f 1115 1294 1639 +f 1291 103 1301 +f 1220 1231 1230 +f 1231 1251 1230 +f 1234 1248 1273 +f 1255 55 1264 +f 1360 1450 1702 +f 363 1280 1298 +f 1369 1203 1272 +f 1415 1240 1222 +f 1216 1231 1220 +f 1243 1263 1235 +f 1375 227 1329 +f 1264 1278 1263 +f 855 899 961 +f 1286 1241 1352 +f 2081 2128 2107 +f 1223 1433 1423 +f 1473 1312 155 +f 154 153 1321 +f 1377 1376 1293 +f 1392 274 267 +f 334 300 1271 +f 1955 1991 1934 +f 1613 1327 1288 +f 1327 1286 1288 +f 1349 1374 1241 +f 2370 2025 2367 +f 1315 1331 133 +f 434 446 1256 +f 1232 1251 1231 +f 1243 1244 1255 +f 1286 1304 1241 +f 1349 1107 1374 +f 1359 1271 1386 +f 1227 516 2431 +f 219 240 1348 +f 1270 271 1275 +f 1255 1263 1243 +f 2026 1926 29 +f 1683 2157 1212 +f 1326 1293 1376 +f 1255 32 55 +f 104 1325 1341 +f 519 2462 2475 +f 2154 2161 2137 +f 1376 434 1246 +f 1246 434 1256 +f 1257 1251 1232 +f 1262 1359 1386 +f 2195 2192 2186 +f 1308 534 1226 +f 2026 2117 544 +f 1327 1613 1324 +f 1327 1326 1286 +f 1286 1326 1304 +f 104 1341 1331 +f 774 524 880 +f 837 1517 534 +f 1127 1123 1567 +f 1279 1237 1285 +f 1297 1381 1294 +f 1217 1232 1216 +f 1142 1519 13 +f 1436 1267 1287 +f 1324 1372 1327 +f 1304 1246 1241 +f 1246 1349 1241 +f 1246 1373 1349 +f 286 1359 1262 +f 1382 1383 1330 +f 1284 1277 1273 +f 489 1998 1799 +f 1675 1116 1075 +f 106 1317 1337 +f 1311 1295 1281 +f 1292 1364 1329 +f 1335 1364 1292 +f 1334 1294 1115 +f 1334 1297 1294 +f 1300 1381 1297 +f 973 842 2461 +f 1217 1239 1232 +f 1232 1239 1257 +f 1258 1267 1436 +f 1359 1190 1274 +f 1862 1405 1877 +f 1372 1339 1327 +f 1339 1326 1327 +f 1373 1351 1349 +f 1276 1311 1281 +f 1256 2386 1351 +f 2 1109 1300 +f 482 1731 520 +f 803 1604 2022 +f 1223 1218 1211 +f 1341 1383 1382 +f 1298 1293 1370 +f 1190 1354 1279 +f 1324 2398 1372 +f 1714 1700 2173 +f 183 2000 489 +f 1701 1666 192 +f 1227 1242 1234 +f 1332 1289 1310 +f 1517 2005 2130 +f 1331 1341 1382 +f 525 1249 1236 +f 23 1268 1450 +f 1264 1291 1278 +f 1281 1287 1267 +f 1295 1305 1287 +f 1281 1295 1287 +f 1487 1305 1295 +f 1605 2097 2058 +f 1326 1376 1304 +f 1304 1376 1246 +f 1316 1919 1984 +f 2500 1949 2460 +f 1332 1313 1289 +f 2189 2181 2177 +f 1335 1334 1353 +f 1292 1297 1334 +f 1428 1250 1245 +f 969 958 952 +f 1217 1233 1239 +f 1233 1257 1239 +f 1876 1367 1338 +f 1379 1260 1372 +f 1372 1260 1339 +f 1128 1302 1310 +f 1310 1302 1332 +f 1335 1353 1313 +f 1292 1334 1335 +f 1297 1329 1300 +f 1279 1290 1237 +f 1301 103 1314 +f 70 1301 102 +f 23 1333 1268 +f 380 1285 390 +f 772 325 1275 +f 1314 103 1315 +f 2473 2458 2487 +f 1276 1281 1267 +f 1344 95 1375 +f 2053 1771 1572 +f 1246 1256 1373 +f 1373 1256 1351 +f 1340 1302 1128 +f 1350 1313 1332 +f 1329 1297 1292 +f 2434 2473 2487 +f 106 1337 271 +f 23 471 1333 +f 622 723 509 +f 1388 1517 2127 +f 1991 1990 1989 +f 183 1636 1226 +f 2133 1605 2151 +f 1260 1370 1339 +f 1339 1370 1326 +f 867 1894 1902 +f 390 426 412 +f 1235 1263 1242 +f 1399 1422 1233 +f 305 11 1333 +f 1300 1329 1306 +f 1302 1350 1332 +f 1350 1309 1313 +f 1309 1335 1313 +f 2470 2102 1502 +f 1787 1531 1599 +f 1724 1725 1691 +f 1827 1601 1927 +f 1678 1358 1476 +f 1823 1812 1846 +f 1805 1824 1708 +f 1746 1676 1797 +f 325 2395 429 +f 1835 1677 1826 +f 1507 1790 1722 +f 1526 1672 858 +f 158 147 1342 +f 1462 1473 1322 +f 1474 1414 1565 +f 1761 1900 1877 +f 940 1759 1008 +f 1565 1015 1008 +f 1924 1533 1933 +f 1878 826 830 +f 1565 1414 1015 +f 1402 1088 1008 +f 1538 1532 1651 +f 1015 1552 1008 +f 1538 1591 1474 +f 1532 1538 1474 +f 1474 1591 1414 +f 1484 1402 1008 +f 1552 1484 1008 +f 1414 1460 1015 +f 1015 1460 1552 +f 806 1289 945 +f 1597 1538 1659 +f 1484 1319 1402 +f 1056 1402 1319 +f 1538 1597 1591 +f 1591 960 1414 +f 1414 960 1460 +f 1925 1466 1455 +f 1552 1400 1484 +f 1484 1400 1319 +f 1400 113 1319 +f 1597 1580 1591 +f 1460 1400 1552 +f 1514 1441 966 +f 1597 1659 1409 +f 1657 113 1400 +f 1460 1657 1400 +f 1288 1095 1634 +f 1551 1597 1409 +f 1580 1598 1591 +f 1591 1598 960 +f 1536 1990 2031 +f 960 1657 1460 +f 1809 1746 1797 +f 1423 1433 1432 +f 2478 1362 1409 +f 1463 1545 113 +f 1657 1463 113 +f 1457 1287 1305 +f 1682 1716 1746 +f 1434 1761 1885 +f 1013 1139 1617 +f 2379 1362 2478 +f 1420 1597 1551 +f 1420 1580 1597 +f 1664 1808 1712 +f 2256 2250 2231 +f 1362 1551 1409 +f 2196 2214 2213 +f 1691 1725 1777 +f 1626 192 1666 +f 1534 1574 2058 +f 1574 1600 1605 +f 1600 1606 1605 +f 1606 1641 1605 +f 1573 1420 1551 +f 1657 1485 1463 +f 678 1806 1742 +f 1534 1553 1574 +f 1574 1575 1600 +f 1810 2170 585 +f 1623 1641 1606 +f 1407 1657 960 +f 1598 1407 960 +f 1485 1142 1463 +f 1716 1581 1676 +f 1738 1743 1733 +f 843 2064 835 +f 1539 1575 1574 +f 1553 1539 1574 +f 1575 1592 1600 +f 1592 1624 1606 +f 1600 1592 1606 +f 1642 585 1641 +f 1623 1642 1641 +f 1485 164 1142 +f 1738 1516 1743 +f 1809 1720 1798 +f 1533 1535 1534 +f 1592 1607 1624 +f 1624 1623 1606 +f 1163 566 1116 +f 1407 1485 1657 +f 1432 1449 1439 +f 1100 802 2382 +f 1743 1516 1722 +f 1746 1716 1676 +f 1535 1539 1534 +f 1534 1539 1553 +f 1642 1623 1624 +f 1095 1208 1654 +f 967 1407 1598 +f 1580 967 1598 +f 1809 1797 1720 +f 1924 1524 1535 +f 1533 1924 1535 +f 1539 1576 1575 +f 1642 216 585 +f 1407 1529 1485 +f 1485 1529 164 +f 1472 1462 1482 +f 1415 1431 1240 +f 966 1194 714 +f 383 1182 152 +f 474 2337 446 +f 1743 1841 1757 +f 1486 1524 1924 +f 1535 1525 1539 +f 1575 1576 1592 +f 1420 967 1580 +f 1288 1634 1613 +f 459 427 1265 +f 1404 2179 1393 +f 1404 1403 1800 +f 1404 1410 1403 +f 1410 1749 1403 +f 1349 1351 218 +f 1486 1498 1524 +f 1535 1524 1525 +f 1607 1636 1624 +f 183 1642 1624 +f 1636 183 1624 +f 1107 1349 218 +f 1351 845 218 +f 164 1519 1142 +f 845 413 218 +f 1525 1576 1539 +f 1576 1582 1592 +f 1592 2134 1607 +f 2134 1636 1607 +f 2147 1491 1401 +f 1407 1589 1529 +f 1529 1519 164 +f 1693 1763 1444 +f 1924 1479 1486 +f 1592 1582 2134 +f 499 165 874 +f 2176 1857 1959 +f 2327 2368 2326 +f 2358 821 953 +f 953 821 1573 +f 1824 1704 1464 +f 1731 1358 1678 +f 1394 1410 1404 +f 1394 1418 1410 +f 1466 1479 1839 +f 1486 1479 1498 +f 1498 1525 1524 +f 1576 2080 1582 +f 1785 1684 1898 +f 804 398 802 +f 804 925 398 +f 1447 1562 2358 +f 2358 1562 821 +f 821 1620 1573 +f 1620 1420 1573 +f 1420 1556 967 +f 1393 1394 1404 +f 1525 2080 1576 +f 1621 1420 1620 +f 1621 1556 1420 +f 967 1589 1407 +f 1505 5 1357 +f 1266 1258 1436 +f 1393 1395 1394 +f 2176 2175 1848 +f 1455 1466 1839 +f 1525 1540 2080 +f 1582 2080 2118 +f 1100 804 802 +f 1556 1589 967 +f 1589 1082 1529 +f 1093 1685 1357 +f 1504 1093 1357 +f 1425 1418 1394 +f 1475 1479 1466 +f 1479 1506 1498 +f 1789 1784 1730 +f 2501 2465 2489 +f 1438 1458 1430 +f 1462 1458 1473 +f 1454 805 1529 +f 1082 1454 1529 +f 1529 805 1519 +f 1425 1394 1395 +f 1425 1744 1418 +f 1479 1475 1506 +f 1540 2060 2080 +f 1556 1082 1589 +f 1443 945 1511 +f 1506 1536 1498 +f 1498 1536 1525 +f 1525 1536 1540 +f 1670 852 1672 +f 1998 1388 1389 +f 1511 966 1509 +f 1509 966 714 +f 1442 1443 1496 +f 1562 1635 821 +f 155 1322 1473 +f 1439 1458 1438 +f 1426 1425 1395 +f 1475 1499 1506 +f 1735 1588 1776 +f 2422 2454 2421 +f 1423 1432 1415 +f 1559 2101 2073 +f 845 866 413 +f 1429 1620 821 +f 1620 1429 1621 +f 1228 1250 1687 +f 1002 945 1443 +f 2382 802 1083 +f 1859 1411 1395 +f 1411 1426 1395 +f 1426 1744 1425 +f 1590 1437 1483 +f 1480 1475 1466 +f 1480 1499 1475 +f 1510 1733 1743 +f 1663 1696 1658 +f 1430 1453 1452 +f 1452 1472 1471 +f 1452 1471 1448 +f 1430 1452 1421 +f 1430 1421 1422 +f 1429 1082 1556 +f 1621 1429 1556 +f 1351 2386 845 +f 1126 1059 487 +f 1639 1437 1563 +f 1504 1928 1093 +f 1499 1536 1506 +f 1588 1770 1727 +f 1110 1747 1397 +f 1776 1588 1531 +f 1322 1320 1482 +f 1590 1629 1571 +f 1730 1877 1838 +f 1429 935 1082 +f 1082 935 1454 +f 804 1443 925 +f 1139 1007 1639 +f 1925 1480 1466 +f 1934 1989 1480 +f 1499 1989 1536 +f 1727 1526 1531 +f 1593 1614 502 +f 2455 2431 2400 +f 1755 1680 908 +f 1563 1571 1564 +f 1647 1078 1501 +f 2490 1635 1106 +f 1496 1511 717 +f 2454 2431 516 +f 1478 1153 1093 +f 1870 1426 1411 +f 1426 1723 1744 +f 962 986 1412 +f 717 1511 1509 +f 1825 1704 1824 +f 2225 2234 2253 +f 1490 1557 1188 +f 1635 80 821 +f 805 1454 935 +f 1186 706 695 +f 1194 1161 714 +f 1512 1007 1013 +f 592 97 204 +f 1258 1266 1257 +f 82 1333 471 +f 1694 1710 1505 +f 1643 490 1661 +f 1661 490 1114 +f 1518 2068 2484 +f 1750 1808 1664 +f 1656 1635 2490 +f 935 1521 805 +f 1546 1629 1076 +f 1301 70 1277 +f 966 1441 1194 +f 1148 1825 1824 +f 1614 1609 1643 +f 1114 1092 1921 +f 1770 1739 1670 +f 1631 1632 1646 +f 821 1016 1429 +f 1429 1016 935 +f 1632 1095 1654 +f 1083 262 688 +f 1724 1686 1725 +f 1644 490 1643 +f 1092 1149 1921 +f 3 893 1832 +f 988 1640 1188 +f 916 1107 284 +f 1656 80 1635 +f 1016 821 80 +f 1016 1521 935 +f 1478 1202 1153 +f 1401 1928 29 +f 1440 1478 1928 +f 1849 1700 1865 +f 1595 1611 1612 +f 1208 198 341 +f 1464 1704 1746 +f 2143 984 1721 +f 1848 1849 1868 +f 1662 1114 490 +f 1669 1787 1682 +f 1656 1618 80 +f 198 1208 916 +f 1440 1928 1401 +f 1521 1369 805 +f 1252 1107 916 +f 1745 678 1672 +f 1703 1779 1721 +f 1750 1465 1808 +f 1609 1644 1643 +f 1092 1114 1662 +f 1826 1523 1793 +f 2262 2261 2224 +f 1696 2166 1767 +f 1016 1648 1521 +f 1208 1252 916 +f 833 688 1067 +f 1794 1803 1558 +f 28 17 512 +f 1750 861 1566 +f 1594 1644 1609 +f 1644 1645 490 +f 490 1645 1662 +f 2229 2262 2224 +f 1602 861 1760 +f 1530 1777 1760 +f 872 1706 1673 +f 1696 1668 2166 +f 1708 1809 1798 +f 1581 1716 1814 +f 1709 1794 1680 +f 1233 1421 1257 +f 1724 1476 1686 +f 1469 1481 1965 +f 1965 1481 1492 +f 2073 1549 1559 +f 1594 1615 1644 +f 1799 1706 1755 +f 1725 1686 1837 +f 1720 1797 1572 +f 1618 2467 2022 +f 1618 1579 80 +f 1648 1016 80 +f 2134 2152 1636 +f 1611 1632 1631 +f 1761 1434 1470 +f 1559 1577 1594 +f 1603 1615 1594 +f 1615 1645 1644 +f 1637 1662 1645 +f 1662 1199 1092 +f 1199 1149 1092 +f 1451 1108 1149 +f 665 734 756 +f 1865 1700 1714 +f 1709 1841 1794 +f 1618 2022 1579 +f 1648 1413 1369 +f 1521 1648 1369 +f 1520 11 1401 +f 1446 1470 1434 +f 1798 1691 1754 +f 2063 1544 2073 +f 2073 1544 1549 +f 1594 1577 1603 +f 1615 1637 1645 +f 1637 1199 1662 +f 1427 1149 1199 +f 2167 1108 1451 +f 1997 1673 1705 +f 1706 1799 1705 +f 1841 1709 1757 +f 1604 1579 2022 +f 1579 707 80 +f 80 707 1648 +f 1520 1401 1491 +f 1649 1520 1491 +f 1435 1434 1885 +f 1470 1469 1461 +f 1481 1508 2024 +f 2370 1544 2063 +f 1549 1568 1559 +f 1559 1568 1577 +f 1603 1610 1615 +f 1615 1610 1637 +f 999 1199 1637 +f 1451 1149 1427 +f 1137 1825 1148 +f 1706 1705 1673 +f 1138 1604 2116 +f 1138 1579 1604 +f 1413 1648 707 +f 2360 2024 1508 +f 598 1075 1116 +f 229 93 1468 +f 1839 1479 1684 +f 2216 2229 2224 +f 1610 1625 1637 +f 329 999 1637 +f 1199 1017 1427 +f 1017 303 1427 +f 303 1451 1427 +f 1792 1754 1777 +f 2309 2391 2301 +f 1655 1138 2116 +f 1138 707 1579 +f 1649 1491 206 +f 1406 1885 1398 +f 1406 1419 1885 +f 1419 1435 1885 +f 1434 1435 1446 +f 1470 1481 1469 +f 1577 1583 1603 +f 999 1017 1199 +f 81 67 941 +f 67 1650 941 +f 1259 1815 2164 +f 1619 2116 2045 +f 1424 707 1138 +f 1702 1649 206 +f 1687 1406 1398 +f 1477 1481 1470 +f 1568 1569 1577 +f 1577 1569 1583 +f 1603 1583 1610 +f 1625 329 1637 +f 2167 340 273 +f 81 273 340 +f 81 962 67 +f 1547 1619 1488 +f 1830 1739 1770 +f 938 1424 1138 +f 1424 1413 707 +f 1527 1649 1702 +f 1527 1520 1649 +f 1527 1268 1520 +f 1250 1406 1687 +f 1441 1353 1115 +f 1203 1413 1051 +f 1250 1419 1406 +f 1477 2372 1481 +f 1481 2372 1508 +f 2449 1560 1568 +f 1549 2449 1568 +f 1568 1560 1569 +f 1569 1584 1583 +f 1652 329 1625 +f 329 817 999 +f 285 1017 999 +f 303 10 1451 +f 10 2167 1451 +f 1412 1650 67 +f 1412 1488 1650 +f 1547 1023 1619 +f 1023 1655 1619 +f 1655 938 1138 +f 1456 1413 1424 +f 1457 1470 1446 +f 1457 1477 1470 +f 329 1652 817 +f 10 340 2167 +f 938 1546 1424 +f 1546 1456 1424 +f 1259 1548 1779 +f 2052 2031 1990 +f 1440 1202 1478 +f 1428 1419 1250 +f 1428 1435 1419 +f 1428 1446 1435 +f 1934 1935 1955 +f 1560 1584 1569 +f 1610 1638 1625 +f 1638 1652 1625 +f 817 1077 999 +f 1077 285 999 +f 980 303 1017 +f 962 1412 67 +f 1494 1023 1547 +f 325 271 1270 +f 1443 1511 1496 +f 1450 1268 1527 +f 1514 1353 1441 +f 1287 1446 1428 +f 1446 1287 1457 +f 1305 2372 1477 +f 1992 1990 1991 +f 1992 1991 1971 +f 1971 1991 1955 +f 2449 1549 2418 +f 1583 1616 1610 +f 1610 1616 1638 +f 10 1396 340 +f 340 1445 81 +f 1445 962 81 +f 1790 984 1753 +f 984 2148 1753 +f 1588 1713 1770 +f 969 978 958 +f 1741 1779 1703 +f 1758 1846 1754 +f 1827 1819 1029 +f 1818 1530 1712 +f 1750 1566 2127 +f 2459 2434 2483 +f 1798 1720 1771 +f 1794 1841 1803 +f 216 1755 1810 +f 1098 1735 1748 +f 1735 1497 1748 +f 1502 2102 1601 +f 881 1502 1601 +f 1455 1839 1744 +f 1706 1709 1680 +f 1212 1741 1703 +f 1788 1969 1671 +f 1075 1074 1692 +f 951 2500 881 +f 2490 2486 2463 +f 1748 1497 1781 +f 1721 984 1840 +f 1815 1259 1741 +f 1626 1756 1837 +f 975 987 1542 +f 2230 2236 2235 +f 1772 678 734 +f 1542 1671 975 +f 1806 1772 1780 +f 678 1772 1806 +f 2218 2225 2268 +f 1828 1732 2007 +f 1526 1688 1531 +f 1752 1526 1554 +f 1844 1818 1712 +f 1823 1846 1804 +f 1781 1669 1704 +f 1721 1779 2143 +f 1770 1670 1526 +f 1497 1669 1781 +f 1098 1713 1735 +f 1742 1815 1741 +f 1526 858 1875 +f 1599 1531 1688 +f 1803 1790 1558 +f 1703 1721 1683 +f 1832 1766 957 +f 1542 1679 1671 +f 1679 1788 1671 +f 1927 1819 1827 +f 1718 1745 1739 +f 1684 1022 1839 +f 1459 1283 1299 +f 1022 1410 1418 +f 2368 2393 2326 +f 1669 1497 1776 +f 1875 858 1212 +f 1739 1745 852 +f 1964 1918 1461 +f 1356 133 1331 +f 1765 1829 1468 +f 858 1742 1741 +f 1006 1674 1021 +f 1723 1936 1935 +f 1468 1713 1098 +f 1724 1678 1476 +f 1680 1783 908 +f 1731 1543 520 +f 1683 1721 1840 +f 1467 1679 1542 +f 1812 1708 1846 +f 1679 1975 1788 +f 1713 1830 1770 +f 1803 1722 1790 +f 2301 2391 2349 +f 1713 1588 1735 +f 1836 1530 1818 +f 1837 1756 861 +f 886 571 556 +f 1181 1805 1812 +f 1706 1680 1755 +f 1677 1729 1775 +f 1776 1787 1669 +f 1526 1670 1672 +f 1727 1770 1526 +f 987 1467 1542 +f 1567 1704 1137 +f 1693 1865 1714 +f 897 1762 912 +f 1135 1697 1062 +f 1697 376 1062 +f 1543 1731 1678 +f 1793 1679 1467 +f 1777 1602 1760 +f 1846 1798 1754 +f 1835 1096 1677 +f 1033 1030 940 +f 1450 1527 1702 +f 1717 376 1697 +f 1711 1717 1697 +f 1717 165 376 +f 1840 984 1790 +f 1669 1746 1704 +f 1669 1682 1746 +f 2301 2349 2308 +f 1882 1444 1898 +f 1820 1789 1730 +f 861 1380 1566 +f 2301 2308 2266 +f 1771 1543 1691 +f 1958 1659 1651 +f 1697 1360 1711 +f 1711 1737 1717 +f 1717 1737 165 +f 1790 1753 1558 +f 1668 1696 1663 +f 1360 1702 1711 +f 1702 1707 1711 +f 1707 1737 1711 +f 1737 1751 165 +f 1444 1782 1693 +f 1716 1787 1599 +f 1744 1839 1022 +f 1898 1444 1785 +f 206 1707 1702 +f 1764 2468 1751 +f 316 1844 893 +f 893 1844 915 +f 1845 1804 1758 +f 1380 861 1756 +f 1780 670 1021 +f 1714 2172 1763 +f 1783 1558 1663 +f 1750 2127 1465 +f 1798 1771 1691 +f 1691 1543 1724 +f 1872 1910 839 +f 1737 2044 1751 +f 1751 2044 1764 +f 1757 1701 482 +f 1725 1602 1777 +f 1836 1845 1530 +f 2102 2470 1503 +f 2496 1899 544 +f 763 2484 946 +f 987 1719 1467 +f 1845 1758 1792 +f 1725 1837 1602 +f 1872 1866 1873 +f 1712 1530 1760 +f 489 1799 216 +f 1760 861 1750 +f 2068 2466 2460 +f 1696 2159 2168 +f 377 1377 1280 +f 1797 1676 1572 +f 1581 2053 1572 +f 1676 1581 1572 +f 1764 2498 2468 +f 2468 2498 1994 +f 1861 1695 1860 +f 2481 2004 2495 +f 1826 1677 1523 +f 1670 1739 852 +f 2234 2269 2253 +f 1724 1543 1678 +f 1658 2168 1791 +f 1397 1747 1719 +f 1696 2168 1658 +f 979 519 272 +f 1774 1975 1679 +f 975 1671 932 +f 1787 1716 1682 +f 1835 1826 1747 +f 2501 2469 961 +f 1810 908 1791 +f 1982 1768 191 +f 1137 1704 1825 +f 1804 1846 1758 +f 2004 2044 1737 +f 913 1969 902 +f 2498 1795 1801 +f 915 1844 1712 +f 1689 915 1712 +f 1740 1752 1541 +f 695 661 199 +f 1865 1693 1782 +f 1824 1464 1809 +f 1829 1765 1718 +f 1816 1768 1982 +f 1816 1622 1768 +f 1622 2165 1681 +f 1768 1622 1681 +f 670 1772 228 +f 1283 1459 52 +f 1785 1444 1749 +f 1675 1075 1685 +f 1567 1781 1704 +f 1858 1857 1848 +f 1526 1752 1688 +f 1791 2160 1810 +f 908 1658 1791 +f 1813 1773 1558 +f 1845 1792 1530 +f 69 376 165 +f 3 1832 1834 +f 1722 1516 1507 +f 1801 1821 1994 +f 1833 1982 2046 +f 1821 1833 2046 +f 1833 1816 1982 +f 1022 1785 1749 +f 2160 2170 1810 +f 1147 1719 1726 +f 1683 1840 1507 +f 1467 1719 1793 +f 1795 1802 1801 +f 1802 1811 1801 +f 1801 1811 1821 +f 1690 2165 1622 +f 1934 1480 1925 +f 229 1468 1091 +f 1780 2164 1742 +f 1672 1742 858 +f 1833 1417 1816 +f 1417 1622 1816 +f 1831 2165 1690 +f 1668 1663 1558 +f 1719 1747 1826 +f 1760 1750 1664 +f 1817 1690 1622 +f 1530 1792 1777 +f 948 1796 1802 +f 1796 1811 1802 +f 1515 1817 1622 +f 1695 1861 1831 +f 1783 1663 1658 +f 1749 1410 1022 +f 854 1796 948 +f 1811 1842 1833 +f 1821 1811 1833 +f 1833 1842 1417 +f 1622 1417 1515 +f 127 1804 1845 +f 1686 1626 1837 +f 1608 1690 1817 +f 1523 1775 1762 +f 127 1845 1836 +f 1812 1805 1708 +f 1523 1677 1775 +f 1780 1772 670 +f 1758 1754 1792 +f 1204 1796 854 +f 1822 1842 1811 +f 1608 1831 1690 +f 1822 1811 1796 +f 1842 1416 1417 +f 1417 1416 1515 +f 1515 1608 1817 +f 1728 1831 1608 +f 908 1783 1658 +f 127 1836 316 +f 1805 1148 1824 +f 852 1745 1672 +f 1478 1093 1928 +f 1822 1843 1842 +f 1843 959 1842 +f 1842 959 1416 +f 1728 1695 1831 +f 1728 1860 1695 +f 2346 446 2337 +f 1602 1837 861 +f 1087 1096 1835 +f 1708 1824 1809 +f 2004 1737 505 +f 1567 1748 1781 +f 520 1543 1883 +f 1760 1664 1712 +f 128 1336 72 +f 2053 1883 1543 +f 1822 180 1843 +f 1786 1608 1515 +f 929 2462 519 +f 512 2402 506 +f 1212 1703 1683 +f 1830 1829 1739 +f 2053 1543 1771 +f 1416 1769 1515 +f 1769 1786 1515 +f 1786 1728 1608 +f 1712 1808 1689 +f 1794 1558 1783 +f 1497 1735 1776 +f 1127 1567 1137 +f 1123 1748 1567 +f 36 205 1185 +f 959 1734 1416 +f 1738 1733 1541 +f 1774 1762 1974 +f 1752 1554 1541 +f 1752 1740 1688 +f 1526 1875 1554 +f 1468 1829 1830 +f 1755 908 1810 +f 1716 1599 1814 +f 1806 1780 1742 +f 2308 2349 2340 +f 1832 915 1689 +f 1713 1468 1830 +f 1814 1599 1346 +f 1832 1689 1766 +f 1022 1684 1785 +f 1093 1153 1116 +f 1672 678 1742 +f 1675 1685 1093 +f 1841 1743 1722 +f 1814 2053 1581 +f 1464 1746 1809 +f 2485 2497 2493 +f 1416 1734 1769 +f 1665 1728 1786 +f 1665 1951 1728 +f 1951 1860 1728 +f 1951 2094 1860 +f 1844 1836 1818 +f 316 1836 1844 +f 1776 1531 1787 +f 1719 1826 1793 +f 2147 1401 29 +f 2111 2121 1548 +f 1741 1259 1779 +f 1843 347 1834 +f 1843 1734 959 +f 1766 1769 1734 +f 957 1766 1734 +f 1766 1786 1769 +f 1766 1689 1786 +f 1689 1665 1786 +f 1754 1691 1777 +f 1507 1840 1790 +f 1761 1470 1461 +f 1523 1679 1793 +f 1091 1468 1098 +f 1820 1730 1838 +f 1843 1834 1734 +f 1808 1951 1665 +f 1588 1727 1531 +f 893 915 1832 +f 1523 1774 1679 +f 272 2488 710 +f 1093 1116 1675 +f 2340 2349 2348 +f 1832 1734 1834 +f 1832 957 1734 +f 1951 1808 2094 +f 1685 1692 1505 +f 1043 295 698 +f 2143 1779 2121 +f 1689 1808 1665 +f 1693 1714 1763 +f 1738 2157 1516 +f 1114 1921 236 +f 1268 1333 1520 +f 1149 1108 431 +f 508 2144 1912 +f 1957 1108 1537 +f 431 1108 1957 +f 1018 1108 2167 +f 1338 1957 1681 +f 2163 1957 1338 +f 1983 1390 2093 +f 30 557 37 +f 1714 2173 2172 +f 1983 1984 1390 +f 1984 2065 1390 +f 884 1762 897 +f 2065 1984 1214 +f 1950 1974 1762 +f 884 1950 1762 +f 2012 1698 1861 +f 1214 2116 803 +f 1950 1938 1974 +f 1938 1967 1974 +f 1900 1761 1461 +f 865 1929 884 +f 884 1929 1950 +f 2062 2071 2042 +f 919 1985 1732 +f 1593 502 2146 +f 1995 1213 2098 +f 1522 2476 1651 +f 2174 1849 2175 +f 1480 1989 1499 +f 1929 1938 1950 +f 1605 2058 1574 +f 2097 1605 2133 +f 1912 2014 1886 +f 2092 2082 2083 +f 206 1930 505 +f 2101 2100 2092 +f 2073 2101 2092 +f 839 1910 865 +f 1910 1901 1929 +f 865 1910 1929 +f 1967 1788 1975 +f 2073 2092 2063 +f 2101 1593 2100 +f 2015 1876 1698 +f 1853 1884 2014 +f 1831 1698 2165 +f 1316 273 81 +f 1901 1920 1929 +f 1929 1920 1938 +f 1920 1968 1967 +f 1938 1920 1967 +f 1849 2174 1700 +f 2173 1700 2174 +f 2062 2072 2091 +f 803 2467 2059 +f 2239 1736 2240 +f 1505 1357 1685 +f 1358 1686 1476 +f 1967 1968 1788 +f 1968 1969 1788 +f 2065 2110 2156 +f 2065 1214 2110 +f 2110 1214 503 +f 273 2093 1018 +f 273 1983 2093 +f 532 1886 2155 +f 2034 2021 1947 +f 216 1810 585 +f 1912 543 2014 +f 1390 2051 1537 +f 1872 1873 1910 +f 1984 2045 1214 +f 597 1912 1886 +f 1593 2146 2100 +f 2071 2062 2090 +f 2034 2046 1982 +f 2034 1947 2046 +f 1214 2045 2116 +f 1873 1887 1910 +f 1887 1901 1910 +f 1562 1447 1106 +f 2163 431 1957 +f 1948 1972 1936 +f 1972 1948 1992 +f 2014 2015 2013 +f 1853 2014 2013 +f 1550 1884 1853 +f 1947 2468 1994 +f 1355 1550 2154 +f 1355 1884 1550 +f 2081 2108 2128 +f 2024 1965 1492 +f 2024 2032 1965 +f 2116 1604 803 +f 1901 1911 1920 +f 1939 1968 1920 +f 1911 1939 1920 +f 872 1626 1666 +f 2062 2091 2120 +f 1819 1927 1759 +f 1021 1674 1780 +f 872 1673 1756 +f 1550 501 2171 +f 1378 1550 2171 +f 2146 2162 2145 +f 1358 482 192 +f 2109 2120 2119 +f 1866 1872 2227 +f 1391 2012 1860 +f 2136 2137 2161 +f 2162 1661 236 +f 1887 1894 1901 +f 1901 1894 1911 +f 505 1707 206 +f 2120 2137 2136 +f 2142 2164 1674 +f 1860 2012 1861 +f 1894 1939 1911 +f 2080 2060 2118 +f 2162 236 508 +f 2164 1815 1742 +f 1018 2093 1537 +f 2154 1378 2161 +f 2041 2098 2491 +f 2043 2042 2032 +f 1108 1018 1537 +f 1465 2094 1808 +f 502 1643 1661 +f 2467 1618 1656 +f 2119 2136 2135 +f 2119 2108 2071 +f 878 1183 1195 +f 2101 1594 1593 +f 2033 2370 2063 +f 2482 2491 2098 +f 1282 2406 1275 +f 2003 1948 1956 +f 2043 2032 2024 +f 2025 2043 2024 +f 2154 1550 1378 +f 1795 2498 1764 +f 2142 1548 2164 +f 2431 2454 2422 +f 1981 2011 1993 +f 2349 2391 2362 +f 502 2162 2146 +f 2025 2024 2360 +f 2129 2120 2091 +f 1732 1985 2007 +f 2171 1308 209 +f 1930 1995 2041 +f 1390 1238 2051 +f 1866 1878 1887 +f 1878 1894 1887 +f 1965 2032 2011 +f 874 2480 2492 +f 2071 2108 2069 +f 1358 1731 482 +f 430 2021 2034 +f 1965 2003 1964 +f 1855 1889 831 +f 1668 1773 2150 +f 1390 2156 1238 +f 898 869 1903 +f 2391 2407 2362 +f 2121 2111 2074 +f 1548 1259 2164 +f 2099 2129 2091 +f 1550 1853 501 +f 1853 1852 501 +f 952 2017 969 +f 2085 2121 2074 +f 2130 2006 1391 +f 2144 1367 543 +f 2100 2146 2099 +f 1545 1319 113 +f 1903 1922 898 +f 1922 1931 898 +f 585 2170 1641 +f 2007 2017 952 +f 2017 2074 969 +f 1558 1753 1813 +f 837 2005 1517 +f 2005 2006 2130 +f 1532 1474 1528 +f 2003 1981 1948 +f 2070 2071 2069 +f 1922 919 1931 +f 2017 2085 2074 +f 2085 2104 2121 +f 2100 2099 2082 +f 2156 2110 2034 +f 505 2474 2004 +f 1903 871 1922 +f 1922 1952 919 +f 919 1952 1985 +f 1985 2001 2007 +f 2001 2036 2017 +f 2007 2001 2017 +f 2017 2036 2085 +f 2036 2047 2085 +f 2047 2075 2085 +f 2075 2104 2085 +f 1948 1993 2023 +f 2400 2422 2407 +f 2011 2070 1993 +f 2033 2043 2025 +f 2012 2015 1698 +f 1876 1338 2165 +f 871 1940 1922 +f 1985 1976 2001 +f 2121 2104 2143 +f 1051 1413 1456 +f 2358 1362 2379 +f 1859 1789 1870 +f 2090 2109 2071 +f 1405 1398 1885 +f 1886 1884 1355 +f 1922 1960 1952 +f 1952 1960 1985 +f 1960 1976 1985 +f 1956 1948 1936 +f 2135 209 2128 +f 2157 1875 1212 +f 2160 2168 2169 +f 1900 1461 1918 +f 2001 2018 2036 +f 2075 2086 2104 +f 2111 2142 2103 +f 1937 1956 1936 +f 2023 2070 2061 +f 2135 2128 2108 +f 2042 2071 2011 +f 2138 413 2383 +f 2033 2072 2043 +f 1922 1940 1960 +f 2070 2069 2061 +f 2069 2108 2061 +f 2108 2119 2135 +f 1855 1904 1889 +f 1889 1904 871 +f 871 1904 1940 +f 1976 2018 2001 +f 2036 2018 2047 +f 2122 2143 2104 +f 216 1642 489 +f 2148 984 2143 +f 1975 1974 1967 +f 2157 1683 1516 +f 1614 1593 1594 +f 2269 2270 2276 +f 1926 2147 29 +f 2082 2091 2072 +f 430 503 2059 +f 1904 1905 1940 +f 1940 1961 1960 +f 1961 1976 1960 +f 2087 2086 2075 +f 2065 2156 1390 +f 1820 1838 1900 +f 534 1308 837 +f 2167 273 1018 +f 831 1850 1855 +f 2019 2037 2018 +f 2018 2037 2047 +f 2037 2075 2047 +f 2086 2095 2104 +f 2095 2122 2104 +f 2122 2148 2143 +f 1926 1213 1995 +f 1405 1885 1761 +f 2006 2013 2012 +f 2211 2233 2216 +f 1855 1890 1904 +f 1904 1895 1905 +f 1905 1932 1940 +f 1961 1977 1976 +f 1976 1986 2018 +f 2484 2476 1518 +f 1870 1411 1859 +f 1548 2142 2111 +f 1904 1890 1895 +f 1895 1932 1905 +f 1940 1932 1961 +f 1976 1977 1986 +f 1986 2008 2018 +f 2018 2008 2019 +f 2087 2075 2037 +f 2087 2095 2086 +f 2094 1391 1860 +f 1852 1853 2006 +f 1853 2013 2006 +f 929 979 850 +f 1855 1874 1890 +f 2008 2028 2019 +f 1993 2070 2023 +f 1705 1799 1998 +f 1491 2147 206 +f 1851 1856 1855 +f 1895 1890 1874 +f 2038 2019 2028 +f 2038 2048 2037 +f 2019 2038 2037 +f 2048 2067 2087 +f 2037 2048 2087 +f 2087 2067 2095 +f 2095 2149 2122 +f 2149 2148 2122 +f 1308 2005 837 +f 209 1308 1387 +f 1601 2102 1927 +f 254 170 201 +f 1800 1403 1763 +f 1510 1346 1740 +f 870 871 1903 +f 1919 1650 1619 +f 2148 1667 1753 +f 1932 1923 1961 +f 1977 1953 1986 +f 2067 2112 2095 +f 2112 2149 2095 +f 2148 2149 1667 +f 2422 2421 2407 +f 1926 2026 1213 +f 1912 2144 543 +f 2128 1387 2153 +f 1733 1510 1740 +f 990 853 2489 +f 503 1214 803 +f 1921 431 2163 +f 2146 2145 2129 +f 2144 1921 2163 +f 1855 1856 1874 +f 1895 1923 1932 +f 1923 1941 1961 +f 1961 1941 1977 +f 2048 2076 2067 +f 2076 2113 2067 +f 2067 2113 2112 +f 1723 1900 1937 +f 1870 1900 1723 +f 1367 2163 1338 +f 520 1346 1510 +f 1698 1831 1861 +f 1984 1919 2045 +f 1895 1891 1923 +f 2008 1986 2028 +f 1948 1981 1993 +f 1883 1346 520 +f 1883 1814 1346 +f 1930 206 2147 +f 2499 2486 1447 +f 1891 1906 1923 +f 1923 1953 1941 +f 1953 1977 1941 +f 1953 1987 1986 +f 2113 2123 2112 +f 2123 2149 2112 +f 1387 1308 1226 +f 1599 1688 1346 +f 2093 1390 1537 +f 2003 2011 1981 +f 1987 2028 1986 +f 2038 2049 2048 +f 2048 2049 2076 +f 1813 1667 2149 +f 2123 1813 2149 +f 1461 1469 1964 +f 1757 1510 1743 +f 505 1930 1999 +f 2223 1784 1789 +f 1532 1522 1651 +f 1906 1913 1923 +f 1913 1943 1923 +f 1943 1942 1923 +f 1923 1942 1953 +f 1942 1987 1953 +f 1308 1852 2005 +f 2053 1814 1883 +f 1733 1740 1541 +f 2154 1886 1355 +f 1503 1528 1474 +f 1874 1879 1895 +f 1895 1879 1891 +f 2076 2124 2113 +f 2113 2124 2123 +f 1896 1891 1879 +f 1891 1896 1906 +f 1942 1962 1987 +f 1962 2009 2028 +f 1987 1962 2028 +f 2009 2038 2028 +f 2109 2119 2071 +f 1918 1956 1937 +f 1851 1864 1856 +f 1896 1897 1906 +f 1906 1897 1913 +f 1943 1962 1942 +f 2049 2077 2076 +f 2124 2125 2123 +f 1930 2147 1926 +f 1902 1894 1878 +f 482 1510 1757 +f 2129 2137 2120 +f 503 803 2059 +f 1847 1857 1851 +f 1851 1857 1864 +f 2039 2038 2009 +f 2038 2039 2049 +f 2076 2077 2124 +f 2150 1813 2123 +f 482 520 1510 +f 1994 1821 2046 +f 2044 2004 1764 +f 1864 1867 1856 +f 1867 1874 1856 +f 1897 1944 1913 +f 1943 1944 1962 +f 2124 2126 2125 +f 2150 2123 2125 +f 2099 2146 2129 +f 2041 1995 2098 +f 1605 1641 2151 +f 1847 1959 1857 +f 1874 1867 1879 +f 1913 1944 1943 +f 1944 1963 1962 +f 2077 2096 2124 +f 2096 2126 2124 +f 2126 2150 2125 +f 941 1650 1919 +f 2135 2136 209 +f 1884 1886 2014 +f 2049 2029 2077 +f 1388 2127 1389 +f 1389 2127 1566 +f 1930 1926 1995 +f 941 1919 1316 +f 2110 503 430 +f 1867 1880 1879 +f 1879 1880 1896 +f 1897 1907 1944 +f 1963 1978 1962 +f 1962 1978 2009 +f 2039 2029 2049 +f 2077 2078 2096 +f 822 823 827 +f 2166 1668 2150 +f 81 941 1316 +f 2204 2216 2203 +f 2011 2071 2070 +f 1880 1892 1896 +f 1892 1907 1897 +f 1896 1892 1897 +f 1907 1914 1944 +f 1978 2010 2009 +f 2010 2039 2009 +f 1688 1740 1346 +f 1789 1820 1870 +f 2130 1391 2094 +f 1944 1945 1963 +f 2029 2078 2077 +f 1767 2150 2126 +f 1767 2166 2150 +f 803 2022 2467 +f 1503 1927 2102 +f 1914 1954 1944 +f 1944 1954 1945 +f 1963 1970 1978 +f 2078 2105 2096 +f 2105 2126 2096 +f 1965 2011 2003 +f 192 1626 1358 +f 2101 1559 1594 +f 1930 2041 1999 +f 1698 1876 2165 +f 1398 1871 891 +f 2165 1338 1681 +f 1970 2010 1978 +f 2010 2030 2029 +f 2039 2010 2029 +f 2030 2055 2078 +f 2029 2030 2078 +f 1849 1848 2175 +f 1871 1862 891 +f 543 2015 2014 +f 1857 1858 1864 +f 1864 1858 1867 +f 1963 1945 1970 +f 2055 2088 2078 +f 2078 2088 2105 +f 2105 2131 2126 +f 2126 2131 1767 +f 2063 2083 2033 +f 2161 2171 209 +f 2032 2042 2011 +f 1813 2150 1773 +f 1914 1908 1954 +f 1970 1979 2010 +f 2088 2131 2105 +f 2015 543 1876 +f 1694 1692 1048 +f 1395 2207 1859 +f 1395 1393 2207 +f 1730 1784 1736 +f 2500 2466 2470 +f 1709 1701 1757 +f 1945 1979 1970 +f 2030 2050 2055 +f 2350 2317 2286 +f 2154 2155 1886 +f 871 860 1889 +f 2161 209 2136 +f 2497 2463 2493 +f 2190 2204 2203 +f 1800 2179 1404 +f 2477 2469 1385 +f 1385 1715 2477 +f 2128 209 1387 +f 1858 1868 1867 +f 1867 1881 1880 +f 1893 1892 1880 +f 1881 1893 1880 +f 1893 1907 1892 +f 1907 1908 1914 +f 1954 1979 1945 +f 1979 1980 2010 +f 2131 2159 1767 +f 1765 93 339 +f 1761 1877 1405 +f 523 1347 515 +f 1541 2157 1738 +f 2144 2163 1367 +f 1380 1389 1566 +f 2317 2392 2316 +f 1994 2498 1801 +f 1867 1868 1881 +f 1980 2050 2030 +f 2010 1980 2030 +f 2050 2089 2055 +f 2055 2089 2088 +f 2088 2114 2131 +f 1538 1651 1659 +f 2145 2155 2129 +f 2140 29 1928 +f 2370 2033 2025 +f 2252 2239 2240 +f 2239 2252 1862 +f 2392 2391 2316 +f 2469 2501 1385 +f 2477 1715 1710 +f 502 1614 1643 +f 2438 1227 2431 +f 1915 1907 1893 +f 1915 1908 1907 +f 1954 1908 1979 +f 1908 1988 1979 +f 1979 1988 1980 +f 2114 2159 2131 +f 2155 2154 2129 +f 508 1966 2144 +f 872 1756 1626 +f 1710 1715 1505 +f 236 1966 508 +f 2272 2284 1398 +f 2325 2355 2319 +f 1548 2121 1779 +f 1532 1528 1522 +f 1980 2056 2050 +f 2050 2056 2089 +f 2013 2015 2012 +f 1964 2003 1956 +f 2006 2012 1391 +f 1565 1927 1503 +f 2244 2243 2226 +f 5 1715 1385 +f 1858 1848 1868 +f 1915 1946 1908 +f 1946 1988 1908 +f 1980 2020 2056 +f 2115 2159 2114 +f 2092 2083 2063 +f 1398 2284 1687 +f 2162 2155 2145 +f 519 2475 2488 +f 2158 5 1385 +f 5 1505 1715 +f 1692 1694 1505 +f 1988 2020 1980 +f 2115 2169 2159 +f 2169 2168 2159 +f 2083 2082 2072 +f 1316 1984 1983 +f 1488 1619 1650 +f 2083 2072 2033 +f 2361 1210 1233 +f 1933 1946 1915 +f 2056 2079 2089 +f 2088 2115 2114 +f 2099 2091 2082 +f 2162 532 2155 +f 1852 2006 2005 +f 2023 2061 2052 +f 2176 2184 2175 +f 2162 985 532 +f 1909 1893 1881 +f 1909 1915 1893 +f 1988 2040 2020 +f 2040 2056 2020 +f 2089 2079 2088 +f 2088 2079 2115 +f 1782 1444 1882 +f 1216 1215 2320 +f 867 1939 1894 +f 867 903 1939 +f 1372 2398 1379 +f 1863 504 2027 +f 2158 1385 504 +f 1868 1782 1881 +f 1909 1933 1915 +f 2040 1988 1946 +f 1481 2024 1492 +f 2120 2136 2119 +f 1522 1528 1518 +f 1871 1398 1405 +f 1221 1408 1399 +f 1357 5 2158 +f 2179 1800 1763 +f 1868 1865 1782 +f 1882 1881 1782 +f 1882 1909 1881 +f 2040 2057 2056 +f 2106 2079 2056 +f 2057 2106 2056 +f 2106 2132 2079 +f 2132 2115 2079 +f 2115 2132 2169 +f 532 985 597 +f 2092 2100 2082 +f 1210 1221 1399 +f 1399 1233 1210 +f 2130 2002 1517 +f 1849 1865 1868 +f 1933 2040 1946 +f 52 1269 30 +f 1667 1813 1753 +f 1997 1380 1673 +f 940 1008 1088 +f 1947 1994 2046 +f 1882 1916 1909 +f 1924 1933 1909 +f 1533 2040 1933 +f 1533 1534 2040 +f 2058 2040 1534 +f 2058 2057 2040 +f 1238 191 1768 +f 1997 1389 1380 +f 1875 1541 1554 +f 1854 504 1863 +f 1854 2158 504 +f 2396 1275 2406 +f 2426 2443 153 +f 1916 1924 1909 +f 1925 1935 1934 +f 1870 1723 1426 +f 2058 2097 2057 +f 2097 2106 2057 +f 2132 2151 2169 +f 2151 2160 2169 +f 1106 1635 1562 +f 1957 1768 1681 +f 1957 2051 1768 +f 526 535 33 +f 1614 1594 1609 +f 2233 2229 2216 +f 2496 2027 2084 +f 2496 1863 2027 +f 2117 1854 1863 +f 2016 2158 1854 +f 2016 1504 1357 +f 2158 2016 1357 +f 1114 236 1661 +f 2129 2154 2137 +f 2133 2106 2097 +f 2491 1999 2041 +f 2051 1238 1768 +f 2061 2108 2081 +f 2189 2195 2186 +f 2348 2349 2362 +f 1701 192 482 +f 505 1737 1707 +f 2133 2132 2106 +f 2132 2133 2151 +f 2151 2170 2160 +f 502 1661 2162 +f 1998 1389 1997 +f 2297 2352 2329 +f 2352 2364 2329 +f 2394 2414 2364 +f 2352 2394 2364 +f 2402 512 2415 +f 2255 2254 2243 +f 2446 1365 2456 +f 2271 2282 2298 +f 846 2283 2264 +f 2293 2310 2318 +f 2254 2295 2294 +f 2283 2290 2278 +f 2270 2294 2293 +f 2423 2455 2400 +f 2281 2287 2267 +f 2190 2191 2204 +f 2271 2263 2282 +f 2334 2329 2364 +f 2424 2432 2409 +f 2282 2263 2298 +f 1409 1659 1958 +f 2263 2302 2298 +f 2297 2329 2296 +f 1256 446 2346 +f 1958 2502 2478 +f 2437 2399 2444 +f 263 2366 2359 +f 849 827 823 +f 2311 2325 2290 +f 2499 2379 2434 +f 2446 2456 2423 +f 947 2358 2379 +f 2499 947 2379 +f 2205 2195 2212 +f 2245 2237 2227 +f 2245 2256 2237 +f 2256 2263 2271 +f 556 571 2305 +f 1528 2068 1518 +f 2424 2439 2432 +f 2302 2352 2297 +f 1866 2237 826 +f 2248 2242 2211 +f 2334 2364 2363 +f 2235 2244 2226 +f 2255 2295 2254 +f 2329 2324 2296 +f 2439 2447 1973 +f 2329 2334 2324 +f 2409 2432 2414 +f 2293 2318 2276 +f 866 2425 2416 +f 1487 1493 2372 +f 2237 2231 2230 +f 2415 512 17 +f 2035 1236 26 +f 921 2138 688 +f 2491 2482 2462 +f 6 181 197 +f 2481 948 1795 +f 2138 2383 2382 +f 2377 2394 2352 +f 2377 506 2394 +f 2394 506 2402 +f 2401 2402 2415 +f 2394 2402 2401 +f 2318 2326 2276 +f 2439 2457 2432 +f 2298 2302 2297 +f 2244 2249 2243 +f 2404 1100 2382 +f 2238 2245 2227 +f 2245 2257 2256 +f 2257 2263 2256 +f 2324 2334 2328 +f 2257 2289 2263 +f 2289 2302 2263 +f 2236 2231 2250 +f 2138 2382 688 +f 2383 2404 2382 +f 1100 2404 2343 +f 2353 2352 2302 +f 2353 2377 2352 +f 2237 2230 2220 +f 2335 2355 2325 +f 2308 2340 2315 +f 2253 2269 2276 +f 2311 2335 2325 +f 2439 2424 511 +f 2268 2267 2248 +f 2383 413 2404 +f 123 971 832 +f 2234 2243 2269 +f 2225 2213 2234 +f 2219 2213 2225 +f 2195 2196 2212 +f 1544 2418 1549 +f 413 866 2404 +f 2404 866 2416 +f 2416 2417 2404 +f 2404 2417 2343 +f 2415 2409 2401 +f 2196 2219 2212 +f 2268 2248 2218 +f 2206 2214 2197 +f 2417 2332 2343 +f 2343 2332 832 +f 2330 2302 2289 +f 2330 2353 2302 +f 2453 2454 515 +f 2218 2248 2217 +f 2218 2217 2205 +f 2276 2281 2268 +f 2178 2197 2177 +f 2197 2189 2177 +f 2332 2066 832 +f 832 2066 123 +f 2231 2236 2230 +f 669 950 1144 +f 2217 2211 2199 +f 1216 1209 1217 +f 2066 2365 123 +f 2230 2226 2214 +f 2290 2325 2304 +f 2325 2319 2304 +f 2217 2248 2211 +f 2191 2192 2199 +f 510 525 2035 +f 2417 1917 2332 +f 2332 1917 2066 +f 2408 2413 2341 +f 2248 2267 2242 +f 2326 2333 2281 +f 1340 2365 2066 +f 2440 1302 1340 +f 2226 2230 2235 +f 1153 1163 1116 +f 2431 2455 2438 +f 2416 2425 2417 +f 2495 2474 2462 +f 2290 2304 2277 +f 825 2227 1872 +f 151 239 1038 +f 9 151 1038 +f 545 928 2381 +f 2440 2406 1384 +f 928 1596 2381 +f 2186 2188 2185 +f 2456 26 1888 +f 2287 2333 2262 +f 2425 2342 2417 +f 2342 1917 2417 +f 1917 877 2066 +f 2336 1340 2066 +f 2336 2440 1340 +f 2328 2351 2327 +f 825 2238 2227 +f 2351 2368 2327 +f 1222 2388 1211 +f 678 756 734 +f 428 263 1343 +f 2188 2191 2190 +f 2341 2376 2333 +f 2066 877 2336 +f 2290 2277 2278 +f 739 634 592 +f 675 304 14 +f 2384 675 14 +f 2199 2211 2204 +f 2191 2199 2204 +f 2322 2318 2310 +f 2287 2262 2233 +f 2185 2188 2184 +f 2386 2425 845 +f 2384 572 675 +f 1128 123 2365 +f 832 971 2343 +f 2188 2186 2191 +f 2185 2184 2176 +f 2345 1917 2342 +f 2345 877 1917 +f 2336 2406 2440 +f 971 1100 2343 +f 2299 2289 2257 +f 2299 2303 2289 +f 2249 2255 2243 +f 506 513 512 +f 2437 955 1219 +f 1587 2398 1324 +f 877 2396 2336 +f 2336 2396 2406 +f 2463 2479 879 +f 2376 2412 2350 +f 2281 2267 2268 +f 2303 2330 2289 +f 624 635 159 +f 1996 2356 1561 +f 2449 2436 1996 +f 2356 2054 2451 +f 928 2398 1587 +f 2333 2350 2262 +f 2035 26 2456 +f 2346 2342 2425 +f 2346 2345 2342 +f 1544 2380 2418 +f 2412 2392 2350 +f 622 509 1151 +f 2436 2054 1996 +f 545 2451 928 +f 2326 2341 2333 +f 2346 2425 2386 +f 1365 2035 2456 +f 2369 2377 2353 +f 2369 506 2377 +f 2451 900 928 +f 900 2398 928 +f 1235 1888 1244 +f 2337 2345 2346 +f 877 772 2396 +f 772 1275 2396 +f 2432 2446 2414 +f 2294 2295 2310 +f 2369 2330 828 +f 2418 2419 2436 +f 2450 2429 2436 +f 2436 2429 2054 +f 2490 2494 1656 +f 1321 155 2338 +f 1256 2346 2386 +f 2448 877 2345 +f 877 2448 772 +f 2446 2423 2414 +f 2351 2334 2363 +f 2243 2254 2269 +f 2380 2419 2418 +f 2419 2450 2436 +f 2283 2278 2264 +f 822 2197 823 +f 1008 1759 1565 +f 2448 2345 2337 +f 2270 2293 2276 +f 2323 2324 2328 +f 2429 1012 2054 +f 2226 2243 2213 +f 2395 325 772 +f 2370 2367 2380 +f 2054 2435 2451 +f 2435 2397 2451 +f 2451 2397 900 +f 1774 1974 1975 +f 2305 2290 2283 +f 846 2305 2283 +f 2320 1215 2285 +f 2139 2448 2337 +f 2448 2395 772 +f 1232 1231 1216 +f 2272 2285 2284 +f 2367 2371 2380 +f 2371 2405 2380 +f 2380 2405 2419 +f 2419 2429 2450 +f 2429 176 1012 +f 2397 2373 900 +f 2373 2398 900 +f 2373 1379 2398 +f 2372 1500 1508 +f 1133 1303 1142 +f 2252 2273 2272 +f 891 2252 2272 +f 2419 2405 2429 +f 2405 2430 2429 +f 2429 2430 176 +f 2189 2186 2181 +f 2212 2219 2218 +f 2312 2139 2337 +f 2139 2384 2448 +f 2448 2384 2395 +f 899 855 843 +f 2272 2273 2285 +f 2331 2303 2299 +f 176 2435 2054 +f 1012 176 2054 +f 2177 2185 2176 +f 2218 2219 2225 +f 1216 1220 1215 +f 2378 2139 2312 +f 2384 14 2395 +f 2324 2295 2255 +f 2240 2273 2252 +f 2371 2387 2405 +f 2410 2430 2405 +f 2430 2442 176 +f 2435 2344 2397 +f 2397 2344 2373 +f 2456 1888 2455 +f 2242 2267 2233 +f 2233 2262 2229 +f 2378 2384 2139 +f 2323 2310 2295 +f 2323 2322 2310 +f 2240 2274 2273 +f 974 841 990 +f 2490 1447 2486 +f 2387 2410 2405 +f 2442 2141 176 +f 2344 1778 2373 +f 972 1379 2373 +f 1778 972 2373 +f 1379 972 428 +f 1211 2437 1223 +f 1228 1215 1220 +f 702 2378 2312 +f 17 518 2415 +f 1888 26 1244 +f 2324 2323 2295 +f 2305 2311 2290 +f 2307 2285 2273 +f 2274 2307 2273 +f 2307 2320 2285 +f 2369 531 506 +f 2435 2258 2344 +f 2296 2324 2288 +f 1233 1217 2361 +f 2360 2371 2367 +f 2410 2442 2430 +f 176 2141 2258 +f 176 2258 2435 +f 539 2331 66 +f 2350 2392 2317 +f 2268 2225 2253 +f 1508 1500 2371 +f 2360 1508 2371 +f 2371 1500 2387 +f 972 2366 428 +f 1626 1686 1358 +f 1759 1807 1819 +f 2277 2257 2245 +f 2277 2299 2257 +f 1784 2228 1736 +f 2265 2240 1736 +f 2228 2265 1736 +f 2265 2274 2240 +f 1209 2320 2307 +f 2320 1209 1216 +f 1555 1584 1560 +f 2387 1500 2372 +f 2410 2420 2442 +f 2433 972 1778 +f 2433 2366 972 +f 955 522 1225 +f 2339 2307 2274 +f 2372 1493 2387 +f 2411 2420 2410 +f 2420 954 2442 +f 2442 954 2141 +f 2344 2433 1778 +f 2205 2212 2218 +f 2328 2334 2351 +f 2394 2401 2414 +f 2250 2256 2271 +f 2339 1209 2307 +f 2328 2322 2323 +f 866 845 2425 +f 3 316 893 +f 2387 2411 2410 +f 2441 2141 954 +f 2141 2441 2258 +f 2354 2433 2344 +f 2254 2294 2270 +f 2269 2254 2270 +f 863 2305 846 +f 2441 2354 2258 +f 2258 2354 2344 +f 2319 2355 51 +f 2223 2228 1784 +f 1493 2411 2387 +f 1560 2449 1555 +f 2288 2324 2255 +f 825 2251 2238 +f 2251 2245 2238 +f 1299 84 1312 +f 2246 2265 2228 +f 2313 2274 2265 +f 2313 2339 2274 +f 2251 2277 2245 +f 2319 51 2331 +f 891 1862 2252 +f 2443 954 2420 +f 2443 2441 954 +f 511 2447 2439 +f 2242 2233 2211 +f 188 15 814 +f 2443 2426 2441 +f 2426 2354 2441 +f 2306 2403 2433 +f 2433 2403 2366 +f 539 2303 2331 +f 2246 2228 2223 +f 1030 1819 1807 +f 2354 2306 2433 +f 2413 2412 2376 +f 2438 2455 1888 +f 1848 1857 2176 +f 2207 2208 2223 +f 2208 2246 2223 +f 1209 2339 1217 +f 2339 2361 1217 +f 1221 1210 2388 +f 554 109 78 +f 386 1375 95 +f 2327 2326 2318 +f 2179 2182 1393 +f 2182 2208 1393 +f 1393 2208 2207 +f 2361 2399 2388 +f 2388 2399 1211 +f 2306 2354 2426 +f 2403 2359 2366 +f 2214 2226 2213 +f 2268 2253 2276 +f 889 2200 2179 +f 2200 2182 2179 +f 2200 2221 2182 +f 2221 2208 2182 +f 2314 2265 2246 +f 2314 2313 2265 +f 2339 2374 2361 +f 2478 2434 2379 +f 2205 2217 2199 +f 2208 2259 2246 +f 2259 2275 2246 +f 2314 2321 2313 +f 2313 2347 2339 +f 2347 2374 2339 +f 2374 2399 2361 +f 153 154 2426 +f 154 2306 2426 +f 2385 2359 2403 +f 2221 2259 2208 +f 2306 2357 2403 +f 2357 2385 2403 +f 2237 2256 2231 +f 2172 2180 889 +f 2180 2200 889 +f 2200 2201 2221 +f 2246 2291 2314 +f 2374 2444 2399 +f 571 555 2311 +f 2192 2205 2199 +f 2173 2180 2172 +f 2279 2246 2275 +f 2279 2291 2246 +f 2292 2314 2291 +f 2321 2362 2313 +f 2362 2347 2313 +f 2347 2389 2374 +f 2444 955 2437 +f 2292 2291 2279 +f 2452 2444 2374 +f 2054 2356 1996 +f 2338 2306 154 +f 2186 2192 2191 +f 2193 2201 2200 +f 2259 2221 2201 +f 2247 2259 2201 +f 2452 955 2444 +f 2278 2277 2251 +f 2338 2357 2306 +f 2181 2186 2185 +f 2276 2326 2281 +f 2432 2457 2446 +f 2198 2201 2193 +f 2198 2232 2201 +f 2232 2247 2201 +f 2389 2452 2374 +f 2452 1630 955 +f 1403 1749 1444 +f 1555 1996 1561 +f 2357 2427 2385 +f 2385 2428 230 +f 2409 2415 2424 +f 2304 2331 2299 +f 2193 2200 2180 +f 2445 2452 2389 +f 1565 1759 1927 +f 2380 1544 2370 +f 2338 2427 2357 +f 2427 2428 2385 +f 230 222 253 +f 2202 2198 2193 +f 2202 2209 2198 +f 2209 2241 2198 +f 2241 2232 2198 +f 2266 2275 2259 +f 2365 1340 1128 +f 2415 518 2424 +f 2338 170 2427 +f 170 2428 2427 +f 2181 2185 2177 +f 2196 2195 2189 +f 2183 2193 2180 +f 2453 1630 2452 +f 2197 2214 2189 +f 2401 2409 2414 +f 822 2220 2197 +f 1210 2361 2388 +f 2187 2193 2183 +f 2187 2202 2193 +f 2266 2279 2275 +f 2279 2300 2292 +f 2375 2347 2362 +f 2375 2390 2347 +f 2390 2389 2347 +f 2453 2452 2445 +f 1347 1630 2453 +f 1630 1347 522 +f 2220 2206 2197 +f 2262 2350 2286 +f 170 254 2428 +f 2457 1973 2446 +f 1973 1365 2446 +f 2174 2183 2180 +f 2194 2202 2187 +f 2222 2241 2209 +f 2222 2260 2241 +f 2266 2259 2247 +f 2390 2445 2389 +f 2264 2251 825 +f 2363 2368 2351 +f 2326 2393 2341 +f 1855 1850 1851 +f 2210 2209 2202 +f 2210 2222 2209 +f 2261 2260 2222 +f 2280 2279 2266 +f 2280 2300 2279 +f 251 263 2359 +f 2277 2304 2299 +f 2220 2230 2206 +f 2202 2194 2210 +f 2213 2243 2234 +f 2328 2327 2322 +f 2294 2310 2293 +f 2214 2196 2189 +f 2196 2213 2219 +f 2224 2222 2210 +f 2421 2390 2375 +f 2206 2230 2214 +f 2194 2203 2210 +f 2224 2261 2222 +f 2421 2445 2390 +f 2322 2327 2318 +f 2393 2408 2341 +f 1365 1973 510 +f 2216 2210 2203 +f 2216 2224 2210 +f 2266 2308 2280 +f 2280 2308 2300 +f 2407 2421 2375 +f 2175 2183 2174 +f 2194 2190 2203 +f 2454 2445 2421 +f 522 1347 523 +f 2456 2455 2423 +f 823 2197 2178 +f 2281 2333 2287 +f 2188 2187 2183 +f 2188 2190 2194 +f 2187 2188 2194 +f 2308 2315 2300 +f 2407 2375 2362 +f 2443 2420 2503 +f 2420 2411 2503 +f 2411 1493 2503 +f 1493 1487 2503 +f 1487 1318 2503 +f 1318 1320 2503 +f 1320 2443 2503 diff --git a/A1/resources/sphere.obj b/A1/resources/sphere.obj new file mode 100644 index 0000000..698f5ce --- /dev/null +++ b/A1/resources/sphere.obj @@ -0,0 +1,204 @@ +#### +# +# OBJ File Generated by LightWave3D +# LightWave3D OBJ Export v2.2 +# +#### +# +# Vertices: 62 +# Points: 0 +# Lines: 0 +# Faces: 120 +# Materials: 1 +# +#### + +# Vertex list + +v 0 -0.5 -0 +v 0.25 -0.433013 -0 +v 0.216506 -0.433013 -0.125 +v 0.125 -0.433013 -0.216506 +v 0 -0.433013 -0.25 +v -0.125 -0.433013 -0.216506 +v -0.216506 -0.433013 -0.125 +v -0.25 -0.433013 -0 +v -0.216506 -0.433013 0.125 +v -0.125 -0.433013 0.216506 +v 0 -0.433013 0.25 +v 0.125 -0.433013 0.216506 +v 0.216506 -0.433013 0.125 +v 0.433013 -0.25 -0 +v 0.375 -0.25 -0.216506 +v 0.216506 -0.25 -0.375 +v 0 -0.25 -0.433013 +v -0.216506 -0.25 -0.375 +v -0.375 -0.25 -0.216506 +v -0.433013 -0.25 -0 +v -0.375 -0.25 0.216506 +v -0.216506 -0.25 0.375 +v 0 -0.25 0.433013 +v 0.216506 -0.25 0.375 +v 0.375 -0.25 0.216506 +v 0.5 2.55171e-12 -0 +v 0.433013 2.55171e-12 -0.25 +v 0.25 2.55171e-12 -0.433013 +v 0 2.55171e-12 -0.5 +v -0.25 2.55171e-12 -0.433013 +v -0.433013 2.55171e-12 -0.25 +v -0.5 2.55171e-12 -0 +v -0.433013 2.55171e-12 0.25 +v -0.25 2.55171e-12 0.433013 +v 0 2.55171e-12 0.5 +v 0.25 2.55171e-12 0.433013 +v 0.433013 2.55171e-12 0.25 +v 0.433013 0.25 -0 +v 0.375 0.25 -0.216506 +v 0.216506 0.25 -0.375 +v 0 0.25 -0.433013 +v -0.216506 0.25 -0.375 +v -0.375 0.25 -0.216506 +v -0.433013 0.25 -0 +v -0.375 0.25 0.216506 +v -0.216506 0.25 0.375 +v 0 0.25 0.433013 +v 0.216506 0.25 0.375 +v 0.375 0.25 0.216506 +v 0.25 0.433013 -0 +v 0.216506 0.433013 -0.125 +v 0.125 0.433013 -0.216506 +v 0 0.433013 -0.25 +v -0.125 0.433013 -0.216506 +v -0.216506 0.433013 -0.125 +v -0.25 0.433013 -0 +v -0.216506 0.433013 0.125 +v -0.125 0.433013 0.216506 +v 0 0.433013 0.25 +v 0.125 0.433013 0.216506 +v 0.216506 0.433013 0.125 +v 5.10341e-12 0.5 -0 + +# Face list + +f 3 2 1 +f 4 3 1 +f 5 4 1 +f 6 5 1 +f 7 6 1 +f 8 7 1 +f 9 8 1 +f 10 9 1 +f 11 10 1 +f 12 11 1 +f 13 12 1 +f 2 13 1 +f 3 14 2 +f 15 14 3 +f 4 15 3 +f 16 15 4 +f 17 16 4 +f 5 17 4 +f 17 5 6 +f 18 17 6 +f 18 6 7 +f 19 18 7 +f 20 7 8 +f 20 19 7 +f 20 8 9 +f 21 20 9 +f 21 9 10 +f 22 21 10 +f 23 10 11 +f 23 22 10 +f 12 23 11 +f 24 23 12 +f 13 24 12 +f 25 24 13 +f 14 25 13 +f 2 14 13 +f 15 26 14 +f 27 26 15 +f 28 27 15 +f 16 28 15 +f 29 28 16 +f 17 29 16 +f 29 17 18 +f 30 29 18 +f 31 18 19 +f 31 30 18 +f 32 19 20 +f 32 31 19 +f 32 20 21 +f 33 32 21 +f 34 21 22 +f 34 33 21 +f 35 22 23 +f 35 34 22 +f 24 35 23 +f 36 35 24 +f 37 36 24 +f 25 37 24 +f 26 37 25 +f 14 26 25 +f 39 38 26 +f 27 39 26 +f 28 39 27 +f 40 39 28 +f 29 40 28 +f 41 40 29 +f 42 29 30 +f 42 41 29 +f 43 30 31 +f 43 42 30 +f 43 31 32 +f 44 43 32 +f 45 32 33 +f 45 44 32 +f 45 33 34 +f 46 45 34 +f 46 34 35 +f 47 46 35 +f 48 47 35 +f 36 48 35 +f 49 48 36 +f 37 49 36 +f 26 49 37 +f 38 49 26 +f 39 50 38 +f 51 50 39 +f 40 51 39 +f 52 51 40 +f 53 52 40 +f 41 53 40 +f 53 41 42 +f 54 53 42 +f 55 42 43 +f 55 54 42 +f 56 43 44 +f 56 55 43 +f 56 44 45 +f 57 56 45 +f 58 45 46 +f 58 57 45 +f 58 46 47 +f 59 58 47 +f 60 59 47 +f 48 60 47 +f 49 60 48 +f 61 60 49 +f 50 61 49 +f 38 50 49 +f 51 62 50 +f 52 62 51 +f 53 62 52 +f 62 53 54 +f 62 54 55 +f 62 55 56 +f 62 56 57 +f 62 57 58 +f 62 58 59 +f 60 62 59 +f 61 62 60 +f 50 62 61 + +# End of file diff --git a/A1/resources/teapot.obj b/A1/resources/teapot.obj new file mode 100644 index 0000000..6fed453 --- /dev/null +++ b/A1/resources/teapot.obj @@ -0,0 +1,5049 @@ +# Blender v2.65 (sub 0) OBJ File +# www.blender.org +o teapot.005 +v -0.498530 0.712498 -0.039883 +v -0.501666 0.699221 -0.063813 +v -0.501255 0.717792 0.000000 +v -0.624036 0.711938 -0.039883 +v -0.526706 0.651362 -0.039883 +v -0.508714 0.682112 -0.071712 +v -0.622039 0.698704 -0.063813 +v -0.624834 0.717232 0.000000 +v -0.498530 0.712498 0.039883 +v -0.638129 0.287158 0.000000 +v -0.517593 0.664661 -0.063813 +v -0.534329 0.646030 0.000000 +v -0.614850 0.651067 -0.039883 +v -0.616848 0.664299 -0.063813 +v -0.619445 0.681503 -0.071790 +v -0.741245 0.707456 -0.039883 +v -0.744483 0.712577 0.000000 +v -0.624036 0.711938 0.039883 +v -0.501667 0.699221 0.063813 +v -0.622039 0.698704 0.063813 +v -0.712095 0.661370 -0.063813 +v -0.733150 0.694655 -0.063813 +v -0.741245 0.707456 0.039883 +v -0.733150 0.694655 0.063813 +v -0.631184 0.277569 -0.039883 +v -0.526706 0.651362 0.039883 +v -0.614053 0.645774 0.000000 +v -0.704000 0.648569 -0.039883 +v -0.722621 0.678012 -0.071790 +v -0.832523 0.695296 -0.039883 +v -0.837545 0.699948 0.000000 +v -0.832523 0.695296 0.039883 +v -0.619445 0.681503 0.071790 +v -0.508714 0.682112 0.071712 +v -0.722621 0.678012 0.071790 +v -0.517593 0.664661 0.063813 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.710066 0.328372 0.000000 +v -0.614850 0.651067 0.039883 +v -0.787321 0.653419 -0.063813 +v -0.803644 0.668539 -0.071790 +v -0.819967 0.683663 -0.063813 +v -0.819967 0.683663 0.063813 +v -0.803644 0.668539 0.071790 +v -0.711425 0.307332 -0.063813 +v -0.615553 0.216807 -0.063813 +v -0.712688 0.287795 -0.071790 +v -0.631184 0.277569 0.039883 +v -0.710455 0.322361 -0.039883 +v -0.710455 0.322361 0.039883 +v -0.700762 0.643448 0.000000 +v -0.774766 0.641786 -0.039883 +v -0.897800 0.671612 -0.039883 +v -0.904015 0.675354 0.000000 +v -0.897800 0.671612 0.039883 +v -0.882265 0.662257 0.063813 +v -0.712095 0.661370 0.063813 +v -0.787321 0.653419 0.063813 +v -0.608884 0.198682 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.766936 0.377559 0.000000 +v -0.769651 0.372307 0.039883 +v -0.616848 0.664299 0.063813 +v -0.704000 0.648569 0.039883 +v -0.841868 0.637931 -0.063813 +v -0.862065 0.650094 -0.071790 +v -0.882265 0.662257 -0.063813 +v -0.862065 0.650094 0.071790 +v -0.841868 0.637931 0.063813 +v -0.611709 0.194244 0.000000 +v -0.776434 0.359177 -0.063813 +v -0.769651 0.372307 -0.039883 +v -0.713952 0.268259 -0.063813 +v -0.711425 0.307332 0.063813 +v -0.776434 0.359177 0.063813 +v -0.769743 0.637131 0.000000 +v -0.826329 0.628576 -0.039883 +v -0.937016 0.632565 -0.039883 +v -0.943899 0.634805 0.000000 +v -0.937016 0.632565 0.039883 +v -0.919812 0.626965 0.063813 +v -0.897443 0.619684 0.071790 +v -0.774766 0.641786 0.039883 +v -0.826329 0.628576 0.039883 +v -0.714922 0.253231 -0.039883 +v -0.608883 0.198681 0.039883 +v -0.715311 0.247220 0.000000 +v -0.785253 0.342107 -0.071790 +v -0.619922 0.238069 0.071790 +v -0.712688 0.287795 0.071790 +v -0.809626 0.430737 0.000000 +v -0.814205 0.426194 0.039883 +v -0.825653 0.414838 0.063813 +v -0.875076 0.612403 -0.063813 +v -0.897443 0.619684 -0.071790 +v -0.919812 0.626965 -0.063813 +v -0.875076 0.612403 0.063813 +v -0.857869 0.606800 0.039883 +v -0.794072 0.325038 -0.063813 +v -0.800855 0.311909 -0.039883 +v -0.825653 0.414838 -0.063813 +v -0.814205 0.426194 -0.039883 +v -0.615480 0.216617 0.063578 +v -0.785253 0.342107 0.071790 +v -0.840534 0.400078 0.071790 +v -0.820114 0.624834 0.000000 +v -0.857869 0.606800 -0.039883 +v -0.950104 0.574316 -0.039883 +v -0.957194 0.574316 0.000000 +v -0.950104 0.574316 0.039883 +v -0.932377 0.574316 0.063813 +v -0.909334 0.574316 0.071790 +v -0.886292 0.574316 0.063813 +v -0.850987 0.604560 0.000000 +v -0.714922 0.253231 0.039883 +v -0.803571 0.306656 0.000000 +v -0.840534 0.400078 -0.071790 +v -0.713952 0.268259 0.063813 +v -0.794072 0.325038 0.063813 +v -0.839022 0.483916 0.000000 +v -0.844976 0.480304 0.039883 +v -0.859854 0.471278 0.063813 +v -0.879202 0.459542 0.071790 +v -0.886292 0.574316 -0.063813 +v -0.909334 0.574316 -0.071790 +v -0.932377 0.574316 -0.063813 +v -0.868564 0.574316 0.039883 +v -0.861474 0.574316 0.000000 +v -0.855419 0.385315 -0.063813 +v -0.866867 0.373960 -0.039883 +v -0.859854 0.471278 -0.063813 +v -0.844976 0.480304 -0.039883 +v -0.855419 0.385315 0.063813 +v -0.898547 0.447807 0.063813 +v -0.868564 0.574316 -0.039883 +v -0.941014 0.505765 -0.039883 +v -0.947813 0.503580 0.000000 +v -0.941014 0.505765 0.039883 +v -0.924011 0.511234 0.063813 +v -0.901913 0.518343 0.071790 +v -0.879811 0.525448 0.063813 +v -0.862808 0.530917 0.039883 +v -0.800855 0.311909 0.039883 +v -0.871445 0.369416 0.000000 +v -0.879202 0.459542 -0.071790 +v -0.866867 0.373960 0.039883 +v -0.856009 0.533103 0.000000 +v -0.879811 0.525448 -0.063813 +v -0.901913 0.518343 -0.071790 +v -0.924011 0.511234 -0.063813 +v -0.862808 0.530917 -0.039883 +v -0.898547 0.447807 -0.063813 +v -0.913428 0.438781 -0.039883 +v -0.913428 0.438781 0.039883 +v -0.919378 0.435169 0.000000 +v 0.600960 0.444810 0.085753 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.656890 0.471064 0.000000 +v 0.661223 0.454734 -0.083705 +v 0.730696 0.501576 -0.073611 +v 0.661223 0.454734 0.083705 +v 0.605101 0.399712 -0.137265 +v 0.746455 0.470391 -0.117778 +v 0.724395 0.514048 0.000000 +v 0.605100 0.399712 0.137265 +v 0.672055 0.413907 -0.133928 +v 0.613258 0.341675 -0.154354 +v 0.786583 0.544847 -0.096783 +v 0.768856 0.565896 -0.060489 +v 0.672055 0.413907 0.133928 +v 0.730696 0.501576 0.073611 +v 0.686135 0.360830 -0.150669 +v 0.809626 0.517481 -0.108881 +v 0.766935 0.429850 -0.132501 +v 0.761767 0.574316 0.000000 +v 0.613258 0.341675 0.154354 +v 0.813417 0.626247 -0.075788 +v 0.839021 0.611098 -0.085261 +v 0.793721 0.637899 -0.047367 +v 0.686135 0.360830 0.150669 +v 0.768856 0.565896 0.060489 +v 0.746455 0.470391 0.117778 +v 0.619427 0.283145 -0.137236 +v 0.864627 0.595949 -0.075788 +v 0.832669 0.490118 -0.096783 +v 0.787419 0.389310 -0.117778 +v 0.785843 0.642561 0.000000 +v 0.619427 0.283145 0.137236 +v 0.700219 0.307756 -0.133928 +v 0.847933 0.703560 -0.059638 +v 0.879938 0.698065 -0.067092 +v 0.911944 0.692571 -0.059638 +v 0.823314 0.707784 -0.037273 +v 0.766935 0.429850 0.132501 +v 0.793721 0.637899 0.047367 +v 0.786583 0.544847 0.096783 +v 0.700219 0.307756 0.133928 +v 0.617684 0.235930 -0.085941 +v 0.936563 0.688344 -0.037273 +v 0.884319 0.584297 -0.047367 +v 0.850396 0.469070 -0.060489 +v 0.803175 0.358128 -0.073611 +v 0.813468 0.709475 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v 0.711051 0.266929 -0.083705 +v 0.911107 0.765755 -0.053178 +v 0.957193 0.765755 -0.059825 +v 1.003279 0.765755 -0.053178 +v 1.038733 0.765755 -0.033236 +v 0.875654 0.765755 -0.033236 +v 0.809626 0.517481 0.108881 +v 0.787419 0.389310 0.117778 +v 0.823314 0.707784 0.037273 +v 0.813417 0.626247 0.075788 +v 0.711051 0.266929 0.083705 +v 0.715384 0.250599 0.000000 +v 1.052913 0.765755 0.000000 +v 0.946409 0.686653 0.000000 +v 0.892200 0.579635 0.000000 +v 0.857486 0.460650 0.000000 +v 0.809479 0.345652 0.000000 +v 0.861474 0.765755 0.000000 +v 0.929990 0.776479 -0.051602 +v 0.979075 0.777181 -0.058052 +v 1.028157 0.777879 -0.051602 +v 1.065915 0.778419 -0.032251 +v 1.081016 0.778632 0.000000 +v 0.892235 0.775943 -0.032251 +v 0.839021 0.611098 0.085261 +v 0.832669 0.490118 0.096783 +v 0.803175 0.358128 0.073611 +v 0.875654 0.765755 0.033236 +v 0.847933 0.703560 0.059638 +v 1.065915 0.778419 0.032174 +v 1.038733 0.765755 0.033236 +v 0.936563 0.688344 0.037273 +v 0.884319 0.584297 0.047367 +v 0.850396 0.469070 0.060489 +v 0.877131 0.775726 0.000000 +v 0.943713 0.783087 -0.047663 +v 0.992645 0.784366 -0.053621 +v 1.041577 0.785649 -0.047663 +v 1.079216 0.786631 -0.029789 +v 1.094273 0.787027 0.000000 +v 1.079216 0.786631 0.029174 +v 0.906073 0.782101 -0.029789 +v 0.879938 0.698065 0.067092 +v 0.864627 0.595949 0.075788 +v 0.892235 0.775943 0.032236 +v 0.911107 0.765755 0.053178 +v 1.041577 0.785649 0.046875 +v 1.028157 0.777879 0.051503 +v 1.003279 0.765755 0.053178 +v 0.911944 0.692571 0.059638 +v 0.891016 0.781708 0.000000 +v 0.951249 0.785448 -0.042542 +v 0.997575 0.787068 -0.047860 +v 1.043903 0.788686 -0.042542 +v 1.079539 0.789934 -0.026589 +v 1.093795 0.790431 0.000000 +v 1.079539 0.789934 0.024511 +v 1.043903 0.788686 0.039883 +v 0.915613 0.784200 -0.026589 +v 0.957193 0.765755 0.059825 +v 0.906073 0.782101 0.029666 +v 0.929990 0.776479 0.051553 +v 0.997575 0.787068 0.045616 +v 0.992645 0.784366 0.052956 +v 0.979075 0.777181 0.057969 +v 0.901357 0.783702 0.000000 +v 0.951569 0.783431 -0.037421 +v 0.993532 0.785033 -0.042099 +v 1.035492 0.786631 -0.037421 +v 1.067772 0.787863 -0.023388 +v 1.080684 0.788354 0.000000 +v 1.067772 0.787863 0.018464 +v 1.035492 0.786631 0.031119 +v 0.993532 0.785033 0.036781 +v 0.919292 0.782200 -0.023388 +v 0.915613 0.784200 0.026173 +v 0.943713 0.783087 0.047269 +v 0.951569 0.783431 0.034270 +v 0.951249 0.785448 0.041213 +v 0.906379 0.781708 0.000000 +v 0.943653 0.776909 -0.033482 +v 0.980182 0.778010 -0.037667 +v 1.016712 0.779111 -0.033482 +v 1.044812 0.779957 -0.020926 +v 1.056052 0.780295 0.000000 +v 1.044812 0.779957 0.011310 +v 1.016712 0.779111 0.021172 +v 0.980182 0.778010 0.027281 +v 0.943653 0.776909 0.027327 +v 0.915553 0.776064 -0.020926 +v 0.919292 0.782200 0.022403 +v 0.915553 0.776064 0.019003 +v 0.904312 0.775726 0.000000 +v 0.926468 0.765755 -0.031906 +v 0.957193 0.765755 -0.035895 +v 0.987920 0.765755 -0.031906 +v 1.011552 0.765755 -0.019942 +v 1.021006 0.765755 0.000000 +v 1.011552 0.765755 0.003324 +v 0.987920 0.765755 0.010635 +v 0.957193 0.765755 0.017947 +v 0.926468 0.765755 0.021271 +v 0.902834 0.765755 0.016618 +v 0.902834 0.765755 -0.019942 +v 0.893380 0.765755 0.000000 +v 0.886428 0.750924 -0.019014 +v 0.908324 0.750924 -0.030099 +v 0.936793 0.750924 -0.033795 +v 0.965261 0.750924 -0.030099 +v 0.987158 0.750924 -0.019014 +v 0.995918 0.750924 -0.000537 +v 0.987158 0.750924 0.002542 +v 0.965261 0.750924 0.009317 +v 0.936793 0.750924 0.016092 +v 0.908324 0.750924 0.019171 +v 0.886428 0.750924 0.014860 +v 0.877668 0.750924 -0.000537 +v 0.936793 0.750924 -0.007312 +v 0.440746 0.783205 0.000000 +v 0.446690 0.765755 0.000000 +v 0.430973 0.765755 0.119945 +v 0.425236 0.783205 0.118348 +v 0.425236 0.783205 -0.118348 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 0.121642 +v 0.441668 0.793673 0.000000 +v 0.386470 0.765755 0.226985 +v 0.430973 0.765755 -0.119945 +v 0.426127 0.793673 -0.118596 +v 0.437073 0.750009 -0.121642 +v 0.426127 0.793673 0.118596 +v 0.381327 0.783205 0.223964 +v 0.381327 0.783205 -0.223964 +v 0.382124 0.793673 -0.224433 +v 0.317150 0.765755 0.317150 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 0.321639 +v 0.386470 0.765755 -0.226985 +v 0.391939 0.750009 -0.230197 +v 0.447686 0.797164 0.000000 +v 0.431936 0.797164 -0.120212 +v 0.387332 0.797164 -0.227491 +v 0.230197 0.750009 0.391940 +v 0.226984 0.765755 0.386470 +v 0.317150 0.765755 -0.317150 +v 0.321638 0.750009 -0.321639 +v 0.431936 0.797164 0.120212 +v 0.382124 0.793673 0.224433 +v 0.312929 0.783205 0.312929 +v 0.313584 0.793673 -0.313584 +v 0.312929 0.783205 -0.312929 +v 0.317858 0.797164 -0.317858 +v 0.121642 0.750009 0.437072 +v 0.119944 0.765755 0.430973 +v 0.226984 0.765755 -0.386470 +v 0.230197 0.750009 -0.391940 +v 0.457031 0.793673 0.000000 +v 0.440950 0.793673 -0.122721 +v 0.395416 0.793673 -0.232239 +v 0.324491 0.793673 -0.324492 +v -0.000000 0.750009 0.453012 +v -0.000000 0.765755 0.446690 +v 0.223963 0.783205 0.381327 +v 0.223963 0.783205 -0.381327 +v 0.119944 0.765755 -0.430973 +v 0.121642 0.750009 -0.437072 +v 0.440950 0.793673 0.122721 +v 0.387332 0.797164 0.227491 +v 0.313584 0.793673 0.313584 +v 0.227491 0.797164 -0.387332 +v 0.224433 0.793673 -0.382125 +v 0.232239 0.793673 -0.395417 +v -0.119945 0.765755 0.430973 +v -0.121642 0.750009 0.437072 +v 0.118348 0.783205 0.425237 +v 0.118348 0.783205 -0.425237 +v -0.000000 0.750009 -0.453012 +v -0.000000 0.765755 -0.446690 +v 0.467924 0.783205 0.000000 +v 0.451460 0.783205 -0.125646 +v 0.404842 0.783205 -0.237775 +v 0.332226 0.783205 -0.332226 +v 0.237775 0.783205 -0.404842 +v -0.226985 0.765755 0.386470 +v -0.000000 0.783205 0.440746 +v 0.224433 0.793673 0.382125 +v 0.118596 0.793673 -0.426127 +v -0.000000 0.783205 -0.440746 +v -0.119945 0.765755 -0.430973 +v -0.121642 0.750009 -0.437072 +v 0.451460 0.783205 0.125646 +v 0.395416 0.793673 0.232239 +v 0.317858 0.797164 0.317858 +v 0.122721 0.793673 -0.440950 +v 0.120212 0.797164 -0.431937 +v 0.125646 0.783205 -0.451460 +v -0.317150 0.765755 0.317150 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.118348 0.783205 0.425237 +v 0.118596 0.793673 0.426127 +v -0.000000 0.793673 -0.441668 +v -0.118348 0.783205 -0.425237 +v -0.226985 0.765755 -0.386470 +v 0.478596 0.765755 0.000000 +v 0.461756 0.765755 -0.128512 +v 0.414076 0.765755 -0.243198 +v 0.339803 0.765755 -0.339804 +v 0.243198 0.765755 -0.414076 +v 0.128512 0.765755 -0.461757 +v -0.391940 0.750009 0.230197 +v -0.386470 0.765755 0.226985 +v -0.223964 0.783205 0.381327 +v -0.000000 0.793673 0.441668 +v 0.227491 0.797164 0.387332 +v -0.000000 0.797164 -0.447686 +v -0.118596 0.793673 -0.426127 +v -0.223964 0.783205 -0.381327 +v -0.317150 0.765755 -0.317150 +v -0.230198 0.750009 -0.391939 +v -0.321639 0.750009 -0.321639 +v 0.461756 0.765755 0.128512 +v 0.404842 0.783205 0.237775 +v 0.324491 0.793673 0.324492 +v -0.000000 0.783205 -0.467924 +v -0.000000 0.793673 -0.457031 +v -0.000000 0.765755 -0.478597 +v -0.437073 0.750009 0.121642 +v -0.430974 0.765755 0.119945 +v -0.312929 0.783205 0.312929 +v -0.118596 0.793673 0.426127 +v 0.120212 0.797164 0.431937 +v -0.120212 0.797164 -0.431937 +v -0.224433 0.793673 -0.382125 +v -0.312929 0.783205 -0.312929 +v -0.386470 0.765755 -0.226985 +v -0.391940 0.750009 -0.230197 +v 0.518110 0.682112 0.000000 +v 0.499881 0.682112 -0.139122 +v 0.448260 0.682112 -0.263277 +v 0.367859 0.682112 -0.367859 +v 0.263277 0.682112 -0.448260 +v 0.139122 0.682112 -0.499882 +v -0.000000 0.682112 -0.518110 +v -0.453012 0.750009 0.000000 +v -0.446690 0.765755 0.000000 +v -0.381327 0.783205 0.223964 +v -0.224433 0.793673 0.382125 +v -0.000000 0.797164 0.447686 +v 0.232239 0.793673 0.395417 +v -0.122721 0.793673 -0.440950 +v -0.227491 0.797164 -0.387332 +v -0.313584 0.793673 -0.313584 +v -0.381327 0.783205 -0.223964 +v -0.430974 0.765755 -0.119945 +v 0.499881 0.682112 0.139122 +v 0.414076 0.765755 0.243198 +v 0.332226 0.783205 0.332226 +v -0.128513 0.765755 -0.461757 +v -0.125646 0.783205 -0.451460 +v -0.139123 0.682112 -0.499882 +v -0.437073 0.750009 -0.121642 +v -0.425237 0.783205 0.118348 +v -0.313584 0.793673 0.313584 +v -0.120212 0.797164 0.431937 +v 0.122721 0.793673 0.440950 +v -0.232240 0.793673 -0.395417 +v -0.317859 0.797164 -0.317858 +v -0.382125 0.793673 -0.224433 +v -0.425237 0.783205 -0.118348 +v 0.555408 0.599133 0.000000 +v 0.535865 0.599133 -0.149137 +v 0.480530 0.599133 -0.282230 +v 0.394341 0.599133 -0.394341 +v 0.282230 0.599133 -0.480530 +v 0.149137 0.599133 -0.535866 +v -0.000000 0.599133 -0.555408 +v -0.149138 0.599133 -0.535866 +v -0.440746 0.783205 0.000000 +v -0.382125 0.793673 0.224433 +v -0.227491 0.797164 0.387332 +v -0.000000 0.793673 0.457031 +v 0.237775 0.783205 0.404842 +v -0.237775 0.783205 -0.404842 +v -0.324492 0.793673 -0.324492 +v -0.387332 0.797164 -0.227491 +v -0.426127 0.793673 -0.118596 +v 0.535865 0.599133 0.149137 +v 0.448260 0.682112 0.263277 +v 0.339803 0.765755 0.339804 +v -0.263278 0.682112 -0.448260 +v -0.243198 0.765755 -0.414076 +v -0.282230 0.599133 -0.480530 +v -0.426127 0.793673 0.118596 +v -0.317859 0.797164 0.317858 +v -0.122721 0.793673 0.440950 +v 0.125646 0.783205 0.451460 +v -0.332226 0.783205 -0.332226 +v -0.395417 0.793673 -0.232239 +v -0.431937 0.797164 -0.120212 +v -0.441668 0.793673 0.000000 +v 0.588275 0.517481 0.000000 +v 0.567578 0.517481 -0.157963 +v 0.508969 0.517485 -0.298931 +v 0.417675 0.517481 -0.417675 +v 0.298931 0.517485 -0.508969 +v 0.157963 0.517485 -0.567578 +v -0.000000 0.517481 -0.588275 +v -0.157963 0.517481 -0.567578 +v -0.298931 0.517485 -0.508969 +v -0.387332 0.797164 0.227491 +v -0.232240 0.793673 0.395417 +v -0.000000 0.783205 0.467924 +v 0.243198 0.765755 0.414076 +v -0.339804 0.765755 -0.339804 +v -0.404842 0.783205 -0.237775 +v -0.440950 0.793673 -0.122721 +v -0.447686 0.797164 0.000000 +v 0.567578 0.517485 0.157963 +v 0.480530 0.599133 0.282230 +v 0.367859 0.682112 0.367859 +v -0.394341 0.599133 -0.394341 +v -0.367859 0.682112 -0.367859 +v -0.417675 0.517481 -0.417675 +v -0.431937 0.797164 0.120212 +v -0.324492 0.793673 0.324492 +v -0.125646 0.783205 0.451460 +v 0.128512 0.765755 0.461757 +v -0.414076 0.765755 -0.243198 +v -0.451461 0.783205 -0.125646 +v -0.457031 0.793673 0.000000 +v 0.592873 0.437827 -0.165003 +v 0.531651 0.437827 -0.312254 +v 0.436292 0.437827 -0.436292 +v 0.312254 0.437827 -0.531651 +v 0.165003 0.437827 -0.592873 +v -0.000000 0.437827 -0.614496 +v -0.165004 0.437827 -0.592873 +v -0.312255 0.437827 -0.531651 +v -0.436292 0.437827 -0.436292 +v -0.395417 0.793673 0.232239 +v -0.237775 0.783205 0.404842 +v -0.000000 0.765755 0.478597 +v 0.263277 0.682112 0.448260 +v -0.448260 0.682112 -0.263277 +v -0.461757 0.765755 -0.128512 +v -0.467924 0.783205 0.000000 +v -0.440950 0.793673 0.122721 +v 0.592873 0.437827 0.165003 +v 0.508969 0.517485 0.298931 +v 0.394341 0.599133 0.394341 +v -0.508969 0.517485 -0.298931 +v -0.480530 0.599133 -0.282230 +v -0.531651 0.437827 -0.312254 +v -0.332226 0.783205 0.332226 +v -0.128513 0.765755 0.461757 +v 0.139122 0.682112 0.499882 +v -0.499882 0.682112 -0.139122 +v -0.478597 0.765755 0.000000 +v -0.451461 0.783205 0.125646 +v 0.546669 0.360830 -0.321075 +v 0.448614 0.360830 -0.448614 +v 0.321074 0.360830 -0.546669 +v 0.169664 0.360830 -0.609621 +v -0.000000 0.360830 -0.631850 +v -0.169664 0.360830 -0.609621 +v -0.321075 0.360830 -0.546669 +v -0.448615 0.360830 -0.448614 +v -0.546669 0.360830 -0.321075 +v -0.404842 0.783205 0.237775 +v -0.243198 0.765755 0.414076 +v -0.000000 0.682112 0.518110 +v 0.282230 0.599133 0.480530 +v -0.535866 0.599133 -0.149137 +v -0.461757 0.765755 0.128512 +v 0.531651 0.437827 0.312254 +v 0.417675 0.517481 0.417675 +v 0.609621 0.360830 -0.169664 +v -0.592873 0.437827 -0.165003 +v -0.567578 0.517485 -0.157963 +v -0.609621 0.360830 -0.169664 +v -0.339804 0.765755 0.339804 +v -0.139123 0.682112 0.499882 +v 0.149137 0.599133 0.535866 +v -0.555408 0.599133 0.000000 +v -0.499882 0.682112 0.139122 +v -0.414076 0.765755 0.243198 +v 0.609621 0.360830 0.169664 +v 0.552100 0.287158 -0.324265 +v 0.453072 0.287158 -0.453072 +v 0.324265 0.287158 -0.552100 +v 0.171349 0.287158 -0.615677 +v -0.000000 0.287158 -0.638129 +v -0.171350 0.287158 -0.615677 +v -0.324265 0.287158 -0.552100 +v -0.453072 0.287158 -0.453072 +v -0.552100 0.287158 -0.324265 +v -0.615677 0.287158 -0.171349 +v -0.263278 0.682112 0.448260 +v -0.000000 0.599133 0.555408 +v 0.298931 0.517485 0.508969 +v -0.588275 0.517481 0.000000 +v -0.448260 0.682112 0.263277 +v 0.546669 0.360830 0.321075 +v 0.436292 0.437827 0.436292 +v 0.615677 0.287158 -0.171349 +v -0.631850 0.360830 0.000000 +v -0.614496 0.437827 0.000000 +v -0.367859 0.682112 0.367859 +v -0.149138 0.599133 0.535866 +v 0.157963 0.517481 0.567578 +v -0.567578 0.517481 0.157963 +v -0.480530 0.599133 0.282230 +v 0.615677 0.287158 0.171349 +v 0.541877 0.221240 -0.318259 +v 0.444680 0.221240 -0.444680 +v 0.318259 0.221240 -0.541877 +v 0.168176 0.221240 -0.604276 +v -0.000000 0.221240 -0.626311 +v -0.168177 0.221240 -0.604276 +v -0.318259 0.221240 -0.541877 +v -0.444680 0.221240 -0.444680 +v -0.541877 0.221240 -0.318259 +v -0.604277 0.221240 -0.168176 +v -0.282230 0.599133 0.480530 +v -0.000000 0.517481 0.588275 +v 0.312254 0.437827 0.531651 +v -0.592873 0.437827 0.165003 +v -0.535866 0.599133 0.149137 +v -0.394341 0.599133 0.394341 +v 0.552100 0.287158 0.324265 +v 0.448614 0.360830 0.448614 +v 0.604276 0.221240 -0.168176 +v -0.615677 0.287158 0.171349 +v -0.609621 0.360830 0.169664 +v -0.157963 0.517485 0.567578 +v 0.165003 0.437827 0.592873 +v -0.531651 0.437827 0.312254 +v -0.508969 0.517485 0.298931 +v -0.417675 0.517481 0.417675 +v 0.604276 0.221240 0.168176 +v 0.516317 0.166623 -0.303247 +v 0.423705 0.166623 -0.423705 +v 0.303247 0.166623 -0.516317 +v 0.160243 0.166623 -0.575771 +v -0.000000 0.166623 -0.596769 +v -0.160244 0.166623 -0.575771 +v -0.303247 0.166623 -0.516317 +v -0.423705 0.166623 -0.423705 +v -0.516317 0.166623 -0.303247 +v -0.575771 0.166623 -0.160243 +v -0.298931 0.517485 0.508969 +v -0.000000 0.437827 0.614496 +v 0.321074 0.360830 0.546669 +v -0.546669 0.360830 0.321075 +v 0.541877 0.221240 0.318259 +v 0.453072 0.287158 0.453072 +v 0.575771 0.166623 -0.160243 +v -0.596769 0.166623 0.000000 +v -0.604277 0.221240 0.168176 +v -0.552100 0.287158 0.324265 +v -0.165004 0.437827 0.592873 +v 0.169664 0.360830 0.609621 +v -0.448615 0.360830 0.448614 +v -0.436292 0.437827 0.436292 +v -0.312255 0.437827 0.531651 +v 0.575771 0.166623 0.160243 +v 0.483086 0.122640 -0.283731 +v 0.396438 0.122640 -0.396438 +v 0.283731 0.122640 -0.483086 +v 0.149931 0.122640 -0.538718 +v -0.000000 0.122640 -0.558363 +v -0.149931 0.122640 -0.538718 +v -0.283731 0.122640 -0.483086 +v -0.396438 0.122640 -0.396438 +v -0.483087 0.122640 -0.283731 +v -0.538718 0.122640 -0.149931 +v -0.558363 0.122640 0.000000 +v -0.541877 0.221240 0.318259 +v -0.000000 0.360830 0.631850 +v 0.324265 0.287158 0.552100 +v -0.453072 0.287158 0.453072 +v 0.516317 0.166623 0.303247 +v 0.596768 0.166623 0.000000 +v 0.444680 0.221240 0.444680 +v 0.538718 0.122640 -0.149931 +v -0.538718 0.122640 0.149931 +v -0.516317 0.166623 0.303247 +v -0.444680 0.221240 0.444680 +v -0.169664 0.360830 0.609621 +v 0.171349 0.287158 0.615677 +v -0.324265 0.287158 0.552100 +v -0.321075 0.360830 0.546669 +v 0.538718 0.122640 0.149931 +v 0.558363 0.122640 0.000000 +v 0.449858 0.088629 -0.264215 +v 0.369171 0.088629 -0.369171 +v 0.264215 0.088629 -0.449859 +v 0.139618 0.088629 -0.501662 +v -0.000000 0.088629 -0.519957 +v -0.139618 0.088629 -0.501662 +v -0.264215 0.088629 -0.449859 +v -0.369171 0.088629 -0.369171 +v -0.449859 0.088629 -0.264215 +v -0.501662 0.088629 -0.139618 +v -0.519957 0.088629 0.000000 +v -0.501662 0.088629 0.139618 +v -0.575771 0.166623 0.160243 +v -0.423705 0.166623 0.423705 +v -0.000000 0.287158 0.638129 +v 0.318259 0.221240 0.541877 +v -0.318259 0.221240 0.541877 +v 0.483086 0.122640 0.283731 +v 0.423705 0.166623 0.423705 +v 0.501662 0.088629 -0.139618 +v -0.449859 0.088629 0.264215 +v -0.483087 0.122640 0.283731 +v -0.396438 0.122640 0.396438 +v -0.303247 0.166623 0.516317 +v -0.171350 0.287158 0.615677 +v 0.168176 0.221240 0.604276 +v -0.168177 0.221240 0.604276 +v 0.501662 0.088629 0.139618 +v 0.519957 0.088629 0.000000 +v 0.424299 0.063924 -0.249203 +v 0.348195 0.063924 -0.348195 +v 0.249203 0.063924 -0.424298 +v 0.131685 0.063924 -0.473160 +v -0.000000 0.063924 -0.490415 +v -0.131686 0.063924 -0.473160 +v -0.249203 0.063924 -0.424298 +v -0.348196 0.063924 -0.348195 +v -0.424299 0.063924 -0.249203 +v -0.473160 0.063924 -0.131685 +v -0.490415 0.063924 0.000000 +v -0.473160 0.063924 0.131685 +v -0.424299 0.063924 0.249203 +v -0.283731 0.122640 0.483086 +v -0.000000 0.221240 0.626311 +v 0.303247 0.166623 0.516317 +v -0.160244 0.166623 0.575771 +v 0.449858 0.088629 0.264215 +v 0.396438 0.122640 0.396438 +v 0.473160 0.063924 -0.131685 +v -0.348196 0.063924 0.348195 +v -0.369171 0.088629 0.369171 +v -0.264215 0.088629 0.449859 +v -0.149931 0.122640 0.538718 +v 0.160243 0.166623 0.575771 +v -0.000000 0.166623 0.596769 +v 0.473160 0.063924 0.131685 +v 0.490415 0.063924 0.000000 +v 0.414076 0.047860 -0.243198 +v 0.339803 0.047860 -0.339804 +v 0.243198 0.047860 -0.414076 +v 0.128512 0.047860 -0.461757 +v -0.000000 0.047860 -0.478597 +v -0.128513 0.047860 -0.461757 +v -0.243198 0.047860 -0.414076 +v -0.339804 0.047860 -0.339804 +v -0.414076 0.047860 -0.243198 +v -0.461757 0.047860 -0.128512 +v -0.478597 0.047860 0.000000 +v -0.461757 0.047860 0.128512 +v -0.414076 0.047860 0.243198 +v -0.339804 0.047860 0.339804 +v -0.139618 0.088629 0.501662 +v 0.283731 0.122640 0.483086 +v -0.000000 0.122640 0.558363 +v 0.424299 0.063924 0.249203 +v 0.369171 0.088629 0.369171 +v 0.461756 0.047860 -0.128512 +v -0.243198 0.047860 0.414076 +v -0.249203 0.063924 0.424298 +v -0.131686 0.063924 0.473160 +v -0.000000 0.088629 0.519957 +v 0.149931 0.122640 0.538718 +v 0.461756 0.047860 0.128512 +v 0.478596 0.047860 0.000000 +v 0.410719 0.036005 -0.241228 +v 0.337050 0.036005 -0.337050 +v 0.241227 0.036005 -0.410719 +v 0.127471 0.036005 -0.458017 +v -0.000000 0.036005 -0.474720 +v -0.127471 0.036005 -0.458017 +v -0.241228 0.036005 -0.410719 +v -0.337051 0.036005 -0.337050 +v -0.410719 0.036005 -0.241228 +v -0.458017 0.036005 -0.127471 +v -0.474721 0.036005 0.000000 +v -0.458017 0.036005 0.127471 +v -0.410719 0.036005 0.241228 +v -0.337051 0.036005 0.337050 +v -0.241228 0.036005 0.410719 +v -0.000000 0.063924 0.490415 +v 0.264215 0.088629 0.449859 +v 0.139618 0.088629 0.501662 +v 0.414076 0.047860 0.243198 +v 0.348195 0.063924 0.348195 +v 0.458017 0.036005 -0.127471 +v -0.127471 0.036005 0.458017 +v -0.128513 0.047860 0.461757 +v -0.000000 0.047860 0.478597 +v 0.131685 0.063924 0.473160 +v 0.458017 0.036005 0.127471 +v 0.474720 0.036005 0.000000 +v 0.394137 0.024816 -0.231489 +v 0.323442 0.024816 -0.323442 +v 0.231489 0.024816 -0.394137 +v 0.122324 0.024816 -0.439524 +v -0.000000 0.024816 -0.455554 +v -0.122325 0.024816 -0.439524 +v -0.231489 0.024816 -0.394137 +v -0.323442 0.024816 -0.323442 +v -0.394137 0.024816 -0.231489 +v -0.439524 0.024816 -0.122325 +v -0.455554 0.024816 0.000000 +v -0.439524 0.024816 0.122325 +v -0.394137 0.024816 0.231489 +v -0.323442 0.024816 0.323442 +v -0.231489 0.024816 0.394137 +v -0.122325 0.024816 0.439524 +v 0.128512 0.047860 0.461757 +v 0.249203 0.063924 0.424298 +v 0.410719 0.036005 0.241228 +v 0.339803 0.047860 0.339804 +v 0.439524 0.024816 -0.122325 +v -0.000000 0.036005 0.474720 +v -0.000000 0.024816 0.455554 +v 0.127471 0.036005 0.458017 +v 0.243198 0.047860 0.414076 +v 0.439524 0.024816 0.122325 +v 0.455554 0.024816 0.000000 +v 0.354551 0.014956 -0.208238 +v 0.290957 0.014956 -0.290957 +v 0.208238 0.014956 -0.354551 +v 0.110038 0.014956 -0.395378 +v -0.000000 0.014956 -0.409797 +v -0.110038 0.014956 -0.395378 +v -0.208239 0.014956 -0.354551 +v -0.290957 0.014956 -0.290957 +v -0.354551 0.014956 -0.208238 +v -0.395378 0.014956 -0.110038 +v -0.409797 0.014956 0.000000 +v -0.395378 0.014956 0.110038 +v -0.354551 0.014956 0.208238 +v -0.290957 0.014956 0.290957 +v -0.208239 0.014956 0.354551 +v -0.110038 0.014956 0.395378 +v -0.000000 0.014956 0.409797 +v 0.241227 0.036005 0.410719 +v 0.337050 0.036005 0.337050 +v 0.394137 0.024816 0.231489 +v 0.395378 0.014956 -0.110038 +v 0.122324 0.024816 0.439524 +v 0.110038 0.014956 0.395378 +v 0.231489 0.024816 0.394137 +v 0.395378 0.014956 0.110038 +v 0.409797 0.014956 0.000000 +v 0.282184 0.007090 -0.165735 +v 0.231570 0.007090 -0.231570 +v 0.165735 0.007090 -0.282185 +v 0.087579 0.007090 -0.314679 +v -0.000000 0.007090 -0.326154 +v -0.087579 0.007090 -0.314679 +v -0.165735 0.007090 -0.282185 +v -0.231570 0.007090 -0.231570 +v -0.282184 0.007090 -0.165735 +v -0.314679 0.007090 -0.087579 +v -0.326155 0.007090 0.000000 +v -0.314679 0.007090 0.087579 +v -0.282184 0.007090 0.165735 +v -0.231570 0.007090 0.231570 +v -0.165735 0.007090 0.282185 +v -0.087579 0.007090 0.314679 +v -0.000000 0.007090 0.326154 +v 0.087579 0.007090 0.314679 +v 0.323442 0.024816 0.323442 +v 0.354551 0.014956 0.208238 +v 0.314679 0.007090 -0.087579 +v 0.208238 0.014956 0.354551 +v 0.165735 0.007090 0.282185 +v 0.290957 0.014956 0.290957 +v 0.314679 0.007090 0.087579 +v 0.326154 0.007090 0.000000 +v 0.167259 0.001883 -0.098236 +v 0.137258 0.001883 -0.137259 +v 0.098236 0.001883 -0.167259 +v 0.051910 0.001883 -0.186520 +v -0.000000 0.001883 -0.193322 +v -0.051911 0.001883 -0.186520 +v -0.098237 0.001883 -0.167259 +v -0.137259 0.001883 -0.137259 +v -0.167259 0.001883 -0.098236 +v -0.186520 0.001883 -0.051911 +v -0.193323 0.001883 0.000000 +v -0.186520 0.001883 0.051911 +v -0.167259 0.001883 0.098236 +v -0.137259 0.001883 0.137259 +v -0.098237 0.001883 0.167259 +v -0.051911 0.001883 0.186520 +v -0.000000 0.001883 0.193322 +v 0.051910 0.001883 0.186520 +v 0.098236 0.001883 0.167259 +v 0.282184 0.007090 0.165735 +v 0.186520 0.001883 -0.051911 +v 0.231570 0.007090 0.231570 +v 0.137258 0.001883 0.137259 +v 0.186520 0.001883 0.051911 +v 0.193322 0.001883 0.000000 +v -0.000000 0.000000 0.000000 +v 0.167259 0.001883 0.098236 +v 0.063813 0.861474 0.000000 +v 0.054654 0.888729 0.000000 +v 0.052734 0.888729 0.014691 +v 0.061568 0.861474 0.017135 +v 0.061568 0.861474 -0.017135 +v 0.072979 0.919969 0.020357 +v 0.111968 0.841089 0.000000 +v 0.047296 0.888729 0.027792 +v 0.052734 0.888729 -0.014691 +v 0.108028 0.841089 -0.030065 +v 0.075630 0.919969 0.000000 +v 0.065466 0.919969 0.038494 +v 0.108028 0.841089 0.030065 +v 0.055210 0.861474 0.032427 +v 0.055210 0.861474 -0.032427 +v 0.096873 0.841089 -0.056896 +v 0.100064 0.951211 0.027927 +v 0.089769 0.951211 0.052799 +v 0.183167 0.826023 0.000000 +v 0.176722 0.826023 -0.049184 +v 0.038821 0.888729 0.038821 +v 0.053751 0.919969 0.053751 +v 0.047296 0.888729 -0.027792 +v 0.072979 0.919969 -0.020357 +v 0.158473 0.826023 -0.093076 +v 0.103696 0.951211 0.000000 +v 0.073714 0.951211 0.073714 +v 0.176722 0.826023 0.049184 +v 0.096873 0.841089 0.056896 +v 0.045307 0.861474 0.045307 +v 0.079497 0.841089 -0.079497 +v 0.045307 0.861474 -0.045307 +v 0.130048 0.826023 -0.130048 +v 0.111754 0.978466 0.031195 +v 0.100259 0.978466 0.058974 +v 0.082330 0.978466 0.082330 +v 0.263228 0.813615 0.000000 +v 0.253966 0.813615 -0.070682 +v 0.227741 0.813615 -0.133759 +v 0.027792 0.888729 0.047296 +v 0.038494 0.919969 0.065466 +v 0.052799 0.951211 0.089769 +v 0.038821 0.888729 -0.038821 +v 0.065466 0.919969 -0.038494 +v 0.100064 0.951211 -0.027927 +v 0.186892 0.813615 -0.186892 +v 0.115809 0.978466 0.000000 +v 0.058974 0.978466 0.100259 +v 0.253966 0.813615 0.070682 +v 0.158473 0.826023 0.093076 +v 0.079497 0.841089 0.079497 +v 0.032426 0.861474 0.055210 +v 0.093076 0.826023 -0.158473 +v 0.056896 0.841089 -0.096873 +v 0.032426 0.861474 -0.055210 +v 0.133759 0.813615 -0.227741 +v 0.085811 0.997741 0.023955 +v 0.076985 0.997741 0.045285 +v 0.063219 0.997741 0.063219 +v 0.045285 0.997741 0.076986 +v 0.337972 0.801206 0.000000 +v 0.326081 0.801206 -0.090752 +v 0.292408 0.801206 -0.171740 +v 0.239960 0.801206 -0.239960 +v 0.014691 0.888729 0.052735 +v 0.020357 0.919969 0.072979 +v 0.027927 0.951211 0.100064 +v 0.031195 0.978466 0.111754 +v 0.027792 0.888729 -0.047296 +v 0.053751 0.919969 -0.053751 +v 0.089769 0.951211 -0.052799 +v 0.111754 0.978466 -0.031195 +v 0.171740 0.801206 -0.292408 +v 0.088924 0.997741 0.000000 +v 0.023955 0.997741 0.085811 +v 0.326081 0.801206 0.090752 +v 0.227741 0.813615 0.133759 +v 0.130048 0.826023 0.130048 +v 0.056896 0.841089 0.096873 +v 0.017135 0.861474 0.061568 +v 0.070682 0.813615 -0.253966 +v 0.049184 0.826023 -0.176722 +v 0.030065 0.841089 -0.108029 +v 0.017135 0.861474 -0.061568 +v 0.090752 0.801206 -0.326081 +v -0.000000 1.005054 0.000000 +v 0.393218 0.786140 0.000000 +v 0.379380 0.786140 -0.105586 +v 0.340206 0.786140 -0.199813 +v 0.279184 0.786140 -0.279184 +v 0.199813 0.786140 -0.340206 +v -0.000000 0.888729 0.054654 +v -0.000000 0.919969 0.075630 +v -0.000000 0.951211 0.103696 +v -0.000000 0.978466 0.115809 +v -0.000000 0.997741 0.088925 +v 0.014691 0.888729 -0.052735 +v 0.038494 0.919969 -0.065466 +v 0.073714 0.951211 -0.073714 +v 0.100259 0.978466 -0.058974 +v 0.085811 0.997741 -0.023955 +v 0.105586 0.786140 -0.379381 +v 0.379380 0.786140 0.105586 +v 0.292408 0.801206 0.171740 +v 0.186892 0.813615 0.186892 +v 0.093076 0.826023 0.158473 +v 0.030065 0.841089 0.108029 +v -0.000000 0.861474 0.063813 +v -0.000000 0.801206 -0.337972 +v -0.000000 0.813615 -0.263228 +v -0.000000 0.826023 -0.183167 +v -0.000000 0.841089 -0.111968 +v -0.000000 0.861474 -0.063813 +v -0.000000 0.786140 -0.393218 +v 0.076985 0.997741 -0.045285 +v -0.023955 0.997741 0.085811 +v 0.414784 0.765755 0.000000 +v 0.400190 0.765755 -0.111377 +v 0.358865 0.765755 -0.210772 +v 0.294497 0.765755 -0.294497 +v 0.210772 0.765755 -0.358865 +v 0.111377 0.765755 -0.400190 +v -0.014691 0.888729 0.052735 +v -0.020357 0.919969 0.072979 +v -0.027927 0.951211 0.100064 +v -0.031195 0.978466 0.111754 +v -0.000000 0.888729 -0.054654 +v 0.020357 0.919969 -0.072979 +v 0.052799 0.951211 -0.089769 +v 0.082330 0.978466 -0.082330 +v -0.000000 0.765755 -0.414784 +v 0.063219 0.997741 -0.063219 +v -0.045285 0.997741 0.076986 +v 0.400190 0.765755 0.111377 +v 0.340206 0.786140 0.199813 +v 0.239960 0.801206 0.239960 +v 0.133759 0.813615 0.227741 +v 0.049184 0.826023 0.176722 +v -0.000000 0.841089 0.111968 +v -0.017135 0.861474 0.061568 +v -0.105586 0.786140 -0.379381 +v -0.090752 0.801206 -0.326081 +v -0.070682 0.813615 -0.253966 +v -0.049184 0.826023 -0.176722 +v -0.030066 0.841089 -0.108029 +v -0.017135 0.861474 -0.061568 +v -0.111377 0.765755 -0.400190 +v 0.045285 0.997741 -0.076986 +v -0.063220 0.997741 0.063219 +v 0.414952 0.750806 0.115486 +v 0.430085 0.750806 0.000000 +v 0.414952 0.750806 -0.115486 +v 0.372103 0.750806 -0.218547 +v 0.305360 0.750806 -0.305360 +v 0.218547 0.750806 -0.372103 +v 0.115486 0.750806 -0.414952 +v -0.000000 0.750806 -0.430085 +v -0.027793 0.888729 0.047296 +v -0.038494 0.919969 0.065466 +v -0.052799 0.951211 0.089769 +v -0.058974 0.978466 0.100259 +v -0.014691 0.888729 -0.052735 +v -0.000000 0.919969 -0.075630 +v 0.027927 0.951211 -0.100064 +v 0.058974 0.978466 -0.100259 +v -0.115486 0.750806 -0.414952 +v 0.023955 0.997741 -0.085811 +v -0.076986 0.997741 0.045285 +v 0.372103 0.750806 0.218547 +v 0.358865 0.765755 0.210772 +v 0.279184 0.786140 0.279184 +v 0.171740 0.801206 0.292408 +v 0.070682 0.813615 0.253966 +v -0.000000 0.826023 0.183167 +v -0.030066 0.841089 0.108029 +v -0.032427 0.861474 0.055210 +v -0.210772 0.765755 -0.358865 +v -0.199813 0.786140 -0.340206 +v -0.171740 0.801206 -0.292408 +v -0.133759 0.813615 -0.227741 +v -0.093076 0.826023 -0.158473 +v -0.056896 0.841089 -0.096873 +v -0.032427 0.861474 -0.055210 +v -0.218547 0.750806 -0.372103 +v 0.031195 0.978466 -0.111754 +v -0.000000 0.997741 -0.088925 +v -0.082331 0.978466 0.082330 +v -0.085811 0.997741 0.023955 +v 0.305360 0.750806 0.305360 +v 0.294497 0.765755 0.294497 +v -0.038821 0.888729 0.038821 +v -0.053751 0.919969 0.053751 +v -0.073714 0.951211 0.073714 +v -0.027793 0.888729 -0.047296 +v -0.020357 0.919969 -0.072979 +v -0.000000 0.951211 -0.103696 +v -0.305360 0.750806 -0.305360 +v -0.294497 0.765755 -0.294497 +v -0.000000 0.978466 -0.115809 +v -0.023955 0.997741 -0.085811 +v -0.100259 0.978466 0.058974 +v -0.088925 0.997741 0.000000 +v 0.210772 0.765755 0.358865 +v 0.218547 0.750806 0.372103 +v 0.199813 0.786140 0.340206 +v 0.090752 0.801206 0.326081 +v -0.000000 0.813615 0.263228 +v -0.049184 0.826023 0.176722 +v -0.056896 0.841089 0.096873 +v -0.045307 0.861474 0.045307 +v -0.279185 0.786140 -0.279184 +v -0.239960 0.801206 -0.239960 +v -0.186892 0.813615 -0.186892 +v -0.130049 0.826023 -0.130048 +v -0.079497 0.841089 -0.079497 +v -0.045307 0.861474 -0.045307 +v -0.372103 0.750806 -0.218547 +v -0.358865 0.765755 -0.210772 +v -0.031195 0.978466 -0.111754 +v -0.045285 0.997741 -0.076986 +v -0.111754 0.978466 0.031195 +v -0.085811 0.997741 -0.023955 +v 0.111377 0.765755 0.400190 +v 0.115486 0.750806 0.414952 +v -0.047296 0.888729 0.027792 +v -0.065466 0.919969 0.038494 +v -0.089770 0.951211 0.052799 +v -0.038821 0.888729 -0.038821 +v -0.038494 0.919969 -0.065466 +v -0.027927 0.951211 -0.100064 +v -0.414952 0.750806 -0.115486 +v -0.400190 0.765755 -0.111377 +v -0.058974 0.978466 -0.100259 +v -0.063220 0.997741 -0.063219 +v -0.115809 0.978466 0.000000 +v -0.076986 0.997741 -0.045285 +v 0.105586 0.786140 0.379381 +v -0.000000 0.765755 0.414784 +v -0.000000 0.750806 0.430085 +v -0.000000 0.801206 0.337972 +v -0.070682 0.813615 0.253966 +v -0.093076 0.826023 0.158473 +v -0.079497 0.841089 0.079497 +v -0.055210 0.861474 0.032427 +v -0.340206 0.786140 -0.199813 +v -0.292408 0.801206 -0.171740 +v -0.227741 0.813615 -0.133759 +v -0.158473 0.826023 -0.093076 +v -0.096873 0.841089 -0.056896 +v -0.055210 0.861474 -0.032427 +v -0.430085 0.750806 0.000000 +v -0.414784 0.765755 0.000000 +v -0.052799 0.951211 -0.089769 +v -0.082331 0.978466 -0.082330 +v -0.100064 0.951211 0.027927 +v -0.111754 0.978466 -0.031195 +v -0.000000 0.786140 0.393218 +v -0.115486 0.750806 0.414952 +v -0.111377 0.765755 0.400190 +v -0.052735 0.888729 0.014691 +v -0.072979 0.919969 0.020357 +v -0.047296 0.888729 -0.027792 +v -0.053751 0.919969 -0.053751 +v -0.414952 0.750806 0.115486 +v -0.400190 0.765755 0.111377 +v -0.379381 0.786140 -0.105586 +v -0.073714 0.951211 -0.073714 +v -0.100259 0.978466 -0.058974 +v -0.103696 0.951211 0.000000 +v -0.105586 0.786140 0.379381 +v -0.218547 0.750806 0.372103 +v -0.210772 0.765755 0.358865 +v -0.090752 0.801206 0.326081 +v -0.133759 0.813615 0.227741 +v -0.130049 0.826023 0.130048 +v -0.096873 0.841089 0.056896 +v -0.061568 0.861474 0.017135 +v -0.326081 0.801206 -0.090752 +v -0.253966 0.813615 -0.070682 +v -0.176722 0.826023 -0.049184 +v -0.108029 0.841089 -0.030065 +v -0.061568 0.861474 -0.017135 +v -0.372103 0.750806 0.218547 +v -0.358865 0.765755 0.210772 +v -0.393219 0.786140 0.000000 +v -0.089770 0.951211 -0.052799 +v -0.100064 0.951211 -0.027927 +v -0.199813 0.786140 0.340206 +v -0.305360 0.750806 0.305360 +v -0.294497 0.765755 0.294497 +v -0.054655 0.888729 0.000000 +v -0.075630 0.919969 0.000000 +v -0.052735 0.888729 -0.014691 +v -0.065466 0.919969 -0.038494 +v -0.379381 0.786140 0.105586 +v -0.171740 0.801206 0.292408 +v -0.279185 0.786140 0.279184 +v -0.186892 0.813615 0.186892 +v -0.158473 0.826023 0.093076 +v -0.108029 0.841089 0.030065 +v -0.063813 0.861474 0.000000 +v -0.337972 0.801206 0.000000 +v -0.263228 0.813615 0.000000 +v -0.183167 0.826023 0.000000 +v -0.111968 0.841089 0.000000 +v -0.340206 0.786140 0.199813 +v -0.072979 0.919969 -0.020357 +v -0.239960 0.801206 0.239960 +v -0.326081 0.801206 0.090752 +v -0.292408 0.801206 0.171740 +v -0.227741 0.813615 0.133759 +v -0.176722 0.826023 0.049184 +v -0.253966 0.813615 0.070682 +v -0.526706 0.651362 -0.039883 +v -0.534329 0.646030 0.000000 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.638129 0.287158 0.000000 +v -0.631184 0.277569 0.039883 +v -0.501666 0.699221 -0.063813 +v -0.508714 0.682112 -0.071712 +v -0.611709 0.194244 0.000000 +v -0.608883 0.198681 0.039883 +v -0.517593 0.664661 0.063813 +v -0.508714 0.682112 0.071712 +v -0.631184 0.277569 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.615480 0.216617 0.063578 +v -0.615553 0.216807 -0.063813 +v -0.517593 0.664661 -0.063813 +v -0.498530 0.712498 -0.039883 +v -0.619922 0.238069 0.071790 +v -0.526706 0.651362 0.039883 +v -0.608884 0.198682 -0.039883 +v 0.605100 0.399712 0.137265 +v 0.613258 0.341675 0.154354 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.613258 0.341675 -0.154354 +v 0.605101 0.399712 -0.137265 +v 0.600960 0.444810 0.085753 +v 0.121642 0.750009 -0.437072 +v -0.000000 0.750009 -0.453012 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 -0.121642 +v -0.453012 0.750009 0.000000 +v -0.437073 0.750009 -0.121642 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.391940 0.750009 0.230197 +v -0.437073 0.750009 0.121642 +v 0.121642 0.750009 0.437072 +v -0.000000 0.750009 0.453012 +v -0.121642 0.750009 0.437072 +v 0.437073 0.750009 0.121642 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 -0.321639 +v 0.230197 0.750009 -0.391940 +v -0.121642 0.750009 -0.437072 +v 0.391939 0.750009 -0.230197 +v 0.321638 0.750009 0.321639 +v 0.230197 0.750009 0.391940 +v -0.230198 0.750009 -0.391939 +v -0.501255 0.717792 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v -0.321639 0.750009 -0.321639 +v -0.391940 0.750009 -0.230197 +v -0.498530 0.712498 0.039883 +v -0.501667 0.699221 0.063813 +v 0.617684 0.235930 -0.085941 +v 0.619427 0.283145 -0.137236 +v 0.619427 0.283145 0.137236 +vn -0.901883 0.415418 0.118168 +vn -0.905637 0.407056 0.118656 +vn -0.877041 0.418744 0.235298 +vn 0.058443 -0.998260 0.000732 +vn 0.015107 -0.999878 0.000183 +vn 0.014557 -0.949278 0.314035 +vn 0.056703 -0.947539 0.314524 +vn 0.162053 -0.986755 0.002014 +vn 0.157933 -0.933592 0.321604 +vn 0.392376 -0.919767 0.004334 +vn 0.378307 -0.856655 0.350688 +vn 0.783776 -0.620991 0.005249 +vn 0.726829 -0.553880 0.406079 +vn 0.994812 -0.101627 0.001984 +vn 0.908139 -0.082766 0.410321 +vn 0.003082 -0.939787 0.341685 +vn 0.002167 -0.619495 0.784967 +vn 0.011536 -0.679403 0.733634 +vn 0.044679 -0.675588 0.735923 +vn 0.123325 -0.652272 0.747856 +vn 0.275399 -0.556871 0.783593 +vn 0.460067 -0.316263 0.829615 +vn 0.563036 -0.041200 0.825373 +vn -0.000427 0.122166 0.992492 +vn 0.000397 0.003632 0.999969 +vn 0.002869 0.011841 0.999908 +vn 0.004852 0.029298 0.999542 +vn -0.008179 0.053499 0.998505 +vn -0.046510 0.041536 0.998047 +vn -0.039155 0.003113 0.999207 +vn -0.850551 0.473769 -0.228217 +vn -0.897885 0.424177 -0.117649 +vn -0.880886 0.473281 0.000000 +vn -0.013611 0.682394 0.730827 +vn -0.053896 0.680441 0.730796 +vn -0.147557 0.656789 0.739464 +vn -0.325968 0.560564 0.761223 +vn -0.537645 0.315806 0.781762 +vn -0.611530 0.029939 0.790613 +vn -0.904172 0.427137 0.000000 +vn -0.897885 0.424146 0.117618 +vn -0.020112 0.949461 0.313150 +vn -0.081820 0.945433 0.315287 +vn -0.227699 0.916379 0.329173 +vn -0.504196 0.785302 0.359203 +vn -0.810633 0.443220 0.382611 +vn -0.921232 0.039705 0.386944 +vn -0.020569 0.949400 -0.313334 +vn -0.021729 0.999756 -0.000092 +vn -0.004242 0.950468 -0.310770 +vn -0.088260 0.996094 -0.000488 +vn -0.246895 0.969024 -0.001343 +vn -0.549730 0.835322 -0.002350 +vn -0.880673 0.473647 -0.001984 +vn -0.999084 0.042146 -0.000610 +vn -0.877041 0.418744 -0.235298 +vn -0.920286 0.391156 0.000000 +vn -0.905637 0.407056 -0.118656 +vn -0.083132 0.945006 -0.316202 +vn -0.230201 0.914823 -0.331797 +vn -0.505570 0.782800 -0.362743 +vn -0.808710 0.444960 -0.384625 +vn -0.920835 0.042055 -0.387646 +vn -0.897885 0.424146 -0.117618 +vn -0.901883 0.415448 -0.118168 +vn -0.014161 0.682394 -0.730796 +vn -0.055361 0.680074 -0.731010 +vn -0.150029 0.655660 -0.739982 +vn -0.327616 0.560594 -0.760491 +vn -0.537431 0.320933 -0.779809 +vn -0.611988 0.033387 -0.790155 +vn 0.015168 -0.949339 -0.313852 +vn 0.011902 -0.679403 -0.733634 +vn 0.003265 -0.939817 -0.341594 +vn 0.000183 0.004212 -0.999969 +vn 0.003510 0.014008 -0.999878 +vn 0.005921 0.035951 -0.999329 +vn -0.010132 0.064333 -0.997864 +vn -0.051576 0.048463 -0.997467 +vn -0.041597 0.003998 -0.999115 +vn 0.003082 -0.620106 -0.784478 +vn -0.000031 0.122440 -0.992462 +vn -0.897885 0.424177 0.117649 +vn 0.046449 -0.674398 -0.736869 +vn 0.125980 -0.648946 -0.750298 +vn 0.275430 -0.552477 -0.786676 +vn 0.455519 -0.320536 -0.830500 +vn 0.561693 -0.046480 -0.826014 +vn -0.888668 0.391644 0.238441 +vn 0.058046 -0.947630 -0.314005 +vn 0.159948 -0.933836 -0.319865 +vn 0.380169 -0.857753 -0.345927 +vn 0.725547 -0.560930 -0.398602 +vn 0.908597 -0.089236 -0.407971 +vn 0.003235 -0.999969 0.000031 +vn 0.973144 0.230110 0.000824 +vn 0.890896 0.211737 0.401776 +vn 0.912900 0.408094 0.002533 +vn 0.836970 0.380932 0.392834 +vn 0.829035 0.559160 0.003784 +vn 0.764519 0.528550 0.368969 +vn 0.718650 0.695334 0.003937 +vn 0.668294 0.663717 0.335917 +vn 0.579577 0.814905 0.002838 +vn 0.542650 0.779687 0.312357 +vn 0.495163 0.868770 0.002258 +vn 0.458052 0.820643 0.341624 +vn 0.561205 0.137028 0.816218 +vn 0.532029 0.253456 0.807886 +vn 0.497543 0.363445 0.787591 +vn 0.449538 0.472060 0.758293 +vn 0.373669 0.563555 0.736686 +vn 0.289041 0.531114 0.796442 +vn -0.023225 -0.005249 0.999695 +vn -0.016785 -0.010254 0.999786 +vn -0.011444 -0.012940 0.999847 +vn -0.009796 -0.013276 0.999847 +vn -0.014801 -0.013916 0.999786 +vn -0.089755 -0.176122 0.980255 +vn -0.585772 -0.152379 0.795984 +vn -0.538896 -0.288766 0.791314 +vn -0.484146 -0.407910 0.774071 +vn -0.424635 -0.509781 0.748161 +vn -0.355907 -0.584765 0.728935 +vn -0.889828 -0.237159 0.389782 +vn -0.808740 -0.446852 0.382366 +vn -0.702475 -0.613269 0.361095 +vn -0.590625 -0.734855 0.333293 +vn -0.483291 -0.816767 0.315104 +vn -0.912076 0.409955 0.000000 +vn -0.965606 -0.259987 -0.000458 +vn -0.872433 -0.488693 -0.001465 +vn -0.748436 -0.663167 -0.002197 +vn -0.621601 -0.783288 -0.002136 +vn -0.507065 -0.861873 -0.001251 +vn -0.438215 -0.854366 0.279183 +vn -0.456130 -0.889889 -0.000732 +vn -0.889126 -0.238868 -0.390332 +vn -0.807001 -0.448531 -0.384075 +vn -0.700980 -0.613392 -0.363750 +vn -0.590442 -0.733757 -0.336039 +vn -0.484787 -0.815332 -0.316477 +vn -0.440962 -0.852931 -0.279305 +vn -0.359691 -0.584185 -0.727531 +vn -0.358074 -0.682241 -0.637410 +vn -0.585467 -0.154668 -0.795770 +vn -0.538499 -0.291696 -0.790490 +vn -0.484512 -0.409772 -0.772851 +vn -0.426496 -0.510056 -0.746910 +vn -0.909543 -0.399274 -0.115207 +vn -0.971191 -0.204688 -0.121891 +vn -0.912931 -0.326609 -0.244606 +vn -0.020478 -0.017853 -0.999603 +vn -0.024537 -0.005737 -0.999664 +vn -0.020844 -0.012207 -0.999695 +vn -0.017548 -0.016846 -0.999695 +vn -0.016724 -0.018097 -0.999695 +vn -0.909116 -0.400311 0.115055 +vn -0.873775 -0.472610 0.114475 +vn -0.795892 -0.566485 0.213538 +vn -0.353069 -0.684103 0.638203 +vn 0.559679 0.139714 -0.816828 +vn 0.528581 0.255501 -0.809473 +vn 0.494217 0.362987 -0.789911 +vn 0.449049 0.469283 -0.760308 +vn 0.378246 0.560869 -0.736412 +vn -0.091983 -0.174383 -0.980346 +vn 0.295267 0.530625 -0.794488 +vn 0.890500 0.214759 -0.401044 +vn 0.836634 0.384075 -0.390515 +vn 0.765191 0.530198 -0.365123 +vn 0.671041 0.663228 -0.331339 +vn 0.547929 0.777642 -0.308206 +vn 0.464522 0.818842 -0.337199 +vn 0.931486 0.265572 -0.248543 +vn 0.939543 0.342357 0.000000 +vn 0.947539 0.295114 -0.122684 +vn -0.351421 0.936186 0.001953 +vn -0.144444 0.989502 0.003174 +vn -0.126743 0.878811 0.459975 +vn -0.716758 0.697287 -0.000946 +vn -0.299997 0.838313 0.455214 +vn -0.621876 0.660207 0.421155 +vn -0.901822 0.432081 -0.004517 +vn -0.807031 0.443434 0.389904 +vn -0.930204 0.366863 -0.008484 +vn -0.824549 0.383312 0.416059 +vn -0.850673 0.525529 -0.011628 +vn -0.722465 0.508988 0.467910 +vn -0.668447 0.743645 -0.011139 +vn -0.531449 0.686514 0.496170 +vn -0.116459 0.505448 0.854946 +vn -0.258400 0.470656 0.843593 +vn -0.407605 0.396985 0.822321 +vn -0.450270 0.352367 0.820399 +vn -0.385876 0.395734 0.833338 +vn -0.270669 0.487838 0.829890 +vn 0.141606 -0.001190 0.989898 +vn -0.067690 0.525346 0.848170 +vn 0.989593 0.100253 0.103122 +vn 0.970244 0.213324 0.114475 +vn 0.960418 0.152654 0.232917 +vn 0.241829 0.092502 0.965880 +vn 0.209296 0.170660 0.962828 +vn 0.096194 0.178625 0.979186 +vn 0.009552 0.154332 0.987945 +vn -0.000122 0.151952 0.988372 +vn 0.361248 -0.477279 0.801019 +vn 0.607929 -0.282540 0.741997 +vn 0.679220 -0.106754 0.726096 +vn 0.583911 -0.078524 0.807978 +vn 0.402722 -0.205237 0.891995 +vn 0.279519 -0.338694 0.898404 +vn 0.488601 -0.768700 0.412671 +vn 0.784570 -0.501511 0.364544 +vn 0.893918 -0.279611 0.350291 +vn 0.861415 -0.285287 0.420179 +vn 0.679373 -0.540452 0.496323 +vn 0.458327 -0.754540 0.469588 +vn 0.524155 -0.851588 -0.000153 +vn 0.827143 -0.561968 0.001679 +vn 0.943205 -0.332133 0.003479 +vn 0.933256 -0.359081 0.005737 +vn 0.756859 -0.653493 0.006470 +vn 0.492843 -0.870083 0.004120 +vn 0.322489 -0.946562 -0.001129 +vn 0.912839 -0.326609 0.244942 +vn 0.824396 -0.565996 0.000000 +vn 0.894162 -0.447676 0.000000 +vn 0.486557 -0.770501 -0.411756 +vn 0.783990 -0.504074 -0.362285 +vn 0.895199 -0.281899 -0.345134 +vn 0.863735 -0.289010 -0.412824 +vn 0.682119 -0.544267 -0.488296 +vn 0.461928 -0.758202 -0.460128 +vn 0.357463 -0.479141 -0.801599 +vn 0.605884 -0.285867 -0.742393 +vn 0.679739 -0.108646 -0.725333 +vn 0.583636 -0.077883 -0.808222 +vn 0.401440 -0.199225 -0.893918 +vn 0.281961 -0.330638 -0.900632 +vn 0.135228 -0.002380 -0.990783 +vn 0.235755 0.091128 -0.967498 +vn 0.200720 0.170629 -0.964660 +vn 0.086123 0.184576 -0.979003 +vn 0.000671 0.174322 -0.984680 +vn -0.007141 0.169012 -0.985565 +vn 0.966613 -0.042848 -0.252602 +vn 0.960418 0.152654 -0.232917 +vn 0.989593 0.100223 -0.103092 +vn -0.119297 0.503342 -0.855770 +vn -0.261269 0.472793 -0.841517 +vn -0.414075 0.399792 -0.817713 +vn -0.459700 0.357036 -0.813105 +vn -0.394024 0.408490 -0.823298 +vn -0.277871 0.487381 -0.827754 +vn -0.072207 0.520127 -0.851009 +vn -0.298654 0.840297 -0.452376 +vn -0.617512 0.663961 -0.421613 +vn -0.801324 0.450209 -0.393872 +vn -0.819422 0.389691 -0.420270 +vn -0.721274 0.506912 -0.471969 +vn -0.538347 0.670644 -0.510239 +vn -0.482009 0.876125 -0.005127 +vn -0.394635 0.815363 0.423536 +vn -0.321909 0.946745 -0.002594 +vn -0.255287 0.921995 0.291086 +vn 0.004242 0.999969 0.000397 +vn -0.002960 0.999939 -0.010102 +vn 0.853450 0.521073 -0.007050 +vn 0.392041 0.688986 -0.609546 +vn 0.805170 -0.592517 -0.023621 +vn 0.588763 -0.206122 -0.781579 +vn 0.681478 -0.731040 -0.033296 +vn 0.485031 -0.441237 -0.754967 +vn -0.206824 0.638203 0.741539 +vn -0.129490 0.862056 0.489944 +vn -0.033418 0.999176 0.022340 +vn 0.047700 0.864040 -0.501114 +vn 0.099307 0.538743 -0.836573 +vn 0.053560 0.251839 -0.966277 +vn 0.020112 0.322611 0.946287 +vn 0.021943 0.748894 0.662282 +vn -0.025941 0.995605 0.089908 +vn -0.059175 0.930876 -0.360424 +vn -0.080172 0.784448 -0.614948 +vn -0.142582 0.557604 -0.817743 +vn 0.281747 -0.174993 0.943388 +vn 0.303903 0.444136 0.842830 +vn 0.034333 0.983764 0.175970 +vn -0.113865 0.956420 -0.268777 +vn -0.155339 0.858852 -0.488021 +vn -0.207404 0.641865 -0.738182 +vn 0.467238 -0.683187 0.561144 +vn 0.699515 0.004364 0.714560 +vn 0.355296 0.891934 0.279641 +vn -0.170354 0.971465 -0.164861 +vn -0.245552 0.901181 -0.357097 +vn -0.248726 0.651082 -0.717063 +vn 0.494430 -0.869167 0.006317 +vn 0.933134 -0.358898 0.019868 +vn 0.703146 0.710685 0.021790 +vn -0.203650 0.978942 -0.012574 +vn -0.326456 0.942869 -0.066073 +vn -0.397595 0.857082 -0.327525 +vn 0.460616 -0.712546 -0.529221 +vn 0.695486 -0.098544 -0.711722 +vn 0.397534 0.853816 -0.336070 +vn -0.198248 0.963439 0.180151 +vn -0.306833 0.888516 0.341075 +vn -0.393689 0.807672 0.438887 +vn 0.276559 -0.211951 -0.937315 +vn 0.294626 0.366161 -0.882656 +vn 0.046632 0.973235 -0.224982 +vn -0.146733 0.912168 0.382611 +vn -0.202643 0.700797 0.683950 +vn -0.232673 0.506485 0.830226 +vn 0.011689 0.309397 -0.950835 +vn 0.013245 0.708640 -0.705435 +vn -0.027589 0.995758 -0.087680 +vn -0.047395 0.829371 0.556658 +vn -0.015259 0.386608 0.922086 +vn 0.004639 0.119510 0.992798 +vn -0.211035 0.631001 -0.746513 +vn -0.138768 0.848781 -0.510147 +vn -0.024995 0.999664 -0.001190 +vn 0.120426 0.724570 0.678579 +vn 0.260750 0.006531 0.965361 +vn 0.272500 -0.255898 0.927488 +vn -0.395581 0.809961 -0.432905 +vn -0.258827 0.918851 -0.297800 +vn 0.004730 0.999878 0.013031 +vn 0.466628 0.599780 0.649983 +vn 0.621937 -0.400861 0.672628 +vn 0.551042 -0.592181 0.587878 +vn 0.649068 0.384991 -0.656087 +vn 0.055971 0.691214 0.720450 +vn -0.115940 0.804590 0.582354 +vn -0.262185 0.897946 0.353435 +vn -0.341655 0.885006 -0.316263 +vn -0.081423 0.793085 -0.603626 +vn -0.155675 0.857753 -0.489883 +vn 0.728690 0.365978 0.578784 +vn 0.318674 0.539384 0.779382 +vn 0.953551 0.300150 -0.024415 +vn -0.133976 0.836818 -0.530808 +vn 0.095401 0.667959 -0.738029 +vn 0.000000 0.999969 0.000000 +vn -0.992523 -0.122013 0.000000 +vn -0.937346 -0.348338 0.000000 +vn -0.905148 -0.348827 -0.242836 +vn -0.958617 -0.122227 -0.257057 +vn -0.832057 0.554674 0.000000 +vn -0.803217 0.555376 -0.215339 +vn -0.048616 0.998810 0.000000 +vn -0.046236 0.998840 -0.012726 +vn 0.544267 0.838893 0.000000 +vn 0.525376 0.839106 0.140843 +vn 0.783471 0.621387 0.000000 +vn 0.756371 0.621845 0.202918 +vn 0.880886 0.473281 0.000000 +vn 0.850551 0.473769 0.228217 +vn -0.810907 -0.349376 -0.469375 +vn -0.859004 -0.122410 -0.497085 +vn -0.719657 0.555559 -0.416425 +vn -0.041749 0.998810 -0.024415 +vn 0.470077 0.839625 0.272011 +vn 0.677236 0.622608 0.391980 +vn 0.761803 0.474471 0.440962 +vn -0.662465 -0.349620 -0.662465 +vn -0.701773 -0.122440 -0.701773 +vn -0.587878 0.555650 -0.587878 +vn -0.034272 0.998810 -0.034272 +vn 0.383831 0.839808 0.383831 +vn 0.553148 0.622913 0.553148 +vn 0.622303 0.474776 0.622303 +vn -0.469375 -0.349376 -0.810907 +vn -0.497085 -0.122379 -0.859004 +vn -0.416425 0.555559 -0.719657 +vn -0.024415 0.998810 -0.041749 +vn 0.272011 0.839625 0.470077 +vn 0.391980 0.622608 0.677236 +vn 0.440962 0.474471 0.761834 +vn -0.242836 -0.348827 -0.905148 +vn -0.257057 -0.122227 -0.958617 +vn -0.215339 0.555376 -0.803217 +vn -0.012726 0.998840 -0.046205 +vn 0.140843 0.839106 0.525376 +vn 0.202918 0.621845 0.756371 +vn 0.228217 0.473769 0.850551 +vn 0.000000 -0.348338 -0.937346 +vn 0.000000 -0.122013 -0.992523 +vn 0.000000 0.554674 -0.832057 +vn 0.000000 0.998810 -0.048616 +vn 0.000000 0.838893 0.544267 +vn 0.000000 0.621387 0.783471 +vn 0.000000 0.473281 0.880886 +vn 0.242836 -0.348827 -0.905148 +vn 0.257057 -0.122227 -0.958617 +vn 0.215308 0.555376 -0.803217 +vn 0.012726 0.998840 -0.046205 +vn -0.140843 0.839106 0.525376 +vn -0.202918 0.621845 0.756340 +vn -0.228217 0.473769 0.850551 +vn 0.469375 -0.349376 -0.810907 +vn 0.497085 -0.122379 -0.859004 +vn 0.416425 0.555559 -0.719657 +vn 0.024415 0.998810 -0.041749 +vn -0.272011 0.839625 0.470077 +vn -0.391980 0.622608 0.677236 +vn -0.440962 0.474502 0.761803 +vn 0.662465 -0.349620 -0.662465 +vn 0.701773 -0.122471 -0.701773 +vn 0.587878 0.555650 -0.587878 +vn 0.034272 0.998810 -0.034272 +vn -0.383831 0.839808 0.383831 +vn -0.553148 0.622913 0.553148 +vn -0.622303 0.474776 0.622303 +vn 0.810907 -0.349406 -0.469375 +vn 0.859004 -0.122379 -0.497085 +vn 0.719657 0.555559 -0.416425 +vn 0.041749 0.998810 -0.024415 +vn -0.470077 0.839625 0.272011 +vn -0.677236 0.622608 0.391980 +vn -0.761803 0.474471 0.440962 +vn 0.905148 -0.348827 -0.242836 +vn 0.958617 -0.122227 -0.257057 +vn 0.803217 0.555376 -0.215339 +vn 0.046205 0.998840 -0.012726 +vn -0.525376 0.839106 0.140843 +vn -0.756340 0.621876 0.202918 +vn -0.850551 0.473769 0.228217 +vn 0.937346 -0.348338 0.000000 +vn 0.992523 -0.122013 0.000000 +vn 0.832026 0.554674 0.000000 +vn 0.048616 0.998810 0.000000 +vn -0.544267 0.838893 0.000000 +vn -0.783471 0.621387 0.000000 +vn 0.905148 -0.348827 0.242836 +vn 0.958617 -0.122227 0.257057 +vn 0.803217 0.555376 0.215308 +vn 0.046205 0.998840 0.012726 +vn -0.525376 0.839106 -0.140843 +vn -0.756340 0.621876 -0.202918 +vn 0.810907 -0.349406 0.469375 +vn 0.859004 -0.122379 0.497085 +vn 0.719657 0.555559 0.416425 +vn 0.041749 0.998810 0.024415 +vn -0.470077 0.839625 -0.272011 +vn -0.677236 0.622608 -0.391980 +vn -0.761803 0.474471 -0.440962 +vn 0.662465 -0.349620 0.662465 +vn 0.701773 -0.122471 0.701773 +vn 0.587878 0.555650 0.587878 +vn 0.034272 0.998810 0.034272 +vn -0.383831 0.839808 -0.383831 +vn -0.553148 0.622913 -0.553148 +vn -0.622303 0.474776 -0.622303 +vn 0.469375 -0.349376 0.810907 +vn 0.497085 -0.122379 0.859004 +vn 0.416425 0.555559 0.719657 +vn 0.024415 0.998810 0.041749 +vn -0.272011 0.839625 -0.470077 +vn -0.391980 0.622608 -0.677236 +vn -0.440962 0.474471 -0.761803 +vn 0.242836 -0.348827 0.905148 +vn 0.257057 -0.122227 0.958617 +vn 0.215339 0.555376 0.803217 +vn 0.012726 0.998840 0.046205 +vn -0.140843 0.839106 -0.525376 +vn -0.202918 0.621845 -0.756371 +vn -0.228217 0.473769 -0.850551 +vn 0.000000 -0.348338 0.937346 +vn 0.000000 -0.122013 0.992523 +vn 0.000000 0.554674 0.832057 +vn 0.000000 0.998810 0.048616 +vn 0.000000 0.838893 -0.544267 +vn 0.000000 0.621387 -0.783471 +vn 0.000000 0.473281 -0.880886 +vn -0.242836 -0.348827 0.905148 +vn -0.257057 -0.122227 0.958617 +vn -0.215308 0.555376 0.803217 +vn -0.012726 0.998840 0.046205 +vn 0.140843 0.839106 -0.525376 +vn 0.202918 0.621845 -0.756371 +vn 0.228217 0.473769 -0.850551 +vn -0.469375 -0.349376 0.810907 +vn -0.497085 -0.122379 0.859004 +vn -0.416425 0.555559 0.719657 +vn -0.024415 0.998810 0.041749 +vn 0.272011 0.839625 -0.470077 +vn 0.391980 0.622608 -0.677236 +vn 0.440962 0.474471 -0.761803 +vn -0.662465 -0.349620 0.662465 +vn -0.701773 -0.122440 0.701773 +vn -0.587878 0.555650 0.587878 +vn -0.034272 0.998810 0.034272 +vn 0.383831 0.839808 -0.383831 +vn 0.553148 0.622913 -0.553148 +vn 0.622303 0.474776 -0.622303 +vn -0.810907 -0.349376 0.469375 +vn -0.859004 -0.122410 0.497085 +vn -0.719657 0.555528 0.416425 +vn -0.041749 0.998810 0.024415 +vn 0.470077 0.839625 -0.272011 +vn 0.677236 0.622639 -0.391980 +vn 0.761803 0.474471 -0.440962 +vn -0.905148 -0.348827 0.242836 +vn -0.958617 -0.122227 0.257057 +vn -0.803217 0.555376 0.215339 +vn -0.046236 0.998840 0.012726 +vn 0.525376 0.839106 -0.140843 +vn 0.756371 0.621845 -0.202918 +vn 0.850551 0.473769 -0.228217 +vn 0.908292 0.418256 0.000000 +vn 0.877041 0.418744 0.235298 +vn 0.920286 0.391156 0.000000 +vn 0.888668 0.391644 0.238441 +vn 0.907315 0.342753 0.243446 +vn 0.785638 0.419416 0.454756 +vn 0.796075 0.392285 0.460799 +vn 0.812830 0.343333 0.470504 +vn 0.931486 0.265542 0.248543 +vn 0.834162 0.266366 0.482864 +vn 0.855312 0.152379 0.495132 +vn 0.966613 -0.042848 0.252602 +vn 0.864498 -0.045808 0.500504 +vn 0.641804 0.419691 0.641804 +vn 0.650349 0.392499 0.650349 +vn 0.664052 0.343577 0.664052 +vn 0.681509 0.266579 0.681509 +vn 0.698813 0.152501 0.698813 +vn 0.706351 -0.045869 0.706351 +vn 0.454756 0.419416 0.785638 +vn 0.460799 0.392285 0.796075 +vn 0.470504 0.343333 0.812830 +vn 0.482864 0.266366 0.834162 +vn 0.495132 0.152409 0.855312 +vn 0.500504 -0.045808 0.864498 +vn 0.235298 0.418744 0.877041 +vn 0.238441 0.391644 0.888668 +vn 0.243446 0.342753 0.907315 +vn 0.249855 0.265908 0.931028 +vn 0.256172 0.152104 0.954558 +vn 0.258980 -0.045717 0.964782 +vn 0.000000 0.418256 0.908292 +vn 0.000000 0.391156 0.920286 +vn 0.000000 0.342357 0.939543 +vn 0.000000 0.265542 0.964080 +vn 0.000000 0.151891 0.988372 +vn 0.000000 -0.045656 0.998932 +vn -0.235298 0.418744 0.877041 +vn -0.238441 0.391644 0.888668 +vn -0.243446 0.342753 0.907315 +vn -0.249855 0.265877 0.931028 +vn -0.256172 0.152104 0.954558 +vn -0.258980 -0.045717 0.964782 +vn -0.454756 0.419416 0.785638 +vn -0.460799 0.392285 0.796075 +vn -0.470504 0.343333 0.812830 +vn -0.482864 0.266366 0.834162 +vn -0.495132 0.152379 0.855312 +vn -0.500504 -0.045808 0.864498 +vn -0.641804 0.419691 0.641804 +vn -0.650349 0.392499 0.650349 +vn -0.664052 0.343577 0.664052 +vn -0.681509 0.266579 0.681509 +vn -0.698813 0.152501 0.698813 +vn -0.706351 -0.045869 0.706351 +vn -0.785638 0.419416 0.454756 +vn -0.796075 0.392285 0.460799 +vn -0.812830 0.343364 0.470504 +vn -0.834162 0.266366 0.482864 +vn -0.855312 0.152379 0.495132 +vn -0.864498 -0.045808 0.500504 +vn -0.907315 0.342753 0.243446 +vn -0.931028 0.265908 0.249855 +vn -0.954558 0.152104 0.256172 +vn -0.964782 -0.045717 0.258980 +vn -0.939543 0.342357 0.000000 +vn -0.964080 0.265542 0.000000 +vn -0.988372 0.151891 0.000000 +vn -0.888668 0.391644 -0.238441 +vn -0.907315 0.342753 -0.243446 +vn -0.931028 0.265877 -0.249855 +vn -0.954558 0.152104 -0.256172 +vn -0.785638 0.419416 -0.454756 +vn -0.796075 0.392285 -0.460799 +vn -0.812830 0.343333 -0.470504 +vn -0.834162 0.266366 -0.482864 +vn -0.855312 0.152379 -0.495132 +vn -0.964782 -0.045717 -0.258980 +vn -0.864498 -0.045808 -0.500504 +vn -0.641804 0.419691 -0.641804 +vn -0.650349 0.392499 -0.650349 +vn -0.664052 0.343577 -0.664052 +vn -0.681509 0.266579 -0.681509 +vn -0.698813 0.152501 -0.698813 +vn -0.706351 -0.045869 -0.706351 +vn -0.454756 0.419416 -0.785638 +vn -0.460799 0.392285 -0.796075 +vn -0.470504 0.343333 -0.812830 +vn -0.482864 0.266366 -0.834162 +vn -0.495132 0.152379 -0.855312 +vn -0.500504 -0.045808 -0.864498 +vn -0.235298 0.418744 -0.877041 +vn -0.238441 0.391644 -0.888668 +vn -0.243446 0.342753 -0.907315 +vn -0.249855 0.265908 -0.931028 +vn -0.256172 0.152104 -0.954558 +vn -0.258980 -0.045717 -0.964782 +vn 0.000000 0.418256 -0.908292 +vn 0.000000 0.391156 -0.920286 +vn 0.000000 0.342357 -0.939543 +vn 0.000000 0.265542 -0.964080 +vn 0.000000 0.151891 -0.988372 +vn 0.000000 -0.045656 -0.998932 +vn 0.235298 0.418744 -0.877041 +vn 0.238441 0.391644 -0.888668 +vn 0.243446 0.342753 -0.907315 +vn 0.249855 0.265877 -0.931028 +vn 0.256172 0.152104 -0.954558 +vn 0.258980 -0.045717 -0.964782 +vn 0.454756 0.419416 -0.785638 +vn 0.460799 0.392285 -0.796075 +vn 0.470504 0.343333 -0.812830 +vn 0.482864 0.266366 -0.834162 +vn 0.495132 0.152379 -0.855312 +vn 0.500504 -0.045808 -0.864498 +vn 0.641804 0.419691 -0.641804 +vn 0.650349 0.392499 -0.650349 +vn 0.664052 0.343577 -0.664052 +vn 0.681509 0.266579 -0.681509 +vn 0.698813 0.152501 -0.698813 +vn 0.706351 -0.045869 -0.706351 +vn 0.785638 0.419416 -0.454756 +vn 0.796075 0.392285 -0.460799 +vn 0.812830 0.343364 -0.470504 +vn 0.834162 0.266366 -0.482864 +vn 0.855312 0.152379 -0.495132 +vn 0.864498 -0.045808 -0.500504 +vn 0.877041 0.418744 -0.235298 +vn 0.888668 0.391644 -0.238441 +vn 0.907315 0.342753 -0.243446 +vn 0.795892 -0.566485 0.213538 +vn 0.712180 -0.701987 0.000000 +vn 0.687399 -0.702445 0.184393 +vn 0.652974 -0.757347 0.000000 +vn 0.630146 -0.757805 0.169012 +vn 0.724021 -0.689749 0.000000 +vn 0.698752 -0.690329 0.187414 +vn 0.886410 -0.462874 0.000000 +vn 0.855861 -0.463454 0.229530 +vn 0.817774 -0.327158 0.473434 +vn 0.712729 -0.567248 0.412549 +vn 0.615345 -0.703146 0.356151 +vn 0.564043 -0.758446 0.326456 +vn 0.625660 -0.690939 0.362102 +vn 0.766625 -0.464125 0.443678 +vn 0.668111 -0.327403 0.668111 +vn 0.582171 -0.567522 0.582171 +vn 0.502579 -0.703421 0.502579 +vn 0.460646 -0.758660 0.460646 +vn 0.510971 -0.691183 0.510971 +vn 0.626209 -0.464370 0.626240 +vn 0.473434 -0.327158 0.817774 +vn 0.412549 -0.567248 0.712729 +vn 0.356151 -0.703146 0.615375 +vn 0.326456 -0.758446 0.564043 +vn 0.362102 -0.690939 0.625660 +vn 0.443678 -0.464125 0.766625 +vn 0.245003 -0.326609 0.912839 +vn 0.213538 -0.566485 0.795892 +vn 0.184393 -0.702445 0.687399 +vn 0.169012 -0.757805 0.630146 +vn 0.187414 -0.690329 0.698752 +vn 0.229530 -0.463454 0.855831 +vn 0.000000 -0.326243 0.945250 +vn 0.000000 -0.565996 0.824396 +vn 0.000000 -0.701987 0.712180 +vn 0.000000 -0.757347 0.652974 +vn 0.000000 -0.689749 0.724021 +vn 0.000000 -0.462905 0.886380 +vn -0.245003 -0.326609 0.912839 +vn -0.213538 -0.566485 0.795892 +vn -0.184393 -0.702445 0.687399 +vn -0.169012 -0.757805 0.630146 +vn -0.187414 -0.690329 0.698752 +vn -0.229530 -0.463454 0.855861 +vn -0.473434 -0.327158 0.817774 +vn -0.412549 -0.567248 0.712729 +vn -0.356151 -0.703146 0.615375 +vn -0.326456 -0.758446 0.564043 +vn -0.362102 -0.690939 0.625660 +vn -0.443678 -0.464125 0.766625 +vn -0.668111 -0.327403 0.668111 +vn -0.582171 -0.567522 0.582171 +vn -0.502579 -0.703421 0.502579 +vn -0.460646 -0.758660 0.460646 +vn -0.510971 -0.691183 0.510971 +vn -0.626209 -0.464370 0.626209 +vn -0.817774 -0.327158 0.473434 +vn -0.712729 -0.567248 0.412549 +vn -0.615375 -0.703146 0.356151 +vn -0.564043 -0.758446 0.326456 +vn -0.625660 -0.690939 0.362102 +vn -0.766625 -0.464125 0.443678 +vn -0.912931 -0.326609 0.244575 +vn -0.687399 -0.702445 0.184393 +vn -0.630146 -0.757805 0.169012 +vn -0.698752 -0.690329 0.187414 +vn -0.855831 -0.463485 0.229530 +vn -0.824396 -0.565996 0.000000 +vn -0.712180 -0.701987 0.000000 +vn -0.652974 -0.757347 0.000000 +vn -0.724021 -0.689749 0.000000 +vn -0.886410 -0.462874 0.000000 +vn -0.795892 -0.566485 -0.213538 +vn -0.687399 -0.702445 -0.184393 +vn -0.630146 -0.757805 -0.169012 +vn -0.698752 -0.690329 -0.187414 +vn -0.855831 -0.463454 -0.229530 +vn -0.817774 -0.327158 -0.473434 +vn -0.712729 -0.567217 -0.412549 +vn -0.615375 -0.703146 -0.356151 +vn -0.564043 -0.758446 -0.326456 +vn -0.625660 -0.690939 -0.362102 +vn -0.766625 -0.464125 -0.443678 +vn -0.668111 -0.327403 -0.668111 +vn -0.582171 -0.567522 -0.582171 +vn -0.502579 -0.703421 -0.502579 +vn -0.460646 -0.758660 -0.460646 +vn -0.510971 -0.691183 -0.510971 +vn -0.626209 -0.464370 -0.626209 +vn -0.473434 -0.327158 -0.817774 +vn -0.412549 -0.567248 -0.712729 +vn -0.356151 -0.703146 -0.615375 +vn -0.326456 -0.758446 -0.564043 +vn -0.362102 -0.690939 -0.625660 +vn -0.443678 -0.464125 -0.766625 +vn -0.245003 -0.326609 -0.912839 +vn -0.213538 -0.566485 -0.795892 +vn -0.184393 -0.702445 -0.687399 +vn -0.169012 -0.757805 -0.630146 +vn -0.187414 -0.690329 -0.698752 +vn -0.229530 -0.463454 -0.855831 +vn 0.000000 -0.326243 -0.945250 +vn 0.000000 -0.565996 -0.824396 +vn 0.000000 -0.701987 -0.712180 +vn 0.000000 -0.757347 -0.652974 +vn 0.000000 -0.689749 -0.724021 +vn 0.000000 -0.462905 -0.886380 +vn 0.245003 -0.326609 -0.912839 +vn 0.213538 -0.566485 -0.795892 +vn 0.184393 -0.702445 -0.687399 +vn 0.169012 -0.757805 -0.630146 +vn 0.187445 -0.690329 -0.698752 +vn 0.229530 -0.463454 -0.855861 +vn 0.473434 -0.327158 -0.817774 +vn 0.412549 -0.567248 -0.712729 +vn 0.356151 -0.703146 -0.615375 +vn 0.326456 -0.758446 -0.564043 +vn 0.362102 -0.690939 -0.625660 +vn 0.443678 -0.464125 -0.766625 +vn 0.668111 -0.327403 -0.668111 +vn 0.582171 -0.567522 -0.582171 +vn 0.502579 -0.703421 -0.502579 +vn 0.460646 -0.758660 -0.460646 +vn 0.510971 -0.691183 -0.510971 +vn 0.626209 -0.464370 -0.626209 +vn 0.817774 -0.327158 -0.473434 +vn 0.712729 -0.567248 -0.412549 +vn 0.615375 -0.703146 -0.356151 +vn 0.564043 -0.758446 -0.326456 +vn 0.625660 -0.690939 -0.362102 +vn 0.766625 -0.464125 -0.443678 +vn 0.912839 -0.326609 -0.244942 +vn 0.795892 -0.566485 -0.213538 +vn 0.687399 -0.702445 -0.184393 +vn 0.630146 -0.757805 -0.169012 +vn 0.698752 -0.690329 -0.187414 +vn 0.855861 -0.463454 -0.229530 +vn 0.025666 -0.999664 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.024781 -0.999664 -0.006623 +vn 0.068667 -0.997620 0.000000 +vn 0.066256 -0.997620 -0.017731 +vn 0.157170 -0.987548 0.000000 +vn 0.151677 -0.987579 -0.040620 +vn 0.373150 -0.927763 0.000000 +vn 0.360118 -0.927885 -0.096469 +vn 0.789148 -0.614154 0.000000 +vn 0.762017 -0.614399 -0.204505 +vn 0.022156 -0.999664 -0.012787 +vn 0.059236 -0.997650 -0.034272 +vn 0.135624 -0.987640 -0.078463 +vn 0.322153 -0.928129 -0.186377 +vn 0.682333 -0.615131 -0.394971 +vn 0.018067 -0.999664 -0.018067 +vn 0.048341 -0.997650 -0.048341 +vn 0.110691 -0.987640 -0.110691 +vn 0.262947 -0.928251 -0.262947 +vn 0.557329 -0.615375 -0.557329 +vn 0.012787 -0.999664 -0.022156 +vn 0.034272 -0.997650 -0.059236 +vn 0.078463 -0.987640 -0.135624 +vn 0.186377 -0.928129 -0.322153 +vn 0.394971 -0.615131 -0.682302 +vn 0.006623 -0.999664 -0.024781 +vn 0.017731 -0.997620 -0.066256 +vn 0.040620 -0.987579 -0.151677 +vn 0.096469 -0.927885 -0.360118 +vn 0.204474 -0.614399 -0.762017 +vn 0.000000 -0.999664 -0.025666 +vn 0.000000 -0.997620 -0.068667 +vn 0.000000 -0.987548 -0.157170 +vn 0.000000 -0.927763 -0.373150 +vn 0.000000 -0.614154 -0.789148 +vn -0.006623 -0.999664 -0.024781 +vn -0.017731 -0.997620 -0.066256 +vn -0.040620 -0.987579 -0.151677 +vn -0.096469 -0.927885 -0.360118 +vn -0.204474 -0.614399 -0.762017 +vn -0.012787 -0.999664 -0.022156 +vn -0.034272 -0.997650 -0.059236 +vn -0.078463 -0.987640 -0.135624 +vn -0.186377 -0.928129 -0.322153 +vn -0.394971 -0.615131 -0.682333 +vn -0.018067 -0.999664 -0.018067 +vn -0.048341 -0.997650 -0.048341 +vn -0.110691 -0.987640 -0.110691 +vn -0.262947 -0.928251 -0.262947 +vn -0.557329 -0.615375 -0.557329 +vn -0.022156 -0.999664 -0.012787 +vn -0.059236 -0.997650 -0.034272 +vn -0.135624 -0.987640 -0.078463 +vn -0.322153 -0.928129 -0.186377 +vn -0.682302 -0.615131 -0.394971 +vn -0.024781 -0.999664 -0.006623 +vn -0.066256 -0.997620 -0.017731 +vn -0.151677 -0.987579 -0.040620 +vn -0.360118 -0.927885 -0.096469 +vn -0.762017 -0.614399 -0.204474 +vn -0.025666 -0.999664 0.000000 +vn -0.068667 -0.997620 0.000000 +vn -0.157170 -0.987548 0.000000 +vn -0.373150 -0.927763 0.000000 +vn -0.789148 -0.614154 0.000000 +vn -0.024781 -0.999664 0.006623 +vn -0.066256 -0.997620 0.017731 +vn -0.151677 -0.987579 0.040620 +vn -0.360149 -0.927885 0.096469 +vn -0.762017 -0.614399 0.204474 +vn -0.022156 -0.999664 0.012787 +vn -0.059236 -0.997650 0.034272 +vn -0.135624 -0.987640 0.078463 +vn -0.322153 -0.928129 0.186377 +vn -0.682333 -0.615131 0.394971 +vn -0.018067 -0.999664 0.018067 +vn -0.048341 -0.997650 0.048341 +vn -0.110691 -0.987640 0.110691 +vn -0.262947 -0.928251 0.262947 +vn -0.557329 -0.615375 0.557329 +vn -0.012787 -0.999664 0.022156 +vn -0.034272 -0.997650 0.059236 +vn -0.078463 -0.987640 0.135624 +vn -0.186377 -0.928129 0.322153 +vn -0.394971 -0.615131 0.682302 +vn -0.006623 -0.999664 0.024781 +vn -0.017731 -0.997620 0.066256 +vn -0.040620 -0.987579 0.151677 +vn -0.096469 -0.927885 0.360118 +vn -0.204474 -0.614399 0.762017 +vn 0.000000 -0.999664 0.025666 +vn 0.000000 -0.997620 0.068667 +vn 0.000000 -0.987548 0.157170 +vn 0.000000 -0.927763 0.373150 +vn 0.000000 -0.614154 0.789148 +vn 0.006623 -0.999664 0.024781 +vn 0.017731 -0.997620 0.066256 +vn 0.040620 -0.987579 0.151677 +vn 0.096469 -0.927885 0.360149 +vn 0.204474 -0.614399 0.762017 +vn 0.012787 -0.999664 0.022156 +vn 0.034272 -0.997650 0.059236 +vn 0.078463 -0.987640 0.135624 +vn 0.186377 -0.928129 0.322153 +vn 0.394971 -0.615131 0.682333 +vn 0.018067 -0.999664 0.018067 +vn 0.048341 -0.997650 0.048341 +vn 0.110691 -0.987640 0.110691 +vn 0.262947 -0.928251 0.262947 +vn 0.557329 -0.615375 0.557329 +vn 0.022156 -0.999664 0.012787 +vn 0.059236 -0.997650 0.034272 +vn 0.135624 -0.987640 0.078463 +vn 0.322153 -0.928129 0.186346 +vn 0.682302 -0.615131 0.394971 +vn 0.024781 -0.999664 0.006623 +vn 0.066256 -0.997620 0.017731 +vn 0.151677 -0.987579 0.040620 +vn 0.360118 -0.927885 0.096469 +vn 0.762017 -0.614399 0.204474 +vn 0.464827 -0.373638 -0.802667 +vn 0.655812 -0.373882 -0.655812 +vn 0.000000 -0.372539 0.927976 +vn -0.240699 -0.373028 0.896023 +vn -0.802667 -0.373608 0.464827 +vn 0.896023 -0.372997 -0.240699 +vn -0.927976 -0.372539 0.000000 +vn 0.927976 -0.372539 0.000000 +vn 0.717063 0.696982 0.000000 +vn 0.990387 -0.138310 -0.000061 +vn 0.956694 -0.138737 0.255806 +vn 0.692129 0.697470 0.185583 +vn 0.857326 -0.139317 0.495529 +vn 0.620045 0.697653 0.358837 +vn 0.700125 -0.139531 0.700217 +vn 0.506516 0.697714 0.506546 +vn 0.495468 -0.139286 0.857356 +vn 0.358776 0.697714 0.620014 +vn 0.255867 -0.138737 0.956694 +vn 0.185583 0.697531 0.692068 +vn 0.000061 -0.138310 0.990387 +vn 0.000000 0.696982 0.717063 +vn -0.255806 -0.138737 0.956694 +vn -0.185583 0.697470 0.692129 +vn -0.495529 -0.139317 0.857326 +vn -0.358837 0.697653 0.620045 +vn -0.700217 -0.139531 0.700156 +vn -0.506546 0.697714 0.506516 +vn -0.857356 -0.139286 0.495468 +vn -0.620014 0.697714 0.358776 +vn -0.956694 -0.138737 0.255867 +vn -0.692068 0.697531 0.185583 +vn -0.990387 -0.138310 0.000061 +vn -0.717063 0.696982 0.000000 +vn -0.956694 -0.138737 -0.255806 +vn -0.692129 0.697470 -0.185583 +vn -0.857326 -0.139317 -0.495529 +vn -0.620045 0.697653 -0.358837 +vn -0.700125 -0.139531 -0.700217 +vn -0.506516 0.697714 -0.506546 +vn -0.495468 -0.139286 -0.857356 +vn -0.358776 0.697714 -0.620014 +vn -0.255867 -0.138737 -0.956694 +vn -0.185583 0.697531 -0.692068 +vn -0.000061 -0.138310 -0.990387 +vn 0.000000 0.696982 -0.717063 +vn 0.255806 -0.138737 -0.956694 +vn 0.185583 0.697470 -0.692129 +vn 0.495529 -0.139317 -0.857326 +vn 0.358837 0.697653 -0.620045 +vn 0.700217 -0.139531 -0.700156 +vn 0.506546 0.697714 -0.506516 +vn 0.857356 -0.139286 -0.495468 +vn 0.620014 0.697714 -0.358776 +vn 0.956694 -0.138737 -0.255867 +vn 0.692068 0.697531 -0.185583 +vn 0.292520 0.956236 0.000000 +vn 0.282083 0.956389 0.075686 +vn 0.177953 0.984008 0.000000 +vn 0.171606 0.984069 0.046022 +vn 0.158879 0.987274 0.000000 +vn 0.153264 0.987304 0.041078 +vn 0.217719 0.975982 0.000000 +vn 0.210059 0.976043 0.056276 +vn 0.504715 0.863277 0.000000 +vn 0.487197 0.863460 0.130558 +vn 0.693258 0.720664 0.000000 +vn 0.669057 0.721183 0.179449 +vn 0.252388 0.956511 0.146092 +vn 0.153508 0.984130 0.088839 +vn 0.137059 0.987365 0.079318 +vn 0.187872 0.976135 0.108676 +vn 0.435926 0.863887 0.252205 +vn 0.598956 0.721824 0.346660 +vn 0.206091 0.956572 0.206091 +vn 0.125340 0.984161 0.125340 +vn 0.111911 0.987396 0.111911 +vn 0.153356 0.976196 0.153356 +vn 0.355907 0.864071 0.355907 +vn 0.489151 0.722098 0.489151 +vn 0.146092 0.956511 0.252388 +vn 0.088839 0.984130 0.153508 +vn 0.079318 0.987365 0.137059 +vn 0.108676 0.976135 0.187872 +vn 0.252205 0.863887 0.435926 +vn 0.346660 0.721824 0.598956 +vn 0.075686 0.956389 0.282083 +vn 0.046022 0.984069 0.171606 +vn 0.041078 0.987304 0.153264 +vn 0.056276 0.976043 0.210059 +vn 0.130558 0.863460 0.487197 +vn 0.179449 0.721183 0.669057 +vn 0.000000 0.956236 0.292520 +vn 0.000000 0.984008 0.177953 +vn 0.000000 0.987274 0.158879 +vn 0.000000 0.975982 0.217719 +vn 0.000000 0.863277 0.504715 +vn 0.000000 0.720664 0.693258 +vn -0.075686 0.956389 0.282083 +vn -0.046022 0.984069 0.171606 +vn -0.041078 0.987304 0.153264 +vn -0.056276 0.976043 0.210059 +vn -0.130558 0.863460 0.487197 +vn -0.179449 0.721183 0.669057 +vn -0.146092 0.956511 0.252388 +vn -0.088839 0.984130 0.153508 +vn -0.079318 0.987365 0.137059 +vn -0.108676 0.976135 0.187872 +vn -0.252205 0.863887 0.435926 +vn -0.346660 0.721824 0.598956 +vn -0.206091 0.956572 0.206091 +vn -0.125340 0.984161 0.125340 +vn -0.111911 0.987396 0.111911 +vn -0.153356 0.976196 0.153356 +vn -0.355907 0.864071 0.355907 +vn -0.489151 0.722098 0.489151 +vn -0.252388 0.956511 0.146092 +vn -0.153508 0.984130 0.088839 +vn -0.137059 0.987365 0.079318 +vn -0.187872 0.976135 0.108676 +vn -0.435926 0.863887 0.252205 +vn -0.598956 0.721824 0.346660 +vn -0.282083 0.956389 0.075686 +vn -0.171606 0.984069 0.046022 +vn -0.153264 0.987304 0.041078 +vn -0.210059 0.976043 0.056276 +vn -0.487197 0.863460 0.130558 +vn -0.669057 0.721183 0.179449 +vn -0.292520 0.956236 0.000000 +vn -0.177953 0.984008 0.000000 +vn -0.158879 0.987274 0.000000 +vn -0.217719 0.975982 0.000000 +vn -0.504715 0.863277 0.000000 +vn -0.693258 0.720664 0.000000 +vn -0.282083 0.956389 -0.075686 +vn -0.171606 0.984069 -0.046022 +vn -0.153264 0.987304 -0.041078 +vn -0.210059 0.976043 -0.056276 +vn -0.487197 0.863460 -0.130558 +vn -0.669057 0.721183 -0.179449 +vn -0.252388 0.956511 -0.146092 +vn -0.153508 0.984130 -0.088839 +vn -0.137059 0.987365 -0.079318 +vn -0.187872 0.976135 -0.108676 +vn -0.435926 0.863887 -0.252205 +vn -0.598956 0.721824 -0.346660 +vn -0.206091 0.956572 -0.206091 +vn -0.125340 0.984161 -0.125340 +vn -0.111911 0.987396 -0.111911 +vn -0.153356 0.976196 -0.153356 +vn -0.355907 0.864071 -0.355907 +vn -0.489151 0.722098 -0.489151 +vn -0.146092 0.956511 -0.252388 +vn -0.088839 0.984130 -0.153508 +vn -0.079318 0.987365 -0.137059 +vn -0.108676 0.976135 -0.187872 +vn -0.252205 0.863887 -0.435926 +vn -0.346660 0.721824 -0.598956 +vn -0.075686 0.956389 -0.282083 +vn -0.046022 0.984069 -0.171606 +vn -0.041078 0.987304 -0.153264 +vn -0.056276 0.976043 -0.210059 +vn -0.130558 0.863460 -0.487197 +vn -0.179449 0.721183 -0.669057 +vn 0.000000 0.956236 -0.292520 +vn 0.000000 0.984008 -0.177953 +vn 0.000000 0.987274 -0.158879 +vn 0.000000 0.975982 -0.217719 +vn 0.000000 0.863277 -0.504715 +vn 0.000000 0.720664 -0.693258 +vn 0.075686 0.956389 -0.282083 +vn 0.046022 0.984069 -0.171606 +vn 0.041078 0.987304 -0.153264 +vn 0.056276 0.976043 -0.210059 +vn 0.130558 0.863460 -0.487197 +vn 0.179449 0.721183 -0.669057 +vn 0.146092 0.956511 -0.252388 +vn 0.088839 0.984130 -0.153508 +vn 0.079318 0.987365 -0.137059 +vn 0.108676 0.976135 -0.187872 +vn 0.252205 0.863887 -0.435926 +vn 0.346660 0.721824 -0.598956 +vn 0.206091 0.956572 -0.206091 +vn 0.125340 0.984161 -0.125340 +vn 0.111911 0.987396 -0.111911 +vn 0.153356 0.976196 -0.153356 +vn 0.355907 0.864071 -0.355907 +vn 0.489151 0.722098 -0.489151 +vn 0.252388 0.956511 -0.146092 +vn 0.153508 0.984130 -0.088839 +vn 0.137059 0.987365 -0.079318 +vn 0.187872 0.976135 -0.108676 +vn 0.435926 0.863887 -0.252205 +vn 0.598956 0.721824 -0.346660 +vn 0.282083 0.956389 -0.075686 +vn 0.171606 0.984069 -0.046022 +vn 0.153264 0.987304 -0.041078 +vn 0.210059 0.976043 -0.056276 +vn 0.487197 0.863460 -0.130558 +vn 0.669057 0.721183 -0.179449 +vn 0.363842 0.931455 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.351451 0.931516 0.093509 +vn 0.968261 0.249916 0.000000 +vn 0.935423 0.249763 0.250130 +vn 0.842860 -0.538102 0.000000 +vn 0.813959 -0.538713 0.217292 +vn 0.786767 -0.617206 -0.000031 +vn 0.759514 -0.618000 0.202857 +vn 0.314432 0.931791 0.181280 +vn 0.838404 0.249855 0.484359 +vn 0.729026 -0.539720 0.420911 +vn 0.680013 -0.619068 0.392743 +vn 0.256386 0.931913 0.256417 +vn 0.684652 0.249886 0.684652 +vn 0.595050 -0.540147 0.595050 +vn 0.555010 -0.619526 0.555040 +vn 0.181280 0.931791 0.314432 +vn 0.484359 0.249825 0.838404 +vn 0.420881 -0.539720 0.729026 +vn 0.392712 -0.619098 0.680013 +vn 0.093509 0.931516 0.351451 +vn 0.250160 0.249763 0.935423 +vn 0.217322 -0.538713 0.813959 +vn 0.202887 -0.618030 0.759484 +vn 0.000000 0.931455 0.363842 +vn 0.000000 0.249916 0.968261 +vn 0.000000 -0.538102 0.842860 +vn 0.000031 -0.617206 0.786767 +vn -0.093509 0.931516 0.351451 +vn -0.250130 0.249763 0.935423 +vn -0.217292 -0.538682 0.813959 +vn -0.202857 -0.618000 0.759514 +vn -0.181280 0.931791 0.314432 +vn -0.484359 0.249855 0.838404 +vn -0.420911 -0.539720 0.729026 +vn -0.392743 -0.619068 0.680013 +vn -0.256417 0.931913 0.256386 +vn -0.684652 0.249886 0.684652 +vn -0.595050 -0.540147 0.595050 +vn -0.555040 -0.619526 0.555010 +vn -0.314432 0.931791 0.181280 +vn -0.838404 0.249825 0.484359 +vn -0.729026 -0.539720 0.420881 +vn -0.680013 -0.619098 0.392712 +vn -0.351451 0.931516 0.093509 +vn -0.935423 0.249763 0.250160 +vn -0.813959 -0.538713 0.217292 +vn -0.759484 -0.618030 0.202887 +vn -0.363842 0.931455 0.000000 +vn -0.968261 0.249916 0.000000 +vn -0.842860 -0.538102 0.000000 +vn -0.786767 -0.617206 0.000031 +vn -0.351451 0.931516 -0.093509 +vn -0.935423 0.249763 -0.250130 +vn -0.813959 -0.538713 -0.217292 +vn -0.759514 -0.618000 -0.202857 +vn -0.314432 0.931791 -0.181280 +vn -0.838404 0.249855 -0.484359 +vn -0.729026 -0.539720 -0.420911 +vn -0.680013 -0.619068 -0.392743 +vn -0.256386 0.931913 -0.256417 +vn -0.684652 0.249886 -0.684652 +vn -0.595050 -0.540147 -0.595050 +vn -0.555010 -0.619526 -0.555040 +vn -0.181280 0.931791 -0.314432 +vn -0.484359 0.249825 -0.838404 +vn -0.420881 -0.539720 -0.729026 +vn -0.392712 -0.619098 -0.680013 +vn -0.093509 0.931516 -0.351451 +vn -0.250160 0.249763 -0.935423 +vn -0.217322 -0.538713 -0.813959 +vn -0.202887 -0.618030 -0.759484 +vn 0.000000 0.931455 -0.363842 +vn 0.000000 0.249916 -0.968261 +vn 0.000000 -0.538102 -0.842860 +vn -0.000031 -0.617206 -0.786767 +vn 0.093509 0.931516 -0.351451 +vn 0.250130 0.249763 -0.935423 +vn 0.217292 -0.538682 -0.813959 +vn 0.202857 -0.618000 -0.759514 +vn 0.181280 0.931791 -0.314432 +vn 0.484359 0.249855 -0.838404 +vn 0.420911 -0.539720 -0.729026 +vn 0.392743 -0.619068 -0.680013 +vn 0.256417 0.931913 -0.256386 +vn 0.684652 0.249886 -0.684652 +vn 0.595050 -0.540147 -0.595050 +vn 0.555040 -0.619526 -0.555010 +vn 0.314432 0.931791 -0.181280 +vn 0.838404 0.249825 -0.484359 +vn 0.729026 -0.539720 -0.420881 +vn 0.680013 -0.619098 -0.392712 +vn 0.351451 0.931516 -0.093509 +vn 0.935423 0.249763 -0.250160 +vn 0.813959 -0.538713 -0.217292 +vn 0.759484 -0.618030 -0.202887 +vn -0.354198 0.930296 -0.095187 +vn 0.095187 0.930296 0.354198 +vn 0.354198 0.930296 0.095187 +vn 0.183721 0.930387 0.317179 +vn -0.183721 0.930387 -0.317179 +vn -0.367443 0.930021 0.000000 +vn -0.183721 0.930387 0.317179 +vn 0.367412 0.930021 0.000000 +vn -0.317179 0.930387 0.183721 +vn -0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 -0.367443 +vn -0.354198 0.930296 0.095187 +vn 0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 0.367443 +vn -0.317179 0.930387 -0.183721 +vn 0.317179 0.930387 -0.183721 +vn -0.095187 0.930296 0.354198 +vn 0.317179 0.930387 0.183721 +vn 0.354198 0.930296 -0.095187 +vn 0.183721 0.930387 -0.317179 +vn -0.034730 0.999390 0.000000 +vn 0.033479 0.999390 -0.009003 +vn 0.034730 0.999390 0.000000 +vn 0.009003 0.999390 -0.033479 +vn 0.000000 0.999390 -0.034730 +vn -0.259163 0.930387 0.259163 +vn -0.017335 0.999390 0.029939 +vn 0.947539 0.295083 0.122654 +vn -0.004486 0.999969 0.000000 +vn -0.004151 0.950468 0.310739 +vn -0.003021 0.719291 0.694662 +vn -0.998688 0.050722 0.000000 +vn -0.003143 0.719321 -0.694632 +vn 0.970214 0.213324 -0.114505 +vn -0.136235 0.879482 -0.455947 +vn 0.949858 0.312662 0.000000 +vn 0.055757 -0.017579 -0.998260 +vn 0.201300 -0.540880 -0.816645 +vn 0.974456 -0.186071 -0.125645 +vn 0.988098 -0.096286 0.119938 +vn 0.974456 -0.186041 0.125614 +vn -0.879574 -0.475723 0.000000 +vn -0.873775 -0.472610 -0.114475 +vn 0.988067 -0.096286 -0.119938 +vn 0.295480 -0.855464 -0.425214 +vn -0.976196 -0.174993 -0.127903 +vn -0.971007 -0.205725 0.121677 +vn -0.976196 -0.174963 0.127903 +vn -0.976196 -0.174993 0.127903 +vn 0.896054 -0.372997 0.240699 +vn -0.802667 -0.373638 -0.464827 +vn -0.655812 -0.373852 -0.655812 +vn -0.240699 -0.373028 -0.896023 +vn -0.464827 -0.373638 -0.802667 +vn -0.896023 -0.373028 0.240699 +vn 0.000000 -0.372539 -0.927976 +vn -0.655812 -0.373852 0.655812 +vn 0.240699 -0.373028 0.896023 +vn -0.896023 -0.373028 -0.240699 +vn 0.802667 -0.373638 -0.464827 +vn 0.655812 -0.373882 0.655812 +vn 0.464827 -0.373638 0.802667 +vn -0.464827 -0.373638 0.802667 +vn 0.240699 -0.373028 -0.896023 +vn 0.802667 -0.373638 0.464827 +vn -0.033479 0.999390 0.009003 +vn -0.259163 0.930387 -0.259163 +vn -0.024445 0.999390 -0.024445 +vn -0.029939 0.999390 -0.017335 +vn 0.259163 0.930387 -0.259163 +vn 0.024445 0.999390 -0.024445 +vn 0.017335 0.999390 -0.029939 +vn 0.029939 0.999390 -0.017335 +vn 0.033479 0.999390 0.009003 +vn -0.009003 0.999390 0.033479 +vn 0.000000 0.999390 0.034730 +vn -0.017335 0.999390 -0.029939 +vn 0.259163 0.930387 0.259163 +vn 0.029939 0.999390 0.017335 +vn -0.009003 0.999390 -0.033479 +vn 0.024445 0.999390 0.024445 +vn 0.017335 0.999390 0.029939 +vn 0.009003 0.999390 0.033479 +vn -0.033479 0.999390 -0.009003 +vn -0.024445 0.999390 0.024445 +vn -0.029939 0.999390 0.017335 +vn 0.055757 -0.017579 0.998260 +vn 0.294198 -0.855403 0.426252 +vn 0.201300 -0.540880 0.816614 +s 1 +f 34//1 1243//2 593//3 +f 52//4 27//5 40//6 +f 52//4 40//6 65//7 +f 77//8 52//4 65//7 +f 77//8 65//7 84//9 +f 107//10 77//8 84//9 +f 107//10 84//9 85//11 +f 115//12 107//10 85//11 +f 115//12 85//11 99//13 +f 129//14 115//12 99//13 +f 129//14 99//13 128//15 +f 1252//16 36//17 40//6 +f 65//7 40//6 64//18 +f 65//7 64//18 58//19 +f 84//9 65//7 58//19 +f 84//9 58//19 59//20 +f 85//11 84//9 59//20 +f 85//11 59//20 70//21 +f 99//13 85//11 70//21 +f 99//13 70//21 98//22 +f 128//15 99//13 98//22 +f 128//15 98//22 114//23 +f 1244//24 33//25 64//18 +f 58//19 64//18 33//25 +f 58//19 33//25 35//26 +f 59//20 58//19 35//26 +f 59//20 35//26 45//27 +f 70//21 59//20 45//27 +f 70//21 45//27 69//28 +f 98//22 70//21 69//28 +f 98//22 69//28 83//29 +f 114//23 98//22 83//29 +f 114//23 83//29 113//30 +f 553//31 1//32 566//33 +f 35//26 33//25 20//34 +f 35//26 20//34 24//35 +f 45//27 35//26 24//35 +f 45//27 24//35 44//36 +f 69//28 45//27 44//36 +f 69//28 44//36 57//37 +f 83//29 69//28 57//37 +f 83//29 57//37 82//38 +f 113//30 83//29 82//38 +f 113//30 82//38 112//39 +f 566//33 1283//40 9//41 +f 24//35 20//34 18//42 +f 24//35 18//42 23//43 +f 44//36 24//35 23//43 +f 44//36 23//43 32//44 +f 57//37 44//36 32//44 +f 57//37 32//44 56//45 +f 82//38 57//37 56//45 +f 82//38 56//45 81//46 +f 112//39 82//38 81//46 +f 112//39 81//46 111//47 +f 4//48 8//49 1250//50 +f 23//43 18//42 8//49 +f 23//43 8//49 17//51 +f 32//44 23//43 17//51 +f 32//44 17//51 31//52 +f 56//45 32//44 31//52 +f 56//45 31//52 55//53 +f 81//46 56//45 55//53 +f 81//46 55//53 80//54 +f 111//47 81//46 80//54 +f 111//47 80//54 110//55 +f 565//56 592//57 1233//58 +f 17//51 8//49 4//48 +f 17//51 4//48 16//59 +f 31//52 17//51 16//59 +f 31//52 16//59 30//60 +f 55//53 31//52 30//60 +f 55//53 30//60 54//61 +f 80//54 55//53 54//61 +f 80//54 54//61 79//62 +f 110//55 80//54 79//62 +f 110//55 79//62 109//63 +f 1//32 565//56 2//64 +f 6//65 2//64 565//56 +f 16//59 4//48 7//66 +f 16//59 7//66 22//67 +f 30//60 16//59 22//67 +f 30//60 22//67 43//68 +f 54//61 30//60 43//68 +f 54//61 43//68 68//69 +f 79//62 54//61 68//69 +f 79//62 68//69 97//70 +f 109//63 79//62 97//70 +f 109//63 97//70 127//71 +f 565//56 1233//58 1249//58 +f 13//72 14//73 5//74 +f 22//67 7//66 15//75 +f 22//67 15//75 29//76 +f 43//68 22//67 29//76 +f 43//68 29//76 42//77 +f 68//69 43//68 42//77 +f 68//69 42//77 67//78 +f 97//70 68//69 67//78 +f 97//70 67//78 96//79 +f 127//71 97//70 96//79 +f 127//71 96//79 126//80 +f 11//81 15//75 1240//82 +f 1289//83 34//1 593//3 +f 29//76 15//75 14//73 +f 29//76 14//73 21//84 +f 42//77 29//76 21//84 +f 42//77 21//84 41//85 +f 67//78 42//77 41//85 +f 67//78 41//85 66//86 +f 96//79 67//78 66//86 +f 96//79 66//86 95//87 +f 126//80 96//79 95//87 +f 126//80 95//87 125//88 +f 636//89 1243//2 26//2 +f 636//89 26//2 592//57 +f 21//84 14//73 13//72 +f 21//84 13//72 28//90 +f 41//85 21//84 28//90 +f 41//85 28//90 53//91 +f 66//86 41//85 53//91 +f 66//86 53//91 78//92 +f 95//87 66//86 78//92 +f 95//87 78//92 108//93 +f 125//88 95//87 108//93 +f 125//88 108//93 136//94 +f 12//95 13//72 5//74 +f 28//90 13//72 27//5 +f 28//90 27//5 52//4 +f 53//91 28//90 52//4 +f 53//91 52//4 77//8 +f 78//92 53//91 77//8 +f 78//92 77//8 107//10 +f 108//93 78//92 107//10 +f 108//93 107//10 115//12 +f 136//94 108//93 115//12 +f 136//94 115//12 129//14 +f 148//96 129//14 128//15 +f 148//96 128//15 143//97 +f 121//98 148//96 143//97 +f 121//98 143//97 122//99 +f 92//100 121//98 122//99 +f 92//100 122//99 93//101 +f 62//102 92//100 93//101 +f 62//102 93//101 63//103 +f 39//104 62//102 63//103 +f 39//104 63//103 51//105 +f 10//106 39//104 51//105 +f 10//106 51//105 49//107 +f 143//97 128//15 114//23 +f 143//97 114//23 142//108 +f 122//99 143//97 142//108 +f 122//99 142//108 123//109 +f 93//101 122//99 123//109 +f 93//101 123//109 94//110 +f 63//103 93//101 94//110 +f 63//103 94//110 76//111 +f 51//105 63//103 76//111 +f 51//105 76//111 75//112 +f 49//107 51//105 75//112 +f 49//107 75//112 61//113 +f 142//108 114//23 113//30 +f 142//108 113//30 141//114 +f 123//109 142//108 141//114 +f 123//109 141//114 124//115 +f 94//110 123//109 124//115 +f 94//110 124//115 106//116 +f 76//111 94//110 106//116 +f 76//111 106//116 105//117 +f 75//112 76//111 105//117 +f 75//112 105//117 91//118 +f 61//113 75//112 91//118 +f 61//113 91//118 90//119 +f 141//114 113//30 112//39 +f 141//114 112//39 140//120 +f 124//115 141//114 140//120 +f 124//115 140//120 135//121 +f 106//116 124//115 135//121 +f 106//116 135//121 134//122 +f 105//117 106//116 134//122 +f 105//117 134//122 120//123 +f 91//118 105//117 120//123 +f 91//118 120//123 119//124 +f 90//119 91//118 119//124 +f 140//120 112//39 111//47 +f 140//120 111//47 139//125 +f 135//121 140//120 139//125 +f 135//121 139//125 155//126 +f 134//122 135//121 155//126 +f 134//122 155//126 147//127 +f 120//123 134//122 147//127 +f 120//123 147//127 144//128 +f 119//124 120//123 144//128 +f 119//124 144//128 116//129 +f 26//2 1234//130 592//57 +f 139//125 111//47 110//55 +f 139//125 110//55 138//131 +f 155//126 139//125 138//131 +f 155//126 138//131 156//132 +f 147//127 155//126 156//132 +f 147//127 156//132 145//133 +f 144//128 147//127 145//133 +f 144//128 145//133 117//134 +f 116//129 144//128 117//134 +f 116//129 117//134 88//135 +f 27//5 13//72 12//95 +f 1242//136 88//135 71//137 +f 138//131 110//55 109//63 +f 138//131 109//63 137//138 +f 156//132 138//131 137//138 +f 156//132 137//138 154//139 +f 145//133 156//132 154//139 +f 145//133 154//139 131//140 +f 117//134 145//133 131//140 +f 117//134 131//140 101//141 +f 88//135 117//134 101//141 +f 88//135 101//141 86//142 +f 60//143 74//144 1248//145 +f 137//138 109//63 127//71 +f 137//138 127//71 151//146 +f 154//139 137//138 151//146 +f 154//139 151//146 153//147 +f 131//140 154//139 153//147 +f 131//140 153//147 130//148 +f 101//141 131//140 130//148 +f 101//141 130//148 100//149 +f 86//142 101//141 100//149 +f 86//142 100//149 74//144 +f 47//150 1235//151 631//152 +f 74//144 48//153 1248//145 +f 151//146 127//71 126//80 +f 151//146 126//80 150//154 +f 153//147 151//146 150//154 +f 153//147 150//154 146//155 +f 130//148 153//147 146//155 +f 130//148 146//155 118//156 +f 100//149 130//148 118//156 +f 100//149 118//156 89//157 +f 74//144 100//149 89//157 +f 74//144 89//157 48//153 +f 1247//158 87//159 715//160 +f 104//161 116//129 1242//136 +f 150//154 126//80 125//88 +f 150//154 125//88 149//162 +f 146//155 150//154 149//162 +f 146//155 149//162 132//163 +f 118//156 146//155 132//163 +f 118//156 132//163 102//164 +f 89//157 118//156 102//164 +f 89//157 102//164 72//165 +f 48//153 89//157 72//165 +f 48//153 72//165 46//166 +f 37//167 48//153 46//166 +f 37//167 46//166 38//168 +f 149//162 125//88 136//94 +f 149//162 136//94 152//169 +f 132//163 149//162 152//169 +f 132//163 152//169 133//170 +f 102//164 132//163 133//170 +f 102//164 133//170 103//171 +f 72//165 102//164 103//171 +f 72//165 103//171 73//172 +f 46//166 72//165 73//172 +f 46//166 73//172 50//173 +f 38//168 46//166 50//173 +f 38//168 50//173 25//174 +f 152//169 136//94 129//14 +f 152//169 129//14 148//96 +f 133//170 152//169 148//96 +f 133//170 148//96 121//98 +f 103//171 133//170 121//98 +f 103//171 121//98 92//100 +f 73//172 103//171 92//100 +f 73//172 92//100 62//102 +f 50//173 73//172 62//102 +f 50//173 62//102 39//104 +f 25//174 50//173 39//104 +f 39//104 10//106 25//174 +f 539//175 509//176 159//177 +f 160//178 158//179 157//180 +f 166//181 160//178 163//182 +f 166//181 163//182 173//183 +f 177//184 166//181 173//183 +f 177//184 173//183 183//185 +f 189//186 177//184 183//185 +f 189//186 183//185 197//187 +f 205//188 189//186 197//187 +f 205//188 197//187 216//189 +f 225//190 205//188 216//189 +f 225//190 216//189 235//191 +f 173//183 163//182 172//192 +f 173//183 172//192 184//193 +f 183//185 173//183 184//193 +f 183//185 184//193 198//194 +f 197//187 183//185 198//194 +f 197//187 198//194 217//195 +f 216//189 197//187 217//195 +f 216//189 217//195 236//196 +f 235//191 216//189 236//196 +f 235//191 236//196 253//197 +f 182//198 172//192 1254//199 +f 1255//200 167//201 595//202 +f 184//193 172//192 182//198 +f 184//193 182//198 196//203 +f 198//194 184//193 196//203 +f 198//194 196//203 214//204 +f 217//195 198//194 214//204 +f 217//195 214//204 232//205 +f 236//196 217//195 232//205 +f 236//196 232//205 250//206 +f 253//197 236//196 250//206 +f 253//197 250//206 267//207 +f 196//203 182//198 199//208 +f 196//203 199//208 215//209 +f 214//204 196//203 215//209 +f 214//204 215//209 233//210 +f 232//205 214//204 233//210 +f 232//205 233//210 251//211 +f 250//206 232//205 251//211 +f 250//206 251//211 257//212 +f 267//207 250//206 257//212 +f 267//207 257//212 256//213 +f 215//209 199//208 218//214 +f 215//209 218//214 234//215 +f 233//210 215//209 234//215 +f 233//210 234//215 241//216 +f 251//211 233//210 241//216 +f 251//211 241//216 240//217 +f 257//212 251//211 240//217 +f 257//212 240//217 239//218 +f 256//213 257//212 239//218 +f 256//213 239//218 238//219 +f 234//215 218//214 219//220 +f 234//215 219//220 224//221 +f 241//216 234//215 224//221 +f 241//216 224//221 223//222 +f 240//217 241//216 223//222 +f 240//217 223//222 222//223 +f 239//218 240//217 222//223 +f 239//218 222//223 221//224 +f 238//219 239//218 221//224 +f 238//219 221//224 220//225 +f 219//220 218//214 1285//226 +f 648//227 691//228 207//229 +f 224//221 219//220 208//230 +f 224//221 208//230 204//231 +f 223//222 224//221 204//231 +f 223//222 204//231 203//232 +f 222//223 223//222 203//232 +f 222//223 203//232 202//233 +f 221//224 222//223 202//233 +f 221//224 202//233 201//234 +f 220//225 221//224 201//234 +f 220//225 201//234 212//235 +f 204//231 208//230 191//236 +f 204//231 191//236 188//237 +f 203//232 204//231 188//237 +f 203//232 188//237 187//238 +f 202//233 203//232 187//238 +f 202//233 187//238 186//239 +f 201//234 202//233 186//239 +f 201//234 186//239 194//240 +f 212//235 201//234 194//240 +f 212//235 194//240 211//241 +f 188//237 191//236 174//242 +f 188//237 174//242 176//243 +f 187//238 188//237 176//243 +f 187//238 176//243 175//244 +f 186//239 187//238 175//244 +f 186//239 175//244 180//245 +f 194//240 186//239 180//245 +f 194//240 180//245 193//246 +f 211//241 194//240 193//246 +f 211//241 193//246 210//247 +f 613//248 585//249 1258//250 +f 176//243 174//242 168//251 +f 176//243 168//251 165//252 +f 175//244 176//243 165//252 +f 175//244 165//252 170//253 +f 180//245 175//244 170//253 +f 180//245 170//253 179//254 +f 193//246 180//245 179//254 +f 193//246 179//254 192//255 +f 210//247 193//246 192//255 +f 210//247 192//255 209//256 +f 168//251 174//242 164//257 +f 165//252 168//251 161//258 +f 165//252 161//258 162//259 +f 170//253 165//252 162//259 +f 170//253 162//259 171//260 +f 179//254 170//253 171//260 +f 179//254 171//260 181//261 +f 192//255 179//254 181//261 +f 192//255 181//261 195//262 +f 209//256 192//255 195//262 +f 209//256 195//262 213//263 +f 160//178 161//258 158//179 +f 161//258 160//178 162//259 +f 162//259 160//178 166//181 +f 171//260 162//259 166//181 +f 171//260 166//181 177//184 +f 181//261 171//260 177//184 +f 181//261 177//184 189//186 +f 195//262 181//261 189//186 +f 195//262 189//186 205//188 +f 213//263 195//262 205//188 +f 213//263 205//188 225//190 +f 242//264 225//190 235//191 +f 242//264 235//191 252//265 +f 258//266 242//264 252//265 +f 258//266 252//265 268//267 +f 273//268 258//266 268//267 +f 273//268 268//267 283//269 +f 287//270 273//268 283//269 +f 287//270 283//269 298//271 +f 300//272 287//270 298//271 +f 300//272 298//271 299//273 +f 312//274 300//272 299//273 +f 312//274 299//273 310//275 +f 252//265 235//191 253//197 +f 252//265 253//197 269//276 +f 268//267 252//265 269//276 +f 268//267 269//276 284//277 +f 283//269 268//267 284//277 +f 283//269 284//277 286//278 +f 298//271 283//269 286//278 +f 298//271 286//278 285//279 +f 299//273 298//271 285//279 +f 299//273 285//279 296//280 +f 310//275 299//273 296//280 +f 310//275 296//280 309//281 +f 269//276 253//197 267//207 +f 269//276 267//207 272//282 +f 284//277 269//276 272//282 +f 284//277 272//282 271//283 +f 286//278 284//277 271//283 +f 286//278 271//283 270//284 +f 285//279 286//278 270//284 +f 285//279 270//284 281//285 +f 296//280 285//279 281//285 +f 296//280 281//285 295//286 +f 309//281 296//280 295//286 +f 309//281 295//286 308//287 +f 272//282 267//207 256//213 +f 272//282 256//213 255//288 +f 271//283 272//282 255//288 +f 271//283 255//288 254//289 +f 270//284 271//283 254//289 +f 270//284 254//289 265//290 +f 281//285 270//284 265//290 +f 281//285 265//290 280//291 +f 295//286 281//285 280//291 +f 295//286 280//291 294//292 +f 308//287 295//286 294//292 +f 308//287 294//292 307//293 +f 255//288 256//213 238//219 +f 255//288 238//219 237//294 +f 254//289 255//288 237//294 +f 254//289 237//294 248//295 +f 265//290 254//289 248//295 +f 265//290 248//295 264//296 +f 280//291 265//290 264//296 +f 280//291 264//296 279//297 +f 294//292 280//291 279//297 +f 294//292 279//297 293//298 +f 307//293 294//292 293//298 +f 307//293 293//298 306//299 +f 237//294 238//219 220//225 +f 237//294 220//225 230//300 +f 248//295 237//294 230//300 +f 248//295 230//300 247//301 +f 264//296 248//295 247//301 +f 264//296 247//301 263//302 +f 279//297 264//296 263//302 +f 279//297 263//302 278//303 +f 293//298 279//297 278//303 +f 293//298 278//303 292//304 +f 306//299 293//298 292//304 +f 306//299 292//304 305//305 +f 230//300 220//225 212//235 +f 230//300 212//235 229//306 +f 247//301 230//300 229//306 +f 247//301 229//306 246//307 +f 263//302 247//301 246//307 +f 263//302 246//307 262//308 +f 278//303 263//302 262//308 +f 278//303 262//308 277//309 +f 292//304 278//303 277//309 +f 292//304 277//309 291//310 +f 305//305 292//304 291//310 +f 305//305 291//310 304//311 +f 229//306 212//235 211//241 +f 229//306 211//241 228//312 +f 246//307 229//306 228//312 +f 246//307 228//312 245//313 +f 262//308 246//307 245//313 +f 262//308 245//313 261//314 +f 277//309 262//308 261//314 +f 277//309 261//314 276//315 +f 291//310 277//309 276//315 +f 291//310 276//315 290//316 +f 304//311 291//310 290//316 +f 304//311 290//316 303//317 +f 228//312 211//241 210//247 +f 228//312 210//247 227//318 +f 245//313 228//312 227//318 +f 245//313 227//318 244//319 +f 261//314 245//313 244//319 +f 261//314 244//319 260//320 +f 276//315 261//314 260//320 +f 276//315 260//320 275//321 +f 290//316 276//315 275//321 +f 290//316 275//321 289//322 +f 303//317 290//316 289//322 +f 303//317 289//322 302//323 +f 227//318 210//247 209//256 +f 227//318 209//256 226//324 +f 244//319 227//318 226//324 +f 244//319 226//324 243//325 +f 260//320 244//319 243//325 +f 260//320 243//325 259//326 +f 275//321 260//320 259//326 +f 275//321 259//326 274//327 +f 289//322 275//321 274//327 +f 289//322 274//327 288//328 +f 302//323 289//322 288//328 +f 302//323 288//328 301//329 +f 226//324 209//256 213//263 +f 226//324 213//263 231//330 +f 243//325 226//324 231//330 +f 243//325 231//330 249//331 +f 259//326 243//325 249//331 +f 259//326 249//331 266//332 +f 274//327 259//326 266//332 +f 274//327 266//332 282//333 +f 288//328 274//327 282//333 +f 288//328 282//333 297//334 +f 301//329 288//328 297//334 +f 301//329 297//334 311//335 +f 231//330 213//263 225//190 +f 231//330 225//190 242//264 +f 249//331 231//330 242//264 +f 249//331 242//264 258//266 +f 266//332 249//331 258//266 +f 266//332 258//266 273//268 +f 282//333 266//332 273//268 +f 282//333 273//268 287//270 +f 297//334 282//333 287//270 +f 297//334 287//270 300//272 +f 311//335 297//334 300//272 +f 311//335 300//272 312//274 +f 312//274 310//275 323//336 +f 302//323 315//337 316//338 +f 304//311 317//339 318//340 +f 303//317 316//338 317//339 +f 309//281 308//287 321//341 +f 307//293 306//299 319//342 +f 311//335 313//343 314//344 +f 301//329 314//344 315//337 +f 312//274 324//345 313//343 +f 306//299 305//305 318//340 +f 308//287 307//293 320//346 +f 310//275 309//281 322//347 +f 322//347 321//341 325//348 +f 314//344 313//343 325//348 +f 323//336 322//347 325//348 +f 319//342 318//340 325//348 +f 315//337 314//344 325//348 +f 321//341 320//346 325//348 +f 324//345 323//336 325//348 +f 320//346 319//342 325//348 +f 317//339 316//338 325//348 +f 316//338 315//337 325//348 +f 313//343 324//345 325//348 +f 318//340 317//339 325//348 +f 326//349 327//350 328//351 +f 326//349 328//351 329//352 +f 333//353 326//349 329//352 +f 333//353 329//352 338//354 +f 347//355 333//353 338//354 +f 347//355 338//354 354//356 +f 364//357 347//355 354//356 +f 364//357 354//356 374//358 +f 386//359 364//357 374//358 +f 386//359 374//358 398//360 +f 412//361 386//359 398//360 +f 412//361 398//360 429//362 +f 329//352 328//351 334//363 +f 329//352 334//363 339//364 +f 338//354 329//352 339//364 +f 338//354 339//364 355//365 +f 354//356 338//354 355//365 +f 354//356 355//365 375//366 +f 374//358 354//356 375//366 +f 374//358 375//366 399//367 +f 398//360 374//358 399//367 +f 398//360 399//367 430//368 +f 429//362 398//360 430//368 +f 429//362 430//368 464//369 +f 339//364 334//363 342//370 +f 339//364 342//370 356//371 +f 355//365 339//364 356//371 +f 355//365 356//371 376//372 +f 375//366 355//365 376//372 +f 375//366 376//372 400//373 +f 399//367 375//366 400//373 +f 399//367 400//373 431//374 +f 430//368 399//367 431//374 +f 430//368 431//374 465//375 +f 464//369 430//368 465//375 +f 464//369 465//375 497//376 +f 356//371 342//370 351//377 +f 356//371 351//377 370//378 +f 376//372 356//371 370//378 +f 376//372 370//378 393//379 +f 400//373 376//372 393//379 +f 400//373 393//379 422//380 +f 431//374 400//373 422//380 +f 431//374 422//380 457//381 +f 465//375 431//374 457//381 +f 465//375 457//381 490//382 +f 497//376 465//375 490//382 +f 497//376 490//382 521//383 +f 370//378 351//377 361//384 +f 370//378 361//384 382//385 +f 393//379 370//378 382//385 +f 393//379 382//385 408//386 +f 422//380 393//379 408//386 +f 422//380 408//386 439//387 +f 457//381 422//380 439//387 +f 457//381 439//387 473//388 +f 490//382 457//381 473//388 +f 490//382 473//388 504//389 +f 521//383 490//382 504//389 +f 521//383 504//389 535//390 +f 382//385 361//384 369//391 +f 382//385 369//391 392//392 +f 408//386 382//385 392//392 +f 408//386 392//392 421//393 +f 439//387 408//386 421//393 +f 439//387 421//393 456//394 +f 473//388 439//387 456//394 +f 473//388 456//394 489//395 +f 504//389 473//388 489//395 +f 504//389 489//395 520//396 +f 535//390 504//389 520//396 +f 535//390 520//396 550//397 +f 392//392 369//391 380//398 +f 392//392 380//398 407//399 +f 421//393 392//392 407//399 +f 421//393 407//399 438//400 +f 456//394 421//393 438//400 +f 456//394 438//400 472//401 +f 489//395 456//394 472//401 +f 489//395 472//401 503//402 +f 520//396 489//395 503//402 +f 520//396 503//402 534//403 +f 550//397 520//396 534//403 +f 550//397 534//403 563//404 +f 407//399 380//398 391//405 +f 407//399 391//405 420//406 +f 438//400 407//399 420//406 +f 438//400 420//406 455//407 +f 472//401 438//400 455//407 +f 472//401 455//407 488//408 +f 503//402 472//401 488//408 +f 503//402 488//408 519//409 +f 534//403 503//402 519//409 +f 534//403 519//409 549//410 +f 563//404 534//403 549//410 +f 563//404 549//410 578//411 +f 420//406 391//405 404//412 +f 420//406 404//412 437//413 +f 455//407 420//406 437//413 +f 455//407 437//413 471//414 +f 488//408 455//407 471//414 +f 488//408 471//414 502//415 +f 519//409 488//408 502//415 +f 519//409 502//415 533//416 +f 549//410 519//409 533//416 +f 549//410 533//416 562//417 +f 578//411 549//410 562//417 +f 578//411 562//417 589//418 +f 437//413 404//412 419//419 +f 437//413 419//419 454//420 +f 471//414 437//413 454//420 +f 471//414 454//420 487//421 +f 502//415 471//414 487//421 +f 502//415 487//421 518//422 +f 533//416 502//415 518//422 +f 533//416 518//422 548//423 +f 562//417 533//416 548//423 +f 562//417 548//423 577//424 +f 589//418 562//417 577//424 +f 589//418 577//424 594//425 +f 454//420 419//419 436//426 +f 454//420 436//426 470//427 +f 487//421 454//420 470//427 +f 487//421 470//427 501//428 +f 518//422 487//421 501//428 +f 518//422 501//428 532//429 +f 548//423 518//422 532//429 +f 548//423 532//429 555//430 +f 577//424 548//423 555//430 +f 577//424 555//430 567//431 +f 594//425 577//424 567//431 +f 594//425 567//431 582//432 +f 470//427 436//426 453//433 +f 470//427 453//433 486//434 +f 501//428 470//427 486//434 +f 501//428 486//434 508//435 +f 532//429 501//428 508//435 +f 532//429 508//435 525//436 +f 555//430 532//429 525//436 +f 555//430 525//436 538//437 +f 567//431 555//430 538//437 +f 567//431 538//437 554//438 +f 582//432 567//431 554//438 +f 582//432 554//438 566//33 +f 486//434 453//433 462//439 +f 486//434 462//439 477//440 +f 508//435 486//434 477//440 +f 508//435 477//440 494//441 +f 525//436 508//435 494//441 +f 525//436 494//441 507//442 +f 538//437 525//436 507//442 +f 538//437 507//442 524//443 +f 554//438 538//437 524//443 +f 554//438 524//443 537//444 +f 566//33 554//438 537//444 +f 566//33 537//444 553//31 +f 477//440 462//439 443//445 +f 477//440 443//445 461//446 +f 494//441 477//440 461//446 +f 494//441 461//446 476//447 +f 507//442 494//441 476//447 +f 507//442 476//447 493//448 +f 524//443 507//442 493//448 +f 524//443 493//448 506//449 +f 537//444 524//443 506//449 +f 537//444 506//449 523//450 +f 553//31 537//444 523//450 +f 553//31 523//450 536//451 +f 461//446 443//445 426//452 +f 461//446 426//452 442//453 +f 476//447 461//446 442//453 +f 476//447 442//453 460//454 +f 493//448 476//447 460//454 +f 493//448 460//454 475//455 +f 506//449 493//448 475//455 +f 506//449 475//455 492//456 +f 523//450 506//449 492//456 +f 523//450 492//456 505//457 +f 536//451 523//450 505//457 +f 536//451 505//457 522//458 +f 442//453 426//452 411//459 +f 442//453 411//459 425//460 +f 460//454 442//453 425//460 +f 460//454 425//460 441//461 +f 475//455 460//454 441//461 +f 475//455 441//461 459//462 +f 492//456 475//455 459//462 +f 492//456 459//462 474//463 +f 505//457 492//456 474//463 +f 505//457 474//463 491//464 +f 522//458 505//457 491//464 +f 522//458 491//464 499//465 +f 425//460 411//459 396//466 +f 425//460 396//466 410//467 +f 441//461 425//460 410//467 +f 441//461 410//467 424//468 +f 459//462 441//461 424//468 +f 459//462 424//468 440//469 +f 474//463 459//462 440//469 +f 474//463 440//469 458//470 +f 491//464 474//463 458//470 +f 491//464 458//470 467//471 +f 499//465 491//464 467//471 +f 499//465 467//471 466//472 +f 410//467 396//466 385//473 +f 410//467 385//473 395//474 +f 424//468 410//467 395//474 +f 424//468 395//474 409//475 +f 440//469 424//468 409//475 +f 440//469 409//475 423//476 +f 458//470 440//469 423//476 +f 458//470 423//476 433//477 +f 467//471 458//470 433//477 +f 467//471 433//477 432//478 +f 466//472 467//471 432//478 +f 466//472 432//478 434//479 +f 395//474 385//473 372//480 +f 395//474 372//480 383//481 +f 409//475 395//474 383//481 +f 409//475 383//481 394//482 +f 423//476 409//475 394//482 +f 423//476 394//482 402//483 +f 433//477 423//476 402//483 +f 433//477 402//483 401//484 +f 432//478 433//477 401//484 +f 432//478 401//484 403//485 +f 434//479 432//478 403//485 +f 434//479 403//485 417//486 +f 383//481 372//480 362//487 +f 383//481 362//487 371//488 +f 394//482 383//481 371//488 +f 394//482 371//488 378//489 +f 402//483 394//482 378//489 +f 402//483 378//489 377//490 +f 401//484 402//483 377//490 +f 401//484 377//490 379//491 +f 403//485 401//484 379//491 +f 403//485 379//491 390//492 +f 417//486 403//485 390//492 +f 417//486 390//492 416//493 +f 371//488 362//487 352//494 +f 371//488 352//494 358//495 +f 378//489 371//488 358//495 +f 378//489 358//495 357//496 +f 377//490 378//489 357//496 +f 377//490 357//496 359//497 +f 379//491 377//490 359//497 +f 379//491 359//497 367//498 +f 390//492 379//491 367//498 +f 390//492 367//498 389//499 +f 416//493 390//492 389//499 +f 416//493 389//499 415//500 +f 358//495 352//494 345//501 +f 358//495 345//501 340//502 +f 357//496 358//495 340//502 +f 357//496 340//502 341//503 +f 359//497 357//496 341//503 +f 359//497 341//503 349//504 +f 367//498 359//497 349//504 +f 367//498 349//504 366//505 +f 389//499 367//498 366//505 +f 389//499 366//505 388//506 +f 415//500 389//499 388//506 +f 415//500 388//506 414//507 +f 340//502 345//501 335//508 +f 340//502 335//508 330//509 +f 341//503 340//502 330//509 +f 341//503 330//509 336//510 +f 349//504 341//503 336//510 +f 349//504 336//510 348//511 +f 366//505 349//504 348//511 +f 366//505 348//511 365//512 +f 388//506 366//505 365//512 +f 388//506 365//512 387//513 +f 414//507 388//506 387//513 +f 414//507 387//513 413//514 +f 330//509 335//508 327//350 +f 327//350 326//349 330//509 +f 330//509 326//349 336//510 +f 336//510 326//349 333//353 +f 348//511 336//510 333//353 +f 348//511 333//353 347//355 +f 365//512 348//511 347//355 +f 365//512 347//355 364//357 +f 387//513 365//512 364//357 +f 387//513 364//357 386//359 +f 413//514 387//513 386//359 +f 413//514 386//359 412//361 +f 445//515 412//361 429//362 +f 445//515 429//362 463//516 +f 478//517 445//515 463//516 +f 478//517 463//516 495//518 +f 509//176 478//517 495//518 +f 509//176 495//518 526//519 +f 463//516 429//362 464//369 +f 463//516 464//369 496//520 +f 495//518 463//516 496//520 +f 495//518 496//520 527//521 +f 526//519 495//518 527//521 +f 526//519 527//521 557//522 +f 556//523 526//519 557//522 +f 556//523 557//522 583//524 +f 595//202 556//523 583//524 +f 595//202 583//524 611//525 +f 621//526 595//202 611//525 +f 621//526 611//525 638//527 +f 496//520 464//369 497//376 +f 496//520 497//376 528//528 +f 527//521 496//520 528//528 +f 527//521 528//528 558//529 +f 557//522 527//521 558//529 +f 557//522 558//529 584//530 +f 583//524 557//522 584//530 +f 583//524 584//530 612//531 +f 611//525 583//524 612//531 +f 611//525 612//531 639//532 +f 638//527 611//525 639//532 +f 638//527 639//532 664//533 +f 528//528 497//376 521//383 +f 528//528 521//383 551//534 +f 558//529 528//528 551//534 +f 558//529 551//534 580//535 +f 584//530 558//529 580//535 +f 584//530 580//535 608//536 +f 612//531 584//530 608//536 +f 612//531 608//536 634//537 +f 639//532 612//531 634//537 +f 639//532 634//537 661//538 +f 664//533 639//532 661//538 +f 664//533 661//538 688//539 +f 551//534 521//383 535//390 +f 551//534 535//390 564//540 +f 580//535 551//534 564//540 +f 580//535 564//540 591//541 +f 608//536 580//535 591//541 +f 608//536 591//541 618//542 +f 634//537 608//536 618//542 +f 634//537 618//542 644//543 +f 661//538 634//537 644//543 +f 661//538 644//543 670//544 +f 688//539 661//538 670//544 +f 688//539 670//544 698//545 +f 564//540 535//390 550//397 +f 564//540 550//397 579//546 +f 591//541 564//540 579//546 +f 591//541 579//546 607//547 +f 618//542 591//541 607//547 +f 618//542 607//547 633//548 +f 644//543 618//542 633//548 +f 644//543 633//548 660//549 +f 670//544 644//543 660//549 +f 670//544 660//549 687//550 +f 698//545 670//544 687//550 +f 698//545 687//550 717//551 +f 579//546 550//397 563//404 +f 579//546 563//404 590//552 +f 607//547 579//546 590//552 +f 607//547 590//552 617//553 +f 633//548 607//547 617//553 +f 633//548 617//553 643//554 +f 660//549 633//548 643//554 +f 660//549 643//554 669//555 +f 687//550 660//549 669//555 +f 687//550 669//555 697//556 +f 717//551 687//550 697//556 +f 717//551 697//556 727//557 +f 590//552 563//404 578//411 +f 590//552 578//411 606//558 +f 617//553 590//552 606//558 +f 617//553 606//558 632//559 +f 643//554 617//553 632//559 +f 643//554 632//559 659//560 +f 669//555 643//554 659//560 +f 669//555 659//560 673//561 +f 697//556 669//555 673//561 +f 697//556 673//561 700//562 +f 727//557 697//556 700//562 +f 727//557 700//562 699//563 +f 606//558 578//411 589//418 +f 606//558 589//418 616//564 +f 632//559 606//558 616//564 +f 632//559 616//564 637//565 +f 659//560 632//559 637//565 +f 659//560 637//565 647//566 +f 673//561 659//560 647//566 +f 673//561 647//566 672//567 +f 700//562 673//561 672//567 +f 700//562 672//567 671//568 +f 699//563 700//562 671//568 +f 699//563 671//568 689//569 +f 616//564 589//418 594//425 +f 616//564 594//425 610//570 +f 637//565 616//564 610//570 +f 637//565 610//570 620//571 +f 647//566 637//565 620//571 +f 647//566 620//571 646//572 +f 672//567 647//566 646//572 +f 672//567 646//572 645//573 +f 671//568 672//567 645//573 +f 671//568 645//573 662//574 +f 689//569 671//568 662//574 +f 689//569 662//574 668//575 +f 610//570 594//425 582//432 +f 610//570 582//432 593//3 +f 620//571 610//570 593//3 +f 620//571 593//3 636//89 +f 646//572 620//571 636//89 +f 646//572 636//89 619//576 +f 645//573 646//572 619//576 +f 645//573 619//576 635//577 +f 662//574 645//573 635//577 +f 662//574 635//577 642//578 +f 668//575 662//574 642//578 +f 668//575 642//578 641//579 +f 593//3 582//432 566//33 +f 619//576 636//89 592//57 +f 619//576 592//57 609//580 +f 635//577 619//576 609//580 +f 635//577 609//580 615//581 +f 642//578 635//577 615//581 +f 642//578 615//581 614//582 +f 641//579 642//578 614//582 +f 592//57 565//56 581//583 +f 609//580 592//57 581//583 +f 609//580 581//583 587//584 +f 615//581 609//580 587//584 +f 615//581 587//584 586//585 +f 614//582 615//581 586//585 +f 614//582 586//585 588//586 +f 565//56 553//31 536//451 +f 565//56 536//451 552//587 +f 581//583 565//56 552//587 +f 581//583 552//587 560//588 +f 587//584 581//583 560//588 +f 587//584 560//588 559//589 +f 586//585 587//584 559//589 +f 586//585 559//589 561//590 +f 588//586 586//585 561//590 +f 588//586 561//590 576//591 +f 605//592 588//586 576//591 +f 605//592 576//591 604//593 +f 552//587 536//451 522//458 +f 552//587 522//458 530//594 +f 560//588 552//587 530//594 +f 560//588 530//594 529//595 +f 559//589 560//588 529//595 +f 559//589 529//595 531//596 +f 561//590 559//589 531//596 +f 561//590 531//596 547//597 +f 576//591 561//590 547//597 +f 576//591 547//597 575//598 +f 604//593 576//591 575//598 +f 604//593 575//598 603//599 +f 530//594 522//458 499//465 +f 530//594 499//465 498//600 +f 529//595 530//594 498//600 +f 529//595 498//600 500//601 +f 531//596 529//595 500//601 +f 531//596 500//601 517//602 +f 547//597 531//596 517//602 +f 547//597 517//602 546//603 +f 575//598 547//597 546//603 +f 575//598 546//603 574//604 +f 603//599 575//598 574//604 +f 603//599 574//604 602//605 +f 498//600 499//465 466//472 +f 498//600 466//472 468//606 +f 500//601 498//600 468//606 +f 500//601 468//606 485//607 +f 517//602 500//601 485//607 +f 517//602 485//607 516//608 +f 546//603 517//602 516//608 +f 546//603 516//608 545//609 +f 574//604 546//603 545//609 +f 574//604 545//609 573//610 +f 602//605 574//604 573//610 +f 602//605 573//610 601//611 +f 468//606 466//472 434//479 +f 468//606 434//479 451//612 +f 485//607 468//606 451//612 +f 485//607 451//612 484//613 +f 516//608 485//607 484//613 +f 516//608 484//613 515//614 +f 545//609 516//608 515//614 +f 545//609 515//614 544//615 +f 573//610 545//609 544//615 +f 573//610 544//615 572//616 +f 601//611 573//610 572//616 +f 601//611 572//616 600//617 +f 451//612 434//479 417//486 +f 451//612 417//486 450//618 +f 484//613 451//612 450//618 +f 484//613 450//618 483//619 +f 515//614 484//613 483//619 +f 515//614 483//619 514//620 +f 544//615 515//614 514//620 +f 544//615 514//620 543//621 +f 572//616 544//615 543//621 +f 572//616 543//621 571//622 +f 600//617 572//616 571//622 +f 600//617 571//622 599//623 +f 450//618 417//486 416//493 +f 450//618 416//493 449//624 +f 483//619 450//618 449//624 +f 483//619 449//624 482//625 +f 514//620 483//619 482//625 +f 514//620 482//625 513//626 +f 543//621 514//620 513//626 +f 543//621 513//626 542//627 +f 571//622 543//621 542//627 +f 571//622 542//627 570//628 +f 599//623 571//622 570//628 +f 599//623 570//628 598//629 +f 449//624 416//493 415//500 +f 449//624 415//500 448//630 +f 482//625 449//624 448//630 +f 482//625 448//630 481//631 +f 513//626 482//625 481//631 +f 513//626 481//631 512//632 +f 542//627 513//626 512//632 +f 542//627 512//632 541//633 +f 570//628 542//627 541//633 +f 570//628 541//633 569//634 +f 598//629 570//628 569//634 +f 598//629 569//634 597//635 +f 448//630 415//500 414//507 +f 448//630 414//507 447//636 +f 481//631 448//630 447//636 +f 481//631 447//636 480//637 +f 512//632 481//631 480//637 +f 512//632 480//637 511//638 +f 541//633 512//632 511//638 +f 541//633 511//638 540//639 +f 569//634 541//633 540//639 +f 569//634 540//639 568//640 +f 597//635 569//634 568//640 +f 597//635 568//640 596//641 +f 447//636 414//507 413//514 +f 447//636 413//514 446//642 +f 480//637 447//636 446//642 +f 480//637 446//642 479//643 +f 511//638 480//637 479//643 +f 511//638 479//643 510//644 +f 540//639 511//638 510//644 +f 540//639 510//644 539//175 +f 568//640 540//639 539//175 +f 568//640 539//175 585//249 +f 596//641 568//640 585//249 +f 596//641 585//249 613//248 +f 446//642 413//514 412//361 +f 446//642 412//361 445//515 +f 479//643 446//642 445//515 +f 479//643 445//515 478//517 +f 510//644 479//643 478//517 +f 510//644 478//517 509//176 +f 539//175 510//644 509//176 +f 691//228 648//227 674//645 +f 702//646 691//228 674//645 +f 702//646 674//645 701//647 +f 731//648 702//646 701//647 +f 731//648 701//647 730//649 +f 759//650 731//648 730//649 +f 759//650 730//649 758//651 +f 786//652 759//650 758//651 +f 786//652 758//651 785//653 +f 648//227 621//526 638//527 +f 648//227 638//527 663//654 +f 674//645 648//227 663//654 +f 674//645 663//654 690//655 +f 701//647 674//645 690//655 +f 701//647 690//655 720//656 +f 730//649 701//647 720//656 +f 730//649 720//656 749//657 +f 758//651 730//649 749//657 +f 758//651 749//657 777//658 +f 785//653 758//651 777//658 +f 785//653 777//658 805//659 +f 663//654 638//527 664//533 +f 663//654 664//533 692//660 +f 690//655 663//654 692//660 +f 690//655 692//660 721//661 +f 720//656 690//655 721//661 +f 720//656 721//661 750//662 +f 749//657 720//656 750//662 +f 749//657 750//662 778//663 +f 777//658 749//657 778//663 +f 777//658 778//663 806//664 +f 805//659 777//658 806//664 +f 805//659 806//664 833//665 +f 692//660 664//533 688//539 +f 692//660 688//539 718//666 +f 721//661 692//660 718//666 +f 721//661 718//666 747//667 +f 750//662 721//661 747//667 +f 750//662 747//667 775//668 +f 778//663 750//662 775//668 +f 778//663 775//668 803//669 +f 806//664 778//663 803//669 +f 806//664 803//669 831//670 +f 833//665 806//664 831//670 +f 833//665 831//670 838//671 +f 718//666 688//539 698//545 +f 718//666 698//545 728//672 +f 747//667 718//666 728//672 +f 747//667 728//672 756//673 +f 775//668 747//667 756//673 +f 775//668 756//673 784//674 +f 803//669 775//668 784//674 +f 803//669 784//674 804//675 +f 831//670 803//669 804//675 +f 831//670 804//675 811//676 +f 838//671 831//670 811//676 +f 838//671 811//676 830//677 +f 728//672 698//545 717//551 +f 728//672 717//551 746//678 +f 756//673 728//672 746//678 +f 756//673 746//678 757//679 +f 784//674 756//673 757//679 +f 784//674 757//679 776//680 +f 804//675 784//674 776//680 +f 804//675 776//680 783//681 +f 811//676 804//675 783//681 +f 811//676 783//681 802//682 +f 830//677 811//676 802//682 +f 830//677 802//682 810//683 +f 746//678 717//551 727//557 +f 746//678 727//557 729//684 +f 757//679 746//678 729//684 +f 757//679 729//684 748//685 +f 776//680 757//679 748//685 +f 776//680 748//685 755//686 +f 783//681 776//680 755//686 +f 783//681 755//686 774//687 +f 802//682 783//681 774//687 +f 802//682 774//687 782//688 +f 810//683 802//682 782//688 +f 810//683 782//688 809//689 +f 729//684 727//557 699//563 +f 729//684 699//563 719//690 +f 748//685 729//684 719//690 +f 748//685 719//690 726//691 +f 755//686 748//685 726//691 +f 755//686 726//691 745//692 +f 774//687 755//686 745//692 +f 774//687 745//692 754//693 +f 782//688 774//687 754//693 +f 782//688 754//693 781//694 +f 809//689 782//688 781//694 +f 809//689 781//694 780//695 +f 719//690 699//563 689//569 +f 719//690 689//569 696//696 +f 726//691 719//690 696//696 +f 726//691 696//696 716//697 +f 745//692 726//691 716//697 +f 745//692 716//697 725//698 +f 754//693 745//692 725//698 +f 754//693 725//698 753//699 +f 781//694 754//693 753//699 +f 781//694 753//699 752//700 +f 780//695 781//694 752//700 +f 780//695 752//700 773//701 +f 696//696 689//569 668//575 +f 696//696 668//575 686//702 +f 716//697 696//696 686//702 +f 716//697 686//702 695//703 +f 725//698 716//697 695//703 +f 725//698 695//703 724//704 +f 753//699 725//698 724//704 +f 753//699 724//704 723//705 +f 752//700 753//699 723//705 +f 752//700 723//705 744//706 +f 773//701 752//700 744//706 +f 773//701 744//706 772//707 +f 686//702 668//575 641//579 +f 686//702 641//579 667//708 +f 695//703 686//702 667//708 +f 695//703 667//708 715//160 +f 724//704 695//703 715//160 +f 724//704 715//160 694//709 +f 723//705 724//704 694//709 +f 723//705 694//709 714//710 +f 744//706 723//705 714//710 +f 744//706 714//710 743//711 +f 772//707 744//706 743//711 +f 772//707 743//711 771//712 +f 694//709 715//160 666//713 +f 694//709 666//713 685//714 +f 714//710 694//709 685//714 +f 714//710 685//714 713//715 +f 743//711 714//710 713//715 +f 743//711 713//715 742//716 +f 771//712 743//711 742//716 +f 771//712 742//716 770//717 +f 666//713 631//152 658//718 +f 685//714 666//713 658//718 +f 685//714 658//718 684//719 +f 713//715 685//714 684//719 +f 713//715 684//719 712//720 +f 742//716 713//715 712//720 +f 742//716 712//720 741//721 +f 770//717 742//716 741//721 +f 770//717 741//721 769//722 +f 631//152 605//592 604//593 +f 631//152 604//593 630//723 +f 658//718 631//152 630//723 +f 658//718 630//723 657//724 +f 684//719 658//718 657//724 +f 684//719 657//724 683//725 +f 712//720 684//719 683//725 +f 712//720 683//725 711//726 +f 741//721 712//720 711//726 +f 741//721 711//726 740//727 +f 769//722 741//721 740//727 +f 769//722 740//727 768//728 +f 630//723 604//593 603//599 +f 630//723 603//599 629//729 +f 657//724 630//723 629//729 +f 657//724 629//729 656//730 +f 683//725 657//724 656//730 +f 683//725 656//730 682//731 +f 711//726 683//725 682//731 +f 711//726 682//731 710//732 +f 740//727 711//726 710//732 +f 740//727 710//732 739//733 +f 768//728 740//727 739//733 +f 768//728 739//733 767//734 +f 629//729 603//599 602//605 +f 629//729 602//605 628//735 +f 656//730 629//729 628//735 +f 656//730 628//735 655//736 +f 682//731 656//730 655//736 +f 682//731 655//736 681//737 +f 710//732 682//731 681//737 +f 710//732 681//737 709//738 +f 739//733 710//732 709//738 +f 739//733 709//738 738//739 +f 767//734 739//733 738//739 +f 767//734 738//739 766//740 +f 628//735 602//605 601//611 +f 628//735 601//611 627//741 +f 655//736 628//735 627//741 +f 655//736 627//741 654//742 +f 681//737 655//736 654//742 +f 681//737 654//742 680//743 +f 709//738 681//737 680//743 +f 709//738 680//743 708//744 +f 738//739 709//738 708//744 +f 738//739 708//744 737//745 +f 766//740 738//739 737//745 +f 766//740 737//745 765//746 +f 627//741 601//611 600//617 +f 627//741 600//617 626//747 +f 654//742 627//741 626//747 +f 654//742 626//747 653//748 +f 680//743 654//742 653//748 +f 680//743 653//748 679//749 +f 708//744 680//743 679//749 +f 708//744 679//749 707//750 +f 737//745 708//744 707//750 +f 737//745 707//750 736//751 +f 765//746 737//745 736//751 +f 765//746 736//751 764//752 +f 626//747 600//617 599//623 +f 626//747 599//623 625//753 +f 653//748 626//747 625//753 +f 653//748 625//753 652//754 +f 679//749 653//748 652//754 +f 679//749 652//754 678//755 +f 707//750 679//749 678//755 +f 707//750 678//755 706//756 +f 736//751 707//750 706//756 +f 736//751 706//756 735//757 +f 764//752 736//751 735//757 +f 764//752 735//757 763//758 +f 625//753 599//623 598//629 +f 625//753 598//629 624//759 +f 652//754 625//753 624//759 +f 652//754 624//759 651//760 +f 678//755 652//754 651//760 +f 678//755 651//760 677//761 +f 706//756 678//755 677//761 +f 706//756 677//761 705//762 +f 735//757 706//756 705//762 +f 735//757 705//762 734//763 +f 763//758 735//757 734//763 +f 763//758 734//763 762//764 +f 624//759 598//629 597//635 +f 624//759 597//635 623//765 +f 651//760 624//759 623//765 +f 651//760 623//765 650//766 +f 677//761 651//760 650//766 +f 677//761 650//766 676//767 +f 705//762 677//761 676//767 +f 705//762 676//767 704//768 +f 734//763 705//762 704//768 +f 734//763 704//768 733//769 +f 762//764 734//763 733//769 +f 762//764 733//769 761//770 +f 623//765 597//635 596//641 +f 623//765 596//641 622//771 +f 650//766 623//765 622//771 +f 650//766 622//771 649//772 +f 676//767 650//766 649//772 +f 676//767 649//772 675//773 +f 704//768 676//767 675//773 +f 704//768 675//773 703//774 +f 733//769 704//768 703//774 +f 733//769 703//774 732//775 +f 761//770 733//769 732//775 +f 761//770 732//775 760//776 +f 622//771 596//641 613//248 +f 622//771 613//248 640//777 +f 649//772 622//771 640//777 +f 649//772 640//777 665//778 +f 675//773 649//772 665//778 +f 675//773 665//778 693//779 +f 703//774 675//773 693//779 +f 703//774 693//779 722//780 +f 732//775 703//774 722//780 +f 732//775 722//780 751//781 +f 760//776 732//775 751//781 +f 760//776 751//781 779//782 +f 693//779 665//778 691//228 +f 693//779 691//228 702//646 +f 722//780 693//779 702//646 +f 722//780 702//646 731//648 +f 751//781 722//780 731//648 +f 751//781 731//648 759//650 +f 779//782 751//781 759//650 +f 779//782 759//650 786//652 +f 917//783 918//784 913//785 +f 892//786 917//783 913//785 +f 892//786 913//785 887//787 +f 866//788 892//786 887//787 +f 866//788 887//787 861//789 +f 840//790 866//788 861//789 +f 840//790 861//789 834//791 +f 813//792 840//790 834//791 +f 813//792 834//791 807//793 +f 786//652 813//792 807//793 +f 786//652 807//793 779//782 +f 913//785 918//784 893//794 +f 887//787 913//785 893//794 +f 887//787 893//794 867//795 +f 861//789 887//787 867//795 +f 861//789 867//795 841//796 +f 834//791 861//789 841//796 +f 834//791 841//796 814//797 +f 807//793 834//791 814//797 +f 807//793 814//797 787//798 +f 779//782 807//793 787//798 +f 779//782 787//798 760//776 +f 893//794 918//784 894//799 +f 867//795 893//794 894//799 +f 867//795 894//799 868//800 +f 841//796 867//795 868//800 +f 841//796 868//800 842//801 +f 814//797 841//796 842//801 +f 814//797 842//801 815//802 +f 787//798 814//797 815//802 +f 787//798 815//802 788//803 +f 760//776 787//798 788//803 +f 760//776 788//803 761//770 +f 894//799 918//784 895//804 +f 868//800 894//799 895//804 +f 868//800 895//804 869//805 +f 842//801 868//800 869//805 +f 842//801 869//805 843//806 +f 815//802 842//801 843//806 +f 815//802 843//806 816//807 +f 788//803 815//802 816//807 +f 788//803 816//807 789//808 +f 761//770 788//803 789//808 +f 761//770 789//808 762//764 +f 895//804 918//784 896//809 +f 869//805 895//804 896//809 +f 869//805 896//809 870//810 +f 843//806 869//805 870//810 +f 843//806 870//810 844//811 +f 816//807 843//806 844//811 +f 816//807 844//811 817//812 +f 789//808 816//807 817//812 +f 789//808 817//812 790//813 +f 762//764 789//808 790//813 +f 762//764 790//813 763//758 +f 896//809 918//784 897//814 +f 870//810 896//809 897//814 +f 870//810 897//814 871//815 +f 844//811 870//810 871//815 +f 844//811 871//815 845//816 +f 817//812 844//811 845//816 +f 817//812 845//816 818//817 +f 790//813 817//812 818//817 +f 790//813 818//817 791//818 +f 763//758 790//813 791//818 +f 763//758 791//818 764//752 +f 897//814 918//784 898//819 +f 871//815 897//814 898//819 +f 871//815 898//819 872//820 +f 845//816 871//815 872//820 +f 845//816 872//820 846//821 +f 818//817 845//816 846//821 +f 818//817 846//821 819//822 +f 791//818 818//817 819//822 +f 791//818 819//822 792//823 +f 764//752 791//818 792//823 +f 764//752 792//823 765//746 +f 898//819 918//784 899//824 +f 872//820 898//819 899//824 +f 872//820 899//824 873//825 +f 846//821 872//820 873//825 +f 846//821 873//825 847//826 +f 819//822 846//821 847//826 +f 819//822 847//826 820//827 +f 792//823 819//822 820//827 +f 792//823 820//827 793//828 +f 765//746 792//823 793//828 +f 765//746 793//828 766//740 +f 899//824 918//784 900//829 +f 873//825 899//824 900//829 +f 873//825 900//829 874//830 +f 847//826 873//825 874//830 +f 847//826 874//830 848//831 +f 820//827 847//826 848//831 +f 820//827 848//831 821//832 +f 793//828 820//827 821//832 +f 793//828 821//832 794//833 +f 766//740 793//828 794//833 +f 766//740 794//833 767//734 +f 900//829 918//784 901//834 +f 874//830 900//829 901//834 +f 874//830 901//834 875//835 +f 848//831 874//830 875//835 +f 848//831 875//835 849//836 +f 821//832 848//831 849//836 +f 821//832 849//836 822//837 +f 794//833 821//832 822//837 +f 794//833 822//837 795//838 +f 767//734 794//833 795//838 +f 767//734 795//838 768//728 +f 901//834 918//784 902//839 +f 875//835 901//834 902//839 +f 875//835 902//839 876//840 +f 849//836 875//835 876//840 +f 849//836 876//840 850//841 +f 822//837 849//836 850//841 +f 822//837 850//841 823//842 +f 795//838 822//837 823//842 +f 795//838 823//842 796//843 +f 768//728 795//838 796//843 +f 768//728 796//843 769//722 +f 902//839 918//784 903//844 +f 876//840 902//839 903//844 +f 876//840 903//844 877//845 +f 850//841 876//840 877//845 +f 850//841 877//845 851//846 +f 823//842 850//841 851//846 +f 823//842 851//846 824//847 +f 796//843 823//842 824//847 +f 796//843 824//847 797//848 +f 769//722 796//843 797//848 +f 769//722 797//848 770//717 +f 903//844 918//784 904//849 +f 877//845 903//844 904//849 +f 877//845 904//849 878//850 +f 851//846 877//845 878//850 +f 851//846 878//850 852//851 +f 824//847 851//846 852//851 +f 824//847 852//851 825//852 +f 797//848 824//847 825//852 +f 797//848 825//852 798//853 +f 770//717 797//848 798//853 +f 770//717 798//853 771//712 +f 904//849 918//784 905//854 +f 878//850 904//849 905//854 +f 878//850 905//854 879//855 +f 852//851 878//850 879//855 +f 852//851 879//855 853//856 +f 825//852 852//851 853//856 +f 825//852 853//856 826//857 +f 798//853 825//852 826//857 +f 798//853 826//857 799//858 +f 771//712 798//853 799//858 +f 771//712 799//858 772//707 +f 905//854 918//784 906//859 +f 879//855 905//854 906//859 +f 879//855 906//859 880//860 +f 853//856 879//855 880//860 +f 853//856 880//860 854//861 +f 826//857 853//856 854//861 +f 826//857 854//861 827//862 +f 799//858 826//857 827//862 +f 799//858 827//862 800//863 +f 772//707 799//858 800//863 +f 772//707 800//863 773//701 +f 906//859 918//784 907//864 +f 880//860 906//859 907//864 +f 880//860 907//864 881//865 +f 854//861 880//860 881//865 +f 854//861 881//865 855//866 +f 827//862 854//861 855//866 +f 827//862 855//866 828//867 +f 800//863 827//862 828//867 +f 800//863 828//867 801//868 +f 773//701 800//863 801//868 +f 773//701 801//868 780//695 +f 907//864 918//784 908//869 +f 881//865 907//864 908//869 +f 881//865 908//869 882//870 +f 855//866 881//865 882//870 +f 855//866 882//870 856//871 +f 828//867 855//866 856//871 +f 828//867 856//871 829//872 +f 801//868 828//867 829//872 +f 801//868 829//872 808//873 +f 780//695 801//868 808//873 +f 780//695 808//873 809//689 +f 908//869 918//784 909//874 +f 882//870 908//869 909//874 +f 882//870 909//874 883//875 +f 856//871 882//870 883//875 +f 856//871 883//875 857//876 +f 829//872 856//871 857//876 +f 829//872 857//876 836//877 +f 808//873 829//872 836//877 +f 808//873 836//877 835//878 +f 809//689 808//873 835//878 +f 809//689 835//878 810//683 +f 909//874 918//784 910//879 +f 883//875 909//874 910//879 +f 883//875 910//879 884//880 +f 857//876 883//875 884//880 +f 857//876 884//880 863//881 +f 836//877 857//876 863//881 +f 836//877 863//881 862//882 +f 835//878 836//877 862//882 +f 835//878 862//882 837//883 +f 810//683 835//878 837//883 +f 810//683 837//883 830//677 +f 910//879 918//784 911//884 +f 884//880 910//879 911//884 +f 884//880 911//884 889//885 +f 863//881 884//880 889//885 +f 863//881 889//885 888//886 +f 862//882 863//881 888//886 +f 862//882 888//886 864//887 +f 837//883 862//882 864//887 +f 837//883 864//887 858//888 +f 830//677 837//883 858//888 +f 830//677 858//888 838//671 +f 911//884 918//784 915//889 +f 889//885 911//884 915//889 +f 889//885 915//889 914//890 +f 888//886 889//885 914//890 +f 888//886 914//890 890//891 +f 864//887 888//886 890//891 +f 864//887 890//891 885//892 +f 858//888 864//887 885//892 +f 858//888 885//892 859//893 +f 838//671 858//888 859//893 +f 838//671 859//893 833//665 +f 915//889 918//784 919//894 +f 914//890 915//889 919//894 +f 914//890 919//894 912//895 +f 890//891 914//890 912//895 +f 890//891 912//895 886//896 +f 885//892 890//891 886//896 +f 885//892 886//896 860//897 +f 859//893 885//892 860//897 +f 859//893 860//897 832//898 +f 833//665 859//893 832//898 +f 833//665 832//898 805//659 +f 919//894 918//784 916//899 +f 912//895 919//894 916//899 +f 912//895 916//899 891//900 +f 886//896 912//895 891//900 +f 886//896 891//900 865//901 +f 860//897 886//896 865//901 +f 860//897 865//901 839//902 +f 832//898 860//897 839//902 +f 832//898 839//902 812//903 +f 805//659 832//898 812//903 +f 805//659 812//903 785//653 +f 916//899 918//784 917//783 +f 891//900 916//899 917//783 +f 891//900 917//783 892//786 +f 865//901 891//900 892//786 +f 865//901 892//786 866//788 +f 839//902 865//901 866//788 +f 839//902 866//788 840//790 +f 812//903 839//902 840//790 +f 812//903 840//790 813//792 +f 785//653 812//903 813//792 +f 785//653 813//792 786//652 +f 404//412 1267//904 1268//905 +f 384//906 373//907 372//480 +f 346//908 345//501 352//494 +f 435//909 436//426 419//419 +f 331//910 327//350 335//508 +f 462//439 453//433 1265//911 +f 920//912 921//913 922//914 +f 920//912 922//914 923//915 +f 923//915 922//914 927//916 +f 923//915 927//916 933//917 +f 933//917 927//916 940//918 +f 933//917 940//918 949//919 +f 949//919 940//918 959//920 +f 949//919 959//920 971//921 +f 971//921 959//920 984//922 +f 971//921 984//922 999//923 +f 999//923 984//922 1011//924 +f 999//923 1011//924 1027//925 +f 1027//925 1011//924 1042//926 +f 1027//925 1042//926 1059//927 +f 1059//927 1042//926 1077//928 +f 1059//927 1077//928 1095//929 +f 1095//929 1077//928 1110//930 +f 1095//929 1110//930 1129//931 +f 1129//931 1110//930 1144//932 +f 1129//931 1144//932 1163//933 +f 1163//933 1144//932 1179//934 +f 1163//933 1179//934 1196//935 +f 1196//935 1179//934 1210//936 +f 1196//935 1210//936 1220//937 +f 1220//937 1210//936 1212//938 +f 1220//937 1212//938 1201//939 +f 1201//939 1212//938 1181//940 +f 1201//939 1181//940 1169//941 +f 1169//941 1181//940 1147//942 +f 1169//941 1147//942 1135//943 +f 1135//943 1147//942 1113//944 +f 1135//943 1113//944 1102//945 +f 1102//945 1113//944 1081//946 +f 1102//945 1081//946 1065//947 +f 1065//947 1081//946 1046//948 +f 1065//947 1046//948 1032//949 +f 1032//949 1046//948 1016//950 +f 1032//949 1016//950 1003//951 +f 1003//951 1016//950 988//952 +f 1003//951 988//952 974//953 +f 974//953 988//952 962//954 +f 974//953 962//954 951//955 +f 951//955 962//954 942//956 +f 951//955 942//956 934//957 +f 934//957 942//956 928//958 +f 934//957 928//958 924//959 +f 924//959 928//958 921//913 +f 921//913 920//912 924//959 +f 926//960 920//912 923//915 +f 926//960 923//915 932//961 +f 938//962 926//960 932//961 +f 938//962 932//961 947//963 +f 956//964 938//962 947//963 +f 956//964 947//963 968//965 +f 980//966 956//964 968//965 +f 980//966 968//965 995//967 +f 1006//968 980//966 995//967 +f 1006//968 995//967 1022//969 +f 1036//970 1006//968 1022//969 +f 1036//970 1022//969 1053//971 +f 932//961 923//915 933//917 +f 932//961 933//917 948//972 +f 947//963 932//961 948//972 +f 947//963 948//972 969//973 +f 968//965 947//963 969//973 +f 968//965 969//973 996//974 +f 995//967 968//965 996//974 +f 995//967 996//974 1023//975 +f 1022//969 995//967 1023//975 +f 1022//969 1023//975 1054//976 +f 1053//971 1022//969 1054//976 +f 1053//971 1054//976 1089//977 +f 948//972 933//917 949//919 +f 948//972 949//919 970//978 +f 969//973 948//972 970//978 +f 969//973 970//978 997//979 +f 996//974 969//973 997//979 +f 996//974 997//979 1024//980 +f 1023//975 996//974 1024//980 +f 1023//975 1024//980 1055//981 +f 1054//976 1023//975 1055//981 +f 1054//976 1055//981 1090//982 +f 1089//977 1054//976 1090//982 +f 1089//977 1090//982 1109//983 +f 970//978 949//919 971//921 +f 970//978 971//921 998//984 +f 997//979 970//978 998//984 +f 997//979 998//984 1025//985 +f 1024//980 997//979 1025//985 +f 1024//980 1025//985 1056//986 +f 1055//981 1024//980 1056//986 +f 1055//981 1056//986 1091//987 +f 1090//982 1055//981 1091//987 +f 1090//982 1091//987 1124//988 +f 1109//983 1090//982 1124//988 +f 1109//983 1124//988 1122//989 +f 998//984 971//921 999//923 +f 998//984 999//923 1026//990 +f 1025//985 998//984 1026//990 +f 1025//985 1026//990 1057//991 +f 1056//986 1025//985 1057//991 +f 1056//986 1057//991 1092//992 +f 1091//987 1056//986 1092//992 +f 1091//987 1092//992 1125//993 +f 1124//988 1091//987 1125//993 +f 1124//988 1125//993 1156//994 +f 1122//989 1124//988 1156//994 +f 1122//989 1156//994 1142//995 +f 1026//990 999//923 1027//925 +f 1026//990 1027//925 1058//996 +f 1057//991 1026//990 1058//996 +f 1057//991 1058//996 1093//997 +f 1092//992 1057//991 1093//997 +f 1092//992 1093//997 1126//998 +f 1125//993 1092//992 1126//998 +f 1125//993 1126//998 1159//999 +f 1156//994 1125//993 1159//999 +f 1156//994 1159//999 1176//1000 +f 1142//995 1156//994 1176//1000 +f 1142//995 1176//1000 1157//1001 +f 1058//996 1027//925 1059//927 +f 1058//996 1059//927 1094//1002 +f 1093//997 1058//996 1094//1002 +f 1093//997 1094//1002 1127//1003 +f 1126//998 1093//997 1127//1003 +f 1126//998 1127//1003 1160//1004 +f 1159//999 1126//998 1160//1004 +f 1159//999 1160//1004 1192//1005 +f 1176//1000 1159//999 1192//1005 +f 1176//1000 1192//1005 1189//1006 +f 1157//1001 1176//1000 1189//1006 +f 1157//1001 1189//1006 1178//1007 +f 1094//1002 1059//927 1095//929 +f 1094//1002 1095//929 1128//1008 +f 1127//1003 1094//1002 1128//1008 +f 1127//1003 1128//1008 1161//1009 +f 1160//1004 1127//1003 1161//1009 +f 1160//1004 1161//1009 1193//1010 +f 1192//1005 1160//1004 1193//1010 +f 1192//1005 1193//1010 1215//1011 +f 1189//1006 1192//1005 1215//1011 +f 1189//1006 1215//1011 1207//1012 +f 1178//1007 1189//1006 1207//1012 +f 1178//1007 1207//1012 1191//1013 +f 1128//1008 1095//929 1129//931 +f 1128//1008 1129//931 1162//1014 +f 1161//1009 1128//1008 1162//1014 +f 1161//1009 1162//1014 1194//1015 +f 1193//1010 1161//1009 1194//1015 +f 1193//1010 1194//1015 1217//1016 +f 1215//1011 1193//1010 1217//1016 +f 1215//1011 1217//1016 1227//1017 +f 1207//1012 1215//1011 1227//1017 +f 1207//1012 1227//1017 1216//1018 +f 1191//1013 1207//1012 1216//1018 +f 1191//1013 1216//1018 1209//1019 +f 1162//1014 1129//931 1163//933 +f 1162//1014 1163//933 1195//1020 +f 1194//1015 1162//1014 1195//1020 +f 1194//1015 1195//1020 1218//1021 +f 1217//1016 1194//1015 1218//1021 +f 1217//1016 1218//1021 1230//1022 +f 1227//1017 1217//1016 1230//1022 +f 1227//1017 1230//1022 1229//1023 +f 1216//1018 1227//1017 1229//1023 +f 1216//1018 1229//1023 1225//1024 +f 1209//1019 1216//1018 1225//1024 +f 1209//1019 1225//1024 1203//1025 +f 1195//1020 1163//933 1196//935 +f 1195//1020 1196//935 1219//1026 +f 1218//1021 1195//1020 1219//1026 +f 1218//1021 1219//1026 1231//1027 +f 1230//1022 1218//1021 1231//1027 +f 1230//1022 1231//1027 1232//1028 +f 1229//1023 1230//1022 1232//1028 +f 1229//1023 1232//1028 1228//1029 +f 1225//1024 1229//1023 1228//1029 +f 1225//1024 1228//1029 1214//1030 +f 1203//1025 1225//1024 1214//1030 +f 1203//1025 1214//1030 1184//1031 +f 1219//1026 1196//935 1220//937 +f 1219//1026 1220//937 1224//1032 +f 1231//1027 1219//1026 1224//1032 +f 1231//1027 1224//1032 1223//1033 +f 1232//1028 1231//1027 1223//1033 +f 1232//1028 1223//1033 1222//1034 +f 1228//1029 1232//1028 1222//1034 +f 1228//1029 1222//1034 1221//1035 +f 1214//1030 1228//1029 1221//1035 +f 1214//1030 1221//1035 1204//1036 +f 1184//1031 1214//1030 1204//1036 +f 1184//1031 1204//1036 1171//1037 +f 1224//1032 1220//937 1201//939 +f 1224//1032 1201//939 1200//1038 +f 1223//1033 1224//1032 1200//1038 +f 1223//1033 1200//1038 1199//1039 +f 1222//1034 1223//1033 1199//1039 +f 1222//1034 1199//1039 1198//1040 +f 1221//1035 1222//1034 1198//1040 +f 1221//1035 1198//1040 1197//1041 +f 1204//1036 1221//1035 1197//1041 +f 1204//1036 1197//1041 1185//1042 +f 1171//1037 1204//1036 1185//1042 +f 1171//1037 1185//1042 1151//1043 +f 1200//1038 1201//939 1169//941 +f 1200//1038 1169//941 1168//1044 +f 1199//1039 1200//1038 1168//1044 +f 1199//1039 1168//1044 1167//1045 +f 1198//1040 1199//1039 1167//1045 +f 1198//1040 1167//1045 1166//1046 +f 1197//1041 1198//1040 1166//1046 +f 1197//1041 1166//1046 1165//1047 +f 1185//1042 1197//1041 1165//1047 +f 1185//1042 1165//1047 1164//1048 +f 1151//1043 1185//1042 1164//1048 +f 1151//1043 1164//1048 1137//1049 +f 1168//1044 1169//941 1135//943 +f 1168//1044 1135//943 1134//1050 +f 1167//1045 1168//1044 1134//1050 +f 1167//1045 1134//1050 1133//1051 +f 1166//1046 1167//1045 1133//1051 +f 1166//1046 1133//1051 1132//1052 +f 1165//1047 1166//1046 1132//1052 +f 1165//1047 1132//1052 1131//1053 +f 1164//1048 1165//1047 1131//1053 +f 1164//1048 1131//1053 1130//1054 +f 1137//1049 1164//1048 1130//1054 +f 1137//1049 1130//1054 1117//1055 +f 1134//1050 1135//943 1102//945 +f 1134//1050 1102//945 1101//1056 +f 1133//1051 1134//1050 1101//1056 +f 1133//1051 1101//1056 1100//1057 +f 1132//1052 1133//1051 1100//1057 +f 1132//1052 1100//1057 1099//1058 +f 1131//1053 1132//1052 1099//1058 +f 1131//1053 1099//1058 1098//1059 +f 1130//1054 1131//1053 1098//1059 +f 1130//1054 1098//1059 1097//1060 +f 1117//1055 1130//1054 1097//1060 +f 1117//1055 1097//1060 1096//1061 +f 1101//1056 1102//945 1065//947 +f 1101//1056 1065//947 1064//1062 +f 1100//1057 1101//1056 1064//1062 +f 1100//1057 1064//1062 1063//1063 +f 1099//1058 1100//1057 1063//1063 +f 1099//1058 1063//1063 1062//1064 +f 1098//1059 1099//1058 1062//1064 +f 1098//1059 1062//1064 1061//1065 +f 1097//1060 1098//1059 1061//1065 +f 1097//1060 1061//1065 1060//1066 +f 1096//1061 1097//1060 1060//1066 +f 1096//1061 1060//1066 1066//1067 +f 1064//1062 1065//947 1032//949 +f 1064//1062 1032//949 1031//1068 +f 1063//1063 1064//1062 1031//1068 +f 1063//1063 1031//1068 1030//1069 +f 1062//1064 1063//1063 1030//1069 +f 1062//1064 1030//1069 1029//1070 +f 1061//1065 1062//1064 1029//1070 +f 1061//1065 1029//1070 1028//1071 +f 1060//1066 1061//1065 1028//1071 +f 1060//1066 1028//1071 1033//1072 +f 1066//1067 1060//1066 1033//1072 +f 1066//1067 1033//1072 1050//1073 +f 1031//1068 1032//949 1003//951 +f 1031//1068 1003//951 1002//1074 +f 1030//1069 1031//1068 1002//1074 +f 1030//1069 1002//1074 1001//1075 +f 1029//1070 1030//1069 1001//1075 +f 1029//1070 1001//1075 1000//1076 +f 1028//1071 1029//1070 1000//1076 +f 1028//1071 1000//1076 1004//1077 +f 1033//1072 1028//1071 1004//1077 +f 1033//1072 1004//1077 1021//1078 +f 1050//1073 1033//1072 1021//1078 +f 1050//1073 1021//1078 1041//1079 +f 1002//1074 1003//951 974//953 +f 1002//1074 974//953 973//1080 +f 1001//1075 1002//1074 973//1080 +f 1001//1075 973//1080 972//1081 +f 1000//1076 1001//1075 972//1081 +f 1000//1076 972//1081 975//1082 +f 1004//1077 1000//1076 975//1082 +f 1004//1077 975//1082 992//1083 +f 1021//1078 1004//1077 992//1083 +f 1021//1078 992//1083 1010//1084 +f 1041//1079 1021//1078 1010//1084 +f 1041//1079 1010//1084 1040//1085 +f 973//1080 974//953 951//955 +f 973//1080 951//955 950//1086 +f 972//1081 973//1080 950//1086 +f 972//1081 950//1086 952//1087 +f 975//1082 972//1081 952//1087 +f 975//1082 952//1087 965//1088 +f 992//1083 975//1082 965//1088 +f 992//1083 965//1088 983//1089 +f 1010//1084 992//1083 983//1089 +f 1010//1084 983//1089 1009//1090 +f 1040//1085 1010//1084 1009//1090 +f 1040//1085 1009//1090 1039//1091 +f 950//1086 951//955 934//957 +f 950//1086 934//957 935//1092 +f 952//1087 950//1086 935//1092 +f 952//1087 935//1092 944//1093 +f 965//1088 952//1087 944//1093 +f 965//1088 944//1093 958//1094 +f 983//1089 965//1088 958//1094 +f 983//1089 958//1094 982//1095 +f 1009//1090 983//1089 982//1095 +f 1009//1090 982//1095 1008//1096 +f 1039//1091 1009//1090 1008//1096 +f 1039//1091 1008//1096 1038//1097 +f 935//1092 934//957 924//959 +f 935//1092 924//959 929//1098 +f 944//1093 935//1092 929//1098 +f 944//1093 929//1098 939//1099 +f 958//1094 944//1093 939//1099 +f 958//1094 939//1099 957//1100 +f 982//1095 958//1094 957//1100 +f 982//1095 957//1100 981//1101 +f 1008//1096 982//1095 981//1101 +f 1008//1096 981//1101 1007//1102 +f 1038//1097 1008//1096 1007//1102 +f 1038//1097 1007//1102 1037//1103 +f 924//959 920//912 929//1098 +f 929//1098 920//912 926//960 +f 939//1099 929//1098 926//960 +f 939//1099 926//960 938//962 +f 957//1100 939//1099 938//962 +f 957//1100 938//962 956//964 +f 981//1101 957//1100 956//964 +f 981//1101 956//964 980//966 +f 1007//1102 981//1101 980//966 +f 1007//1102 980//966 1006//968 +f 1037//1103 1007//1102 1006//968 +f 1037//1103 1006//968 1036//970 +f 993//1104 1005//1105 976//1106 +f 966//1107 993//1104 976//1106 +f 966//1107 976//1106 953//1108 +f 945//1109 966//1107 953//1108 +f 945//1109 953//1108 936//1110 +f 930//1111 945//1109 936//1110 +f 930//1111 936//1110 925//1112 +f 921//913 930//1111 925//1112 +f 921//913 925//1112 922//914 +f 976//1106 1005//1105 977//1113 +f 953//1108 976//1106 977//1113 +f 953//1108 977//1113 954//1114 +f 936//1110 953//1108 954//1114 +f 936//1110 954//1114 937//1115 +f 925//1112 936//1110 937//1115 +f 925//1112 937//1115 931//1116 +f 922//914 925//1112 931//1116 +f 922//914 931//1116 927//916 +f 977//1113 1005//1105 978//1117 +f 954//1114 977//1113 978//1117 +f 954//1114 978//1117 955//1118 +f 937//1115 954//1114 955//1118 +f 937//1115 955//1118 946//1119 +f 931//1116 937//1115 946//1119 +f 931//1116 946//1119 941//1120 +f 927//916 931//1116 941//1120 +f 927//916 941//1120 940//918 +f 978//1117 1005//1105 979//1121 +f 955//1118 978//1117 979//1121 +f 955//1118 979//1121 967//1122 +f 946//1119 955//1118 967//1122 +f 946//1119 967//1122 961//1123 +f 941//1120 946//1119 961//1123 +f 941//1120 961//1123 960//1124 +f 940//918 941//1120 960//1124 +f 940//918 960//1124 959//920 +f 979//1121 1005//1105 994//1125 +f 967//1122 979//1121 994//1125 +f 967//1122 994//1125 987//1126 +f 961//1123 967//1122 987//1126 +f 961//1123 987//1126 986//1127 +f 960//1124 961//1123 986//1127 +f 960//1124 986//1127 985//1128 +f 959//920 960//1124 985//1128 +f 959//920 985//1128 984//922 +f 994//1125 1005//1105 1015//1129 +f 987//1126 994//1125 1015//1129 +f 987//1126 1015//1129 1014//1130 +f 986//1127 987//1126 1014//1130 +f 986//1127 1014//1130 1013//1131 +f 985//1128 986//1127 1013//1131 +f 985//1128 1013//1131 1012//1132 +f 984//922 985//1128 1012//1132 +f 984//922 1012//1132 1011//924 +f 1015//1129 1005//1105 1035//1133 +f 1014//1130 1015//1129 1035//1133 +f 1014//1130 1035//1133 1045//1134 +f 1013//1131 1014//1130 1045//1134 +f 1013//1131 1045//1134 1044//1135 +f 1012//1132 1013//1131 1044//1135 +f 1012//1132 1044//1135 1043//1136 +f 1011//924 1012//1132 1043//1136 +f 1011//924 1043//1136 1042//926 +f 1035//1133 1005//1105 1052//1137 +f 1045//1134 1035//1133 1052//1137 +f 1045//1134 1052//1137 1080//1138 +f 1044//1135 1045//1134 1080//1138 +f 1044//1135 1080//1138 1079//1139 +f 1043//1136 1044//1135 1079//1139 +f 1043//1136 1079//1139 1078//1140 +f 1042//926 1043//1136 1078//1140 +f 1042//926 1078//1140 1077//928 +f 1052//1137 1005//1105 1068//1141 +f 1080//1138 1052//1137 1068//1141 +f 1080//1138 1068//1141 1106//1142 +f 1079//1139 1080//1138 1106//1142 +f 1079//1139 1106//1142 1112//1143 +f 1078//1140 1079//1139 1112//1143 +f 1078//1140 1112//1143 1111//1144 +f 1077//928 1078//1140 1111//1144 +f 1077//928 1111//1144 1110//930 +f 1068//1141 1005//1105 1087//1145 +f 1106//1142 1068//1141 1087//1145 +f 1106//1142 1087//1145 1120//1146 +f 1112//1143 1106//1142 1120//1146 +f 1112//1143 1120//1146 1146//1147 +f 1111//1144 1112//1143 1146//1147 +f 1111//1144 1146//1147 1145//1148 +f 1110//930 1111//1144 1145//1148 +f 1110//930 1145//1148 1144//932 +f 1087//1145 1005//1105 1107//1149 +f 1120//1146 1087//1145 1107//1149 +f 1120//1146 1107//1149 1140//1150 +f 1146//1147 1120//1146 1140//1150 +f 1146//1147 1140//1150 1174//1151 +f 1145//1148 1146//1147 1174//1151 +f 1145//1148 1174//1151 1180//1152 +f 1144//932 1145//1148 1180//1152 +f 1144//932 1180//1152 1179//934 +f 1107//1149 1005//1105 1121//1153 +f 1140//1150 1107//1149 1121//1153 +f 1140//1150 1121//1153 1154//1154 +f 1174//1151 1140//1150 1154//1154 +f 1174//1151 1154//1154 1188//1155 +f 1180//1152 1174//1151 1188//1155 +f 1180//1152 1188//1155 1211//1156 +f 1179//934 1180//1152 1211//1156 +f 1179//934 1211//1156 1210//936 +f 1121//1153 1005//1105 1141//1157 +f 1154//1154 1121//1153 1141//1157 +f 1154//1154 1141//1157 1175//1158 +f 1188//1155 1154//1154 1175//1158 +f 1188//1155 1175//1158 1206//1159 +f 1211//1156 1188//1155 1206//1159 +f 1211//1156 1206//1159 1226//1160 +f 1210//936 1211//1156 1226//1160 +f 1210//936 1226//1160 1212//938 +f 1141//1157 1005//1105 1155//1161 +f 1175//1158 1141//1157 1155//1161 +f 1175//1158 1155//1161 1187//1162 +f 1206//1159 1175//1158 1187//1162 +f 1206//1159 1187//1162 1205//1163 +f 1226//1160 1206//1159 1205//1163 +f 1226//1160 1205//1163 1213//1164 +f 1212//938 1226//1160 1213//1164 +f 1212//938 1213//1164 1181//940 +f 1155//1161 1005//1105 1153//1165 +f 1187//1162 1155//1161 1153//1165 +f 1187//1162 1153//1165 1173//1166 +f 1205//1163 1187//1162 1173//1166 +f 1205//1163 1173//1166 1186//1167 +f 1213//1164 1205//1163 1186//1167 +f 1213//1164 1186//1167 1182//1168 +f 1181//940 1213//1164 1182//1168 +f 1181//940 1182//1168 1147//942 +f 1153//1165 1005//1105 1139//1169 +f 1173//1166 1153//1165 1139//1169 +f 1173//1166 1139//1169 1152//1170 +f 1186//1167 1173//1166 1152//1170 +f 1186//1167 1152//1170 1172//1171 +f 1182//1168 1186//1167 1172//1171 +f 1182//1168 1172//1171 1148//1172 +f 1147//942 1182//1168 1148//1172 +f 1147//942 1148//1172 1113//944 +f 1139//1169 1005//1105 1119//1173 +f 1152//1170 1139//1169 1119//1173 +f 1152//1170 1119//1173 1138//1174 +f 1172//1171 1152//1170 1138//1174 +f 1172//1171 1138//1174 1149//1175 +f 1148//1172 1172//1171 1149//1175 +f 1148//1172 1149//1175 1114//1176 +f 1113//944 1148//1172 1114//1176 +f 1113//944 1114//1176 1081//946 +f 1119//1173 1005//1105 1105//1177 +f 1138//1174 1119//1173 1105//1177 +f 1138//1174 1105//1177 1118//1178 +f 1149//1175 1138//1174 1118//1178 +f 1149//1175 1118//1178 1115//1179 +f 1114//1176 1149//1175 1115//1179 +f 1114//1176 1115//1179 1082//1180 +f 1081//946 1114//1176 1082//1180 +f 1081//946 1082//1180 1046//948 +f 1105//1177 1005//1105 1086//1181 +f 1118//1178 1105//1177 1086//1181 +f 1118//1178 1086//1181 1104//1182 +f 1115//1179 1118//1178 1104//1182 +f 1115//1179 1104//1182 1083//1183 +f 1082//1180 1115//1179 1083//1183 +f 1082//1180 1083//1183 1047//1184 +f 1046//948 1082//1180 1047//1184 +f 1046//948 1047//1184 1016//950 +f 1086//1181 1005//1105 1067//1185 +f 1104//1182 1086//1181 1067//1185 +f 1104//1182 1067//1185 1084//1186 +f 1083//1183 1104//1182 1084//1186 +f 1083//1183 1084//1186 1048//1187 +f 1047//1184 1083//1183 1048//1187 +f 1047//1184 1048//1187 1017//1188 +f 1016//950 1047//1184 1017//1188 +f 1016//950 1017//1188 988//952 +f 1067//1185 1005//1105 1051//1189 +f 1084//1186 1067//1185 1051//1189 +f 1084//1186 1051//1189 1049//1190 +f 1048//1187 1084//1186 1049//1190 +f 1048//1187 1049//1190 1018//1191 +f 1017//1188 1048//1187 1018//1191 +f 1017//1188 1018//1191 989//1192 +f 988//952 1017//1188 989//1192 +f 988//952 989//1192 962//954 +f 1051//1189 1005//1105 1034//1193 +f 1049//1190 1051//1189 1034//1193 +f 1049//1190 1034//1193 1019//1194 +f 1018//1191 1049//1190 1019//1194 +f 1018//1191 1019//1194 990//1195 +f 989//1192 1018//1191 990//1195 +f 989//1192 990//1195 963//1196 +f 962//954 989//1192 963//1196 +f 962//954 963//1196 942//956 +f 1034//1193 1005//1105 1020//1197 +f 1019//1194 1034//1193 1020//1197 +f 1019//1194 1020//1197 991//1198 +f 990//1195 1019//1194 991//1198 +f 990//1195 991//1198 964//1199 +f 963//1196 990//1195 964//1199 +f 963//1196 964//1199 943//1200 +f 942//956 963//1196 943//1200 +f 942//956 943//1200 928//958 +f 1020//1197 1005//1105 993//1104 +f 991//1198 1020//1197 993//1104 +f 991//1198 993//1104 966//1107 +f 964//1199 991//1198 966//1107 +f 964//1199 966//1107 945//1109 +f 943//1200 964//1199 945//1109 +f 943//1200 945//1109 930//1111 +f 928//958 943//1200 930//1111 +f 928//958 930//1111 921//913 +f 1151//1043 1137//1049 1150//1201 +f 1142//995 1143//1202 1122//989 +f 1053//971 1089//977 1069//1203 +f 1122//989 1123//1204 1109//983 +f 1096//1061 1103//1205 1117//1055 +f 1171//1037 1170//1206 1184//1031 +f 1191//1013 1209//1019 1190//1207 +f 1036//970 1053//971 1070//1208 +f 1036//970 1070//1208 1037//1103 +f 1203//1025 1202//1209 1209//1019 +f 1066//1067 1085//1210 1096//1061 +f 1050//1073 1076//1211 1066//1067 +f 1184//1031 1183//1212 1203//1025 +f 1041//1079 1040//1085 1075//1213 +f 1171//1037 1151//1043 1170//1206 +f 1157//1001 1158//1214 1142//995 +f 1137//1049 1117//1055 1136//1215 +f 1038//1097 1072//1216 1039//1091 +f 1178//1007 1191//1013 1177//1217 +f 1089//977 1109//983 1088//1218 +f 1037//1103 1071//1219 1038//1097 +f 1050//1073 1041//1079 1076//1211 +f 1157//1001 1178//1007 1158//1214 +f 1040//1085 1039//1091 1074//1220 +f 1170//1206 1150//1201 452//1221 +f 1264//1222 1071//1219 1263//1223 +f 1261//1224 1262//1225 1076//1211 +f 1085//1210 1076//1211 1262//1225 +f 1190//1207 1208//1226 405//1227 +f 509//176 526//519 1260//1228 +f 1260//1228 526//519 556//523 +f 167//201 556//523 595//202 +f 595//202 621//526 1255//200 +f 172//192 163//182 1254//199 +f 8//49 18//42 3//1229 +f 3//1229 18//42 1288//1230 +f 15//75 7//66 1240//82 +f 1250//50 8//49 3//1229 +f 1//32 1283//40 566//33 +f 593//3 566//33 9//41 +f 19//1231 20//34 33//25 +f 1243//2 636//89 593//3 +f 64//18 40//6 36//17 +f 1244//24 64//18 36//17 +f 641//579 614//582 1237//1232 +f 1250//50 1239//1233 4//48 +f 7//66 4//48 1239//1233 +f 5//74 14//73 11//81 +f 1240//82 7//66 1239//1233 +f 1//32 553//31 565//56 +f 593//3 9//41 1289//83 +f 18//42 20//34 1288//1230 +f 40//6 27//5 1252//16 +f 1249//58 6//65 565//56 +f 14//73 15//75 11//81 +f 592//57 1234//130 1233//58 +f 1237//1232 614//582 588//586 +f 1237//1232 588//586 605//592 +f 539//175 159//177 1259//1234 +f 164//257 1257//1235 168//251 +f 509//176 1256//1236 159//177 +f 1258//250 585//249 1259//1234 +f 169//1237 164//257 174//242 +f 191//236 208//230 185//1238 +f 1290//1239 207//229 640//777 +f 621//526 1292//1240 1255//200 +f 163//182 160//178 157//180 +f 1284//1241 1292//1240 648//227 +f 1252//16 27//5 12//95 +f 119//124 116//129 104//161 +f 116//129 88//135 1242//136 +f 87//159 666//713 715//160 +f 87//159 1241//1242 666//713 +f 1253//1243 47//150 631//152 +f 631//152 666//713 1253//1243 +f 86//142 74//144 60//143 +f 640//777 1291//1244 1290//1239 +f 1291//1244 640//777 613//248 +f 208//230 219//220 200//1245 +f 665//778 640//777 207//229 +f 1285//226 200//1245 219//220 +f 648//227 207//229 1284//1241 +f 691//228 665//778 207//229 +f 605//592 1236//1246 1245//1246 +f 1235//151 605//592 631//152 +f 1248//145 48//153 37//167 +f 667//708 1251//1247 1247//158 +f 605//592 1235//151 1236//1246 +f 641//579 1238//1248 1246//1249 +f 641//579 1237//1232 1238//1248 +f 404//412 391//405 1267//904 +f 1265//911 453//433 436//426 +f 328//351 327//350 331//910 +f 443//445 462//439 469//1250 +f 342//370 1275//1251 344//1252 +f 342//370 334//363 1275//1251 +f 372//480 385//473 384//906 +f 351//377 1271//1253 361//384 +f 351//377 350//1254 1271//1253 +f 337//1255 335//508 345//501 +f 384//906 385//473 396//466 +f 361//384 368//1256 369//391 +f 361//384 1271//1253 368//1256 +f 352//494 1276//1257 346//908 +f 397//1258 396//466 411//459 +f 342//370 350//1254 351//377 +f 342//370 344//1252 350//1254 +f 380//398 369//391 368//1256 +f 334//363 328//351 332//1259 +f 404//412 418//1260 419//419 +f 404//412 1268//905 418//1260 +f 426//452 1286//1261 1282//1262 +f 1282//1262 411//459 426//452 +f 352//494 362//487 1277//1263 +f 1277//1263 1276//1257 352//494 +f 391//405 380//398 381//1264 +f 426//452 443//445 444//1265 +f 444//1265 1286//1261 426//452 +f 362//487 372//480 373//907 +f 373//907 1277//1263 362//487 +f 1202//1209 1183//1212 1270//1266 +f 1116//1267 428//1268 1136//1215 +f 428//1268 1287//1269 1136//1215 +f 1073//1270 353//1271 1074//1220 +f 353//1271 363//1272 1074//1220 +f 353//1271 1073//1270 1279//1273 +f 1070//1208 1069//1203 1263//1223 +f 1274//1274 1069//1203 1088//1218 +f 1177//1217 1273//1275 1272//1276 +f 1272//1276 1158//1214 1177//1217 +f 428//1268 1116//1267 427//1277 +f 1088//1218 1108//1278 343//1279 +f 1103//1205 1085//1210 1278//1280 +f 1108//1278 1123//1204 1280//1281 +f 1123//1204 1281//1282 1280//1281 +f 1143//1202 1158//1214 360//1283 +f 1158//1214 1272//1276 360//1283 +f 1075//1213 1261//1224 1076//1211 +f 1085//1210 1262//1225 1278//1280 +f 1123//1204 1143//1202 1281//1282 +f 1143//1202 360//1283 1281//1282 +f 1074//1220 363//1272 1075//1213 +f 363//1272 1261//1224 1075//1213 +f 1270//1266 1183//1212 452//1221 +f 1266//1284 1150//1201 1136//1215 +f 1273//1275 1177//1217 1190//1207 +f 1208//1226 1202//1209 406//1285 +f 1202//1209 1269//1286 406//1285 +f 1072//1216 1071//1219 1264//1222 +f 1241//1242 1253//1243 666//713 +f 71//137 86//142 60//143 +f 88//135 86//142 71//137 +f 1245//1246 1237//1232 605//592 +f 119//124 104//161 90//119 +f 667//708 1246//1249 1251//1247 +f 621//526 648//227 1292//1240 +f 208//230 200//1245 185//1238 +f 174//242 191//236 169//1237 +f 1258//250 1291//1244 613//248 +f 1244//24 19//1231 33//25 +f 1288//1230 20//34 19//1231 +f 199//208 182//198 178//1287 +f 206//1288 218//214 190//1289 +f 1260//1228 556//523 167//201 +f 157//180 1254//199 163//182 +f 178//1287 182//198 1254//199 +f 218//214 206//1288 1285//226 +f 161//258 1257//1235 158//179 +f 324//345 312//274 323//336 +f 303//317 302//323 316//338 +f 305//305 304//311 318//340 +f 304//311 303//317 317//339 +f 322//347 309//281 321//341 +f 320//346 307//293 319//342 +f 301//329 311//335 314//344 +f 302//323 301//329 315//337 +f 311//335 312//274 313//343 +f 319//342 306//299 318//340 +f 321//341 308//287 320//346 +f 323//336 310//275 322//347 +f 418//1260 435//909 419//419 +f 337//1255 331//910 335//508 +f 469//1250 462//439 1265//911 +f 1137//1049 1136//1215 1150//1201 +f 1143//1202 1123//1204 1122//989 +f 1089//977 1088//1218 1069//1203 +f 1123//1204 1108//1278 1109//983 +f 1103//1205 1116//1267 1117//1055 +f 1170//1206 1183//1212 1184//1031 +f 1209//1019 1208//1226 1190//1207 +f 1053//971 1069//1203 1070//1208 +f 1070//1208 1071//1219 1037//1103 +f 1202//1209 1208//1226 1209//1019 +f 1085//1210 1103//1205 1096//1061 +f 1076//1211 1085//1210 1066//1067 +f 1183//1212 1202//1209 1203//1025 +f 1040//1085 1074//1220 1075//1213 +f 1151//1043 1150//1201 1170//1206 +f 1158//1214 1143//1202 1142//995 +f 1117//1055 1116//1267 1136//1215 +f 1072//1216 1073//1270 1039//1091 +f 1191//1013 1190//1207 1177//1217 +f 1109//983 1108//1278 1088//1218 +f 1071//1219 1072//1216 1038//1097 +f 1041//1079 1075//1213 1076//1211 +f 1178//1007 1177//1217 1158//1214 +f 1039//1091 1073//1270 1074//1220 +f 1150//1201 1266//1284 452//1221 +f 1071//1219 1070//1208 1263//1223 +f 1208//1226 406//1285 405//1227 +f 1256//1236 509//176 1260//1228 +f 1257//1235 161//258 168//251 +f 585//249 539//175 1259//1234 +f 715//160 667//708 1247//158 +f 667//708 641//579 1246//1249 +f 435//909 1265//911 436//426 +f 332//1259 328//351 331//910 +f 444//1265 443//445 469//1250 +f 346//908 337//1255 345//501 +f 397//1258 384//906 396//466 +f 1282//1262 397//1258 411//459 +f 381//1264 380//398 368//1256 +f 1275//1251 334//363 332//1259 +f 1267//904 391//405 381//1264 +f 1269//1286 1202//1209 1270//1266 +f 1073//1270 1072//1216 1279//1273 +f 1069//1203 1274//1274 1263//1223 +f 343//1279 1274//1274 1088//1218 +f 1116//1267 1103//1205 427//1277 +f 1108//1278 1280//1281 343//1279 +f 427//1277 1103//1205 1278//1280 +f 1183//1212 1170//1206 452//1221 +f 1287//1269 1266//1284 1136//1215 +f 405//1227 1273//1275 1190//1207 +f 1279//1273 1072//1216 1264//1222 +f 191//236 185//1238 169//1237 +f 190//1289 199//208 178//1287 +f 218//214 199//208 190//1289 diff --git a/A1/resources/tri.obj b/A1/resources/tri.obj new file mode 100644 index 0000000..0373bf9 --- /dev/null +++ b/A1/resources/tri.obj @@ -0,0 +1,4 @@ +v 0 0 0 +v 10 0 0 +v 5 5 5 +f 1 2 3 diff --git a/A1/resources/tri2.obj b/A1/resources/tri2.obj new file mode 100644 index 0000000..78273e0 --- /dev/null +++ b/A1/resources/tri2.obj @@ -0,0 +1,8 @@ +v 0 0 0 +v 10 0 0 +v 5 5 5 +v 0 5 0 +v 5 0 5 +v 10 5 0 +f 1 2 3 +f 4 5 6 diff --git a/A1/shadow8t4.zip b/A1/shadow8t4.zip new file mode 100644 index 0000000000000000000000000000000000000000..e70344d10954f5bb4b54f9f6ba3edcce46ab5779 GIT binary patch literal 30291 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 literal 0 HcmV?d00001 diff --git a/A1/shadow8t4/shadow8t4/CMakeLists.txt b/A1/shadow8t4/shadow8t4/CMakeLists.txt new file mode 100644 index 0000000..5deaf8f --- /dev/null +++ b/A1/shadow8t4/shadow8t4/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(A1) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/A1/shadow8t4/shadow8t4/README.txt b/A1/shadow8t4/shadow8t4/README.txt new file mode 100644 index 0000000..2f808ed --- /dev/null +++ b/A1/shadow8t4/shadow8t4/README.txt @@ -0,0 +1,7 @@ +1) Alexander Huddleston + +2) The last coloring mode goes from blue to green, top to bottom respectively. + +3) http://www.mathopenref.com/coordtrianglearea.html + +4) This was written and compiled on Arch Linux on a 64-bit machine. There should not be any errors when run on another machine, but I am making note here just in case. diff --git a/A1/shadow8t4/shadow8t4/src/Image.cpp b/A1/shadow8t4/shadow8t4/src/Image.cpp new file mode 100644 index 0000000..298edfb --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Image.cpp @@ -0,0 +1,61 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/A1/shadow8t4/shadow8t4/src/Image.h b/A1/shadow8t4/shadow8t4/src/Image.h new file mode 100644 index 0000000..2f27d46 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Image.h @@ -0,0 +1,25 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/A1/shadow8t4/shadow8t4/src/Triangle.cpp b/A1/shadow8t4/shadow8t4/src/Triangle.cpp new file mode 100644 index 0000000..46fd23c --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Triangle.cpp @@ -0,0 +1,45 @@ +#include "Triangle.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); + xmin = 0; + xmax = 0; + ymin = 0; + ymax = 0; + area = 0.0; +} + +float findArea(vertex &one, vertex &two, vertex &three) +{ + return abs(one.x*two.y + two.x*three.y + three.x*one.y - one.y*two.x - two.y*three.x - three.y*one.x)/2.0; +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); + xmin = one.x; + xmax = one.x; + ymin = one.y; + ymax = one.y; + area = findArea(one, two, three); +} + diff --git a/A1/shadow8t4/shadow8t4/src/Triangle.h b/A1/shadow8t4/shadow8t4/src/Triangle.h new file mode 100644 index 0000000..e366b09 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/Triangle.h @@ -0,0 +1,34 @@ +#pragma once +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; + float r = 0.0; + float g = 0.0; + float b = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; + float xmin; + float xmax; + float ymin; + float ymax; + float area; +}; + +float findArea(vertex &one, vertex &two, vertex &three); + +#endif diff --git a/A1/shadow8t4/shadow8t4/src/main.cpp b/A1/shadow8t4/shadow8t4/src/main.cpp new file mode 100644 index 0000000..3b64734 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/main.cpp @@ -0,0 +1,347 @@ +#include +#include +#include +#include + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include "Image.h" +#include "Triangle.h" + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 6) { + cout << "Usage: A1 meshfile image width height colormode" << endl; + return 0; + } + + srand(743298); + string meshName(argv[1]); + string filename(argv[2]); + int width = atoi(argv[3]); + int height = atoi(argv[4]); + int colormode = atoi(argv[5]); + + // Load geometry + vector posBuf; // list of vertex positions + + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + + } + index_offset += fv; + + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + cout << "Number of vertices: " << posBuf.size()/3 << endl; + + vector> zbuf; + + std::vector tris; + + // Split posBuf into triangles. + for(int i = 0; i < (int)posBuf.size()/9; i++) + { + vertex v1; + v1.x = posBuf[i*9]; + v1.y = posBuf[i*9 + 1]; + v1.z = posBuf[i*9 + 2]; + vertex v2; + v2.x = posBuf[i*9 + 3]; + v2.y = posBuf[i*9 + 4]; + v2.z = posBuf[i*9 + 5]; + vertex v3; + v3.x = posBuf[i*9 + 6]; + v3.y = posBuf[i*9 + 7]; + v3.z = posBuf[i*9 + 8]; + Tri t(v1, v2, v3); + tris.push_back(t); + } + + // Initialize min/max variables. + float xmin = posBuf[0]; + float xmax = xmin; + float ymin = posBuf[1]; + float ymax = ymin; + float zmin = tris[0].v[0].z; + float zmax = zmin; + + // First time finding max and min. + // Also, initializing r,g,b per triangle. + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + int temp1 = rand()%255; + int temp2 = rand()%255; + int temp3 = rand()%255; + tris[i].v[j].r = temp1; + tris[i].v[j].g = temp2; + tris[i].v[j].b = temp3; + } + } + + unsigned char r = rand()%255; + unsigned char b = rand()%255; + unsigned char g = rand()%255; + + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + + // Find scaling ratio. + float xratio = (1.0*width/(xmax - xmin)); + float yratio = (1.0*height/(ymax - ymin)); + float zratio = (255.0/(zmax-zmin)); + + float aratio = 1.0; + + // Determine and assign smaller ratio. + if(xratio < yratio) + { + aratio = xratio; + } + else + { + aratio = yratio; + } + + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + tris[i].v[j].x *= aratio; + tris[i].v[j].y *= aratio; + tris[i].v[j].z *= zratio; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + } + } + + float xoffset = ((width)/2 - (xmax + xmin)/2); + float yoffset = ((height)/2 - (ymax + ymin)/2); + float zoffset = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size();j++) + { + tris[i].v[j].x += xoffset; + tris[i].v[j].y += yoffset; + tris[i].v[j].z -= zoffset; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].xmin = tris[i].v[0].x; + tris[i].xmax = tris[i].v[0].x; + tris[i].ymin = tris[i].v[0].y; + tris[i].ymax = tris[i].v[0].y; + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + if(tris[i].xmin > tris[i].v[j].x) + tris[i].xmin = tris[i].v[j].x; + if(tris[i].xmax < tris[i].v[j].x) + tris[i].xmax = tris[i].v[j].x; + if(tris[i].ymin > tris[i].v[j].y) + tris[i].ymin = tris[i].v[j].y; + if(tris[i].ymax < tris[i].v[j].y) + tris[i].ymax = tris[i].v[j].y; + } + } + + + for(int r = 0; r < width; r++) + { + vector temp; + zbuf.push_back(temp); + for(int c = 0; c < height; c++) + { + zbuf.at(r).push_back(zmin); + } + } + + // Initialize variables for the three + // Barycentric areas. + float a1 = 0.0; + float a2 = 0.0; + float a3 = 0.0; + + // Initialize variables for the three + // Barycentric coordinates. + float l1 = 0.0; + float l2 = 0.0; + float l3 = 0.0; + + // Variable to hold current z coordinate. + float z = 0.0; + + // I had each triangle hold a variable which was its area, + // Here, I make sure they all have their areas set correctly. + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].area = findArea(tris[i].v[0], tris[i].v[1], tris[i].v[2]); + } + for(int i = 0; i < (int)tris.size(); i++) + { + for(int x = tris[i].xmin; x < tris[i].xmax; x++) + { + for(int y = tris[i].ymin; y < tris[i].ymax; y++) + { + // Temporary vertex so we can utilize findArea. + vertex tempv; + tempv.x = x; + tempv.y = y; + + a3 = findArea(tris[i].v[0], tris[i].v[1], tempv); + a2 = findArea(tris[i].v[0], tempv, tris[i].v[2]); + a1 = findArea(tempv, tris[i].v[1], tris[i].v[2]); + + l1 = a1/tris[i].area; + l2 = a2/tris[i].area; + l3 = a3/tris[i].area; + + r = (a1*tris[i].v[0].r + a2*tris[i].v[1].r + a3*tris[i].v[2].r)/tris[i].area; + g = (a1*tris[i].v[0].g + a2*tris[i].v[1].g + a3*tris[i].v[2].g)/tris[i].area; + b = (a1*tris[i].v[0].b + a2*tris[i].v[1].b + a3*tris[i].v[2].b)/tris[i].area; + + if(colormode == 0) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, r, g ,b); + zbuf.at(x).at(y) = z; + } + } + + float z1 = tris[i].v[0].z; + float z2 = tris[i].v[1].z; + float z3 = tris[i].v[2].z; + + z = (a1*z1 + a2*z2 + a3*z3)/tris[i].area; + if(colormode == 1) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, z, 0, 0); + zbuf.at(x).at(y) = z; + } + } + else if(colormode == 2) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, 0, (255/(ymax - ymin)) - (y - ymin)*(255/(ymax - ymin)), (y - ymin)*(255/(ymax - ymin))); + zbuf.at(x).at(y) = z; + } + } + } + } + } + + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/A1/shadow8t4/shadow8t4/src/stb_image_write.h b/A1/shadow8t4/shadow8t4/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h b/A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/A1/shadow8t4/shadow8t4/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/A1/src/Image.cpp b/A1/src/Image.cpp new file mode 100644 index 0000000..298edfb --- /dev/null +++ b/A1/src/Image.cpp @@ -0,0 +1,61 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/A1/src/Image.h b/A1/src/Image.h new file mode 100644 index 0000000..2f27d46 --- /dev/null +++ b/A1/src/Image.h @@ -0,0 +1,25 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/A1/src/Triangle.cpp b/A1/src/Triangle.cpp new file mode 100644 index 0000000..46fd23c --- /dev/null +++ b/A1/src/Triangle.cpp @@ -0,0 +1,45 @@ +#include "Triangle.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); + xmin = 0; + xmax = 0; + ymin = 0; + ymax = 0; + area = 0.0; +} + +float findArea(vertex &one, vertex &two, vertex &three) +{ + return abs(one.x*two.y + two.x*three.y + three.x*one.y - one.y*two.x - two.y*three.x - three.y*one.x)/2.0; +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); + xmin = one.x; + xmax = one.x; + ymin = one.y; + ymax = one.y; + area = findArea(one, two, three); +} + diff --git a/A1/src/Triangle.h b/A1/src/Triangle.h new file mode 100644 index 0000000..e366b09 --- /dev/null +++ b/A1/src/Triangle.h @@ -0,0 +1,34 @@ +#pragma once +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; + float r = 0.0; + float g = 0.0; + float b = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; + float xmin; + float xmax; + float ymin; + float ymax; + float area; +}; + +float findArea(vertex &one, vertex &two, vertex &three); + +#endif diff --git a/A1/src/main.cpp b/A1/src/main.cpp new file mode 100644 index 0000000..3b64734 --- /dev/null +++ b/A1/src/main.cpp @@ -0,0 +1,347 @@ +#include +#include +#include +#include + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include "Image.h" +#include "Triangle.h" + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 6) { + cout << "Usage: A1 meshfile image width height colormode" << endl; + return 0; + } + + srand(743298); + string meshName(argv[1]); + string filename(argv[2]); + int width = atoi(argv[3]); + int height = atoi(argv[4]); + int colormode = atoi(argv[5]); + + // Load geometry + vector posBuf; // list of vertex positions + + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + + } + index_offset += fv; + + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + cout << "Number of vertices: " << posBuf.size()/3 << endl; + + vector> zbuf; + + std::vector tris; + + // Split posBuf into triangles. + for(int i = 0; i < (int)posBuf.size()/9; i++) + { + vertex v1; + v1.x = posBuf[i*9]; + v1.y = posBuf[i*9 + 1]; + v1.z = posBuf[i*9 + 2]; + vertex v2; + v2.x = posBuf[i*9 + 3]; + v2.y = posBuf[i*9 + 4]; + v2.z = posBuf[i*9 + 5]; + vertex v3; + v3.x = posBuf[i*9 + 6]; + v3.y = posBuf[i*9 + 7]; + v3.z = posBuf[i*9 + 8]; + Tri t(v1, v2, v3); + tris.push_back(t); + } + + // Initialize min/max variables. + float xmin = posBuf[0]; + float xmax = xmin; + float ymin = posBuf[1]; + float ymax = ymin; + float zmin = tris[0].v[0].z; + float zmax = zmin; + + // First time finding max and min. + // Also, initializing r,g,b per triangle. + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + int temp1 = rand()%255; + int temp2 = rand()%255; + int temp3 = rand()%255; + tris[i].v[j].r = temp1; + tris[i].v[j].g = temp2; + tris[i].v[j].b = temp3; + } + } + + unsigned char r = rand()%255; + unsigned char b = rand()%255; + unsigned char g = rand()%255; + + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + + // Find scaling ratio. + float xratio = (1.0*width/(xmax - xmin)); + float yratio = (1.0*height/(ymax - ymin)); + float zratio = (255.0/(zmax-zmin)); + + float aratio = 1.0; + + // Determine and assign smaller ratio. + if(xratio < yratio) + { + aratio = xratio; + } + else + { + aratio = yratio; + } + + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + tris[i].v[j].x *= aratio; + tris[i].v[j].y *= aratio; + tris[i].v[j].z *= zratio; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + } + } + + float xoffset = ((width)/2 - (xmax + xmin)/2); + float yoffset = ((height)/2 - (ymax + ymin)/2); + float zoffset = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + for(int j = 0; j < (int)tris[i].v.size();j++) + { + tris[i].v[j].x += xoffset; + tris[i].v[j].y += yoffset; + tris[i].v[j].z -= zoffset; + } + } + + xmin = tris[0].v[0].x; + xmax = xmin; + ymin = tris[0].v[0].y; + ymax = ymin; + zmin = tris[0].v[0].z; + zmax = zmin; + + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].xmin = tris[i].v[0].x; + tris[i].xmax = tris[i].v[0].x; + tris[i].ymin = tris[i].v[0].y; + tris[i].ymax = tris[i].v[0].y; + + for(int j = 0; j < (int)tris[i].v.size(); j++) + { + + if(xmin > tris[i].v[j].x) + xmin = tris[i].v[j].x; + if(xmax < tris[i].v[j].x) + xmax = tris[i].v[j].x; + if(ymin > tris[i].v[j].y) + ymin = tris[i].v[j].y; + if(ymax < tris[i].v[j].y) + ymax = tris[i].v[j].y; + if(zmin > tris[i].v[j].z) + zmin = tris[i].v[j].z; + if(zmax < tris[i].v[j].z) + zmax = tris[i].v[j].z; + + if(tris[i].xmin > tris[i].v[j].x) + tris[i].xmin = tris[i].v[j].x; + if(tris[i].xmax < tris[i].v[j].x) + tris[i].xmax = tris[i].v[j].x; + if(tris[i].ymin > tris[i].v[j].y) + tris[i].ymin = tris[i].v[j].y; + if(tris[i].ymax < tris[i].v[j].y) + tris[i].ymax = tris[i].v[j].y; + } + } + + + for(int r = 0; r < width; r++) + { + vector temp; + zbuf.push_back(temp); + for(int c = 0; c < height; c++) + { + zbuf.at(r).push_back(zmin); + } + } + + // Initialize variables for the three + // Barycentric areas. + float a1 = 0.0; + float a2 = 0.0; + float a3 = 0.0; + + // Initialize variables for the three + // Barycentric coordinates. + float l1 = 0.0; + float l2 = 0.0; + float l3 = 0.0; + + // Variable to hold current z coordinate. + float z = 0.0; + + // I had each triangle hold a variable which was its area, + // Here, I make sure they all have their areas set correctly. + for(int i = 0; i < (int)tris.size(); i++) + { + tris[i].area = findArea(tris[i].v[0], tris[i].v[1], tris[i].v[2]); + } + for(int i = 0; i < (int)tris.size(); i++) + { + for(int x = tris[i].xmin; x < tris[i].xmax; x++) + { + for(int y = tris[i].ymin; y < tris[i].ymax; y++) + { + // Temporary vertex so we can utilize findArea. + vertex tempv; + tempv.x = x; + tempv.y = y; + + a3 = findArea(tris[i].v[0], tris[i].v[1], tempv); + a2 = findArea(tris[i].v[0], tempv, tris[i].v[2]); + a1 = findArea(tempv, tris[i].v[1], tris[i].v[2]); + + l1 = a1/tris[i].area; + l2 = a2/tris[i].area; + l3 = a3/tris[i].area; + + r = (a1*tris[i].v[0].r + a2*tris[i].v[1].r + a3*tris[i].v[2].r)/tris[i].area; + g = (a1*tris[i].v[0].g + a2*tris[i].v[1].g + a3*tris[i].v[2].g)/tris[i].area; + b = (a1*tris[i].v[0].b + a2*tris[i].v[1].b + a3*tris[i].v[2].b)/tris[i].area; + + if(colormode == 0) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, r, g ,b); + zbuf.at(x).at(y) = z; + } + } + + float z1 = tris[i].v[0].z; + float z2 = tris[i].v[1].z; + float z3 = tris[i].v[2].z; + + z = (a1*z1 + a2*z2 + a3*z3)/tris[i].area; + if(colormode == 1) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, z, 0, 0); + zbuf.at(x).at(y) = z; + } + } + else if(colormode == 2) + { + if(l1 + l2 + l3 <= 1.01 && zbuf.at(x).at(y) <= z) + { + image->setPixel(x, y, 0, (255/(ymax - ymin)) - (y - ymin)*(255/(ymax - ymin)), (y - ymin)*(255/(ymax - ymin))); + zbuf.at(x).at(y) = z; + } + } + } + } + } + + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/A1/src/stb_image_write.h b/A1/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/A1/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/A1/src/tiny_obj_loader.h b/A1/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/A1/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/A2/.gitignore b/A2/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/A2/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/A2/CMakeLists.txt b/A2/CMakeLists.txt new file mode 100644 index 0000000..e451276 --- /dev/null +++ b/A2/CMakeLists.txt @@ -0,0 +1,126 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(A2) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/A2/resources/cube.obj b/A2/resources/cube.obj new file mode 100644 index 0000000..e81edd5 --- /dev/null +++ b/A2/resources/cube.obj @@ -0,0 +1,29 @@ +# Blender v2.71 (sub 0) OBJ File: '' +# www.blender.org +v 0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 -0.000000 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +s off +f 2//1 3//1 4//1 +f 8//2 7//2 6//2 +f 1//3 5//3 6//3 +f 2//4 6//4 7//4 +f 7//5 8//5 4//5 +f 1//6 4//6 8//6 +f 1//1 2//1 4//1 +f 5//2 8//2 6//2 +f 2//3 1//3 6//3 +f 3//4 2//4 7//4 +f 3//5 7//5 4//5 +f 5//6 1//6 8//6 diff --git a/A2/resources/frag.glsl b/A2/resources/frag.glsl new file mode 100644 index 0000000..9d07efa --- /dev/null +++ b/A2/resources/frag.glsl @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 vCol; + +void main() +{ + gl_FragColor = vec4(vCol.r, vCol.g, vCol.b, 1.0); +} diff --git a/A2/resources/vert.glsl b/A2/resources/vert.glsl new file mode 100644 index 0000000..3ecb3f4 --- /dev/null +++ b/A2/resources/vert.glsl @@ -0,0 +1,13 @@ +#version 120 + +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vCol; + +void main() +{ + gl_Position = P * MV * aPos; + vCol = 0.5*(aNor + 1.0); +} diff --git a/A2/src/Body.h b/A2/src/Body.h new file mode 100644 index 0000000..9d0f5a8 --- /dev/null +++ b/A2/src/Body.h @@ -0,0 +1,43 @@ +// Create Body Class + +/* +Class Body +{ + Head h; + Shoulder sl; + Shoulder sr; + Leg ull; + Leg ulr; + bool selected = true; + + draw(MatrixStack MV); +} +*/ + +/* + +static void renderA(MatrixStack MV) +{ + MV.pushMatrix(); + MV.translate(-1, 0, 0); + MV.rotate(-(2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #1 + MV.pushMatrix(); + MV.scale(2, 0.5, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #2 + MV.pushMatrix(); + MV.translate(1, 0, 0); + MV.rotate((2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #3 +} + + +*/ diff --git a/A2/src/GLSL.cpp b/A2/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/A2/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/A2/src/GLSL.h b/A2/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/A2/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/A2/src/MatrixStack.cpp b/A2/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/A2/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/A2/src/MatrixStack.h b/A2/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/A2/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/A2/src/Program.cpp b/A2/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/A2/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/A2/src/Program.h b/A2/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/A2/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/A2/src/Shape.cpp b/A2/src/Shape.cpp new file mode 100644 index 0000000..cf80379 --- /dev/null +++ b/A2/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("aPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("aNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("aTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/A2/src/Shape.h b/A2/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/A2/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/A2/src/main.cpp b/A2/src/main.cpp new file mode 100644 index 0000000..0985a74 --- /dev/null +++ b/A2/src/main.cpp @@ -0,0 +1,187 @@ +#include +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include +#include + +#include "tiny_obj_loader.h" + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Shape.h" +#include "Program.h" + +#define PI 3.14159 + +using namespace std; +using namespace glm; + +GLFWwindow *window; // Main application window +string RESOURCE_DIR = "./"; // Where the resources are loaded from +shared_ptr prog; +shared_ptr shape; + + +GLuint progID; +map attrIDs; +map unifIDs; +map bufIDs; +int indCount; +// This function is called when a GLFW error occurs +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +// This function is called when a key is pressed +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// This function is called when the mouse is clicked +static void mouse_callback(GLFWwindow *window, int button, int action, int mods) +{ + // Do nothing +} + +// If the window is resized, capture the new size and reset the viewport +static void resize_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +static void init() +{ + GLSL::checkVersion(); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // Initialize mesh. + shape = make_shared(); + shape->loadMesh(RESOURCE_DIR + "teapot.obj"); + shape->init(); + + // Initialize the GLSL program. + prog = make_shared(); + prog->setVerbose(false); // Set this to true when debugging. + prog->setShaderNames(RESOURCE_DIR + "simple_vert.glsl", RESOURCE_DIR + "simple_frag.glsl"); + prog->init(); + prog->addUniform("P"); + prog->addUniform("MV"); + prog->addAttribute("aPos"); + prog->addAttribute("aNor"); + + // If there were any OpenGL errors, this will print something. + // You can intersperse this line in your code to find the exact location + // of your OpenGL error. + GLSL::checkError(GET_FILE_LINE); +} + +static void render() +{ + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + glViewport(0, 0, width, height); + + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Create matrix stacks. + auto P = make_shared(); + auto MV = make_shared(); + // Apply projection. + P->pushMatrix(); + P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f)); + // Apply camera transform. + MV->pushMatrix(); + MV->translate(glm::vec3(0, -0.5, -3)); + + // Draw mesh using GLSL. + prog->bind(); + glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]); + glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]); + shape->draw(prog); + prog->unbind(); + + // Pop matrix stacks. + MV->popMatrix(); + P->popMatrix(); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RESOURCE_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "Alexander Huddleston", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + GLSL::checkVersion(); + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Set the mouse call back. + glfwSetMouseButtonCallback(window, mouse_callback); + // Set the window resize call back. + glfwSetFramebufferSizeCallback(window, resize_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/A2/src/tiny_obj_loader.h b/A2/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/A2/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L00(old)/.gitignore b/L00(old)/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L00(old)/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L00(old)/CMakeLists.txt b/L00(old)/CMakeLists.txt new file mode 100644 index 0000000..f6a10e7 --- /dev/null +++ b/L00(old)/CMakeLists.txt @@ -0,0 +1,118 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L00) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Use glob to get the list of all source files. +FILE(GLOB_RECURSE SOURCES "src/*.cpp") + +# We don't really need to include header and resource files to build, but it's +# nice to have them show up in IDEs. +FILE(GLOB_RECURSE HEADERS "src/*.h") +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L00(old)/resources/simple_frag.glsl b/L00(old)/resources/simple_frag.glsl new file mode 100644 index 0000000..14d1353 --- /dev/null +++ b/L00(old)/resources/simple_frag.glsl @@ -0,0 +1,11 @@ +#version 120 + +varying vec3 fragNor; + +void main() +{ + vec3 normal = normalize(fragNor); + // Map normal in the range [-1, 1] to color in range [0, 1]; + vec3 color = 0.5*normal + 0.5; + gl_FragColor = vec4(color, 1.0); +} diff --git a/L00(old)/resources/simple_vert.glsl b/L00(old)/resources/simple_vert.glsl new file mode 100644 index 0000000..059c4b3 --- /dev/null +++ b/L00(old)/resources/simple_vert.glsl @@ -0,0 +1,12 @@ +#version 120 +attribute vec4 vertPos; +attribute vec3 vertNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 fragNor; + +void main() +{ + gl_Position = P * MV * vertPos; + fragNor = (MV * vec4(vertNor, 0.0)).xyz; +} diff --git a/L00(old)/resources/teapot.obj b/L00(old)/resources/teapot.obj new file mode 100644 index 0000000..6fed453 --- /dev/null +++ b/L00(old)/resources/teapot.obj @@ -0,0 +1,5049 @@ +# Blender v2.65 (sub 0) OBJ File +# www.blender.org +o teapot.005 +v -0.498530 0.712498 -0.039883 +v -0.501666 0.699221 -0.063813 +v -0.501255 0.717792 0.000000 +v -0.624036 0.711938 -0.039883 +v -0.526706 0.651362 -0.039883 +v -0.508714 0.682112 -0.071712 +v -0.622039 0.698704 -0.063813 +v -0.624834 0.717232 0.000000 +v -0.498530 0.712498 0.039883 +v -0.638129 0.287158 0.000000 +v -0.517593 0.664661 -0.063813 +v -0.534329 0.646030 0.000000 +v -0.614850 0.651067 -0.039883 +v -0.616848 0.664299 -0.063813 +v -0.619445 0.681503 -0.071790 +v -0.741245 0.707456 -0.039883 +v -0.744483 0.712577 0.000000 +v -0.624036 0.711938 0.039883 +v -0.501667 0.699221 0.063813 +v -0.622039 0.698704 0.063813 +v -0.712095 0.661370 -0.063813 +v -0.733150 0.694655 -0.063813 +v -0.741245 0.707456 0.039883 +v -0.733150 0.694655 0.063813 +v -0.631184 0.277569 -0.039883 +v -0.526706 0.651362 0.039883 +v -0.614053 0.645774 0.000000 +v -0.704000 0.648569 -0.039883 +v -0.722621 0.678012 -0.071790 +v -0.832523 0.695296 -0.039883 +v -0.837545 0.699948 0.000000 +v -0.832523 0.695296 0.039883 +v -0.619445 0.681503 0.071790 +v -0.508714 0.682112 0.071712 +v -0.722621 0.678012 0.071790 +v -0.517593 0.664661 0.063813 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.710066 0.328372 0.000000 +v -0.614850 0.651067 0.039883 +v -0.787321 0.653419 -0.063813 +v -0.803644 0.668539 -0.071790 +v -0.819967 0.683663 -0.063813 +v -0.819967 0.683663 0.063813 +v -0.803644 0.668539 0.071790 +v -0.711425 0.307332 -0.063813 +v -0.615553 0.216807 -0.063813 +v -0.712688 0.287795 -0.071790 +v -0.631184 0.277569 0.039883 +v -0.710455 0.322361 -0.039883 +v -0.710455 0.322361 0.039883 +v -0.700762 0.643448 0.000000 +v -0.774766 0.641786 -0.039883 +v -0.897800 0.671612 -0.039883 +v -0.904015 0.675354 0.000000 +v -0.897800 0.671612 0.039883 +v -0.882265 0.662257 0.063813 +v -0.712095 0.661370 0.063813 +v -0.787321 0.653419 0.063813 +v -0.608884 0.198682 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.766936 0.377559 0.000000 +v -0.769651 0.372307 0.039883 +v -0.616848 0.664299 0.063813 +v -0.704000 0.648569 0.039883 +v -0.841868 0.637931 -0.063813 +v -0.862065 0.650094 -0.071790 +v -0.882265 0.662257 -0.063813 +v -0.862065 0.650094 0.071790 +v -0.841868 0.637931 0.063813 +v -0.611709 0.194244 0.000000 +v -0.776434 0.359177 -0.063813 +v -0.769651 0.372307 -0.039883 +v -0.713952 0.268259 -0.063813 +v -0.711425 0.307332 0.063813 +v -0.776434 0.359177 0.063813 +v -0.769743 0.637131 0.000000 +v -0.826329 0.628576 -0.039883 +v -0.937016 0.632565 -0.039883 +v -0.943899 0.634805 0.000000 +v -0.937016 0.632565 0.039883 +v -0.919812 0.626965 0.063813 +v -0.897443 0.619684 0.071790 +v -0.774766 0.641786 0.039883 +v -0.826329 0.628576 0.039883 +v -0.714922 0.253231 -0.039883 +v -0.608883 0.198681 0.039883 +v -0.715311 0.247220 0.000000 +v -0.785253 0.342107 -0.071790 +v -0.619922 0.238069 0.071790 +v -0.712688 0.287795 0.071790 +v -0.809626 0.430737 0.000000 +v -0.814205 0.426194 0.039883 +v -0.825653 0.414838 0.063813 +v -0.875076 0.612403 -0.063813 +v -0.897443 0.619684 -0.071790 +v -0.919812 0.626965 -0.063813 +v -0.875076 0.612403 0.063813 +v -0.857869 0.606800 0.039883 +v -0.794072 0.325038 -0.063813 +v -0.800855 0.311909 -0.039883 +v -0.825653 0.414838 -0.063813 +v -0.814205 0.426194 -0.039883 +v -0.615480 0.216617 0.063578 +v -0.785253 0.342107 0.071790 +v -0.840534 0.400078 0.071790 +v -0.820114 0.624834 0.000000 +v -0.857869 0.606800 -0.039883 +v -0.950104 0.574316 -0.039883 +v -0.957194 0.574316 0.000000 +v -0.950104 0.574316 0.039883 +v -0.932377 0.574316 0.063813 +v -0.909334 0.574316 0.071790 +v -0.886292 0.574316 0.063813 +v -0.850987 0.604560 0.000000 +v -0.714922 0.253231 0.039883 +v -0.803571 0.306656 0.000000 +v -0.840534 0.400078 -0.071790 +v -0.713952 0.268259 0.063813 +v -0.794072 0.325038 0.063813 +v -0.839022 0.483916 0.000000 +v -0.844976 0.480304 0.039883 +v -0.859854 0.471278 0.063813 +v -0.879202 0.459542 0.071790 +v -0.886292 0.574316 -0.063813 +v -0.909334 0.574316 -0.071790 +v -0.932377 0.574316 -0.063813 +v -0.868564 0.574316 0.039883 +v -0.861474 0.574316 0.000000 +v -0.855419 0.385315 -0.063813 +v -0.866867 0.373960 -0.039883 +v -0.859854 0.471278 -0.063813 +v -0.844976 0.480304 -0.039883 +v -0.855419 0.385315 0.063813 +v -0.898547 0.447807 0.063813 +v -0.868564 0.574316 -0.039883 +v -0.941014 0.505765 -0.039883 +v -0.947813 0.503580 0.000000 +v -0.941014 0.505765 0.039883 +v -0.924011 0.511234 0.063813 +v -0.901913 0.518343 0.071790 +v -0.879811 0.525448 0.063813 +v -0.862808 0.530917 0.039883 +v -0.800855 0.311909 0.039883 +v -0.871445 0.369416 0.000000 +v -0.879202 0.459542 -0.071790 +v -0.866867 0.373960 0.039883 +v -0.856009 0.533103 0.000000 +v -0.879811 0.525448 -0.063813 +v -0.901913 0.518343 -0.071790 +v -0.924011 0.511234 -0.063813 +v -0.862808 0.530917 -0.039883 +v -0.898547 0.447807 -0.063813 +v -0.913428 0.438781 -0.039883 +v -0.913428 0.438781 0.039883 +v -0.919378 0.435169 0.000000 +v 0.600960 0.444810 0.085753 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.656890 0.471064 0.000000 +v 0.661223 0.454734 -0.083705 +v 0.730696 0.501576 -0.073611 +v 0.661223 0.454734 0.083705 +v 0.605101 0.399712 -0.137265 +v 0.746455 0.470391 -0.117778 +v 0.724395 0.514048 0.000000 +v 0.605100 0.399712 0.137265 +v 0.672055 0.413907 -0.133928 +v 0.613258 0.341675 -0.154354 +v 0.786583 0.544847 -0.096783 +v 0.768856 0.565896 -0.060489 +v 0.672055 0.413907 0.133928 +v 0.730696 0.501576 0.073611 +v 0.686135 0.360830 -0.150669 +v 0.809626 0.517481 -0.108881 +v 0.766935 0.429850 -0.132501 +v 0.761767 0.574316 0.000000 +v 0.613258 0.341675 0.154354 +v 0.813417 0.626247 -0.075788 +v 0.839021 0.611098 -0.085261 +v 0.793721 0.637899 -0.047367 +v 0.686135 0.360830 0.150669 +v 0.768856 0.565896 0.060489 +v 0.746455 0.470391 0.117778 +v 0.619427 0.283145 -0.137236 +v 0.864627 0.595949 -0.075788 +v 0.832669 0.490118 -0.096783 +v 0.787419 0.389310 -0.117778 +v 0.785843 0.642561 0.000000 +v 0.619427 0.283145 0.137236 +v 0.700219 0.307756 -0.133928 +v 0.847933 0.703560 -0.059638 +v 0.879938 0.698065 -0.067092 +v 0.911944 0.692571 -0.059638 +v 0.823314 0.707784 -0.037273 +v 0.766935 0.429850 0.132501 +v 0.793721 0.637899 0.047367 +v 0.786583 0.544847 0.096783 +v 0.700219 0.307756 0.133928 +v 0.617684 0.235930 -0.085941 +v 0.936563 0.688344 -0.037273 +v 0.884319 0.584297 -0.047367 +v 0.850396 0.469070 -0.060489 +v 0.803175 0.358128 -0.073611 +v 0.813468 0.709475 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v 0.711051 0.266929 -0.083705 +v 0.911107 0.765755 -0.053178 +v 0.957193 0.765755 -0.059825 +v 1.003279 0.765755 -0.053178 +v 1.038733 0.765755 -0.033236 +v 0.875654 0.765755 -0.033236 +v 0.809626 0.517481 0.108881 +v 0.787419 0.389310 0.117778 +v 0.823314 0.707784 0.037273 +v 0.813417 0.626247 0.075788 +v 0.711051 0.266929 0.083705 +v 0.715384 0.250599 0.000000 +v 1.052913 0.765755 0.000000 +v 0.946409 0.686653 0.000000 +v 0.892200 0.579635 0.000000 +v 0.857486 0.460650 0.000000 +v 0.809479 0.345652 0.000000 +v 0.861474 0.765755 0.000000 +v 0.929990 0.776479 -0.051602 +v 0.979075 0.777181 -0.058052 +v 1.028157 0.777879 -0.051602 +v 1.065915 0.778419 -0.032251 +v 1.081016 0.778632 0.000000 +v 0.892235 0.775943 -0.032251 +v 0.839021 0.611098 0.085261 +v 0.832669 0.490118 0.096783 +v 0.803175 0.358128 0.073611 +v 0.875654 0.765755 0.033236 +v 0.847933 0.703560 0.059638 +v 1.065915 0.778419 0.032174 +v 1.038733 0.765755 0.033236 +v 0.936563 0.688344 0.037273 +v 0.884319 0.584297 0.047367 +v 0.850396 0.469070 0.060489 +v 0.877131 0.775726 0.000000 +v 0.943713 0.783087 -0.047663 +v 0.992645 0.784366 -0.053621 +v 1.041577 0.785649 -0.047663 +v 1.079216 0.786631 -0.029789 +v 1.094273 0.787027 0.000000 +v 1.079216 0.786631 0.029174 +v 0.906073 0.782101 -0.029789 +v 0.879938 0.698065 0.067092 +v 0.864627 0.595949 0.075788 +v 0.892235 0.775943 0.032236 +v 0.911107 0.765755 0.053178 +v 1.041577 0.785649 0.046875 +v 1.028157 0.777879 0.051503 +v 1.003279 0.765755 0.053178 +v 0.911944 0.692571 0.059638 +v 0.891016 0.781708 0.000000 +v 0.951249 0.785448 -0.042542 +v 0.997575 0.787068 -0.047860 +v 1.043903 0.788686 -0.042542 +v 1.079539 0.789934 -0.026589 +v 1.093795 0.790431 0.000000 +v 1.079539 0.789934 0.024511 +v 1.043903 0.788686 0.039883 +v 0.915613 0.784200 -0.026589 +v 0.957193 0.765755 0.059825 +v 0.906073 0.782101 0.029666 +v 0.929990 0.776479 0.051553 +v 0.997575 0.787068 0.045616 +v 0.992645 0.784366 0.052956 +v 0.979075 0.777181 0.057969 +v 0.901357 0.783702 0.000000 +v 0.951569 0.783431 -0.037421 +v 0.993532 0.785033 -0.042099 +v 1.035492 0.786631 -0.037421 +v 1.067772 0.787863 -0.023388 +v 1.080684 0.788354 0.000000 +v 1.067772 0.787863 0.018464 +v 1.035492 0.786631 0.031119 +v 0.993532 0.785033 0.036781 +v 0.919292 0.782200 -0.023388 +v 0.915613 0.784200 0.026173 +v 0.943713 0.783087 0.047269 +v 0.951569 0.783431 0.034270 +v 0.951249 0.785448 0.041213 +v 0.906379 0.781708 0.000000 +v 0.943653 0.776909 -0.033482 +v 0.980182 0.778010 -0.037667 +v 1.016712 0.779111 -0.033482 +v 1.044812 0.779957 -0.020926 +v 1.056052 0.780295 0.000000 +v 1.044812 0.779957 0.011310 +v 1.016712 0.779111 0.021172 +v 0.980182 0.778010 0.027281 +v 0.943653 0.776909 0.027327 +v 0.915553 0.776064 -0.020926 +v 0.919292 0.782200 0.022403 +v 0.915553 0.776064 0.019003 +v 0.904312 0.775726 0.000000 +v 0.926468 0.765755 -0.031906 +v 0.957193 0.765755 -0.035895 +v 0.987920 0.765755 -0.031906 +v 1.011552 0.765755 -0.019942 +v 1.021006 0.765755 0.000000 +v 1.011552 0.765755 0.003324 +v 0.987920 0.765755 0.010635 +v 0.957193 0.765755 0.017947 +v 0.926468 0.765755 0.021271 +v 0.902834 0.765755 0.016618 +v 0.902834 0.765755 -0.019942 +v 0.893380 0.765755 0.000000 +v 0.886428 0.750924 -0.019014 +v 0.908324 0.750924 -0.030099 +v 0.936793 0.750924 -0.033795 +v 0.965261 0.750924 -0.030099 +v 0.987158 0.750924 -0.019014 +v 0.995918 0.750924 -0.000537 +v 0.987158 0.750924 0.002542 +v 0.965261 0.750924 0.009317 +v 0.936793 0.750924 0.016092 +v 0.908324 0.750924 0.019171 +v 0.886428 0.750924 0.014860 +v 0.877668 0.750924 -0.000537 +v 0.936793 0.750924 -0.007312 +v 0.440746 0.783205 0.000000 +v 0.446690 0.765755 0.000000 +v 0.430973 0.765755 0.119945 +v 0.425236 0.783205 0.118348 +v 0.425236 0.783205 -0.118348 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 0.121642 +v 0.441668 0.793673 0.000000 +v 0.386470 0.765755 0.226985 +v 0.430973 0.765755 -0.119945 +v 0.426127 0.793673 -0.118596 +v 0.437073 0.750009 -0.121642 +v 0.426127 0.793673 0.118596 +v 0.381327 0.783205 0.223964 +v 0.381327 0.783205 -0.223964 +v 0.382124 0.793673 -0.224433 +v 0.317150 0.765755 0.317150 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 0.321639 +v 0.386470 0.765755 -0.226985 +v 0.391939 0.750009 -0.230197 +v 0.447686 0.797164 0.000000 +v 0.431936 0.797164 -0.120212 +v 0.387332 0.797164 -0.227491 +v 0.230197 0.750009 0.391940 +v 0.226984 0.765755 0.386470 +v 0.317150 0.765755 -0.317150 +v 0.321638 0.750009 -0.321639 +v 0.431936 0.797164 0.120212 +v 0.382124 0.793673 0.224433 +v 0.312929 0.783205 0.312929 +v 0.313584 0.793673 -0.313584 +v 0.312929 0.783205 -0.312929 +v 0.317858 0.797164 -0.317858 +v 0.121642 0.750009 0.437072 +v 0.119944 0.765755 0.430973 +v 0.226984 0.765755 -0.386470 +v 0.230197 0.750009 -0.391940 +v 0.457031 0.793673 0.000000 +v 0.440950 0.793673 -0.122721 +v 0.395416 0.793673 -0.232239 +v 0.324491 0.793673 -0.324492 +v -0.000000 0.750009 0.453012 +v -0.000000 0.765755 0.446690 +v 0.223963 0.783205 0.381327 +v 0.223963 0.783205 -0.381327 +v 0.119944 0.765755 -0.430973 +v 0.121642 0.750009 -0.437072 +v 0.440950 0.793673 0.122721 +v 0.387332 0.797164 0.227491 +v 0.313584 0.793673 0.313584 +v 0.227491 0.797164 -0.387332 +v 0.224433 0.793673 -0.382125 +v 0.232239 0.793673 -0.395417 +v -0.119945 0.765755 0.430973 +v -0.121642 0.750009 0.437072 +v 0.118348 0.783205 0.425237 +v 0.118348 0.783205 -0.425237 +v -0.000000 0.750009 -0.453012 +v -0.000000 0.765755 -0.446690 +v 0.467924 0.783205 0.000000 +v 0.451460 0.783205 -0.125646 +v 0.404842 0.783205 -0.237775 +v 0.332226 0.783205 -0.332226 +v 0.237775 0.783205 -0.404842 +v -0.226985 0.765755 0.386470 +v -0.000000 0.783205 0.440746 +v 0.224433 0.793673 0.382125 +v 0.118596 0.793673 -0.426127 +v -0.000000 0.783205 -0.440746 +v -0.119945 0.765755 -0.430973 +v -0.121642 0.750009 -0.437072 +v 0.451460 0.783205 0.125646 +v 0.395416 0.793673 0.232239 +v 0.317858 0.797164 0.317858 +v 0.122721 0.793673 -0.440950 +v 0.120212 0.797164 -0.431937 +v 0.125646 0.783205 -0.451460 +v -0.317150 0.765755 0.317150 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.118348 0.783205 0.425237 +v 0.118596 0.793673 0.426127 +v -0.000000 0.793673 -0.441668 +v -0.118348 0.783205 -0.425237 +v -0.226985 0.765755 -0.386470 +v 0.478596 0.765755 0.000000 +v 0.461756 0.765755 -0.128512 +v 0.414076 0.765755 -0.243198 +v 0.339803 0.765755 -0.339804 +v 0.243198 0.765755 -0.414076 +v 0.128512 0.765755 -0.461757 +v -0.391940 0.750009 0.230197 +v -0.386470 0.765755 0.226985 +v -0.223964 0.783205 0.381327 +v -0.000000 0.793673 0.441668 +v 0.227491 0.797164 0.387332 +v -0.000000 0.797164 -0.447686 +v -0.118596 0.793673 -0.426127 +v -0.223964 0.783205 -0.381327 +v -0.317150 0.765755 -0.317150 +v -0.230198 0.750009 -0.391939 +v -0.321639 0.750009 -0.321639 +v 0.461756 0.765755 0.128512 +v 0.404842 0.783205 0.237775 +v 0.324491 0.793673 0.324492 +v -0.000000 0.783205 -0.467924 +v -0.000000 0.793673 -0.457031 +v -0.000000 0.765755 -0.478597 +v -0.437073 0.750009 0.121642 +v -0.430974 0.765755 0.119945 +v -0.312929 0.783205 0.312929 +v -0.118596 0.793673 0.426127 +v 0.120212 0.797164 0.431937 +v -0.120212 0.797164 -0.431937 +v -0.224433 0.793673 -0.382125 +v -0.312929 0.783205 -0.312929 +v -0.386470 0.765755 -0.226985 +v -0.391940 0.750009 -0.230197 +v 0.518110 0.682112 0.000000 +v 0.499881 0.682112 -0.139122 +v 0.448260 0.682112 -0.263277 +v 0.367859 0.682112 -0.367859 +v 0.263277 0.682112 -0.448260 +v 0.139122 0.682112 -0.499882 +v -0.000000 0.682112 -0.518110 +v -0.453012 0.750009 0.000000 +v -0.446690 0.765755 0.000000 +v -0.381327 0.783205 0.223964 +v -0.224433 0.793673 0.382125 +v -0.000000 0.797164 0.447686 +v 0.232239 0.793673 0.395417 +v -0.122721 0.793673 -0.440950 +v -0.227491 0.797164 -0.387332 +v -0.313584 0.793673 -0.313584 +v -0.381327 0.783205 -0.223964 +v -0.430974 0.765755 -0.119945 +v 0.499881 0.682112 0.139122 +v 0.414076 0.765755 0.243198 +v 0.332226 0.783205 0.332226 +v -0.128513 0.765755 -0.461757 +v -0.125646 0.783205 -0.451460 +v -0.139123 0.682112 -0.499882 +v -0.437073 0.750009 -0.121642 +v -0.425237 0.783205 0.118348 +v -0.313584 0.793673 0.313584 +v -0.120212 0.797164 0.431937 +v 0.122721 0.793673 0.440950 +v -0.232240 0.793673 -0.395417 +v -0.317859 0.797164 -0.317858 +v -0.382125 0.793673 -0.224433 +v -0.425237 0.783205 -0.118348 +v 0.555408 0.599133 0.000000 +v 0.535865 0.599133 -0.149137 +v 0.480530 0.599133 -0.282230 +v 0.394341 0.599133 -0.394341 +v 0.282230 0.599133 -0.480530 +v 0.149137 0.599133 -0.535866 +v -0.000000 0.599133 -0.555408 +v -0.149138 0.599133 -0.535866 +v -0.440746 0.783205 0.000000 +v -0.382125 0.793673 0.224433 +v -0.227491 0.797164 0.387332 +v -0.000000 0.793673 0.457031 +v 0.237775 0.783205 0.404842 +v -0.237775 0.783205 -0.404842 +v -0.324492 0.793673 -0.324492 +v -0.387332 0.797164 -0.227491 +v -0.426127 0.793673 -0.118596 +v 0.535865 0.599133 0.149137 +v 0.448260 0.682112 0.263277 +v 0.339803 0.765755 0.339804 +v -0.263278 0.682112 -0.448260 +v -0.243198 0.765755 -0.414076 +v -0.282230 0.599133 -0.480530 +v -0.426127 0.793673 0.118596 +v -0.317859 0.797164 0.317858 +v -0.122721 0.793673 0.440950 +v 0.125646 0.783205 0.451460 +v -0.332226 0.783205 -0.332226 +v -0.395417 0.793673 -0.232239 +v -0.431937 0.797164 -0.120212 +v -0.441668 0.793673 0.000000 +v 0.588275 0.517481 0.000000 +v 0.567578 0.517481 -0.157963 +v 0.508969 0.517485 -0.298931 +v 0.417675 0.517481 -0.417675 +v 0.298931 0.517485 -0.508969 +v 0.157963 0.517485 -0.567578 +v -0.000000 0.517481 -0.588275 +v -0.157963 0.517481 -0.567578 +v -0.298931 0.517485 -0.508969 +v -0.387332 0.797164 0.227491 +v -0.232240 0.793673 0.395417 +v -0.000000 0.783205 0.467924 +v 0.243198 0.765755 0.414076 +v -0.339804 0.765755 -0.339804 +v -0.404842 0.783205 -0.237775 +v -0.440950 0.793673 -0.122721 +v -0.447686 0.797164 0.000000 +v 0.567578 0.517485 0.157963 +v 0.480530 0.599133 0.282230 +v 0.367859 0.682112 0.367859 +v -0.394341 0.599133 -0.394341 +v -0.367859 0.682112 -0.367859 +v -0.417675 0.517481 -0.417675 +v -0.431937 0.797164 0.120212 +v -0.324492 0.793673 0.324492 +v -0.125646 0.783205 0.451460 +v 0.128512 0.765755 0.461757 +v -0.414076 0.765755 -0.243198 +v -0.451461 0.783205 -0.125646 +v -0.457031 0.793673 0.000000 +v 0.592873 0.437827 -0.165003 +v 0.531651 0.437827 -0.312254 +v 0.436292 0.437827 -0.436292 +v 0.312254 0.437827 -0.531651 +v 0.165003 0.437827 -0.592873 +v -0.000000 0.437827 -0.614496 +v -0.165004 0.437827 -0.592873 +v -0.312255 0.437827 -0.531651 +v -0.436292 0.437827 -0.436292 +v -0.395417 0.793673 0.232239 +v -0.237775 0.783205 0.404842 +v -0.000000 0.765755 0.478597 +v 0.263277 0.682112 0.448260 +v -0.448260 0.682112 -0.263277 +v -0.461757 0.765755 -0.128512 +v -0.467924 0.783205 0.000000 +v -0.440950 0.793673 0.122721 +v 0.592873 0.437827 0.165003 +v 0.508969 0.517485 0.298931 +v 0.394341 0.599133 0.394341 +v -0.508969 0.517485 -0.298931 +v -0.480530 0.599133 -0.282230 +v -0.531651 0.437827 -0.312254 +v -0.332226 0.783205 0.332226 +v -0.128513 0.765755 0.461757 +v 0.139122 0.682112 0.499882 +v -0.499882 0.682112 -0.139122 +v -0.478597 0.765755 0.000000 +v -0.451461 0.783205 0.125646 +v 0.546669 0.360830 -0.321075 +v 0.448614 0.360830 -0.448614 +v 0.321074 0.360830 -0.546669 +v 0.169664 0.360830 -0.609621 +v -0.000000 0.360830 -0.631850 +v -0.169664 0.360830 -0.609621 +v -0.321075 0.360830 -0.546669 +v -0.448615 0.360830 -0.448614 +v -0.546669 0.360830 -0.321075 +v -0.404842 0.783205 0.237775 +v -0.243198 0.765755 0.414076 +v -0.000000 0.682112 0.518110 +v 0.282230 0.599133 0.480530 +v -0.535866 0.599133 -0.149137 +v -0.461757 0.765755 0.128512 +v 0.531651 0.437827 0.312254 +v 0.417675 0.517481 0.417675 +v 0.609621 0.360830 -0.169664 +v -0.592873 0.437827 -0.165003 +v -0.567578 0.517485 -0.157963 +v -0.609621 0.360830 -0.169664 +v -0.339804 0.765755 0.339804 +v -0.139123 0.682112 0.499882 +v 0.149137 0.599133 0.535866 +v -0.555408 0.599133 0.000000 +v -0.499882 0.682112 0.139122 +v -0.414076 0.765755 0.243198 +v 0.609621 0.360830 0.169664 +v 0.552100 0.287158 -0.324265 +v 0.453072 0.287158 -0.453072 +v 0.324265 0.287158 -0.552100 +v 0.171349 0.287158 -0.615677 +v -0.000000 0.287158 -0.638129 +v -0.171350 0.287158 -0.615677 +v -0.324265 0.287158 -0.552100 +v -0.453072 0.287158 -0.453072 +v -0.552100 0.287158 -0.324265 +v -0.615677 0.287158 -0.171349 +v -0.263278 0.682112 0.448260 +v -0.000000 0.599133 0.555408 +v 0.298931 0.517485 0.508969 +v -0.588275 0.517481 0.000000 +v -0.448260 0.682112 0.263277 +v 0.546669 0.360830 0.321075 +v 0.436292 0.437827 0.436292 +v 0.615677 0.287158 -0.171349 +v -0.631850 0.360830 0.000000 +v -0.614496 0.437827 0.000000 +v -0.367859 0.682112 0.367859 +v -0.149138 0.599133 0.535866 +v 0.157963 0.517481 0.567578 +v -0.567578 0.517481 0.157963 +v -0.480530 0.599133 0.282230 +v 0.615677 0.287158 0.171349 +v 0.541877 0.221240 -0.318259 +v 0.444680 0.221240 -0.444680 +v 0.318259 0.221240 -0.541877 +v 0.168176 0.221240 -0.604276 +v -0.000000 0.221240 -0.626311 +v -0.168177 0.221240 -0.604276 +v -0.318259 0.221240 -0.541877 +v -0.444680 0.221240 -0.444680 +v -0.541877 0.221240 -0.318259 +v -0.604277 0.221240 -0.168176 +v -0.282230 0.599133 0.480530 +v -0.000000 0.517481 0.588275 +v 0.312254 0.437827 0.531651 +v -0.592873 0.437827 0.165003 +v -0.535866 0.599133 0.149137 +v -0.394341 0.599133 0.394341 +v 0.552100 0.287158 0.324265 +v 0.448614 0.360830 0.448614 +v 0.604276 0.221240 -0.168176 +v -0.615677 0.287158 0.171349 +v -0.609621 0.360830 0.169664 +v -0.157963 0.517485 0.567578 +v 0.165003 0.437827 0.592873 +v -0.531651 0.437827 0.312254 +v -0.508969 0.517485 0.298931 +v -0.417675 0.517481 0.417675 +v 0.604276 0.221240 0.168176 +v 0.516317 0.166623 -0.303247 +v 0.423705 0.166623 -0.423705 +v 0.303247 0.166623 -0.516317 +v 0.160243 0.166623 -0.575771 +v -0.000000 0.166623 -0.596769 +v -0.160244 0.166623 -0.575771 +v -0.303247 0.166623 -0.516317 +v -0.423705 0.166623 -0.423705 +v -0.516317 0.166623 -0.303247 +v -0.575771 0.166623 -0.160243 +v -0.298931 0.517485 0.508969 +v -0.000000 0.437827 0.614496 +v 0.321074 0.360830 0.546669 +v -0.546669 0.360830 0.321075 +v 0.541877 0.221240 0.318259 +v 0.453072 0.287158 0.453072 +v 0.575771 0.166623 -0.160243 +v -0.596769 0.166623 0.000000 +v -0.604277 0.221240 0.168176 +v -0.552100 0.287158 0.324265 +v -0.165004 0.437827 0.592873 +v 0.169664 0.360830 0.609621 +v -0.448615 0.360830 0.448614 +v -0.436292 0.437827 0.436292 +v -0.312255 0.437827 0.531651 +v 0.575771 0.166623 0.160243 +v 0.483086 0.122640 -0.283731 +v 0.396438 0.122640 -0.396438 +v 0.283731 0.122640 -0.483086 +v 0.149931 0.122640 -0.538718 +v -0.000000 0.122640 -0.558363 +v -0.149931 0.122640 -0.538718 +v -0.283731 0.122640 -0.483086 +v -0.396438 0.122640 -0.396438 +v -0.483087 0.122640 -0.283731 +v -0.538718 0.122640 -0.149931 +v -0.558363 0.122640 0.000000 +v -0.541877 0.221240 0.318259 +v -0.000000 0.360830 0.631850 +v 0.324265 0.287158 0.552100 +v -0.453072 0.287158 0.453072 +v 0.516317 0.166623 0.303247 +v 0.596768 0.166623 0.000000 +v 0.444680 0.221240 0.444680 +v 0.538718 0.122640 -0.149931 +v -0.538718 0.122640 0.149931 +v -0.516317 0.166623 0.303247 +v -0.444680 0.221240 0.444680 +v -0.169664 0.360830 0.609621 +v 0.171349 0.287158 0.615677 +v -0.324265 0.287158 0.552100 +v -0.321075 0.360830 0.546669 +v 0.538718 0.122640 0.149931 +v 0.558363 0.122640 0.000000 +v 0.449858 0.088629 -0.264215 +v 0.369171 0.088629 -0.369171 +v 0.264215 0.088629 -0.449859 +v 0.139618 0.088629 -0.501662 +v -0.000000 0.088629 -0.519957 +v -0.139618 0.088629 -0.501662 +v -0.264215 0.088629 -0.449859 +v -0.369171 0.088629 -0.369171 +v -0.449859 0.088629 -0.264215 +v -0.501662 0.088629 -0.139618 +v -0.519957 0.088629 0.000000 +v -0.501662 0.088629 0.139618 +v -0.575771 0.166623 0.160243 +v -0.423705 0.166623 0.423705 +v -0.000000 0.287158 0.638129 +v 0.318259 0.221240 0.541877 +v -0.318259 0.221240 0.541877 +v 0.483086 0.122640 0.283731 +v 0.423705 0.166623 0.423705 +v 0.501662 0.088629 -0.139618 +v -0.449859 0.088629 0.264215 +v -0.483087 0.122640 0.283731 +v -0.396438 0.122640 0.396438 +v -0.303247 0.166623 0.516317 +v -0.171350 0.287158 0.615677 +v 0.168176 0.221240 0.604276 +v -0.168177 0.221240 0.604276 +v 0.501662 0.088629 0.139618 +v 0.519957 0.088629 0.000000 +v 0.424299 0.063924 -0.249203 +v 0.348195 0.063924 -0.348195 +v 0.249203 0.063924 -0.424298 +v 0.131685 0.063924 -0.473160 +v -0.000000 0.063924 -0.490415 +v -0.131686 0.063924 -0.473160 +v -0.249203 0.063924 -0.424298 +v -0.348196 0.063924 -0.348195 +v -0.424299 0.063924 -0.249203 +v -0.473160 0.063924 -0.131685 +v -0.490415 0.063924 0.000000 +v -0.473160 0.063924 0.131685 +v -0.424299 0.063924 0.249203 +v -0.283731 0.122640 0.483086 +v -0.000000 0.221240 0.626311 +v 0.303247 0.166623 0.516317 +v -0.160244 0.166623 0.575771 +v 0.449858 0.088629 0.264215 +v 0.396438 0.122640 0.396438 +v 0.473160 0.063924 -0.131685 +v -0.348196 0.063924 0.348195 +v -0.369171 0.088629 0.369171 +v -0.264215 0.088629 0.449859 +v -0.149931 0.122640 0.538718 +v 0.160243 0.166623 0.575771 +v -0.000000 0.166623 0.596769 +v 0.473160 0.063924 0.131685 +v 0.490415 0.063924 0.000000 +v 0.414076 0.047860 -0.243198 +v 0.339803 0.047860 -0.339804 +v 0.243198 0.047860 -0.414076 +v 0.128512 0.047860 -0.461757 +v -0.000000 0.047860 -0.478597 +v -0.128513 0.047860 -0.461757 +v -0.243198 0.047860 -0.414076 +v -0.339804 0.047860 -0.339804 +v -0.414076 0.047860 -0.243198 +v -0.461757 0.047860 -0.128512 +v -0.478597 0.047860 0.000000 +v -0.461757 0.047860 0.128512 +v -0.414076 0.047860 0.243198 +v -0.339804 0.047860 0.339804 +v -0.139618 0.088629 0.501662 +v 0.283731 0.122640 0.483086 +v -0.000000 0.122640 0.558363 +v 0.424299 0.063924 0.249203 +v 0.369171 0.088629 0.369171 +v 0.461756 0.047860 -0.128512 +v -0.243198 0.047860 0.414076 +v -0.249203 0.063924 0.424298 +v -0.131686 0.063924 0.473160 +v -0.000000 0.088629 0.519957 +v 0.149931 0.122640 0.538718 +v 0.461756 0.047860 0.128512 +v 0.478596 0.047860 0.000000 +v 0.410719 0.036005 -0.241228 +v 0.337050 0.036005 -0.337050 +v 0.241227 0.036005 -0.410719 +v 0.127471 0.036005 -0.458017 +v -0.000000 0.036005 -0.474720 +v -0.127471 0.036005 -0.458017 +v -0.241228 0.036005 -0.410719 +v -0.337051 0.036005 -0.337050 +v -0.410719 0.036005 -0.241228 +v -0.458017 0.036005 -0.127471 +v -0.474721 0.036005 0.000000 +v -0.458017 0.036005 0.127471 +v -0.410719 0.036005 0.241228 +v -0.337051 0.036005 0.337050 +v -0.241228 0.036005 0.410719 +v -0.000000 0.063924 0.490415 +v 0.264215 0.088629 0.449859 +v 0.139618 0.088629 0.501662 +v 0.414076 0.047860 0.243198 +v 0.348195 0.063924 0.348195 +v 0.458017 0.036005 -0.127471 +v -0.127471 0.036005 0.458017 +v -0.128513 0.047860 0.461757 +v -0.000000 0.047860 0.478597 +v 0.131685 0.063924 0.473160 +v 0.458017 0.036005 0.127471 +v 0.474720 0.036005 0.000000 +v 0.394137 0.024816 -0.231489 +v 0.323442 0.024816 -0.323442 +v 0.231489 0.024816 -0.394137 +v 0.122324 0.024816 -0.439524 +v -0.000000 0.024816 -0.455554 +v -0.122325 0.024816 -0.439524 +v -0.231489 0.024816 -0.394137 +v -0.323442 0.024816 -0.323442 +v -0.394137 0.024816 -0.231489 +v -0.439524 0.024816 -0.122325 +v -0.455554 0.024816 0.000000 +v -0.439524 0.024816 0.122325 +v -0.394137 0.024816 0.231489 +v -0.323442 0.024816 0.323442 +v -0.231489 0.024816 0.394137 +v -0.122325 0.024816 0.439524 +v 0.128512 0.047860 0.461757 +v 0.249203 0.063924 0.424298 +v 0.410719 0.036005 0.241228 +v 0.339803 0.047860 0.339804 +v 0.439524 0.024816 -0.122325 +v -0.000000 0.036005 0.474720 +v -0.000000 0.024816 0.455554 +v 0.127471 0.036005 0.458017 +v 0.243198 0.047860 0.414076 +v 0.439524 0.024816 0.122325 +v 0.455554 0.024816 0.000000 +v 0.354551 0.014956 -0.208238 +v 0.290957 0.014956 -0.290957 +v 0.208238 0.014956 -0.354551 +v 0.110038 0.014956 -0.395378 +v -0.000000 0.014956 -0.409797 +v -0.110038 0.014956 -0.395378 +v -0.208239 0.014956 -0.354551 +v -0.290957 0.014956 -0.290957 +v -0.354551 0.014956 -0.208238 +v -0.395378 0.014956 -0.110038 +v -0.409797 0.014956 0.000000 +v -0.395378 0.014956 0.110038 +v -0.354551 0.014956 0.208238 +v -0.290957 0.014956 0.290957 +v -0.208239 0.014956 0.354551 +v -0.110038 0.014956 0.395378 +v -0.000000 0.014956 0.409797 +v 0.241227 0.036005 0.410719 +v 0.337050 0.036005 0.337050 +v 0.394137 0.024816 0.231489 +v 0.395378 0.014956 -0.110038 +v 0.122324 0.024816 0.439524 +v 0.110038 0.014956 0.395378 +v 0.231489 0.024816 0.394137 +v 0.395378 0.014956 0.110038 +v 0.409797 0.014956 0.000000 +v 0.282184 0.007090 -0.165735 +v 0.231570 0.007090 -0.231570 +v 0.165735 0.007090 -0.282185 +v 0.087579 0.007090 -0.314679 +v -0.000000 0.007090 -0.326154 +v -0.087579 0.007090 -0.314679 +v -0.165735 0.007090 -0.282185 +v -0.231570 0.007090 -0.231570 +v -0.282184 0.007090 -0.165735 +v -0.314679 0.007090 -0.087579 +v -0.326155 0.007090 0.000000 +v -0.314679 0.007090 0.087579 +v -0.282184 0.007090 0.165735 +v -0.231570 0.007090 0.231570 +v -0.165735 0.007090 0.282185 +v -0.087579 0.007090 0.314679 +v -0.000000 0.007090 0.326154 +v 0.087579 0.007090 0.314679 +v 0.323442 0.024816 0.323442 +v 0.354551 0.014956 0.208238 +v 0.314679 0.007090 -0.087579 +v 0.208238 0.014956 0.354551 +v 0.165735 0.007090 0.282185 +v 0.290957 0.014956 0.290957 +v 0.314679 0.007090 0.087579 +v 0.326154 0.007090 0.000000 +v 0.167259 0.001883 -0.098236 +v 0.137258 0.001883 -0.137259 +v 0.098236 0.001883 -0.167259 +v 0.051910 0.001883 -0.186520 +v -0.000000 0.001883 -0.193322 +v -0.051911 0.001883 -0.186520 +v -0.098237 0.001883 -0.167259 +v -0.137259 0.001883 -0.137259 +v -0.167259 0.001883 -0.098236 +v -0.186520 0.001883 -0.051911 +v -0.193323 0.001883 0.000000 +v -0.186520 0.001883 0.051911 +v -0.167259 0.001883 0.098236 +v -0.137259 0.001883 0.137259 +v -0.098237 0.001883 0.167259 +v -0.051911 0.001883 0.186520 +v -0.000000 0.001883 0.193322 +v 0.051910 0.001883 0.186520 +v 0.098236 0.001883 0.167259 +v 0.282184 0.007090 0.165735 +v 0.186520 0.001883 -0.051911 +v 0.231570 0.007090 0.231570 +v 0.137258 0.001883 0.137259 +v 0.186520 0.001883 0.051911 +v 0.193322 0.001883 0.000000 +v -0.000000 0.000000 0.000000 +v 0.167259 0.001883 0.098236 +v 0.063813 0.861474 0.000000 +v 0.054654 0.888729 0.000000 +v 0.052734 0.888729 0.014691 +v 0.061568 0.861474 0.017135 +v 0.061568 0.861474 -0.017135 +v 0.072979 0.919969 0.020357 +v 0.111968 0.841089 0.000000 +v 0.047296 0.888729 0.027792 +v 0.052734 0.888729 -0.014691 +v 0.108028 0.841089 -0.030065 +v 0.075630 0.919969 0.000000 +v 0.065466 0.919969 0.038494 +v 0.108028 0.841089 0.030065 +v 0.055210 0.861474 0.032427 +v 0.055210 0.861474 -0.032427 +v 0.096873 0.841089 -0.056896 +v 0.100064 0.951211 0.027927 +v 0.089769 0.951211 0.052799 +v 0.183167 0.826023 0.000000 +v 0.176722 0.826023 -0.049184 +v 0.038821 0.888729 0.038821 +v 0.053751 0.919969 0.053751 +v 0.047296 0.888729 -0.027792 +v 0.072979 0.919969 -0.020357 +v 0.158473 0.826023 -0.093076 +v 0.103696 0.951211 0.000000 +v 0.073714 0.951211 0.073714 +v 0.176722 0.826023 0.049184 +v 0.096873 0.841089 0.056896 +v 0.045307 0.861474 0.045307 +v 0.079497 0.841089 -0.079497 +v 0.045307 0.861474 -0.045307 +v 0.130048 0.826023 -0.130048 +v 0.111754 0.978466 0.031195 +v 0.100259 0.978466 0.058974 +v 0.082330 0.978466 0.082330 +v 0.263228 0.813615 0.000000 +v 0.253966 0.813615 -0.070682 +v 0.227741 0.813615 -0.133759 +v 0.027792 0.888729 0.047296 +v 0.038494 0.919969 0.065466 +v 0.052799 0.951211 0.089769 +v 0.038821 0.888729 -0.038821 +v 0.065466 0.919969 -0.038494 +v 0.100064 0.951211 -0.027927 +v 0.186892 0.813615 -0.186892 +v 0.115809 0.978466 0.000000 +v 0.058974 0.978466 0.100259 +v 0.253966 0.813615 0.070682 +v 0.158473 0.826023 0.093076 +v 0.079497 0.841089 0.079497 +v 0.032426 0.861474 0.055210 +v 0.093076 0.826023 -0.158473 +v 0.056896 0.841089 -0.096873 +v 0.032426 0.861474 -0.055210 +v 0.133759 0.813615 -0.227741 +v 0.085811 0.997741 0.023955 +v 0.076985 0.997741 0.045285 +v 0.063219 0.997741 0.063219 +v 0.045285 0.997741 0.076986 +v 0.337972 0.801206 0.000000 +v 0.326081 0.801206 -0.090752 +v 0.292408 0.801206 -0.171740 +v 0.239960 0.801206 -0.239960 +v 0.014691 0.888729 0.052735 +v 0.020357 0.919969 0.072979 +v 0.027927 0.951211 0.100064 +v 0.031195 0.978466 0.111754 +v 0.027792 0.888729 -0.047296 +v 0.053751 0.919969 -0.053751 +v 0.089769 0.951211 -0.052799 +v 0.111754 0.978466 -0.031195 +v 0.171740 0.801206 -0.292408 +v 0.088924 0.997741 0.000000 +v 0.023955 0.997741 0.085811 +v 0.326081 0.801206 0.090752 +v 0.227741 0.813615 0.133759 +v 0.130048 0.826023 0.130048 +v 0.056896 0.841089 0.096873 +v 0.017135 0.861474 0.061568 +v 0.070682 0.813615 -0.253966 +v 0.049184 0.826023 -0.176722 +v 0.030065 0.841089 -0.108029 +v 0.017135 0.861474 -0.061568 +v 0.090752 0.801206 -0.326081 +v -0.000000 1.005054 0.000000 +v 0.393218 0.786140 0.000000 +v 0.379380 0.786140 -0.105586 +v 0.340206 0.786140 -0.199813 +v 0.279184 0.786140 -0.279184 +v 0.199813 0.786140 -0.340206 +v -0.000000 0.888729 0.054654 +v -0.000000 0.919969 0.075630 +v -0.000000 0.951211 0.103696 +v -0.000000 0.978466 0.115809 +v -0.000000 0.997741 0.088925 +v 0.014691 0.888729 -0.052735 +v 0.038494 0.919969 -0.065466 +v 0.073714 0.951211 -0.073714 +v 0.100259 0.978466 -0.058974 +v 0.085811 0.997741 -0.023955 +v 0.105586 0.786140 -0.379381 +v 0.379380 0.786140 0.105586 +v 0.292408 0.801206 0.171740 +v 0.186892 0.813615 0.186892 +v 0.093076 0.826023 0.158473 +v 0.030065 0.841089 0.108029 +v -0.000000 0.861474 0.063813 +v -0.000000 0.801206 -0.337972 +v -0.000000 0.813615 -0.263228 +v -0.000000 0.826023 -0.183167 +v -0.000000 0.841089 -0.111968 +v -0.000000 0.861474 -0.063813 +v -0.000000 0.786140 -0.393218 +v 0.076985 0.997741 -0.045285 +v -0.023955 0.997741 0.085811 +v 0.414784 0.765755 0.000000 +v 0.400190 0.765755 -0.111377 +v 0.358865 0.765755 -0.210772 +v 0.294497 0.765755 -0.294497 +v 0.210772 0.765755 -0.358865 +v 0.111377 0.765755 -0.400190 +v -0.014691 0.888729 0.052735 +v -0.020357 0.919969 0.072979 +v -0.027927 0.951211 0.100064 +v -0.031195 0.978466 0.111754 +v -0.000000 0.888729 -0.054654 +v 0.020357 0.919969 -0.072979 +v 0.052799 0.951211 -0.089769 +v 0.082330 0.978466 -0.082330 +v -0.000000 0.765755 -0.414784 +v 0.063219 0.997741 -0.063219 +v -0.045285 0.997741 0.076986 +v 0.400190 0.765755 0.111377 +v 0.340206 0.786140 0.199813 +v 0.239960 0.801206 0.239960 +v 0.133759 0.813615 0.227741 +v 0.049184 0.826023 0.176722 +v -0.000000 0.841089 0.111968 +v -0.017135 0.861474 0.061568 +v -0.105586 0.786140 -0.379381 +v -0.090752 0.801206 -0.326081 +v -0.070682 0.813615 -0.253966 +v -0.049184 0.826023 -0.176722 +v -0.030066 0.841089 -0.108029 +v -0.017135 0.861474 -0.061568 +v -0.111377 0.765755 -0.400190 +v 0.045285 0.997741 -0.076986 +v -0.063220 0.997741 0.063219 +v 0.414952 0.750806 0.115486 +v 0.430085 0.750806 0.000000 +v 0.414952 0.750806 -0.115486 +v 0.372103 0.750806 -0.218547 +v 0.305360 0.750806 -0.305360 +v 0.218547 0.750806 -0.372103 +v 0.115486 0.750806 -0.414952 +v -0.000000 0.750806 -0.430085 +v -0.027793 0.888729 0.047296 +v -0.038494 0.919969 0.065466 +v -0.052799 0.951211 0.089769 +v -0.058974 0.978466 0.100259 +v -0.014691 0.888729 -0.052735 +v -0.000000 0.919969 -0.075630 +v 0.027927 0.951211 -0.100064 +v 0.058974 0.978466 -0.100259 +v -0.115486 0.750806 -0.414952 +v 0.023955 0.997741 -0.085811 +v -0.076986 0.997741 0.045285 +v 0.372103 0.750806 0.218547 +v 0.358865 0.765755 0.210772 +v 0.279184 0.786140 0.279184 +v 0.171740 0.801206 0.292408 +v 0.070682 0.813615 0.253966 +v -0.000000 0.826023 0.183167 +v -0.030066 0.841089 0.108029 +v -0.032427 0.861474 0.055210 +v -0.210772 0.765755 -0.358865 +v -0.199813 0.786140 -0.340206 +v -0.171740 0.801206 -0.292408 +v -0.133759 0.813615 -0.227741 +v -0.093076 0.826023 -0.158473 +v -0.056896 0.841089 -0.096873 +v -0.032427 0.861474 -0.055210 +v -0.218547 0.750806 -0.372103 +v 0.031195 0.978466 -0.111754 +v -0.000000 0.997741 -0.088925 +v -0.082331 0.978466 0.082330 +v -0.085811 0.997741 0.023955 +v 0.305360 0.750806 0.305360 +v 0.294497 0.765755 0.294497 +v -0.038821 0.888729 0.038821 +v -0.053751 0.919969 0.053751 +v -0.073714 0.951211 0.073714 +v -0.027793 0.888729 -0.047296 +v -0.020357 0.919969 -0.072979 +v -0.000000 0.951211 -0.103696 +v -0.305360 0.750806 -0.305360 +v -0.294497 0.765755 -0.294497 +v -0.000000 0.978466 -0.115809 +v -0.023955 0.997741 -0.085811 +v -0.100259 0.978466 0.058974 +v -0.088925 0.997741 0.000000 +v 0.210772 0.765755 0.358865 +v 0.218547 0.750806 0.372103 +v 0.199813 0.786140 0.340206 +v 0.090752 0.801206 0.326081 +v -0.000000 0.813615 0.263228 +v -0.049184 0.826023 0.176722 +v -0.056896 0.841089 0.096873 +v -0.045307 0.861474 0.045307 +v -0.279185 0.786140 -0.279184 +v -0.239960 0.801206 -0.239960 +v -0.186892 0.813615 -0.186892 +v -0.130049 0.826023 -0.130048 +v -0.079497 0.841089 -0.079497 +v -0.045307 0.861474 -0.045307 +v -0.372103 0.750806 -0.218547 +v -0.358865 0.765755 -0.210772 +v -0.031195 0.978466 -0.111754 +v -0.045285 0.997741 -0.076986 +v -0.111754 0.978466 0.031195 +v -0.085811 0.997741 -0.023955 +v 0.111377 0.765755 0.400190 +v 0.115486 0.750806 0.414952 +v -0.047296 0.888729 0.027792 +v -0.065466 0.919969 0.038494 +v -0.089770 0.951211 0.052799 +v -0.038821 0.888729 -0.038821 +v -0.038494 0.919969 -0.065466 +v -0.027927 0.951211 -0.100064 +v -0.414952 0.750806 -0.115486 +v -0.400190 0.765755 -0.111377 +v -0.058974 0.978466 -0.100259 +v -0.063220 0.997741 -0.063219 +v -0.115809 0.978466 0.000000 +v -0.076986 0.997741 -0.045285 +v 0.105586 0.786140 0.379381 +v -0.000000 0.765755 0.414784 +v -0.000000 0.750806 0.430085 +v -0.000000 0.801206 0.337972 +v -0.070682 0.813615 0.253966 +v -0.093076 0.826023 0.158473 +v -0.079497 0.841089 0.079497 +v -0.055210 0.861474 0.032427 +v -0.340206 0.786140 -0.199813 +v -0.292408 0.801206 -0.171740 +v -0.227741 0.813615 -0.133759 +v -0.158473 0.826023 -0.093076 +v -0.096873 0.841089 -0.056896 +v -0.055210 0.861474 -0.032427 +v -0.430085 0.750806 0.000000 +v -0.414784 0.765755 0.000000 +v -0.052799 0.951211 -0.089769 +v -0.082331 0.978466 -0.082330 +v -0.100064 0.951211 0.027927 +v -0.111754 0.978466 -0.031195 +v -0.000000 0.786140 0.393218 +v -0.115486 0.750806 0.414952 +v -0.111377 0.765755 0.400190 +v -0.052735 0.888729 0.014691 +v -0.072979 0.919969 0.020357 +v -0.047296 0.888729 -0.027792 +v -0.053751 0.919969 -0.053751 +v -0.414952 0.750806 0.115486 +v -0.400190 0.765755 0.111377 +v -0.379381 0.786140 -0.105586 +v -0.073714 0.951211 -0.073714 +v -0.100259 0.978466 -0.058974 +v -0.103696 0.951211 0.000000 +v -0.105586 0.786140 0.379381 +v -0.218547 0.750806 0.372103 +v -0.210772 0.765755 0.358865 +v -0.090752 0.801206 0.326081 +v -0.133759 0.813615 0.227741 +v -0.130049 0.826023 0.130048 +v -0.096873 0.841089 0.056896 +v -0.061568 0.861474 0.017135 +v -0.326081 0.801206 -0.090752 +v -0.253966 0.813615 -0.070682 +v -0.176722 0.826023 -0.049184 +v -0.108029 0.841089 -0.030065 +v -0.061568 0.861474 -0.017135 +v -0.372103 0.750806 0.218547 +v -0.358865 0.765755 0.210772 +v -0.393219 0.786140 0.000000 +v -0.089770 0.951211 -0.052799 +v -0.100064 0.951211 -0.027927 +v -0.199813 0.786140 0.340206 +v -0.305360 0.750806 0.305360 +v -0.294497 0.765755 0.294497 +v -0.054655 0.888729 0.000000 +v -0.075630 0.919969 0.000000 +v -0.052735 0.888729 -0.014691 +v -0.065466 0.919969 -0.038494 +v -0.379381 0.786140 0.105586 +v -0.171740 0.801206 0.292408 +v -0.279185 0.786140 0.279184 +v -0.186892 0.813615 0.186892 +v -0.158473 0.826023 0.093076 +v -0.108029 0.841089 0.030065 +v -0.063813 0.861474 0.000000 +v -0.337972 0.801206 0.000000 +v -0.263228 0.813615 0.000000 +v -0.183167 0.826023 0.000000 +v -0.111968 0.841089 0.000000 +v -0.340206 0.786140 0.199813 +v -0.072979 0.919969 -0.020357 +v -0.239960 0.801206 0.239960 +v -0.326081 0.801206 0.090752 +v -0.292408 0.801206 0.171740 +v -0.227741 0.813615 0.133759 +v -0.176722 0.826023 0.049184 +v -0.253966 0.813615 0.070682 +v -0.526706 0.651362 -0.039883 +v -0.534329 0.646030 0.000000 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.638129 0.287158 0.000000 +v -0.631184 0.277569 0.039883 +v -0.501666 0.699221 -0.063813 +v -0.508714 0.682112 -0.071712 +v -0.611709 0.194244 0.000000 +v -0.608883 0.198681 0.039883 +v -0.517593 0.664661 0.063813 +v -0.508714 0.682112 0.071712 +v -0.631184 0.277569 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.615480 0.216617 0.063578 +v -0.615553 0.216807 -0.063813 +v -0.517593 0.664661 -0.063813 +v -0.498530 0.712498 -0.039883 +v -0.619922 0.238069 0.071790 +v -0.526706 0.651362 0.039883 +v -0.608884 0.198682 -0.039883 +v 0.605100 0.399712 0.137265 +v 0.613258 0.341675 0.154354 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.613258 0.341675 -0.154354 +v 0.605101 0.399712 -0.137265 +v 0.600960 0.444810 0.085753 +v 0.121642 0.750009 -0.437072 +v -0.000000 0.750009 -0.453012 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 -0.121642 +v -0.453012 0.750009 0.000000 +v -0.437073 0.750009 -0.121642 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.391940 0.750009 0.230197 +v -0.437073 0.750009 0.121642 +v 0.121642 0.750009 0.437072 +v -0.000000 0.750009 0.453012 +v -0.121642 0.750009 0.437072 +v 0.437073 0.750009 0.121642 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 -0.321639 +v 0.230197 0.750009 -0.391940 +v -0.121642 0.750009 -0.437072 +v 0.391939 0.750009 -0.230197 +v 0.321638 0.750009 0.321639 +v 0.230197 0.750009 0.391940 +v -0.230198 0.750009 -0.391939 +v -0.501255 0.717792 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v -0.321639 0.750009 -0.321639 +v -0.391940 0.750009 -0.230197 +v -0.498530 0.712498 0.039883 +v -0.501667 0.699221 0.063813 +v 0.617684 0.235930 -0.085941 +v 0.619427 0.283145 -0.137236 +v 0.619427 0.283145 0.137236 +vn -0.901883 0.415418 0.118168 +vn -0.905637 0.407056 0.118656 +vn -0.877041 0.418744 0.235298 +vn 0.058443 -0.998260 0.000732 +vn 0.015107 -0.999878 0.000183 +vn 0.014557 -0.949278 0.314035 +vn 0.056703 -0.947539 0.314524 +vn 0.162053 -0.986755 0.002014 +vn 0.157933 -0.933592 0.321604 +vn 0.392376 -0.919767 0.004334 +vn 0.378307 -0.856655 0.350688 +vn 0.783776 -0.620991 0.005249 +vn 0.726829 -0.553880 0.406079 +vn 0.994812 -0.101627 0.001984 +vn 0.908139 -0.082766 0.410321 +vn 0.003082 -0.939787 0.341685 +vn 0.002167 -0.619495 0.784967 +vn 0.011536 -0.679403 0.733634 +vn 0.044679 -0.675588 0.735923 +vn 0.123325 -0.652272 0.747856 +vn 0.275399 -0.556871 0.783593 +vn 0.460067 -0.316263 0.829615 +vn 0.563036 -0.041200 0.825373 +vn -0.000427 0.122166 0.992492 +vn 0.000397 0.003632 0.999969 +vn 0.002869 0.011841 0.999908 +vn 0.004852 0.029298 0.999542 +vn -0.008179 0.053499 0.998505 +vn -0.046510 0.041536 0.998047 +vn -0.039155 0.003113 0.999207 +vn -0.850551 0.473769 -0.228217 +vn -0.897885 0.424177 -0.117649 +vn -0.880886 0.473281 0.000000 +vn -0.013611 0.682394 0.730827 +vn -0.053896 0.680441 0.730796 +vn -0.147557 0.656789 0.739464 +vn -0.325968 0.560564 0.761223 +vn -0.537645 0.315806 0.781762 +vn -0.611530 0.029939 0.790613 +vn -0.904172 0.427137 0.000000 +vn -0.897885 0.424146 0.117618 +vn -0.020112 0.949461 0.313150 +vn -0.081820 0.945433 0.315287 +vn -0.227699 0.916379 0.329173 +vn -0.504196 0.785302 0.359203 +vn -0.810633 0.443220 0.382611 +vn -0.921232 0.039705 0.386944 +vn -0.020569 0.949400 -0.313334 +vn -0.021729 0.999756 -0.000092 +vn -0.004242 0.950468 -0.310770 +vn -0.088260 0.996094 -0.000488 +vn -0.246895 0.969024 -0.001343 +vn -0.549730 0.835322 -0.002350 +vn -0.880673 0.473647 -0.001984 +vn -0.999084 0.042146 -0.000610 +vn -0.877041 0.418744 -0.235298 +vn -0.920286 0.391156 0.000000 +vn -0.905637 0.407056 -0.118656 +vn -0.083132 0.945006 -0.316202 +vn -0.230201 0.914823 -0.331797 +vn -0.505570 0.782800 -0.362743 +vn -0.808710 0.444960 -0.384625 +vn -0.920835 0.042055 -0.387646 +vn -0.897885 0.424146 -0.117618 +vn -0.901883 0.415448 -0.118168 +vn -0.014161 0.682394 -0.730796 +vn -0.055361 0.680074 -0.731010 +vn -0.150029 0.655660 -0.739982 +vn -0.327616 0.560594 -0.760491 +vn -0.537431 0.320933 -0.779809 +vn -0.611988 0.033387 -0.790155 +vn 0.015168 -0.949339 -0.313852 +vn 0.011902 -0.679403 -0.733634 +vn 0.003265 -0.939817 -0.341594 +vn 0.000183 0.004212 -0.999969 +vn 0.003510 0.014008 -0.999878 +vn 0.005921 0.035951 -0.999329 +vn -0.010132 0.064333 -0.997864 +vn -0.051576 0.048463 -0.997467 +vn -0.041597 0.003998 -0.999115 +vn 0.003082 -0.620106 -0.784478 +vn -0.000031 0.122440 -0.992462 +vn -0.897885 0.424177 0.117649 +vn 0.046449 -0.674398 -0.736869 +vn 0.125980 -0.648946 -0.750298 +vn 0.275430 -0.552477 -0.786676 +vn 0.455519 -0.320536 -0.830500 +vn 0.561693 -0.046480 -0.826014 +vn -0.888668 0.391644 0.238441 +vn 0.058046 -0.947630 -0.314005 +vn 0.159948 -0.933836 -0.319865 +vn 0.380169 -0.857753 -0.345927 +vn 0.725547 -0.560930 -0.398602 +vn 0.908597 -0.089236 -0.407971 +vn 0.003235 -0.999969 0.000031 +vn 0.973144 0.230110 0.000824 +vn 0.890896 0.211737 0.401776 +vn 0.912900 0.408094 0.002533 +vn 0.836970 0.380932 0.392834 +vn 0.829035 0.559160 0.003784 +vn 0.764519 0.528550 0.368969 +vn 0.718650 0.695334 0.003937 +vn 0.668294 0.663717 0.335917 +vn 0.579577 0.814905 0.002838 +vn 0.542650 0.779687 0.312357 +vn 0.495163 0.868770 0.002258 +vn 0.458052 0.820643 0.341624 +vn 0.561205 0.137028 0.816218 +vn 0.532029 0.253456 0.807886 +vn 0.497543 0.363445 0.787591 +vn 0.449538 0.472060 0.758293 +vn 0.373669 0.563555 0.736686 +vn 0.289041 0.531114 0.796442 +vn -0.023225 -0.005249 0.999695 +vn -0.016785 -0.010254 0.999786 +vn -0.011444 -0.012940 0.999847 +vn -0.009796 -0.013276 0.999847 +vn -0.014801 -0.013916 0.999786 +vn -0.089755 -0.176122 0.980255 +vn -0.585772 -0.152379 0.795984 +vn -0.538896 -0.288766 0.791314 +vn -0.484146 -0.407910 0.774071 +vn -0.424635 -0.509781 0.748161 +vn -0.355907 -0.584765 0.728935 +vn -0.889828 -0.237159 0.389782 +vn -0.808740 -0.446852 0.382366 +vn -0.702475 -0.613269 0.361095 +vn -0.590625 -0.734855 0.333293 +vn -0.483291 -0.816767 0.315104 +vn -0.912076 0.409955 0.000000 +vn -0.965606 -0.259987 -0.000458 +vn -0.872433 -0.488693 -0.001465 +vn -0.748436 -0.663167 -0.002197 +vn -0.621601 -0.783288 -0.002136 +vn -0.507065 -0.861873 -0.001251 +vn -0.438215 -0.854366 0.279183 +vn -0.456130 -0.889889 -0.000732 +vn -0.889126 -0.238868 -0.390332 +vn -0.807001 -0.448531 -0.384075 +vn -0.700980 -0.613392 -0.363750 +vn -0.590442 -0.733757 -0.336039 +vn -0.484787 -0.815332 -0.316477 +vn -0.440962 -0.852931 -0.279305 +vn -0.359691 -0.584185 -0.727531 +vn -0.358074 -0.682241 -0.637410 +vn -0.585467 -0.154668 -0.795770 +vn -0.538499 -0.291696 -0.790490 +vn -0.484512 -0.409772 -0.772851 +vn -0.426496 -0.510056 -0.746910 +vn -0.909543 -0.399274 -0.115207 +vn -0.971191 -0.204688 -0.121891 +vn -0.912931 -0.326609 -0.244606 +vn -0.020478 -0.017853 -0.999603 +vn -0.024537 -0.005737 -0.999664 +vn -0.020844 -0.012207 -0.999695 +vn -0.017548 -0.016846 -0.999695 +vn -0.016724 -0.018097 -0.999695 +vn -0.909116 -0.400311 0.115055 +vn -0.873775 -0.472610 0.114475 +vn -0.795892 -0.566485 0.213538 +vn -0.353069 -0.684103 0.638203 +vn 0.559679 0.139714 -0.816828 +vn 0.528581 0.255501 -0.809473 +vn 0.494217 0.362987 -0.789911 +vn 0.449049 0.469283 -0.760308 +vn 0.378246 0.560869 -0.736412 +vn -0.091983 -0.174383 -0.980346 +vn 0.295267 0.530625 -0.794488 +vn 0.890500 0.214759 -0.401044 +vn 0.836634 0.384075 -0.390515 +vn 0.765191 0.530198 -0.365123 +vn 0.671041 0.663228 -0.331339 +vn 0.547929 0.777642 -0.308206 +vn 0.464522 0.818842 -0.337199 +vn 0.931486 0.265572 -0.248543 +vn 0.939543 0.342357 0.000000 +vn 0.947539 0.295114 -0.122684 +vn -0.351421 0.936186 0.001953 +vn -0.144444 0.989502 0.003174 +vn -0.126743 0.878811 0.459975 +vn -0.716758 0.697287 -0.000946 +vn -0.299997 0.838313 0.455214 +vn -0.621876 0.660207 0.421155 +vn -0.901822 0.432081 -0.004517 +vn -0.807031 0.443434 0.389904 +vn -0.930204 0.366863 -0.008484 +vn -0.824549 0.383312 0.416059 +vn -0.850673 0.525529 -0.011628 +vn -0.722465 0.508988 0.467910 +vn -0.668447 0.743645 -0.011139 +vn -0.531449 0.686514 0.496170 +vn -0.116459 0.505448 0.854946 +vn -0.258400 0.470656 0.843593 +vn -0.407605 0.396985 0.822321 +vn -0.450270 0.352367 0.820399 +vn -0.385876 0.395734 0.833338 +vn -0.270669 0.487838 0.829890 +vn 0.141606 -0.001190 0.989898 +vn -0.067690 0.525346 0.848170 +vn 0.989593 0.100253 0.103122 +vn 0.970244 0.213324 0.114475 +vn 0.960418 0.152654 0.232917 +vn 0.241829 0.092502 0.965880 +vn 0.209296 0.170660 0.962828 +vn 0.096194 0.178625 0.979186 +vn 0.009552 0.154332 0.987945 +vn -0.000122 0.151952 0.988372 +vn 0.361248 -0.477279 0.801019 +vn 0.607929 -0.282540 0.741997 +vn 0.679220 -0.106754 0.726096 +vn 0.583911 -0.078524 0.807978 +vn 0.402722 -0.205237 0.891995 +vn 0.279519 -0.338694 0.898404 +vn 0.488601 -0.768700 0.412671 +vn 0.784570 -0.501511 0.364544 +vn 0.893918 -0.279611 0.350291 +vn 0.861415 -0.285287 0.420179 +vn 0.679373 -0.540452 0.496323 +vn 0.458327 -0.754540 0.469588 +vn 0.524155 -0.851588 -0.000153 +vn 0.827143 -0.561968 0.001679 +vn 0.943205 -0.332133 0.003479 +vn 0.933256 -0.359081 0.005737 +vn 0.756859 -0.653493 0.006470 +vn 0.492843 -0.870083 0.004120 +vn 0.322489 -0.946562 -0.001129 +vn 0.912839 -0.326609 0.244942 +vn 0.824396 -0.565996 0.000000 +vn 0.894162 -0.447676 0.000000 +vn 0.486557 -0.770501 -0.411756 +vn 0.783990 -0.504074 -0.362285 +vn 0.895199 -0.281899 -0.345134 +vn 0.863735 -0.289010 -0.412824 +vn 0.682119 -0.544267 -0.488296 +vn 0.461928 -0.758202 -0.460128 +vn 0.357463 -0.479141 -0.801599 +vn 0.605884 -0.285867 -0.742393 +vn 0.679739 -0.108646 -0.725333 +vn 0.583636 -0.077883 -0.808222 +vn 0.401440 -0.199225 -0.893918 +vn 0.281961 -0.330638 -0.900632 +vn 0.135228 -0.002380 -0.990783 +vn 0.235755 0.091128 -0.967498 +vn 0.200720 0.170629 -0.964660 +vn 0.086123 0.184576 -0.979003 +vn 0.000671 0.174322 -0.984680 +vn -0.007141 0.169012 -0.985565 +vn 0.966613 -0.042848 -0.252602 +vn 0.960418 0.152654 -0.232917 +vn 0.989593 0.100223 -0.103092 +vn -0.119297 0.503342 -0.855770 +vn -0.261269 0.472793 -0.841517 +vn -0.414075 0.399792 -0.817713 +vn -0.459700 0.357036 -0.813105 +vn -0.394024 0.408490 -0.823298 +vn -0.277871 0.487381 -0.827754 +vn -0.072207 0.520127 -0.851009 +vn -0.298654 0.840297 -0.452376 +vn -0.617512 0.663961 -0.421613 +vn -0.801324 0.450209 -0.393872 +vn -0.819422 0.389691 -0.420270 +vn -0.721274 0.506912 -0.471969 +vn -0.538347 0.670644 -0.510239 +vn -0.482009 0.876125 -0.005127 +vn -0.394635 0.815363 0.423536 +vn -0.321909 0.946745 -0.002594 +vn -0.255287 0.921995 0.291086 +vn 0.004242 0.999969 0.000397 +vn -0.002960 0.999939 -0.010102 +vn 0.853450 0.521073 -0.007050 +vn 0.392041 0.688986 -0.609546 +vn 0.805170 -0.592517 -0.023621 +vn 0.588763 -0.206122 -0.781579 +vn 0.681478 -0.731040 -0.033296 +vn 0.485031 -0.441237 -0.754967 +vn -0.206824 0.638203 0.741539 +vn -0.129490 0.862056 0.489944 +vn -0.033418 0.999176 0.022340 +vn 0.047700 0.864040 -0.501114 +vn 0.099307 0.538743 -0.836573 +vn 0.053560 0.251839 -0.966277 +vn 0.020112 0.322611 0.946287 +vn 0.021943 0.748894 0.662282 +vn -0.025941 0.995605 0.089908 +vn -0.059175 0.930876 -0.360424 +vn -0.080172 0.784448 -0.614948 +vn -0.142582 0.557604 -0.817743 +vn 0.281747 -0.174993 0.943388 +vn 0.303903 0.444136 0.842830 +vn 0.034333 0.983764 0.175970 +vn -0.113865 0.956420 -0.268777 +vn -0.155339 0.858852 -0.488021 +vn -0.207404 0.641865 -0.738182 +vn 0.467238 -0.683187 0.561144 +vn 0.699515 0.004364 0.714560 +vn 0.355296 0.891934 0.279641 +vn -0.170354 0.971465 -0.164861 +vn -0.245552 0.901181 -0.357097 +vn -0.248726 0.651082 -0.717063 +vn 0.494430 -0.869167 0.006317 +vn 0.933134 -0.358898 0.019868 +vn 0.703146 0.710685 0.021790 +vn -0.203650 0.978942 -0.012574 +vn -0.326456 0.942869 -0.066073 +vn -0.397595 0.857082 -0.327525 +vn 0.460616 -0.712546 -0.529221 +vn 0.695486 -0.098544 -0.711722 +vn 0.397534 0.853816 -0.336070 +vn -0.198248 0.963439 0.180151 +vn -0.306833 0.888516 0.341075 +vn -0.393689 0.807672 0.438887 +vn 0.276559 -0.211951 -0.937315 +vn 0.294626 0.366161 -0.882656 +vn 0.046632 0.973235 -0.224982 +vn -0.146733 0.912168 0.382611 +vn -0.202643 0.700797 0.683950 +vn -0.232673 0.506485 0.830226 +vn 0.011689 0.309397 -0.950835 +vn 0.013245 0.708640 -0.705435 +vn -0.027589 0.995758 -0.087680 +vn -0.047395 0.829371 0.556658 +vn -0.015259 0.386608 0.922086 +vn 0.004639 0.119510 0.992798 +vn -0.211035 0.631001 -0.746513 +vn -0.138768 0.848781 -0.510147 +vn -0.024995 0.999664 -0.001190 +vn 0.120426 0.724570 0.678579 +vn 0.260750 0.006531 0.965361 +vn 0.272500 -0.255898 0.927488 +vn -0.395581 0.809961 -0.432905 +vn -0.258827 0.918851 -0.297800 +vn 0.004730 0.999878 0.013031 +vn 0.466628 0.599780 0.649983 +vn 0.621937 -0.400861 0.672628 +vn 0.551042 -0.592181 0.587878 +vn 0.649068 0.384991 -0.656087 +vn 0.055971 0.691214 0.720450 +vn -0.115940 0.804590 0.582354 +vn -0.262185 0.897946 0.353435 +vn -0.341655 0.885006 -0.316263 +vn -0.081423 0.793085 -0.603626 +vn -0.155675 0.857753 -0.489883 +vn 0.728690 0.365978 0.578784 +vn 0.318674 0.539384 0.779382 +vn 0.953551 0.300150 -0.024415 +vn -0.133976 0.836818 -0.530808 +vn 0.095401 0.667959 -0.738029 +vn 0.000000 0.999969 0.000000 +vn -0.992523 -0.122013 0.000000 +vn -0.937346 -0.348338 0.000000 +vn -0.905148 -0.348827 -0.242836 +vn -0.958617 -0.122227 -0.257057 +vn -0.832057 0.554674 0.000000 +vn -0.803217 0.555376 -0.215339 +vn -0.048616 0.998810 0.000000 +vn -0.046236 0.998840 -0.012726 +vn 0.544267 0.838893 0.000000 +vn 0.525376 0.839106 0.140843 +vn 0.783471 0.621387 0.000000 +vn 0.756371 0.621845 0.202918 +vn 0.880886 0.473281 0.000000 +vn 0.850551 0.473769 0.228217 +vn -0.810907 -0.349376 -0.469375 +vn -0.859004 -0.122410 -0.497085 +vn -0.719657 0.555559 -0.416425 +vn -0.041749 0.998810 -0.024415 +vn 0.470077 0.839625 0.272011 +vn 0.677236 0.622608 0.391980 +vn 0.761803 0.474471 0.440962 +vn -0.662465 -0.349620 -0.662465 +vn -0.701773 -0.122440 -0.701773 +vn -0.587878 0.555650 -0.587878 +vn -0.034272 0.998810 -0.034272 +vn 0.383831 0.839808 0.383831 +vn 0.553148 0.622913 0.553148 +vn 0.622303 0.474776 0.622303 +vn -0.469375 -0.349376 -0.810907 +vn -0.497085 -0.122379 -0.859004 +vn -0.416425 0.555559 -0.719657 +vn -0.024415 0.998810 -0.041749 +vn 0.272011 0.839625 0.470077 +vn 0.391980 0.622608 0.677236 +vn 0.440962 0.474471 0.761834 +vn -0.242836 -0.348827 -0.905148 +vn -0.257057 -0.122227 -0.958617 +vn -0.215339 0.555376 -0.803217 +vn -0.012726 0.998840 -0.046205 +vn 0.140843 0.839106 0.525376 +vn 0.202918 0.621845 0.756371 +vn 0.228217 0.473769 0.850551 +vn 0.000000 -0.348338 -0.937346 +vn 0.000000 -0.122013 -0.992523 +vn 0.000000 0.554674 -0.832057 +vn 0.000000 0.998810 -0.048616 +vn 0.000000 0.838893 0.544267 +vn 0.000000 0.621387 0.783471 +vn 0.000000 0.473281 0.880886 +vn 0.242836 -0.348827 -0.905148 +vn 0.257057 -0.122227 -0.958617 +vn 0.215308 0.555376 -0.803217 +vn 0.012726 0.998840 -0.046205 +vn -0.140843 0.839106 0.525376 +vn -0.202918 0.621845 0.756340 +vn -0.228217 0.473769 0.850551 +vn 0.469375 -0.349376 -0.810907 +vn 0.497085 -0.122379 -0.859004 +vn 0.416425 0.555559 -0.719657 +vn 0.024415 0.998810 -0.041749 +vn -0.272011 0.839625 0.470077 +vn -0.391980 0.622608 0.677236 +vn -0.440962 0.474502 0.761803 +vn 0.662465 -0.349620 -0.662465 +vn 0.701773 -0.122471 -0.701773 +vn 0.587878 0.555650 -0.587878 +vn 0.034272 0.998810 -0.034272 +vn -0.383831 0.839808 0.383831 +vn -0.553148 0.622913 0.553148 +vn -0.622303 0.474776 0.622303 +vn 0.810907 -0.349406 -0.469375 +vn 0.859004 -0.122379 -0.497085 +vn 0.719657 0.555559 -0.416425 +vn 0.041749 0.998810 -0.024415 +vn -0.470077 0.839625 0.272011 +vn -0.677236 0.622608 0.391980 +vn -0.761803 0.474471 0.440962 +vn 0.905148 -0.348827 -0.242836 +vn 0.958617 -0.122227 -0.257057 +vn 0.803217 0.555376 -0.215339 +vn 0.046205 0.998840 -0.012726 +vn -0.525376 0.839106 0.140843 +vn -0.756340 0.621876 0.202918 +vn -0.850551 0.473769 0.228217 +vn 0.937346 -0.348338 0.000000 +vn 0.992523 -0.122013 0.000000 +vn 0.832026 0.554674 0.000000 +vn 0.048616 0.998810 0.000000 +vn -0.544267 0.838893 0.000000 +vn -0.783471 0.621387 0.000000 +vn 0.905148 -0.348827 0.242836 +vn 0.958617 -0.122227 0.257057 +vn 0.803217 0.555376 0.215308 +vn 0.046205 0.998840 0.012726 +vn -0.525376 0.839106 -0.140843 +vn -0.756340 0.621876 -0.202918 +vn 0.810907 -0.349406 0.469375 +vn 0.859004 -0.122379 0.497085 +vn 0.719657 0.555559 0.416425 +vn 0.041749 0.998810 0.024415 +vn -0.470077 0.839625 -0.272011 +vn -0.677236 0.622608 -0.391980 +vn -0.761803 0.474471 -0.440962 +vn 0.662465 -0.349620 0.662465 +vn 0.701773 -0.122471 0.701773 +vn 0.587878 0.555650 0.587878 +vn 0.034272 0.998810 0.034272 +vn -0.383831 0.839808 -0.383831 +vn -0.553148 0.622913 -0.553148 +vn -0.622303 0.474776 -0.622303 +vn 0.469375 -0.349376 0.810907 +vn 0.497085 -0.122379 0.859004 +vn 0.416425 0.555559 0.719657 +vn 0.024415 0.998810 0.041749 +vn -0.272011 0.839625 -0.470077 +vn -0.391980 0.622608 -0.677236 +vn -0.440962 0.474471 -0.761803 +vn 0.242836 -0.348827 0.905148 +vn 0.257057 -0.122227 0.958617 +vn 0.215339 0.555376 0.803217 +vn 0.012726 0.998840 0.046205 +vn -0.140843 0.839106 -0.525376 +vn -0.202918 0.621845 -0.756371 +vn -0.228217 0.473769 -0.850551 +vn 0.000000 -0.348338 0.937346 +vn 0.000000 -0.122013 0.992523 +vn 0.000000 0.554674 0.832057 +vn 0.000000 0.998810 0.048616 +vn 0.000000 0.838893 -0.544267 +vn 0.000000 0.621387 -0.783471 +vn 0.000000 0.473281 -0.880886 +vn -0.242836 -0.348827 0.905148 +vn -0.257057 -0.122227 0.958617 +vn -0.215308 0.555376 0.803217 +vn -0.012726 0.998840 0.046205 +vn 0.140843 0.839106 -0.525376 +vn 0.202918 0.621845 -0.756371 +vn 0.228217 0.473769 -0.850551 +vn -0.469375 -0.349376 0.810907 +vn -0.497085 -0.122379 0.859004 +vn -0.416425 0.555559 0.719657 +vn -0.024415 0.998810 0.041749 +vn 0.272011 0.839625 -0.470077 +vn 0.391980 0.622608 -0.677236 +vn 0.440962 0.474471 -0.761803 +vn -0.662465 -0.349620 0.662465 +vn -0.701773 -0.122440 0.701773 +vn -0.587878 0.555650 0.587878 +vn -0.034272 0.998810 0.034272 +vn 0.383831 0.839808 -0.383831 +vn 0.553148 0.622913 -0.553148 +vn 0.622303 0.474776 -0.622303 +vn -0.810907 -0.349376 0.469375 +vn -0.859004 -0.122410 0.497085 +vn -0.719657 0.555528 0.416425 +vn -0.041749 0.998810 0.024415 +vn 0.470077 0.839625 -0.272011 +vn 0.677236 0.622639 -0.391980 +vn 0.761803 0.474471 -0.440962 +vn -0.905148 -0.348827 0.242836 +vn -0.958617 -0.122227 0.257057 +vn -0.803217 0.555376 0.215339 +vn -0.046236 0.998840 0.012726 +vn 0.525376 0.839106 -0.140843 +vn 0.756371 0.621845 -0.202918 +vn 0.850551 0.473769 -0.228217 +vn 0.908292 0.418256 0.000000 +vn 0.877041 0.418744 0.235298 +vn 0.920286 0.391156 0.000000 +vn 0.888668 0.391644 0.238441 +vn 0.907315 0.342753 0.243446 +vn 0.785638 0.419416 0.454756 +vn 0.796075 0.392285 0.460799 +vn 0.812830 0.343333 0.470504 +vn 0.931486 0.265542 0.248543 +vn 0.834162 0.266366 0.482864 +vn 0.855312 0.152379 0.495132 +vn 0.966613 -0.042848 0.252602 +vn 0.864498 -0.045808 0.500504 +vn 0.641804 0.419691 0.641804 +vn 0.650349 0.392499 0.650349 +vn 0.664052 0.343577 0.664052 +vn 0.681509 0.266579 0.681509 +vn 0.698813 0.152501 0.698813 +vn 0.706351 -0.045869 0.706351 +vn 0.454756 0.419416 0.785638 +vn 0.460799 0.392285 0.796075 +vn 0.470504 0.343333 0.812830 +vn 0.482864 0.266366 0.834162 +vn 0.495132 0.152409 0.855312 +vn 0.500504 -0.045808 0.864498 +vn 0.235298 0.418744 0.877041 +vn 0.238441 0.391644 0.888668 +vn 0.243446 0.342753 0.907315 +vn 0.249855 0.265908 0.931028 +vn 0.256172 0.152104 0.954558 +vn 0.258980 -0.045717 0.964782 +vn 0.000000 0.418256 0.908292 +vn 0.000000 0.391156 0.920286 +vn 0.000000 0.342357 0.939543 +vn 0.000000 0.265542 0.964080 +vn 0.000000 0.151891 0.988372 +vn 0.000000 -0.045656 0.998932 +vn -0.235298 0.418744 0.877041 +vn -0.238441 0.391644 0.888668 +vn -0.243446 0.342753 0.907315 +vn -0.249855 0.265877 0.931028 +vn -0.256172 0.152104 0.954558 +vn -0.258980 -0.045717 0.964782 +vn -0.454756 0.419416 0.785638 +vn -0.460799 0.392285 0.796075 +vn -0.470504 0.343333 0.812830 +vn -0.482864 0.266366 0.834162 +vn -0.495132 0.152379 0.855312 +vn -0.500504 -0.045808 0.864498 +vn -0.641804 0.419691 0.641804 +vn -0.650349 0.392499 0.650349 +vn -0.664052 0.343577 0.664052 +vn -0.681509 0.266579 0.681509 +vn -0.698813 0.152501 0.698813 +vn -0.706351 -0.045869 0.706351 +vn -0.785638 0.419416 0.454756 +vn -0.796075 0.392285 0.460799 +vn -0.812830 0.343364 0.470504 +vn -0.834162 0.266366 0.482864 +vn -0.855312 0.152379 0.495132 +vn -0.864498 -0.045808 0.500504 +vn -0.907315 0.342753 0.243446 +vn -0.931028 0.265908 0.249855 +vn -0.954558 0.152104 0.256172 +vn -0.964782 -0.045717 0.258980 +vn -0.939543 0.342357 0.000000 +vn -0.964080 0.265542 0.000000 +vn -0.988372 0.151891 0.000000 +vn -0.888668 0.391644 -0.238441 +vn -0.907315 0.342753 -0.243446 +vn -0.931028 0.265877 -0.249855 +vn -0.954558 0.152104 -0.256172 +vn -0.785638 0.419416 -0.454756 +vn -0.796075 0.392285 -0.460799 +vn -0.812830 0.343333 -0.470504 +vn -0.834162 0.266366 -0.482864 +vn -0.855312 0.152379 -0.495132 +vn -0.964782 -0.045717 -0.258980 +vn -0.864498 -0.045808 -0.500504 +vn -0.641804 0.419691 -0.641804 +vn -0.650349 0.392499 -0.650349 +vn -0.664052 0.343577 -0.664052 +vn -0.681509 0.266579 -0.681509 +vn -0.698813 0.152501 -0.698813 +vn -0.706351 -0.045869 -0.706351 +vn -0.454756 0.419416 -0.785638 +vn -0.460799 0.392285 -0.796075 +vn -0.470504 0.343333 -0.812830 +vn -0.482864 0.266366 -0.834162 +vn -0.495132 0.152379 -0.855312 +vn -0.500504 -0.045808 -0.864498 +vn -0.235298 0.418744 -0.877041 +vn -0.238441 0.391644 -0.888668 +vn -0.243446 0.342753 -0.907315 +vn -0.249855 0.265908 -0.931028 +vn -0.256172 0.152104 -0.954558 +vn -0.258980 -0.045717 -0.964782 +vn 0.000000 0.418256 -0.908292 +vn 0.000000 0.391156 -0.920286 +vn 0.000000 0.342357 -0.939543 +vn 0.000000 0.265542 -0.964080 +vn 0.000000 0.151891 -0.988372 +vn 0.000000 -0.045656 -0.998932 +vn 0.235298 0.418744 -0.877041 +vn 0.238441 0.391644 -0.888668 +vn 0.243446 0.342753 -0.907315 +vn 0.249855 0.265877 -0.931028 +vn 0.256172 0.152104 -0.954558 +vn 0.258980 -0.045717 -0.964782 +vn 0.454756 0.419416 -0.785638 +vn 0.460799 0.392285 -0.796075 +vn 0.470504 0.343333 -0.812830 +vn 0.482864 0.266366 -0.834162 +vn 0.495132 0.152379 -0.855312 +vn 0.500504 -0.045808 -0.864498 +vn 0.641804 0.419691 -0.641804 +vn 0.650349 0.392499 -0.650349 +vn 0.664052 0.343577 -0.664052 +vn 0.681509 0.266579 -0.681509 +vn 0.698813 0.152501 -0.698813 +vn 0.706351 -0.045869 -0.706351 +vn 0.785638 0.419416 -0.454756 +vn 0.796075 0.392285 -0.460799 +vn 0.812830 0.343364 -0.470504 +vn 0.834162 0.266366 -0.482864 +vn 0.855312 0.152379 -0.495132 +vn 0.864498 -0.045808 -0.500504 +vn 0.877041 0.418744 -0.235298 +vn 0.888668 0.391644 -0.238441 +vn 0.907315 0.342753 -0.243446 +vn 0.795892 -0.566485 0.213538 +vn 0.712180 -0.701987 0.000000 +vn 0.687399 -0.702445 0.184393 +vn 0.652974 -0.757347 0.000000 +vn 0.630146 -0.757805 0.169012 +vn 0.724021 -0.689749 0.000000 +vn 0.698752 -0.690329 0.187414 +vn 0.886410 -0.462874 0.000000 +vn 0.855861 -0.463454 0.229530 +vn 0.817774 -0.327158 0.473434 +vn 0.712729 -0.567248 0.412549 +vn 0.615345 -0.703146 0.356151 +vn 0.564043 -0.758446 0.326456 +vn 0.625660 -0.690939 0.362102 +vn 0.766625 -0.464125 0.443678 +vn 0.668111 -0.327403 0.668111 +vn 0.582171 -0.567522 0.582171 +vn 0.502579 -0.703421 0.502579 +vn 0.460646 -0.758660 0.460646 +vn 0.510971 -0.691183 0.510971 +vn 0.626209 -0.464370 0.626240 +vn 0.473434 -0.327158 0.817774 +vn 0.412549 -0.567248 0.712729 +vn 0.356151 -0.703146 0.615375 +vn 0.326456 -0.758446 0.564043 +vn 0.362102 -0.690939 0.625660 +vn 0.443678 -0.464125 0.766625 +vn 0.245003 -0.326609 0.912839 +vn 0.213538 -0.566485 0.795892 +vn 0.184393 -0.702445 0.687399 +vn 0.169012 -0.757805 0.630146 +vn 0.187414 -0.690329 0.698752 +vn 0.229530 -0.463454 0.855831 +vn 0.000000 -0.326243 0.945250 +vn 0.000000 -0.565996 0.824396 +vn 0.000000 -0.701987 0.712180 +vn 0.000000 -0.757347 0.652974 +vn 0.000000 -0.689749 0.724021 +vn 0.000000 -0.462905 0.886380 +vn -0.245003 -0.326609 0.912839 +vn -0.213538 -0.566485 0.795892 +vn -0.184393 -0.702445 0.687399 +vn -0.169012 -0.757805 0.630146 +vn -0.187414 -0.690329 0.698752 +vn -0.229530 -0.463454 0.855861 +vn -0.473434 -0.327158 0.817774 +vn -0.412549 -0.567248 0.712729 +vn -0.356151 -0.703146 0.615375 +vn -0.326456 -0.758446 0.564043 +vn -0.362102 -0.690939 0.625660 +vn -0.443678 -0.464125 0.766625 +vn -0.668111 -0.327403 0.668111 +vn -0.582171 -0.567522 0.582171 +vn -0.502579 -0.703421 0.502579 +vn -0.460646 -0.758660 0.460646 +vn -0.510971 -0.691183 0.510971 +vn -0.626209 -0.464370 0.626209 +vn -0.817774 -0.327158 0.473434 +vn -0.712729 -0.567248 0.412549 +vn -0.615375 -0.703146 0.356151 +vn -0.564043 -0.758446 0.326456 +vn -0.625660 -0.690939 0.362102 +vn -0.766625 -0.464125 0.443678 +vn -0.912931 -0.326609 0.244575 +vn -0.687399 -0.702445 0.184393 +vn -0.630146 -0.757805 0.169012 +vn -0.698752 -0.690329 0.187414 +vn -0.855831 -0.463485 0.229530 +vn -0.824396 -0.565996 0.000000 +vn -0.712180 -0.701987 0.000000 +vn -0.652974 -0.757347 0.000000 +vn -0.724021 -0.689749 0.000000 +vn -0.886410 -0.462874 0.000000 +vn -0.795892 -0.566485 -0.213538 +vn -0.687399 -0.702445 -0.184393 +vn -0.630146 -0.757805 -0.169012 +vn -0.698752 -0.690329 -0.187414 +vn -0.855831 -0.463454 -0.229530 +vn -0.817774 -0.327158 -0.473434 +vn -0.712729 -0.567217 -0.412549 +vn -0.615375 -0.703146 -0.356151 +vn -0.564043 -0.758446 -0.326456 +vn -0.625660 -0.690939 -0.362102 +vn -0.766625 -0.464125 -0.443678 +vn -0.668111 -0.327403 -0.668111 +vn -0.582171 -0.567522 -0.582171 +vn -0.502579 -0.703421 -0.502579 +vn -0.460646 -0.758660 -0.460646 +vn -0.510971 -0.691183 -0.510971 +vn -0.626209 -0.464370 -0.626209 +vn -0.473434 -0.327158 -0.817774 +vn -0.412549 -0.567248 -0.712729 +vn -0.356151 -0.703146 -0.615375 +vn -0.326456 -0.758446 -0.564043 +vn -0.362102 -0.690939 -0.625660 +vn -0.443678 -0.464125 -0.766625 +vn -0.245003 -0.326609 -0.912839 +vn -0.213538 -0.566485 -0.795892 +vn -0.184393 -0.702445 -0.687399 +vn -0.169012 -0.757805 -0.630146 +vn -0.187414 -0.690329 -0.698752 +vn -0.229530 -0.463454 -0.855831 +vn 0.000000 -0.326243 -0.945250 +vn 0.000000 -0.565996 -0.824396 +vn 0.000000 -0.701987 -0.712180 +vn 0.000000 -0.757347 -0.652974 +vn 0.000000 -0.689749 -0.724021 +vn 0.000000 -0.462905 -0.886380 +vn 0.245003 -0.326609 -0.912839 +vn 0.213538 -0.566485 -0.795892 +vn 0.184393 -0.702445 -0.687399 +vn 0.169012 -0.757805 -0.630146 +vn 0.187445 -0.690329 -0.698752 +vn 0.229530 -0.463454 -0.855861 +vn 0.473434 -0.327158 -0.817774 +vn 0.412549 -0.567248 -0.712729 +vn 0.356151 -0.703146 -0.615375 +vn 0.326456 -0.758446 -0.564043 +vn 0.362102 -0.690939 -0.625660 +vn 0.443678 -0.464125 -0.766625 +vn 0.668111 -0.327403 -0.668111 +vn 0.582171 -0.567522 -0.582171 +vn 0.502579 -0.703421 -0.502579 +vn 0.460646 -0.758660 -0.460646 +vn 0.510971 -0.691183 -0.510971 +vn 0.626209 -0.464370 -0.626209 +vn 0.817774 -0.327158 -0.473434 +vn 0.712729 -0.567248 -0.412549 +vn 0.615375 -0.703146 -0.356151 +vn 0.564043 -0.758446 -0.326456 +vn 0.625660 -0.690939 -0.362102 +vn 0.766625 -0.464125 -0.443678 +vn 0.912839 -0.326609 -0.244942 +vn 0.795892 -0.566485 -0.213538 +vn 0.687399 -0.702445 -0.184393 +vn 0.630146 -0.757805 -0.169012 +vn 0.698752 -0.690329 -0.187414 +vn 0.855861 -0.463454 -0.229530 +vn 0.025666 -0.999664 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.024781 -0.999664 -0.006623 +vn 0.068667 -0.997620 0.000000 +vn 0.066256 -0.997620 -0.017731 +vn 0.157170 -0.987548 0.000000 +vn 0.151677 -0.987579 -0.040620 +vn 0.373150 -0.927763 0.000000 +vn 0.360118 -0.927885 -0.096469 +vn 0.789148 -0.614154 0.000000 +vn 0.762017 -0.614399 -0.204505 +vn 0.022156 -0.999664 -0.012787 +vn 0.059236 -0.997650 -0.034272 +vn 0.135624 -0.987640 -0.078463 +vn 0.322153 -0.928129 -0.186377 +vn 0.682333 -0.615131 -0.394971 +vn 0.018067 -0.999664 -0.018067 +vn 0.048341 -0.997650 -0.048341 +vn 0.110691 -0.987640 -0.110691 +vn 0.262947 -0.928251 -0.262947 +vn 0.557329 -0.615375 -0.557329 +vn 0.012787 -0.999664 -0.022156 +vn 0.034272 -0.997650 -0.059236 +vn 0.078463 -0.987640 -0.135624 +vn 0.186377 -0.928129 -0.322153 +vn 0.394971 -0.615131 -0.682302 +vn 0.006623 -0.999664 -0.024781 +vn 0.017731 -0.997620 -0.066256 +vn 0.040620 -0.987579 -0.151677 +vn 0.096469 -0.927885 -0.360118 +vn 0.204474 -0.614399 -0.762017 +vn 0.000000 -0.999664 -0.025666 +vn 0.000000 -0.997620 -0.068667 +vn 0.000000 -0.987548 -0.157170 +vn 0.000000 -0.927763 -0.373150 +vn 0.000000 -0.614154 -0.789148 +vn -0.006623 -0.999664 -0.024781 +vn -0.017731 -0.997620 -0.066256 +vn -0.040620 -0.987579 -0.151677 +vn -0.096469 -0.927885 -0.360118 +vn -0.204474 -0.614399 -0.762017 +vn -0.012787 -0.999664 -0.022156 +vn -0.034272 -0.997650 -0.059236 +vn -0.078463 -0.987640 -0.135624 +vn -0.186377 -0.928129 -0.322153 +vn -0.394971 -0.615131 -0.682333 +vn -0.018067 -0.999664 -0.018067 +vn -0.048341 -0.997650 -0.048341 +vn -0.110691 -0.987640 -0.110691 +vn -0.262947 -0.928251 -0.262947 +vn -0.557329 -0.615375 -0.557329 +vn -0.022156 -0.999664 -0.012787 +vn -0.059236 -0.997650 -0.034272 +vn -0.135624 -0.987640 -0.078463 +vn -0.322153 -0.928129 -0.186377 +vn -0.682302 -0.615131 -0.394971 +vn -0.024781 -0.999664 -0.006623 +vn -0.066256 -0.997620 -0.017731 +vn -0.151677 -0.987579 -0.040620 +vn -0.360118 -0.927885 -0.096469 +vn -0.762017 -0.614399 -0.204474 +vn -0.025666 -0.999664 0.000000 +vn -0.068667 -0.997620 0.000000 +vn -0.157170 -0.987548 0.000000 +vn -0.373150 -0.927763 0.000000 +vn -0.789148 -0.614154 0.000000 +vn -0.024781 -0.999664 0.006623 +vn -0.066256 -0.997620 0.017731 +vn -0.151677 -0.987579 0.040620 +vn -0.360149 -0.927885 0.096469 +vn -0.762017 -0.614399 0.204474 +vn -0.022156 -0.999664 0.012787 +vn -0.059236 -0.997650 0.034272 +vn -0.135624 -0.987640 0.078463 +vn -0.322153 -0.928129 0.186377 +vn -0.682333 -0.615131 0.394971 +vn -0.018067 -0.999664 0.018067 +vn -0.048341 -0.997650 0.048341 +vn -0.110691 -0.987640 0.110691 +vn -0.262947 -0.928251 0.262947 +vn -0.557329 -0.615375 0.557329 +vn -0.012787 -0.999664 0.022156 +vn -0.034272 -0.997650 0.059236 +vn -0.078463 -0.987640 0.135624 +vn -0.186377 -0.928129 0.322153 +vn -0.394971 -0.615131 0.682302 +vn -0.006623 -0.999664 0.024781 +vn -0.017731 -0.997620 0.066256 +vn -0.040620 -0.987579 0.151677 +vn -0.096469 -0.927885 0.360118 +vn -0.204474 -0.614399 0.762017 +vn 0.000000 -0.999664 0.025666 +vn 0.000000 -0.997620 0.068667 +vn 0.000000 -0.987548 0.157170 +vn 0.000000 -0.927763 0.373150 +vn 0.000000 -0.614154 0.789148 +vn 0.006623 -0.999664 0.024781 +vn 0.017731 -0.997620 0.066256 +vn 0.040620 -0.987579 0.151677 +vn 0.096469 -0.927885 0.360149 +vn 0.204474 -0.614399 0.762017 +vn 0.012787 -0.999664 0.022156 +vn 0.034272 -0.997650 0.059236 +vn 0.078463 -0.987640 0.135624 +vn 0.186377 -0.928129 0.322153 +vn 0.394971 -0.615131 0.682333 +vn 0.018067 -0.999664 0.018067 +vn 0.048341 -0.997650 0.048341 +vn 0.110691 -0.987640 0.110691 +vn 0.262947 -0.928251 0.262947 +vn 0.557329 -0.615375 0.557329 +vn 0.022156 -0.999664 0.012787 +vn 0.059236 -0.997650 0.034272 +vn 0.135624 -0.987640 0.078463 +vn 0.322153 -0.928129 0.186346 +vn 0.682302 -0.615131 0.394971 +vn 0.024781 -0.999664 0.006623 +vn 0.066256 -0.997620 0.017731 +vn 0.151677 -0.987579 0.040620 +vn 0.360118 -0.927885 0.096469 +vn 0.762017 -0.614399 0.204474 +vn 0.464827 -0.373638 -0.802667 +vn 0.655812 -0.373882 -0.655812 +vn 0.000000 -0.372539 0.927976 +vn -0.240699 -0.373028 0.896023 +vn -0.802667 -0.373608 0.464827 +vn 0.896023 -0.372997 -0.240699 +vn -0.927976 -0.372539 0.000000 +vn 0.927976 -0.372539 0.000000 +vn 0.717063 0.696982 0.000000 +vn 0.990387 -0.138310 -0.000061 +vn 0.956694 -0.138737 0.255806 +vn 0.692129 0.697470 0.185583 +vn 0.857326 -0.139317 0.495529 +vn 0.620045 0.697653 0.358837 +vn 0.700125 -0.139531 0.700217 +vn 0.506516 0.697714 0.506546 +vn 0.495468 -0.139286 0.857356 +vn 0.358776 0.697714 0.620014 +vn 0.255867 -0.138737 0.956694 +vn 0.185583 0.697531 0.692068 +vn 0.000061 -0.138310 0.990387 +vn 0.000000 0.696982 0.717063 +vn -0.255806 -0.138737 0.956694 +vn -0.185583 0.697470 0.692129 +vn -0.495529 -0.139317 0.857326 +vn -0.358837 0.697653 0.620045 +vn -0.700217 -0.139531 0.700156 +vn -0.506546 0.697714 0.506516 +vn -0.857356 -0.139286 0.495468 +vn -0.620014 0.697714 0.358776 +vn -0.956694 -0.138737 0.255867 +vn -0.692068 0.697531 0.185583 +vn -0.990387 -0.138310 0.000061 +vn -0.717063 0.696982 0.000000 +vn -0.956694 -0.138737 -0.255806 +vn -0.692129 0.697470 -0.185583 +vn -0.857326 -0.139317 -0.495529 +vn -0.620045 0.697653 -0.358837 +vn -0.700125 -0.139531 -0.700217 +vn -0.506516 0.697714 -0.506546 +vn -0.495468 -0.139286 -0.857356 +vn -0.358776 0.697714 -0.620014 +vn -0.255867 -0.138737 -0.956694 +vn -0.185583 0.697531 -0.692068 +vn -0.000061 -0.138310 -0.990387 +vn 0.000000 0.696982 -0.717063 +vn 0.255806 -0.138737 -0.956694 +vn 0.185583 0.697470 -0.692129 +vn 0.495529 -0.139317 -0.857326 +vn 0.358837 0.697653 -0.620045 +vn 0.700217 -0.139531 -0.700156 +vn 0.506546 0.697714 -0.506516 +vn 0.857356 -0.139286 -0.495468 +vn 0.620014 0.697714 -0.358776 +vn 0.956694 -0.138737 -0.255867 +vn 0.692068 0.697531 -0.185583 +vn 0.292520 0.956236 0.000000 +vn 0.282083 0.956389 0.075686 +vn 0.177953 0.984008 0.000000 +vn 0.171606 0.984069 0.046022 +vn 0.158879 0.987274 0.000000 +vn 0.153264 0.987304 0.041078 +vn 0.217719 0.975982 0.000000 +vn 0.210059 0.976043 0.056276 +vn 0.504715 0.863277 0.000000 +vn 0.487197 0.863460 0.130558 +vn 0.693258 0.720664 0.000000 +vn 0.669057 0.721183 0.179449 +vn 0.252388 0.956511 0.146092 +vn 0.153508 0.984130 0.088839 +vn 0.137059 0.987365 0.079318 +vn 0.187872 0.976135 0.108676 +vn 0.435926 0.863887 0.252205 +vn 0.598956 0.721824 0.346660 +vn 0.206091 0.956572 0.206091 +vn 0.125340 0.984161 0.125340 +vn 0.111911 0.987396 0.111911 +vn 0.153356 0.976196 0.153356 +vn 0.355907 0.864071 0.355907 +vn 0.489151 0.722098 0.489151 +vn 0.146092 0.956511 0.252388 +vn 0.088839 0.984130 0.153508 +vn 0.079318 0.987365 0.137059 +vn 0.108676 0.976135 0.187872 +vn 0.252205 0.863887 0.435926 +vn 0.346660 0.721824 0.598956 +vn 0.075686 0.956389 0.282083 +vn 0.046022 0.984069 0.171606 +vn 0.041078 0.987304 0.153264 +vn 0.056276 0.976043 0.210059 +vn 0.130558 0.863460 0.487197 +vn 0.179449 0.721183 0.669057 +vn 0.000000 0.956236 0.292520 +vn 0.000000 0.984008 0.177953 +vn 0.000000 0.987274 0.158879 +vn 0.000000 0.975982 0.217719 +vn 0.000000 0.863277 0.504715 +vn 0.000000 0.720664 0.693258 +vn -0.075686 0.956389 0.282083 +vn -0.046022 0.984069 0.171606 +vn -0.041078 0.987304 0.153264 +vn -0.056276 0.976043 0.210059 +vn -0.130558 0.863460 0.487197 +vn -0.179449 0.721183 0.669057 +vn -0.146092 0.956511 0.252388 +vn -0.088839 0.984130 0.153508 +vn -0.079318 0.987365 0.137059 +vn -0.108676 0.976135 0.187872 +vn -0.252205 0.863887 0.435926 +vn -0.346660 0.721824 0.598956 +vn -0.206091 0.956572 0.206091 +vn -0.125340 0.984161 0.125340 +vn -0.111911 0.987396 0.111911 +vn -0.153356 0.976196 0.153356 +vn -0.355907 0.864071 0.355907 +vn -0.489151 0.722098 0.489151 +vn -0.252388 0.956511 0.146092 +vn -0.153508 0.984130 0.088839 +vn -0.137059 0.987365 0.079318 +vn -0.187872 0.976135 0.108676 +vn -0.435926 0.863887 0.252205 +vn -0.598956 0.721824 0.346660 +vn -0.282083 0.956389 0.075686 +vn -0.171606 0.984069 0.046022 +vn -0.153264 0.987304 0.041078 +vn -0.210059 0.976043 0.056276 +vn -0.487197 0.863460 0.130558 +vn -0.669057 0.721183 0.179449 +vn -0.292520 0.956236 0.000000 +vn -0.177953 0.984008 0.000000 +vn -0.158879 0.987274 0.000000 +vn -0.217719 0.975982 0.000000 +vn -0.504715 0.863277 0.000000 +vn -0.693258 0.720664 0.000000 +vn -0.282083 0.956389 -0.075686 +vn -0.171606 0.984069 -0.046022 +vn -0.153264 0.987304 -0.041078 +vn -0.210059 0.976043 -0.056276 +vn -0.487197 0.863460 -0.130558 +vn -0.669057 0.721183 -0.179449 +vn -0.252388 0.956511 -0.146092 +vn -0.153508 0.984130 -0.088839 +vn -0.137059 0.987365 -0.079318 +vn -0.187872 0.976135 -0.108676 +vn -0.435926 0.863887 -0.252205 +vn -0.598956 0.721824 -0.346660 +vn -0.206091 0.956572 -0.206091 +vn -0.125340 0.984161 -0.125340 +vn -0.111911 0.987396 -0.111911 +vn -0.153356 0.976196 -0.153356 +vn -0.355907 0.864071 -0.355907 +vn -0.489151 0.722098 -0.489151 +vn -0.146092 0.956511 -0.252388 +vn -0.088839 0.984130 -0.153508 +vn -0.079318 0.987365 -0.137059 +vn -0.108676 0.976135 -0.187872 +vn -0.252205 0.863887 -0.435926 +vn -0.346660 0.721824 -0.598956 +vn -0.075686 0.956389 -0.282083 +vn -0.046022 0.984069 -0.171606 +vn -0.041078 0.987304 -0.153264 +vn -0.056276 0.976043 -0.210059 +vn -0.130558 0.863460 -0.487197 +vn -0.179449 0.721183 -0.669057 +vn 0.000000 0.956236 -0.292520 +vn 0.000000 0.984008 -0.177953 +vn 0.000000 0.987274 -0.158879 +vn 0.000000 0.975982 -0.217719 +vn 0.000000 0.863277 -0.504715 +vn 0.000000 0.720664 -0.693258 +vn 0.075686 0.956389 -0.282083 +vn 0.046022 0.984069 -0.171606 +vn 0.041078 0.987304 -0.153264 +vn 0.056276 0.976043 -0.210059 +vn 0.130558 0.863460 -0.487197 +vn 0.179449 0.721183 -0.669057 +vn 0.146092 0.956511 -0.252388 +vn 0.088839 0.984130 -0.153508 +vn 0.079318 0.987365 -0.137059 +vn 0.108676 0.976135 -0.187872 +vn 0.252205 0.863887 -0.435926 +vn 0.346660 0.721824 -0.598956 +vn 0.206091 0.956572 -0.206091 +vn 0.125340 0.984161 -0.125340 +vn 0.111911 0.987396 -0.111911 +vn 0.153356 0.976196 -0.153356 +vn 0.355907 0.864071 -0.355907 +vn 0.489151 0.722098 -0.489151 +vn 0.252388 0.956511 -0.146092 +vn 0.153508 0.984130 -0.088839 +vn 0.137059 0.987365 -0.079318 +vn 0.187872 0.976135 -0.108676 +vn 0.435926 0.863887 -0.252205 +vn 0.598956 0.721824 -0.346660 +vn 0.282083 0.956389 -0.075686 +vn 0.171606 0.984069 -0.046022 +vn 0.153264 0.987304 -0.041078 +vn 0.210059 0.976043 -0.056276 +vn 0.487197 0.863460 -0.130558 +vn 0.669057 0.721183 -0.179449 +vn 0.363842 0.931455 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.351451 0.931516 0.093509 +vn 0.968261 0.249916 0.000000 +vn 0.935423 0.249763 0.250130 +vn 0.842860 -0.538102 0.000000 +vn 0.813959 -0.538713 0.217292 +vn 0.786767 -0.617206 -0.000031 +vn 0.759514 -0.618000 0.202857 +vn 0.314432 0.931791 0.181280 +vn 0.838404 0.249855 0.484359 +vn 0.729026 -0.539720 0.420911 +vn 0.680013 -0.619068 0.392743 +vn 0.256386 0.931913 0.256417 +vn 0.684652 0.249886 0.684652 +vn 0.595050 -0.540147 0.595050 +vn 0.555010 -0.619526 0.555040 +vn 0.181280 0.931791 0.314432 +vn 0.484359 0.249825 0.838404 +vn 0.420881 -0.539720 0.729026 +vn 0.392712 -0.619098 0.680013 +vn 0.093509 0.931516 0.351451 +vn 0.250160 0.249763 0.935423 +vn 0.217322 -0.538713 0.813959 +vn 0.202887 -0.618030 0.759484 +vn 0.000000 0.931455 0.363842 +vn 0.000000 0.249916 0.968261 +vn 0.000000 -0.538102 0.842860 +vn 0.000031 -0.617206 0.786767 +vn -0.093509 0.931516 0.351451 +vn -0.250130 0.249763 0.935423 +vn -0.217292 -0.538682 0.813959 +vn -0.202857 -0.618000 0.759514 +vn -0.181280 0.931791 0.314432 +vn -0.484359 0.249855 0.838404 +vn -0.420911 -0.539720 0.729026 +vn -0.392743 -0.619068 0.680013 +vn -0.256417 0.931913 0.256386 +vn -0.684652 0.249886 0.684652 +vn -0.595050 -0.540147 0.595050 +vn -0.555040 -0.619526 0.555010 +vn -0.314432 0.931791 0.181280 +vn -0.838404 0.249825 0.484359 +vn -0.729026 -0.539720 0.420881 +vn -0.680013 -0.619098 0.392712 +vn -0.351451 0.931516 0.093509 +vn -0.935423 0.249763 0.250160 +vn -0.813959 -0.538713 0.217292 +vn -0.759484 -0.618030 0.202887 +vn -0.363842 0.931455 0.000000 +vn -0.968261 0.249916 0.000000 +vn -0.842860 -0.538102 0.000000 +vn -0.786767 -0.617206 0.000031 +vn -0.351451 0.931516 -0.093509 +vn -0.935423 0.249763 -0.250130 +vn -0.813959 -0.538713 -0.217292 +vn -0.759514 -0.618000 -0.202857 +vn -0.314432 0.931791 -0.181280 +vn -0.838404 0.249855 -0.484359 +vn -0.729026 -0.539720 -0.420911 +vn -0.680013 -0.619068 -0.392743 +vn -0.256386 0.931913 -0.256417 +vn -0.684652 0.249886 -0.684652 +vn -0.595050 -0.540147 -0.595050 +vn -0.555010 -0.619526 -0.555040 +vn -0.181280 0.931791 -0.314432 +vn -0.484359 0.249825 -0.838404 +vn -0.420881 -0.539720 -0.729026 +vn -0.392712 -0.619098 -0.680013 +vn -0.093509 0.931516 -0.351451 +vn -0.250160 0.249763 -0.935423 +vn -0.217322 -0.538713 -0.813959 +vn -0.202887 -0.618030 -0.759484 +vn 0.000000 0.931455 -0.363842 +vn 0.000000 0.249916 -0.968261 +vn 0.000000 -0.538102 -0.842860 +vn -0.000031 -0.617206 -0.786767 +vn 0.093509 0.931516 -0.351451 +vn 0.250130 0.249763 -0.935423 +vn 0.217292 -0.538682 -0.813959 +vn 0.202857 -0.618000 -0.759514 +vn 0.181280 0.931791 -0.314432 +vn 0.484359 0.249855 -0.838404 +vn 0.420911 -0.539720 -0.729026 +vn 0.392743 -0.619068 -0.680013 +vn 0.256417 0.931913 -0.256386 +vn 0.684652 0.249886 -0.684652 +vn 0.595050 -0.540147 -0.595050 +vn 0.555040 -0.619526 -0.555010 +vn 0.314432 0.931791 -0.181280 +vn 0.838404 0.249825 -0.484359 +vn 0.729026 -0.539720 -0.420881 +vn 0.680013 -0.619098 -0.392712 +vn 0.351451 0.931516 -0.093509 +vn 0.935423 0.249763 -0.250160 +vn 0.813959 -0.538713 -0.217292 +vn 0.759484 -0.618030 -0.202887 +vn -0.354198 0.930296 -0.095187 +vn 0.095187 0.930296 0.354198 +vn 0.354198 0.930296 0.095187 +vn 0.183721 0.930387 0.317179 +vn -0.183721 0.930387 -0.317179 +vn -0.367443 0.930021 0.000000 +vn -0.183721 0.930387 0.317179 +vn 0.367412 0.930021 0.000000 +vn -0.317179 0.930387 0.183721 +vn -0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 -0.367443 +vn -0.354198 0.930296 0.095187 +vn 0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 0.367443 +vn -0.317179 0.930387 -0.183721 +vn 0.317179 0.930387 -0.183721 +vn -0.095187 0.930296 0.354198 +vn 0.317179 0.930387 0.183721 +vn 0.354198 0.930296 -0.095187 +vn 0.183721 0.930387 -0.317179 +vn -0.034730 0.999390 0.000000 +vn 0.033479 0.999390 -0.009003 +vn 0.034730 0.999390 0.000000 +vn 0.009003 0.999390 -0.033479 +vn 0.000000 0.999390 -0.034730 +vn -0.259163 0.930387 0.259163 +vn -0.017335 0.999390 0.029939 +vn 0.947539 0.295083 0.122654 +vn -0.004486 0.999969 0.000000 +vn -0.004151 0.950468 0.310739 +vn -0.003021 0.719291 0.694662 +vn -0.998688 0.050722 0.000000 +vn -0.003143 0.719321 -0.694632 +vn 0.970214 0.213324 -0.114505 +vn -0.136235 0.879482 -0.455947 +vn 0.949858 0.312662 0.000000 +vn 0.055757 -0.017579 -0.998260 +vn 0.201300 -0.540880 -0.816645 +vn 0.974456 -0.186071 -0.125645 +vn 0.988098 -0.096286 0.119938 +vn 0.974456 -0.186041 0.125614 +vn -0.879574 -0.475723 0.000000 +vn -0.873775 -0.472610 -0.114475 +vn 0.988067 -0.096286 -0.119938 +vn 0.295480 -0.855464 -0.425214 +vn -0.976196 -0.174993 -0.127903 +vn -0.971007 -0.205725 0.121677 +vn -0.976196 -0.174963 0.127903 +vn -0.976196 -0.174993 0.127903 +vn 0.896054 -0.372997 0.240699 +vn -0.802667 -0.373638 -0.464827 +vn -0.655812 -0.373852 -0.655812 +vn -0.240699 -0.373028 -0.896023 +vn -0.464827 -0.373638 -0.802667 +vn -0.896023 -0.373028 0.240699 +vn 0.000000 -0.372539 -0.927976 +vn -0.655812 -0.373852 0.655812 +vn 0.240699 -0.373028 0.896023 +vn -0.896023 -0.373028 -0.240699 +vn 0.802667 -0.373638 -0.464827 +vn 0.655812 -0.373882 0.655812 +vn 0.464827 -0.373638 0.802667 +vn -0.464827 -0.373638 0.802667 +vn 0.240699 -0.373028 -0.896023 +vn 0.802667 -0.373638 0.464827 +vn -0.033479 0.999390 0.009003 +vn -0.259163 0.930387 -0.259163 +vn -0.024445 0.999390 -0.024445 +vn -0.029939 0.999390 -0.017335 +vn 0.259163 0.930387 -0.259163 +vn 0.024445 0.999390 -0.024445 +vn 0.017335 0.999390 -0.029939 +vn 0.029939 0.999390 -0.017335 +vn 0.033479 0.999390 0.009003 +vn -0.009003 0.999390 0.033479 +vn 0.000000 0.999390 0.034730 +vn -0.017335 0.999390 -0.029939 +vn 0.259163 0.930387 0.259163 +vn 0.029939 0.999390 0.017335 +vn -0.009003 0.999390 -0.033479 +vn 0.024445 0.999390 0.024445 +vn 0.017335 0.999390 0.029939 +vn 0.009003 0.999390 0.033479 +vn -0.033479 0.999390 -0.009003 +vn -0.024445 0.999390 0.024445 +vn -0.029939 0.999390 0.017335 +vn 0.055757 -0.017579 0.998260 +vn 0.294198 -0.855403 0.426252 +vn 0.201300 -0.540880 0.816614 +s 1 +f 34//1 1243//2 593//3 +f 52//4 27//5 40//6 +f 52//4 40//6 65//7 +f 77//8 52//4 65//7 +f 77//8 65//7 84//9 +f 107//10 77//8 84//9 +f 107//10 84//9 85//11 +f 115//12 107//10 85//11 +f 115//12 85//11 99//13 +f 129//14 115//12 99//13 +f 129//14 99//13 128//15 +f 1252//16 36//17 40//6 +f 65//7 40//6 64//18 +f 65//7 64//18 58//19 +f 84//9 65//7 58//19 +f 84//9 58//19 59//20 +f 85//11 84//9 59//20 +f 85//11 59//20 70//21 +f 99//13 85//11 70//21 +f 99//13 70//21 98//22 +f 128//15 99//13 98//22 +f 128//15 98//22 114//23 +f 1244//24 33//25 64//18 +f 58//19 64//18 33//25 +f 58//19 33//25 35//26 +f 59//20 58//19 35//26 +f 59//20 35//26 45//27 +f 70//21 59//20 45//27 +f 70//21 45//27 69//28 +f 98//22 70//21 69//28 +f 98//22 69//28 83//29 +f 114//23 98//22 83//29 +f 114//23 83//29 113//30 +f 553//31 1//32 566//33 +f 35//26 33//25 20//34 +f 35//26 20//34 24//35 +f 45//27 35//26 24//35 +f 45//27 24//35 44//36 +f 69//28 45//27 44//36 +f 69//28 44//36 57//37 +f 83//29 69//28 57//37 +f 83//29 57//37 82//38 +f 113//30 83//29 82//38 +f 113//30 82//38 112//39 +f 566//33 1283//40 9//41 +f 24//35 20//34 18//42 +f 24//35 18//42 23//43 +f 44//36 24//35 23//43 +f 44//36 23//43 32//44 +f 57//37 44//36 32//44 +f 57//37 32//44 56//45 +f 82//38 57//37 56//45 +f 82//38 56//45 81//46 +f 112//39 82//38 81//46 +f 112//39 81//46 111//47 +f 4//48 8//49 1250//50 +f 23//43 18//42 8//49 +f 23//43 8//49 17//51 +f 32//44 23//43 17//51 +f 32//44 17//51 31//52 +f 56//45 32//44 31//52 +f 56//45 31//52 55//53 +f 81//46 56//45 55//53 +f 81//46 55//53 80//54 +f 111//47 81//46 80//54 +f 111//47 80//54 110//55 +f 565//56 592//57 1233//58 +f 17//51 8//49 4//48 +f 17//51 4//48 16//59 +f 31//52 17//51 16//59 +f 31//52 16//59 30//60 +f 55//53 31//52 30//60 +f 55//53 30//60 54//61 +f 80//54 55//53 54//61 +f 80//54 54//61 79//62 +f 110//55 80//54 79//62 +f 110//55 79//62 109//63 +f 1//32 565//56 2//64 +f 6//65 2//64 565//56 +f 16//59 4//48 7//66 +f 16//59 7//66 22//67 +f 30//60 16//59 22//67 +f 30//60 22//67 43//68 +f 54//61 30//60 43//68 +f 54//61 43//68 68//69 +f 79//62 54//61 68//69 +f 79//62 68//69 97//70 +f 109//63 79//62 97//70 +f 109//63 97//70 127//71 +f 565//56 1233//58 1249//58 +f 13//72 14//73 5//74 +f 22//67 7//66 15//75 +f 22//67 15//75 29//76 +f 43//68 22//67 29//76 +f 43//68 29//76 42//77 +f 68//69 43//68 42//77 +f 68//69 42//77 67//78 +f 97//70 68//69 67//78 +f 97//70 67//78 96//79 +f 127//71 97//70 96//79 +f 127//71 96//79 126//80 +f 11//81 15//75 1240//82 +f 1289//83 34//1 593//3 +f 29//76 15//75 14//73 +f 29//76 14//73 21//84 +f 42//77 29//76 21//84 +f 42//77 21//84 41//85 +f 67//78 42//77 41//85 +f 67//78 41//85 66//86 +f 96//79 67//78 66//86 +f 96//79 66//86 95//87 +f 126//80 96//79 95//87 +f 126//80 95//87 125//88 +f 636//89 1243//2 26//2 +f 636//89 26//2 592//57 +f 21//84 14//73 13//72 +f 21//84 13//72 28//90 +f 41//85 21//84 28//90 +f 41//85 28//90 53//91 +f 66//86 41//85 53//91 +f 66//86 53//91 78//92 +f 95//87 66//86 78//92 +f 95//87 78//92 108//93 +f 125//88 95//87 108//93 +f 125//88 108//93 136//94 +f 12//95 13//72 5//74 +f 28//90 13//72 27//5 +f 28//90 27//5 52//4 +f 53//91 28//90 52//4 +f 53//91 52//4 77//8 +f 78//92 53//91 77//8 +f 78//92 77//8 107//10 +f 108//93 78//92 107//10 +f 108//93 107//10 115//12 +f 136//94 108//93 115//12 +f 136//94 115//12 129//14 +f 148//96 129//14 128//15 +f 148//96 128//15 143//97 +f 121//98 148//96 143//97 +f 121//98 143//97 122//99 +f 92//100 121//98 122//99 +f 92//100 122//99 93//101 +f 62//102 92//100 93//101 +f 62//102 93//101 63//103 +f 39//104 62//102 63//103 +f 39//104 63//103 51//105 +f 10//106 39//104 51//105 +f 10//106 51//105 49//107 +f 143//97 128//15 114//23 +f 143//97 114//23 142//108 +f 122//99 143//97 142//108 +f 122//99 142//108 123//109 +f 93//101 122//99 123//109 +f 93//101 123//109 94//110 +f 63//103 93//101 94//110 +f 63//103 94//110 76//111 +f 51//105 63//103 76//111 +f 51//105 76//111 75//112 +f 49//107 51//105 75//112 +f 49//107 75//112 61//113 +f 142//108 114//23 113//30 +f 142//108 113//30 141//114 +f 123//109 142//108 141//114 +f 123//109 141//114 124//115 +f 94//110 123//109 124//115 +f 94//110 124//115 106//116 +f 76//111 94//110 106//116 +f 76//111 106//116 105//117 +f 75//112 76//111 105//117 +f 75//112 105//117 91//118 +f 61//113 75//112 91//118 +f 61//113 91//118 90//119 +f 141//114 113//30 112//39 +f 141//114 112//39 140//120 +f 124//115 141//114 140//120 +f 124//115 140//120 135//121 +f 106//116 124//115 135//121 +f 106//116 135//121 134//122 +f 105//117 106//116 134//122 +f 105//117 134//122 120//123 +f 91//118 105//117 120//123 +f 91//118 120//123 119//124 +f 90//119 91//118 119//124 +f 140//120 112//39 111//47 +f 140//120 111//47 139//125 +f 135//121 140//120 139//125 +f 135//121 139//125 155//126 +f 134//122 135//121 155//126 +f 134//122 155//126 147//127 +f 120//123 134//122 147//127 +f 120//123 147//127 144//128 +f 119//124 120//123 144//128 +f 119//124 144//128 116//129 +f 26//2 1234//130 592//57 +f 139//125 111//47 110//55 +f 139//125 110//55 138//131 +f 155//126 139//125 138//131 +f 155//126 138//131 156//132 +f 147//127 155//126 156//132 +f 147//127 156//132 145//133 +f 144//128 147//127 145//133 +f 144//128 145//133 117//134 +f 116//129 144//128 117//134 +f 116//129 117//134 88//135 +f 27//5 13//72 12//95 +f 1242//136 88//135 71//137 +f 138//131 110//55 109//63 +f 138//131 109//63 137//138 +f 156//132 138//131 137//138 +f 156//132 137//138 154//139 +f 145//133 156//132 154//139 +f 145//133 154//139 131//140 +f 117//134 145//133 131//140 +f 117//134 131//140 101//141 +f 88//135 117//134 101//141 +f 88//135 101//141 86//142 +f 60//143 74//144 1248//145 +f 137//138 109//63 127//71 +f 137//138 127//71 151//146 +f 154//139 137//138 151//146 +f 154//139 151//146 153//147 +f 131//140 154//139 153//147 +f 131//140 153//147 130//148 +f 101//141 131//140 130//148 +f 101//141 130//148 100//149 +f 86//142 101//141 100//149 +f 86//142 100//149 74//144 +f 47//150 1235//151 631//152 +f 74//144 48//153 1248//145 +f 151//146 127//71 126//80 +f 151//146 126//80 150//154 +f 153//147 151//146 150//154 +f 153//147 150//154 146//155 +f 130//148 153//147 146//155 +f 130//148 146//155 118//156 +f 100//149 130//148 118//156 +f 100//149 118//156 89//157 +f 74//144 100//149 89//157 +f 74//144 89//157 48//153 +f 1247//158 87//159 715//160 +f 104//161 116//129 1242//136 +f 150//154 126//80 125//88 +f 150//154 125//88 149//162 +f 146//155 150//154 149//162 +f 146//155 149//162 132//163 +f 118//156 146//155 132//163 +f 118//156 132//163 102//164 +f 89//157 118//156 102//164 +f 89//157 102//164 72//165 +f 48//153 89//157 72//165 +f 48//153 72//165 46//166 +f 37//167 48//153 46//166 +f 37//167 46//166 38//168 +f 149//162 125//88 136//94 +f 149//162 136//94 152//169 +f 132//163 149//162 152//169 +f 132//163 152//169 133//170 +f 102//164 132//163 133//170 +f 102//164 133//170 103//171 +f 72//165 102//164 103//171 +f 72//165 103//171 73//172 +f 46//166 72//165 73//172 +f 46//166 73//172 50//173 +f 38//168 46//166 50//173 +f 38//168 50//173 25//174 +f 152//169 136//94 129//14 +f 152//169 129//14 148//96 +f 133//170 152//169 148//96 +f 133//170 148//96 121//98 +f 103//171 133//170 121//98 +f 103//171 121//98 92//100 +f 73//172 103//171 92//100 +f 73//172 92//100 62//102 +f 50//173 73//172 62//102 +f 50//173 62//102 39//104 +f 25//174 50//173 39//104 +f 39//104 10//106 25//174 +f 539//175 509//176 159//177 +f 160//178 158//179 157//180 +f 166//181 160//178 163//182 +f 166//181 163//182 173//183 +f 177//184 166//181 173//183 +f 177//184 173//183 183//185 +f 189//186 177//184 183//185 +f 189//186 183//185 197//187 +f 205//188 189//186 197//187 +f 205//188 197//187 216//189 +f 225//190 205//188 216//189 +f 225//190 216//189 235//191 +f 173//183 163//182 172//192 +f 173//183 172//192 184//193 +f 183//185 173//183 184//193 +f 183//185 184//193 198//194 +f 197//187 183//185 198//194 +f 197//187 198//194 217//195 +f 216//189 197//187 217//195 +f 216//189 217//195 236//196 +f 235//191 216//189 236//196 +f 235//191 236//196 253//197 +f 182//198 172//192 1254//199 +f 1255//200 167//201 595//202 +f 184//193 172//192 182//198 +f 184//193 182//198 196//203 +f 198//194 184//193 196//203 +f 198//194 196//203 214//204 +f 217//195 198//194 214//204 +f 217//195 214//204 232//205 +f 236//196 217//195 232//205 +f 236//196 232//205 250//206 +f 253//197 236//196 250//206 +f 253//197 250//206 267//207 +f 196//203 182//198 199//208 +f 196//203 199//208 215//209 +f 214//204 196//203 215//209 +f 214//204 215//209 233//210 +f 232//205 214//204 233//210 +f 232//205 233//210 251//211 +f 250//206 232//205 251//211 +f 250//206 251//211 257//212 +f 267//207 250//206 257//212 +f 267//207 257//212 256//213 +f 215//209 199//208 218//214 +f 215//209 218//214 234//215 +f 233//210 215//209 234//215 +f 233//210 234//215 241//216 +f 251//211 233//210 241//216 +f 251//211 241//216 240//217 +f 257//212 251//211 240//217 +f 257//212 240//217 239//218 +f 256//213 257//212 239//218 +f 256//213 239//218 238//219 +f 234//215 218//214 219//220 +f 234//215 219//220 224//221 +f 241//216 234//215 224//221 +f 241//216 224//221 223//222 +f 240//217 241//216 223//222 +f 240//217 223//222 222//223 +f 239//218 240//217 222//223 +f 239//218 222//223 221//224 +f 238//219 239//218 221//224 +f 238//219 221//224 220//225 +f 219//220 218//214 1285//226 +f 648//227 691//228 207//229 +f 224//221 219//220 208//230 +f 224//221 208//230 204//231 +f 223//222 224//221 204//231 +f 223//222 204//231 203//232 +f 222//223 223//222 203//232 +f 222//223 203//232 202//233 +f 221//224 222//223 202//233 +f 221//224 202//233 201//234 +f 220//225 221//224 201//234 +f 220//225 201//234 212//235 +f 204//231 208//230 191//236 +f 204//231 191//236 188//237 +f 203//232 204//231 188//237 +f 203//232 188//237 187//238 +f 202//233 203//232 187//238 +f 202//233 187//238 186//239 +f 201//234 202//233 186//239 +f 201//234 186//239 194//240 +f 212//235 201//234 194//240 +f 212//235 194//240 211//241 +f 188//237 191//236 174//242 +f 188//237 174//242 176//243 +f 187//238 188//237 176//243 +f 187//238 176//243 175//244 +f 186//239 187//238 175//244 +f 186//239 175//244 180//245 +f 194//240 186//239 180//245 +f 194//240 180//245 193//246 +f 211//241 194//240 193//246 +f 211//241 193//246 210//247 +f 613//248 585//249 1258//250 +f 176//243 174//242 168//251 +f 176//243 168//251 165//252 +f 175//244 176//243 165//252 +f 175//244 165//252 170//253 +f 180//245 175//244 170//253 +f 180//245 170//253 179//254 +f 193//246 180//245 179//254 +f 193//246 179//254 192//255 +f 210//247 193//246 192//255 +f 210//247 192//255 209//256 +f 168//251 174//242 164//257 +f 165//252 168//251 161//258 +f 165//252 161//258 162//259 +f 170//253 165//252 162//259 +f 170//253 162//259 171//260 +f 179//254 170//253 171//260 +f 179//254 171//260 181//261 +f 192//255 179//254 181//261 +f 192//255 181//261 195//262 +f 209//256 192//255 195//262 +f 209//256 195//262 213//263 +f 160//178 161//258 158//179 +f 161//258 160//178 162//259 +f 162//259 160//178 166//181 +f 171//260 162//259 166//181 +f 171//260 166//181 177//184 +f 181//261 171//260 177//184 +f 181//261 177//184 189//186 +f 195//262 181//261 189//186 +f 195//262 189//186 205//188 +f 213//263 195//262 205//188 +f 213//263 205//188 225//190 +f 242//264 225//190 235//191 +f 242//264 235//191 252//265 +f 258//266 242//264 252//265 +f 258//266 252//265 268//267 +f 273//268 258//266 268//267 +f 273//268 268//267 283//269 +f 287//270 273//268 283//269 +f 287//270 283//269 298//271 +f 300//272 287//270 298//271 +f 300//272 298//271 299//273 +f 312//274 300//272 299//273 +f 312//274 299//273 310//275 +f 252//265 235//191 253//197 +f 252//265 253//197 269//276 +f 268//267 252//265 269//276 +f 268//267 269//276 284//277 +f 283//269 268//267 284//277 +f 283//269 284//277 286//278 +f 298//271 283//269 286//278 +f 298//271 286//278 285//279 +f 299//273 298//271 285//279 +f 299//273 285//279 296//280 +f 310//275 299//273 296//280 +f 310//275 296//280 309//281 +f 269//276 253//197 267//207 +f 269//276 267//207 272//282 +f 284//277 269//276 272//282 +f 284//277 272//282 271//283 +f 286//278 284//277 271//283 +f 286//278 271//283 270//284 +f 285//279 286//278 270//284 +f 285//279 270//284 281//285 +f 296//280 285//279 281//285 +f 296//280 281//285 295//286 +f 309//281 296//280 295//286 +f 309//281 295//286 308//287 +f 272//282 267//207 256//213 +f 272//282 256//213 255//288 +f 271//283 272//282 255//288 +f 271//283 255//288 254//289 +f 270//284 271//283 254//289 +f 270//284 254//289 265//290 +f 281//285 270//284 265//290 +f 281//285 265//290 280//291 +f 295//286 281//285 280//291 +f 295//286 280//291 294//292 +f 308//287 295//286 294//292 +f 308//287 294//292 307//293 +f 255//288 256//213 238//219 +f 255//288 238//219 237//294 +f 254//289 255//288 237//294 +f 254//289 237//294 248//295 +f 265//290 254//289 248//295 +f 265//290 248//295 264//296 +f 280//291 265//290 264//296 +f 280//291 264//296 279//297 +f 294//292 280//291 279//297 +f 294//292 279//297 293//298 +f 307//293 294//292 293//298 +f 307//293 293//298 306//299 +f 237//294 238//219 220//225 +f 237//294 220//225 230//300 +f 248//295 237//294 230//300 +f 248//295 230//300 247//301 +f 264//296 248//295 247//301 +f 264//296 247//301 263//302 +f 279//297 264//296 263//302 +f 279//297 263//302 278//303 +f 293//298 279//297 278//303 +f 293//298 278//303 292//304 +f 306//299 293//298 292//304 +f 306//299 292//304 305//305 +f 230//300 220//225 212//235 +f 230//300 212//235 229//306 +f 247//301 230//300 229//306 +f 247//301 229//306 246//307 +f 263//302 247//301 246//307 +f 263//302 246//307 262//308 +f 278//303 263//302 262//308 +f 278//303 262//308 277//309 +f 292//304 278//303 277//309 +f 292//304 277//309 291//310 +f 305//305 292//304 291//310 +f 305//305 291//310 304//311 +f 229//306 212//235 211//241 +f 229//306 211//241 228//312 +f 246//307 229//306 228//312 +f 246//307 228//312 245//313 +f 262//308 246//307 245//313 +f 262//308 245//313 261//314 +f 277//309 262//308 261//314 +f 277//309 261//314 276//315 +f 291//310 277//309 276//315 +f 291//310 276//315 290//316 +f 304//311 291//310 290//316 +f 304//311 290//316 303//317 +f 228//312 211//241 210//247 +f 228//312 210//247 227//318 +f 245//313 228//312 227//318 +f 245//313 227//318 244//319 +f 261//314 245//313 244//319 +f 261//314 244//319 260//320 +f 276//315 261//314 260//320 +f 276//315 260//320 275//321 +f 290//316 276//315 275//321 +f 290//316 275//321 289//322 +f 303//317 290//316 289//322 +f 303//317 289//322 302//323 +f 227//318 210//247 209//256 +f 227//318 209//256 226//324 +f 244//319 227//318 226//324 +f 244//319 226//324 243//325 +f 260//320 244//319 243//325 +f 260//320 243//325 259//326 +f 275//321 260//320 259//326 +f 275//321 259//326 274//327 +f 289//322 275//321 274//327 +f 289//322 274//327 288//328 +f 302//323 289//322 288//328 +f 302//323 288//328 301//329 +f 226//324 209//256 213//263 +f 226//324 213//263 231//330 +f 243//325 226//324 231//330 +f 243//325 231//330 249//331 +f 259//326 243//325 249//331 +f 259//326 249//331 266//332 +f 274//327 259//326 266//332 +f 274//327 266//332 282//333 +f 288//328 274//327 282//333 +f 288//328 282//333 297//334 +f 301//329 288//328 297//334 +f 301//329 297//334 311//335 +f 231//330 213//263 225//190 +f 231//330 225//190 242//264 +f 249//331 231//330 242//264 +f 249//331 242//264 258//266 +f 266//332 249//331 258//266 +f 266//332 258//266 273//268 +f 282//333 266//332 273//268 +f 282//333 273//268 287//270 +f 297//334 282//333 287//270 +f 297//334 287//270 300//272 +f 311//335 297//334 300//272 +f 311//335 300//272 312//274 +f 312//274 310//275 323//336 +f 302//323 315//337 316//338 +f 304//311 317//339 318//340 +f 303//317 316//338 317//339 +f 309//281 308//287 321//341 +f 307//293 306//299 319//342 +f 311//335 313//343 314//344 +f 301//329 314//344 315//337 +f 312//274 324//345 313//343 +f 306//299 305//305 318//340 +f 308//287 307//293 320//346 +f 310//275 309//281 322//347 +f 322//347 321//341 325//348 +f 314//344 313//343 325//348 +f 323//336 322//347 325//348 +f 319//342 318//340 325//348 +f 315//337 314//344 325//348 +f 321//341 320//346 325//348 +f 324//345 323//336 325//348 +f 320//346 319//342 325//348 +f 317//339 316//338 325//348 +f 316//338 315//337 325//348 +f 313//343 324//345 325//348 +f 318//340 317//339 325//348 +f 326//349 327//350 328//351 +f 326//349 328//351 329//352 +f 333//353 326//349 329//352 +f 333//353 329//352 338//354 +f 347//355 333//353 338//354 +f 347//355 338//354 354//356 +f 364//357 347//355 354//356 +f 364//357 354//356 374//358 +f 386//359 364//357 374//358 +f 386//359 374//358 398//360 +f 412//361 386//359 398//360 +f 412//361 398//360 429//362 +f 329//352 328//351 334//363 +f 329//352 334//363 339//364 +f 338//354 329//352 339//364 +f 338//354 339//364 355//365 +f 354//356 338//354 355//365 +f 354//356 355//365 375//366 +f 374//358 354//356 375//366 +f 374//358 375//366 399//367 +f 398//360 374//358 399//367 +f 398//360 399//367 430//368 +f 429//362 398//360 430//368 +f 429//362 430//368 464//369 +f 339//364 334//363 342//370 +f 339//364 342//370 356//371 +f 355//365 339//364 356//371 +f 355//365 356//371 376//372 +f 375//366 355//365 376//372 +f 375//366 376//372 400//373 +f 399//367 375//366 400//373 +f 399//367 400//373 431//374 +f 430//368 399//367 431//374 +f 430//368 431//374 465//375 +f 464//369 430//368 465//375 +f 464//369 465//375 497//376 +f 356//371 342//370 351//377 +f 356//371 351//377 370//378 +f 376//372 356//371 370//378 +f 376//372 370//378 393//379 +f 400//373 376//372 393//379 +f 400//373 393//379 422//380 +f 431//374 400//373 422//380 +f 431//374 422//380 457//381 +f 465//375 431//374 457//381 +f 465//375 457//381 490//382 +f 497//376 465//375 490//382 +f 497//376 490//382 521//383 +f 370//378 351//377 361//384 +f 370//378 361//384 382//385 +f 393//379 370//378 382//385 +f 393//379 382//385 408//386 +f 422//380 393//379 408//386 +f 422//380 408//386 439//387 +f 457//381 422//380 439//387 +f 457//381 439//387 473//388 +f 490//382 457//381 473//388 +f 490//382 473//388 504//389 +f 521//383 490//382 504//389 +f 521//383 504//389 535//390 +f 382//385 361//384 369//391 +f 382//385 369//391 392//392 +f 408//386 382//385 392//392 +f 408//386 392//392 421//393 +f 439//387 408//386 421//393 +f 439//387 421//393 456//394 +f 473//388 439//387 456//394 +f 473//388 456//394 489//395 +f 504//389 473//388 489//395 +f 504//389 489//395 520//396 +f 535//390 504//389 520//396 +f 535//390 520//396 550//397 +f 392//392 369//391 380//398 +f 392//392 380//398 407//399 +f 421//393 392//392 407//399 +f 421//393 407//399 438//400 +f 456//394 421//393 438//400 +f 456//394 438//400 472//401 +f 489//395 456//394 472//401 +f 489//395 472//401 503//402 +f 520//396 489//395 503//402 +f 520//396 503//402 534//403 +f 550//397 520//396 534//403 +f 550//397 534//403 563//404 +f 407//399 380//398 391//405 +f 407//399 391//405 420//406 +f 438//400 407//399 420//406 +f 438//400 420//406 455//407 +f 472//401 438//400 455//407 +f 472//401 455//407 488//408 +f 503//402 472//401 488//408 +f 503//402 488//408 519//409 +f 534//403 503//402 519//409 +f 534//403 519//409 549//410 +f 563//404 534//403 549//410 +f 563//404 549//410 578//411 +f 420//406 391//405 404//412 +f 420//406 404//412 437//413 +f 455//407 420//406 437//413 +f 455//407 437//413 471//414 +f 488//408 455//407 471//414 +f 488//408 471//414 502//415 +f 519//409 488//408 502//415 +f 519//409 502//415 533//416 +f 549//410 519//409 533//416 +f 549//410 533//416 562//417 +f 578//411 549//410 562//417 +f 578//411 562//417 589//418 +f 437//413 404//412 419//419 +f 437//413 419//419 454//420 +f 471//414 437//413 454//420 +f 471//414 454//420 487//421 +f 502//415 471//414 487//421 +f 502//415 487//421 518//422 +f 533//416 502//415 518//422 +f 533//416 518//422 548//423 +f 562//417 533//416 548//423 +f 562//417 548//423 577//424 +f 589//418 562//417 577//424 +f 589//418 577//424 594//425 +f 454//420 419//419 436//426 +f 454//420 436//426 470//427 +f 487//421 454//420 470//427 +f 487//421 470//427 501//428 +f 518//422 487//421 501//428 +f 518//422 501//428 532//429 +f 548//423 518//422 532//429 +f 548//423 532//429 555//430 +f 577//424 548//423 555//430 +f 577//424 555//430 567//431 +f 594//425 577//424 567//431 +f 594//425 567//431 582//432 +f 470//427 436//426 453//433 +f 470//427 453//433 486//434 +f 501//428 470//427 486//434 +f 501//428 486//434 508//435 +f 532//429 501//428 508//435 +f 532//429 508//435 525//436 +f 555//430 532//429 525//436 +f 555//430 525//436 538//437 +f 567//431 555//430 538//437 +f 567//431 538//437 554//438 +f 582//432 567//431 554//438 +f 582//432 554//438 566//33 +f 486//434 453//433 462//439 +f 486//434 462//439 477//440 +f 508//435 486//434 477//440 +f 508//435 477//440 494//441 +f 525//436 508//435 494//441 +f 525//436 494//441 507//442 +f 538//437 525//436 507//442 +f 538//437 507//442 524//443 +f 554//438 538//437 524//443 +f 554//438 524//443 537//444 +f 566//33 554//438 537//444 +f 566//33 537//444 553//31 +f 477//440 462//439 443//445 +f 477//440 443//445 461//446 +f 494//441 477//440 461//446 +f 494//441 461//446 476//447 +f 507//442 494//441 476//447 +f 507//442 476//447 493//448 +f 524//443 507//442 493//448 +f 524//443 493//448 506//449 +f 537//444 524//443 506//449 +f 537//444 506//449 523//450 +f 553//31 537//444 523//450 +f 553//31 523//450 536//451 +f 461//446 443//445 426//452 +f 461//446 426//452 442//453 +f 476//447 461//446 442//453 +f 476//447 442//453 460//454 +f 493//448 476//447 460//454 +f 493//448 460//454 475//455 +f 506//449 493//448 475//455 +f 506//449 475//455 492//456 +f 523//450 506//449 492//456 +f 523//450 492//456 505//457 +f 536//451 523//450 505//457 +f 536//451 505//457 522//458 +f 442//453 426//452 411//459 +f 442//453 411//459 425//460 +f 460//454 442//453 425//460 +f 460//454 425//460 441//461 +f 475//455 460//454 441//461 +f 475//455 441//461 459//462 +f 492//456 475//455 459//462 +f 492//456 459//462 474//463 +f 505//457 492//456 474//463 +f 505//457 474//463 491//464 +f 522//458 505//457 491//464 +f 522//458 491//464 499//465 +f 425//460 411//459 396//466 +f 425//460 396//466 410//467 +f 441//461 425//460 410//467 +f 441//461 410//467 424//468 +f 459//462 441//461 424//468 +f 459//462 424//468 440//469 +f 474//463 459//462 440//469 +f 474//463 440//469 458//470 +f 491//464 474//463 458//470 +f 491//464 458//470 467//471 +f 499//465 491//464 467//471 +f 499//465 467//471 466//472 +f 410//467 396//466 385//473 +f 410//467 385//473 395//474 +f 424//468 410//467 395//474 +f 424//468 395//474 409//475 +f 440//469 424//468 409//475 +f 440//469 409//475 423//476 +f 458//470 440//469 423//476 +f 458//470 423//476 433//477 +f 467//471 458//470 433//477 +f 467//471 433//477 432//478 +f 466//472 467//471 432//478 +f 466//472 432//478 434//479 +f 395//474 385//473 372//480 +f 395//474 372//480 383//481 +f 409//475 395//474 383//481 +f 409//475 383//481 394//482 +f 423//476 409//475 394//482 +f 423//476 394//482 402//483 +f 433//477 423//476 402//483 +f 433//477 402//483 401//484 +f 432//478 433//477 401//484 +f 432//478 401//484 403//485 +f 434//479 432//478 403//485 +f 434//479 403//485 417//486 +f 383//481 372//480 362//487 +f 383//481 362//487 371//488 +f 394//482 383//481 371//488 +f 394//482 371//488 378//489 +f 402//483 394//482 378//489 +f 402//483 378//489 377//490 +f 401//484 402//483 377//490 +f 401//484 377//490 379//491 +f 403//485 401//484 379//491 +f 403//485 379//491 390//492 +f 417//486 403//485 390//492 +f 417//486 390//492 416//493 +f 371//488 362//487 352//494 +f 371//488 352//494 358//495 +f 378//489 371//488 358//495 +f 378//489 358//495 357//496 +f 377//490 378//489 357//496 +f 377//490 357//496 359//497 +f 379//491 377//490 359//497 +f 379//491 359//497 367//498 +f 390//492 379//491 367//498 +f 390//492 367//498 389//499 +f 416//493 390//492 389//499 +f 416//493 389//499 415//500 +f 358//495 352//494 345//501 +f 358//495 345//501 340//502 +f 357//496 358//495 340//502 +f 357//496 340//502 341//503 +f 359//497 357//496 341//503 +f 359//497 341//503 349//504 +f 367//498 359//497 349//504 +f 367//498 349//504 366//505 +f 389//499 367//498 366//505 +f 389//499 366//505 388//506 +f 415//500 389//499 388//506 +f 415//500 388//506 414//507 +f 340//502 345//501 335//508 +f 340//502 335//508 330//509 +f 341//503 340//502 330//509 +f 341//503 330//509 336//510 +f 349//504 341//503 336//510 +f 349//504 336//510 348//511 +f 366//505 349//504 348//511 +f 366//505 348//511 365//512 +f 388//506 366//505 365//512 +f 388//506 365//512 387//513 +f 414//507 388//506 387//513 +f 414//507 387//513 413//514 +f 330//509 335//508 327//350 +f 327//350 326//349 330//509 +f 330//509 326//349 336//510 +f 336//510 326//349 333//353 +f 348//511 336//510 333//353 +f 348//511 333//353 347//355 +f 365//512 348//511 347//355 +f 365//512 347//355 364//357 +f 387//513 365//512 364//357 +f 387//513 364//357 386//359 +f 413//514 387//513 386//359 +f 413//514 386//359 412//361 +f 445//515 412//361 429//362 +f 445//515 429//362 463//516 +f 478//517 445//515 463//516 +f 478//517 463//516 495//518 +f 509//176 478//517 495//518 +f 509//176 495//518 526//519 +f 463//516 429//362 464//369 +f 463//516 464//369 496//520 +f 495//518 463//516 496//520 +f 495//518 496//520 527//521 +f 526//519 495//518 527//521 +f 526//519 527//521 557//522 +f 556//523 526//519 557//522 +f 556//523 557//522 583//524 +f 595//202 556//523 583//524 +f 595//202 583//524 611//525 +f 621//526 595//202 611//525 +f 621//526 611//525 638//527 +f 496//520 464//369 497//376 +f 496//520 497//376 528//528 +f 527//521 496//520 528//528 +f 527//521 528//528 558//529 +f 557//522 527//521 558//529 +f 557//522 558//529 584//530 +f 583//524 557//522 584//530 +f 583//524 584//530 612//531 +f 611//525 583//524 612//531 +f 611//525 612//531 639//532 +f 638//527 611//525 639//532 +f 638//527 639//532 664//533 +f 528//528 497//376 521//383 +f 528//528 521//383 551//534 +f 558//529 528//528 551//534 +f 558//529 551//534 580//535 +f 584//530 558//529 580//535 +f 584//530 580//535 608//536 +f 612//531 584//530 608//536 +f 612//531 608//536 634//537 +f 639//532 612//531 634//537 +f 639//532 634//537 661//538 +f 664//533 639//532 661//538 +f 664//533 661//538 688//539 +f 551//534 521//383 535//390 +f 551//534 535//390 564//540 +f 580//535 551//534 564//540 +f 580//535 564//540 591//541 +f 608//536 580//535 591//541 +f 608//536 591//541 618//542 +f 634//537 608//536 618//542 +f 634//537 618//542 644//543 +f 661//538 634//537 644//543 +f 661//538 644//543 670//544 +f 688//539 661//538 670//544 +f 688//539 670//544 698//545 +f 564//540 535//390 550//397 +f 564//540 550//397 579//546 +f 591//541 564//540 579//546 +f 591//541 579//546 607//547 +f 618//542 591//541 607//547 +f 618//542 607//547 633//548 +f 644//543 618//542 633//548 +f 644//543 633//548 660//549 +f 670//544 644//543 660//549 +f 670//544 660//549 687//550 +f 698//545 670//544 687//550 +f 698//545 687//550 717//551 +f 579//546 550//397 563//404 +f 579//546 563//404 590//552 +f 607//547 579//546 590//552 +f 607//547 590//552 617//553 +f 633//548 607//547 617//553 +f 633//548 617//553 643//554 +f 660//549 633//548 643//554 +f 660//549 643//554 669//555 +f 687//550 660//549 669//555 +f 687//550 669//555 697//556 +f 717//551 687//550 697//556 +f 717//551 697//556 727//557 +f 590//552 563//404 578//411 +f 590//552 578//411 606//558 +f 617//553 590//552 606//558 +f 617//553 606//558 632//559 +f 643//554 617//553 632//559 +f 643//554 632//559 659//560 +f 669//555 643//554 659//560 +f 669//555 659//560 673//561 +f 697//556 669//555 673//561 +f 697//556 673//561 700//562 +f 727//557 697//556 700//562 +f 727//557 700//562 699//563 +f 606//558 578//411 589//418 +f 606//558 589//418 616//564 +f 632//559 606//558 616//564 +f 632//559 616//564 637//565 +f 659//560 632//559 637//565 +f 659//560 637//565 647//566 +f 673//561 659//560 647//566 +f 673//561 647//566 672//567 +f 700//562 673//561 672//567 +f 700//562 672//567 671//568 +f 699//563 700//562 671//568 +f 699//563 671//568 689//569 +f 616//564 589//418 594//425 +f 616//564 594//425 610//570 +f 637//565 616//564 610//570 +f 637//565 610//570 620//571 +f 647//566 637//565 620//571 +f 647//566 620//571 646//572 +f 672//567 647//566 646//572 +f 672//567 646//572 645//573 +f 671//568 672//567 645//573 +f 671//568 645//573 662//574 +f 689//569 671//568 662//574 +f 689//569 662//574 668//575 +f 610//570 594//425 582//432 +f 610//570 582//432 593//3 +f 620//571 610//570 593//3 +f 620//571 593//3 636//89 +f 646//572 620//571 636//89 +f 646//572 636//89 619//576 +f 645//573 646//572 619//576 +f 645//573 619//576 635//577 +f 662//574 645//573 635//577 +f 662//574 635//577 642//578 +f 668//575 662//574 642//578 +f 668//575 642//578 641//579 +f 593//3 582//432 566//33 +f 619//576 636//89 592//57 +f 619//576 592//57 609//580 +f 635//577 619//576 609//580 +f 635//577 609//580 615//581 +f 642//578 635//577 615//581 +f 642//578 615//581 614//582 +f 641//579 642//578 614//582 +f 592//57 565//56 581//583 +f 609//580 592//57 581//583 +f 609//580 581//583 587//584 +f 615//581 609//580 587//584 +f 615//581 587//584 586//585 +f 614//582 615//581 586//585 +f 614//582 586//585 588//586 +f 565//56 553//31 536//451 +f 565//56 536//451 552//587 +f 581//583 565//56 552//587 +f 581//583 552//587 560//588 +f 587//584 581//583 560//588 +f 587//584 560//588 559//589 +f 586//585 587//584 559//589 +f 586//585 559//589 561//590 +f 588//586 586//585 561//590 +f 588//586 561//590 576//591 +f 605//592 588//586 576//591 +f 605//592 576//591 604//593 +f 552//587 536//451 522//458 +f 552//587 522//458 530//594 +f 560//588 552//587 530//594 +f 560//588 530//594 529//595 +f 559//589 560//588 529//595 +f 559//589 529//595 531//596 +f 561//590 559//589 531//596 +f 561//590 531//596 547//597 +f 576//591 561//590 547//597 +f 576//591 547//597 575//598 +f 604//593 576//591 575//598 +f 604//593 575//598 603//599 +f 530//594 522//458 499//465 +f 530//594 499//465 498//600 +f 529//595 530//594 498//600 +f 529//595 498//600 500//601 +f 531//596 529//595 500//601 +f 531//596 500//601 517//602 +f 547//597 531//596 517//602 +f 547//597 517//602 546//603 +f 575//598 547//597 546//603 +f 575//598 546//603 574//604 +f 603//599 575//598 574//604 +f 603//599 574//604 602//605 +f 498//600 499//465 466//472 +f 498//600 466//472 468//606 +f 500//601 498//600 468//606 +f 500//601 468//606 485//607 +f 517//602 500//601 485//607 +f 517//602 485//607 516//608 +f 546//603 517//602 516//608 +f 546//603 516//608 545//609 +f 574//604 546//603 545//609 +f 574//604 545//609 573//610 +f 602//605 574//604 573//610 +f 602//605 573//610 601//611 +f 468//606 466//472 434//479 +f 468//606 434//479 451//612 +f 485//607 468//606 451//612 +f 485//607 451//612 484//613 +f 516//608 485//607 484//613 +f 516//608 484//613 515//614 +f 545//609 516//608 515//614 +f 545//609 515//614 544//615 +f 573//610 545//609 544//615 +f 573//610 544//615 572//616 +f 601//611 573//610 572//616 +f 601//611 572//616 600//617 +f 451//612 434//479 417//486 +f 451//612 417//486 450//618 +f 484//613 451//612 450//618 +f 484//613 450//618 483//619 +f 515//614 484//613 483//619 +f 515//614 483//619 514//620 +f 544//615 515//614 514//620 +f 544//615 514//620 543//621 +f 572//616 544//615 543//621 +f 572//616 543//621 571//622 +f 600//617 572//616 571//622 +f 600//617 571//622 599//623 +f 450//618 417//486 416//493 +f 450//618 416//493 449//624 +f 483//619 450//618 449//624 +f 483//619 449//624 482//625 +f 514//620 483//619 482//625 +f 514//620 482//625 513//626 +f 543//621 514//620 513//626 +f 543//621 513//626 542//627 +f 571//622 543//621 542//627 +f 571//622 542//627 570//628 +f 599//623 571//622 570//628 +f 599//623 570//628 598//629 +f 449//624 416//493 415//500 +f 449//624 415//500 448//630 +f 482//625 449//624 448//630 +f 482//625 448//630 481//631 +f 513//626 482//625 481//631 +f 513//626 481//631 512//632 +f 542//627 513//626 512//632 +f 542//627 512//632 541//633 +f 570//628 542//627 541//633 +f 570//628 541//633 569//634 +f 598//629 570//628 569//634 +f 598//629 569//634 597//635 +f 448//630 415//500 414//507 +f 448//630 414//507 447//636 +f 481//631 448//630 447//636 +f 481//631 447//636 480//637 +f 512//632 481//631 480//637 +f 512//632 480//637 511//638 +f 541//633 512//632 511//638 +f 541//633 511//638 540//639 +f 569//634 541//633 540//639 +f 569//634 540//639 568//640 +f 597//635 569//634 568//640 +f 597//635 568//640 596//641 +f 447//636 414//507 413//514 +f 447//636 413//514 446//642 +f 480//637 447//636 446//642 +f 480//637 446//642 479//643 +f 511//638 480//637 479//643 +f 511//638 479//643 510//644 +f 540//639 511//638 510//644 +f 540//639 510//644 539//175 +f 568//640 540//639 539//175 +f 568//640 539//175 585//249 +f 596//641 568//640 585//249 +f 596//641 585//249 613//248 +f 446//642 413//514 412//361 +f 446//642 412//361 445//515 +f 479//643 446//642 445//515 +f 479//643 445//515 478//517 +f 510//644 479//643 478//517 +f 510//644 478//517 509//176 +f 539//175 510//644 509//176 +f 691//228 648//227 674//645 +f 702//646 691//228 674//645 +f 702//646 674//645 701//647 +f 731//648 702//646 701//647 +f 731//648 701//647 730//649 +f 759//650 731//648 730//649 +f 759//650 730//649 758//651 +f 786//652 759//650 758//651 +f 786//652 758//651 785//653 +f 648//227 621//526 638//527 +f 648//227 638//527 663//654 +f 674//645 648//227 663//654 +f 674//645 663//654 690//655 +f 701//647 674//645 690//655 +f 701//647 690//655 720//656 +f 730//649 701//647 720//656 +f 730//649 720//656 749//657 +f 758//651 730//649 749//657 +f 758//651 749//657 777//658 +f 785//653 758//651 777//658 +f 785//653 777//658 805//659 +f 663//654 638//527 664//533 +f 663//654 664//533 692//660 +f 690//655 663//654 692//660 +f 690//655 692//660 721//661 +f 720//656 690//655 721//661 +f 720//656 721//661 750//662 +f 749//657 720//656 750//662 +f 749//657 750//662 778//663 +f 777//658 749//657 778//663 +f 777//658 778//663 806//664 +f 805//659 777//658 806//664 +f 805//659 806//664 833//665 +f 692//660 664//533 688//539 +f 692//660 688//539 718//666 +f 721//661 692//660 718//666 +f 721//661 718//666 747//667 +f 750//662 721//661 747//667 +f 750//662 747//667 775//668 +f 778//663 750//662 775//668 +f 778//663 775//668 803//669 +f 806//664 778//663 803//669 +f 806//664 803//669 831//670 +f 833//665 806//664 831//670 +f 833//665 831//670 838//671 +f 718//666 688//539 698//545 +f 718//666 698//545 728//672 +f 747//667 718//666 728//672 +f 747//667 728//672 756//673 +f 775//668 747//667 756//673 +f 775//668 756//673 784//674 +f 803//669 775//668 784//674 +f 803//669 784//674 804//675 +f 831//670 803//669 804//675 +f 831//670 804//675 811//676 +f 838//671 831//670 811//676 +f 838//671 811//676 830//677 +f 728//672 698//545 717//551 +f 728//672 717//551 746//678 +f 756//673 728//672 746//678 +f 756//673 746//678 757//679 +f 784//674 756//673 757//679 +f 784//674 757//679 776//680 +f 804//675 784//674 776//680 +f 804//675 776//680 783//681 +f 811//676 804//675 783//681 +f 811//676 783//681 802//682 +f 830//677 811//676 802//682 +f 830//677 802//682 810//683 +f 746//678 717//551 727//557 +f 746//678 727//557 729//684 +f 757//679 746//678 729//684 +f 757//679 729//684 748//685 +f 776//680 757//679 748//685 +f 776//680 748//685 755//686 +f 783//681 776//680 755//686 +f 783//681 755//686 774//687 +f 802//682 783//681 774//687 +f 802//682 774//687 782//688 +f 810//683 802//682 782//688 +f 810//683 782//688 809//689 +f 729//684 727//557 699//563 +f 729//684 699//563 719//690 +f 748//685 729//684 719//690 +f 748//685 719//690 726//691 +f 755//686 748//685 726//691 +f 755//686 726//691 745//692 +f 774//687 755//686 745//692 +f 774//687 745//692 754//693 +f 782//688 774//687 754//693 +f 782//688 754//693 781//694 +f 809//689 782//688 781//694 +f 809//689 781//694 780//695 +f 719//690 699//563 689//569 +f 719//690 689//569 696//696 +f 726//691 719//690 696//696 +f 726//691 696//696 716//697 +f 745//692 726//691 716//697 +f 745//692 716//697 725//698 +f 754//693 745//692 725//698 +f 754//693 725//698 753//699 +f 781//694 754//693 753//699 +f 781//694 753//699 752//700 +f 780//695 781//694 752//700 +f 780//695 752//700 773//701 +f 696//696 689//569 668//575 +f 696//696 668//575 686//702 +f 716//697 696//696 686//702 +f 716//697 686//702 695//703 +f 725//698 716//697 695//703 +f 725//698 695//703 724//704 +f 753//699 725//698 724//704 +f 753//699 724//704 723//705 +f 752//700 753//699 723//705 +f 752//700 723//705 744//706 +f 773//701 752//700 744//706 +f 773//701 744//706 772//707 +f 686//702 668//575 641//579 +f 686//702 641//579 667//708 +f 695//703 686//702 667//708 +f 695//703 667//708 715//160 +f 724//704 695//703 715//160 +f 724//704 715//160 694//709 +f 723//705 724//704 694//709 +f 723//705 694//709 714//710 +f 744//706 723//705 714//710 +f 744//706 714//710 743//711 +f 772//707 744//706 743//711 +f 772//707 743//711 771//712 +f 694//709 715//160 666//713 +f 694//709 666//713 685//714 +f 714//710 694//709 685//714 +f 714//710 685//714 713//715 +f 743//711 714//710 713//715 +f 743//711 713//715 742//716 +f 771//712 743//711 742//716 +f 771//712 742//716 770//717 +f 666//713 631//152 658//718 +f 685//714 666//713 658//718 +f 685//714 658//718 684//719 +f 713//715 685//714 684//719 +f 713//715 684//719 712//720 +f 742//716 713//715 712//720 +f 742//716 712//720 741//721 +f 770//717 742//716 741//721 +f 770//717 741//721 769//722 +f 631//152 605//592 604//593 +f 631//152 604//593 630//723 +f 658//718 631//152 630//723 +f 658//718 630//723 657//724 +f 684//719 658//718 657//724 +f 684//719 657//724 683//725 +f 712//720 684//719 683//725 +f 712//720 683//725 711//726 +f 741//721 712//720 711//726 +f 741//721 711//726 740//727 +f 769//722 741//721 740//727 +f 769//722 740//727 768//728 +f 630//723 604//593 603//599 +f 630//723 603//599 629//729 +f 657//724 630//723 629//729 +f 657//724 629//729 656//730 +f 683//725 657//724 656//730 +f 683//725 656//730 682//731 +f 711//726 683//725 682//731 +f 711//726 682//731 710//732 +f 740//727 711//726 710//732 +f 740//727 710//732 739//733 +f 768//728 740//727 739//733 +f 768//728 739//733 767//734 +f 629//729 603//599 602//605 +f 629//729 602//605 628//735 +f 656//730 629//729 628//735 +f 656//730 628//735 655//736 +f 682//731 656//730 655//736 +f 682//731 655//736 681//737 +f 710//732 682//731 681//737 +f 710//732 681//737 709//738 +f 739//733 710//732 709//738 +f 739//733 709//738 738//739 +f 767//734 739//733 738//739 +f 767//734 738//739 766//740 +f 628//735 602//605 601//611 +f 628//735 601//611 627//741 +f 655//736 628//735 627//741 +f 655//736 627//741 654//742 +f 681//737 655//736 654//742 +f 681//737 654//742 680//743 +f 709//738 681//737 680//743 +f 709//738 680//743 708//744 +f 738//739 709//738 708//744 +f 738//739 708//744 737//745 +f 766//740 738//739 737//745 +f 766//740 737//745 765//746 +f 627//741 601//611 600//617 +f 627//741 600//617 626//747 +f 654//742 627//741 626//747 +f 654//742 626//747 653//748 +f 680//743 654//742 653//748 +f 680//743 653//748 679//749 +f 708//744 680//743 679//749 +f 708//744 679//749 707//750 +f 737//745 708//744 707//750 +f 737//745 707//750 736//751 +f 765//746 737//745 736//751 +f 765//746 736//751 764//752 +f 626//747 600//617 599//623 +f 626//747 599//623 625//753 +f 653//748 626//747 625//753 +f 653//748 625//753 652//754 +f 679//749 653//748 652//754 +f 679//749 652//754 678//755 +f 707//750 679//749 678//755 +f 707//750 678//755 706//756 +f 736//751 707//750 706//756 +f 736//751 706//756 735//757 +f 764//752 736//751 735//757 +f 764//752 735//757 763//758 +f 625//753 599//623 598//629 +f 625//753 598//629 624//759 +f 652//754 625//753 624//759 +f 652//754 624//759 651//760 +f 678//755 652//754 651//760 +f 678//755 651//760 677//761 +f 706//756 678//755 677//761 +f 706//756 677//761 705//762 +f 735//757 706//756 705//762 +f 735//757 705//762 734//763 +f 763//758 735//757 734//763 +f 763//758 734//763 762//764 +f 624//759 598//629 597//635 +f 624//759 597//635 623//765 +f 651//760 624//759 623//765 +f 651//760 623//765 650//766 +f 677//761 651//760 650//766 +f 677//761 650//766 676//767 +f 705//762 677//761 676//767 +f 705//762 676//767 704//768 +f 734//763 705//762 704//768 +f 734//763 704//768 733//769 +f 762//764 734//763 733//769 +f 762//764 733//769 761//770 +f 623//765 597//635 596//641 +f 623//765 596//641 622//771 +f 650//766 623//765 622//771 +f 650//766 622//771 649//772 +f 676//767 650//766 649//772 +f 676//767 649//772 675//773 +f 704//768 676//767 675//773 +f 704//768 675//773 703//774 +f 733//769 704//768 703//774 +f 733//769 703//774 732//775 +f 761//770 733//769 732//775 +f 761//770 732//775 760//776 +f 622//771 596//641 613//248 +f 622//771 613//248 640//777 +f 649//772 622//771 640//777 +f 649//772 640//777 665//778 +f 675//773 649//772 665//778 +f 675//773 665//778 693//779 +f 703//774 675//773 693//779 +f 703//774 693//779 722//780 +f 732//775 703//774 722//780 +f 732//775 722//780 751//781 +f 760//776 732//775 751//781 +f 760//776 751//781 779//782 +f 693//779 665//778 691//228 +f 693//779 691//228 702//646 +f 722//780 693//779 702//646 +f 722//780 702//646 731//648 +f 751//781 722//780 731//648 +f 751//781 731//648 759//650 +f 779//782 751//781 759//650 +f 779//782 759//650 786//652 +f 917//783 918//784 913//785 +f 892//786 917//783 913//785 +f 892//786 913//785 887//787 +f 866//788 892//786 887//787 +f 866//788 887//787 861//789 +f 840//790 866//788 861//789 +f 840//790 861//789 834//791 +f 813//792 840//790 834//791 +f 813//792 834//791 807//793 +f 786//652 813//792 807//793 +f 786//652 807//793 779//782 +f 913//785 918//784 893//794 +f 887//787 913//785 893//794 +f 887//787 893//794 867//795 +f 861//789 887//787 867//795 +f 861//789 867//795 841//796 +f 834//791 861//789 841//796 +f 834//791 841//796 814//797 +f 807//793 834//791 814//797 +f 807//793 814//797 787//798 +f 779//782 807//793 787//798 +f 779//782 787//798 760//776 +f 893//794 918//784 894//799 +f 867//795 893//794 894//799 +f 867//795 894//799 868//800 +f 841//796 867//795 868//800 +f 841//796 868//800 842//801 +f 814//797 841//796 842//801 +f 814//797 842//801 815//802 +f 787//798 814//797 815//802 +f 787//798 815//802 788//803 +f 760//776 787//798 788//803 +f 760//776 788//803 761//770 +f 894//799 918//784 895//804 +f 868//800 894//799 895//804 +f 868//800 895//804 869//805 +f 842//801 868//800 869//805 +f 842//801 869//805 843//806 +f 815//802 842//801 843//806 +f 815//802 843//806 816//807 +f 788//803 815//802 816//807 +f 788//803 816//807 789//808 +f 761//770 788//803 789//808 +f 761//770 789//808 762//764 +f 895//804 918//784 896//809 +f 869//805 895//804 896//809 +f 869//805 896//809 870//810 +f 843//806 869//805 870//810 +f 843//806 870//810 844//811 +f 816//807 843//806 844//811 +f 816//807 844//811 817//812 +f 789//808 816//807 817//812 +f 789//808 817//812 790//813 +f 762//764 789//808 790//813 +f 762//764 790//813 763//758 +f 896//809 918//784 897//814 +f 870//810 896//809 897//814 +f 870//810 897//814 871//815 +f 844//811 870//810 871//815 +f 844//811 871//815 845//816 +f 817//812 844//811 845//816 +f 817//812 845//816 818//817 +f 790//813 817//812 818//817 +f 790//813 818//817 791//818 +f 763//758 790//813 791//818 +f 763//758 791//818 764//752 +f 897//814 918//784 898//819 +f 871//815 897//814 898//819 +f 871//815 898//819 872//820 +f 845//816 871//815 872//820 +f 845//816 872//820 846//821 +f 818//817 845//816 846//821 +f 818//817 846//821 819//822 +f 791//818 818//817 819//822 +f 791//818 819//822 792//823 +f 764//752 791//818 792//823 +f 764//752 792//823 765//746 +f 898//819 918//784 899//824 +f 872//820 898//819 899//824 +f 872//820 899//824 873//825 +f 846//821 872//820 873//825 +f 846//821 873//825 847//826 +f 819//822 846//821 847//826 +f 819//822 847//826 820//827 +f 792//823 819//822 820//827 +f 792//823 820//827 793//828 +f 765//746 792//823 793//828 +f 765//746 793//828 766//740 +f 899//824 918//784 900//829 +f 873//825 899//824 900//829 +f 873//825 900//829 874//830 +f 847//826 873//825 874//830 +f 847//826 874//830 848//831 +f 820//827 847//826 848//831 +f 820//827 848//831 821//832 +f 793//828 820//827 821//832 +f 793//828 821//832 794//833 +f 766//740 793//828 794//833 +f 766//740 794//833 767//734 +f 900//829 918//784 901//834 +f 874//830 900//829 901//834 +f 874//830 901//834 875//835 +f 848//831 874//830 875//835 +f 848//831 875//835 849//836 +f 821//832 848//831 849//836 +f 821//832 849//836 822//837 +f 794//833 821//832 822//837 +f 794//833 822//837 795//838 +f 767//734 794//833 795//838 +f 767//734 795//838 768//728 +f 901//834 918//784 902//839 +f 875//835 901//834 902//839 +f 875//835 902//839 876//840 +f 849//836 875//835 876//840 +f 849//836 876//840 850//841 +f 822//837 849//836 850//841 +f 822//837 850//841 823//842 +f 795//838 822//837 823//842 +f 795//838 823//842 796//843 +f 768//728 795//838 796//843 +f 768//728 796//843 769//722 +f 902//839 918//784 903//844 +f 876//840 902//839 903//844 +f 876//840 903//844 877//845 +f 850//841 876//840 877//845 +f 850//841 877//845 851//846 +f 823//842 850//841 851//846 +f 823//842 851//846 824//847 +f 796//843 823//842 824//847 +f 796//843 824//847 797//848 +f 769//722 796//843 797//848 +f 769//722 797//848 770//717 +f 903//844 918//784 904//849 +f 877//845 903//844 904//849 +f 877//845 904//849 878//850 +f 851//846 877//845 878//850 +f 851//846 878//850 852//851 +f 824//847 851//846 852//851 +f 824//847 852//851 825//852 +f 797//848 824//847 825//852 +f 797//848 825//852 798//853 +f 770//717 797//848 798//853 +f 770//717 798//853 771//712 +f 904//849 918//784 905//854 +f 878//850 904//849 905//854 +f 878//850 905//854 879//855 +f 852//851 878//850 879//855 +f 852//851 879//855 853//856 +f 825//852 852//851 853//856 +f 825//852 853//856 826//857 +f 798//853 825//852 826//857 +f 798//853 826//857 799//858 +f 771//712 798//853 799//858 +f 771//712 799//858 772//707 +f 905//854 918//784 906//859 +f 879//855 905//854 906//859 +f 879//855 906//859 880//860 +f 853//856 879//855 880//860 +f 853//856 880//860 854//861 +f 826//857 853//856 854//861 +f 826//857 854//861 827//862 +f 799//858 826//857 827//862 +f 799//858 827//862 800//863 +f 772//707 799//858 800//863 +f 772//707 800//863 773//701 +f 906//859 918//784 907//864 +f 880//860 906//859 907//864 +f 880//860 907//864 881//865 +f 854//861 880//860 881//865 +f 854//861 881//865 855//866 +f 827//862 854//861 855//866 +f 827//862 855//866 828//867 +f 800//863 827//862 828//867 +f 800//863 828//867 801//868 +f 773//701 800//863 801//868 +f 773//701 801//868 780//695 +f 907//864 918//784 908//869 +f 881//865 907//864 908//869 +f 881//865 908//869 882//870 +f 855//866 881//865 882//870 +f 855//866 882//870 856//871 +f 828//867 855//866 856//871 +f 828//867 856//871 829//872 +f 801//868 828//867 829//872 +f 801//868 829//872 808//873 +f 780//695 801//868 808//873 +f 780//695 808//873 809//689 +f 908//869 918//784 909//874 +f 882//870 908//869 909//874 +f 882//870 909//874 883//875 +f 856//871 882//870 883//875 +f 856//871 883//875 857//876 +f 829//872 856//871 857//876 +f 829//872 857//876 836//877 +f 808//873 829//872 836//877 +f 808//873 836//877 835//878 +f 809//689 808//873 835//878 +f 809//689 835//878 810//683 +f 909//874 918//784 910//879 +f 883//875 909//874 910//879 +f 883//875 910//879 884//880 +f 857//876 883//875 884//880 +f 857//876 884//880 863//881 +f 836//877 857//876 863//881 +f 836//877 863//881 862//882 +f 835//878 836//877 862//882 +f 835//878 862//882 837//883 +f 810//683 835//878 837//883 +f 810//683 837//883 830//677 +f 910//879 918//784 911//884 +f 884//880 910//879 911//884 +f 884//880 911//884 889//885 +f 863//881 884//880 889//885 +f 863//881 889//885 888//886 +f 862//882 863//881 888//886 +f 862//882 888//886 864//887 +f 837//883 862//882 864//887 +f 837//883 864//887 858//888 +f 830//677 837//883 858//888 +f 830//677 858//888 838//671 +f 911//884 918//784 915//889 +f 889//885 911//884 915//889 +f 889//885 915//889 914//890 +f 888//886 889//885 914//890 +f 888//886 914//890 890//891 +f 864//887 888//886 890//891 +f 864//887 890//891 885//892 +f 858//888 864//887 885//892 +f 858//888 885//892 859//893 +f 838//671 858//888 859//893 +f 838//671 859//893 833//665 +f 915//889 918//784 919//894 +f 914//890 915//889 919//894 +f 914//890 919//894 912//895 +f 890//891 914//890 912//895 +f 890//891 912//895 886//896 +f 885//892 890//891 886//896 +f 885//892 886//896 860//897 +f 859//893 885//892 860//897 +f 859//893 860//897 832//898 +f 833//665 859//893 832//898 +f 833//665 832//898 805//659 +f 919//894 918//784 916//899 +f 912//895 919//894 916//899 +f 912//895 916//899 891//900 +f 886//896 912//895 891//900 +f 886//896 891//900 865//901 +f 860//897 886//896 865//901 +f 860//897 865//901 839//902 +f 832//898 860//897 839//902 +f 832//898 839//902 812//903 +f 805//659 832//898 812//903 +f 805//659 812//903 785//653 +f 916//899 918//784 917//783 +f 891//900 916//899 917//783 +f 891//900 917//783 892//786 +f 865//901 891//900 892//786 +f 865//901 892//786 866//788 +f 839//902 865//901 866//788 +f 839//902 866//788 840//790 +f 812//903 839//902 840//790 +f 812//903 840//790 813//792 +f 785//653 812//903 813//792 +f 785//653 813//792 786//652 +f 404//412 1267//904 1268//905 +f 384//906 373//907 372//480 +f 346//908 345//501 352//494 +f 435//909 436//426 419//419 +f 331//910 327//350 335//508 +f 462//439 453//433 1265//911 +f 920//912 921//913 922//914 +f 920//912 922//914 923//915 +f 923//915 922//914 927//916 +f 923//915 927//916 933//917 +f 933//917 927//916 940//918 +f 933//917 940//918 949//919 +f 949//919 940//918 959//920 +f 949//919 959//920 971//921 +f 971//921 959//920 984//922 +f 971//921 984//922 999//923 +f 999//923 984//922 1011//924 +f 999//923 1011//924 1027//925 +f 1027//925 1011//924 1042//926 +f 1027//925 1042//926 1059//927 +f 1059//927 1042//926 1077//928 +f 1059//927 1077//928 1095//929 +f 1095//929 1077//928 1110//930 +f 1095//929 1110//930 1129//931 +f 1129//931 1110//930 1144//932 +f 1129//931 1144//932 1163//933 +f 1163//933 1144//932 1179//934 +f 1163//933 1179//934 1196//935 +f 1196//935 1179//934 1210//936 +f 1196//935 1210//936 1220//937 +f 1220//937 1210//936 1212//938 +f 1220//937 1212//938 1201//939 +f 1201//939 1212//938 1181//940 +f 1201//939 1181//940 1169//941 +f 1169//941 1181//940 1147//942 +f 1169//941 1147//942 1135//943 +f 1135//943 1147//942 1113//944 +f 1135//943 1113//944 1102//945 +f 1102//945 1113//944 1081//946 +f 1102//945 1081//946 1065//947 +f 1065//947 1081//946 1046//948 +f 1065//947 1046//948 1032//949 +f 1032//949 1046//948 1016//950 +f 1032//949 1016//950 1003//951 +f 1003//951 1016//950 988//952 +f 1003//951 988//952 974//953 +f 974//953 988//952 962//954 +f 974//953 962//954 951//955 +f 951//955 962//954 942//956 +f 951//955 942//956 934//957 +f 934//957 942//956 928//958 +f 934//957 928//958 924//959 +f 924//959 928//958 921//913 +f 921//913 920//912 924//959 +f 926//960 920//912 923//915 +f 926//960 923//915 932//961 +f 938//962 926//960 932//961 +f 938//962 932//961 947//963 +f 956//964 938//962 947//963 +f 956//964 947//963 968//965 +f 980//966 956//964 968//965 +f 980//966 968//965 995//967 +f 1006//968 980//966 995//967 +f 1006//968 995//967 1022//969 +f 1036//970 1006//968 1022//969 +f 1036//970 1022//969 1053//971 +f 932//961 923//915 933//917 +f 932//961 933//917 948//972 +f 947//963 932//961 948//972 +f 947//963 948//972 969//973 +f 968//965 947//963 969//973 +f 968//965 969//973 996//974 +f 995//967 968//965 996//974 +f 995//967 996//974 1023//975 +f 1022//969 995//967 1023//975 +f 1022//969 1023//975 1054//976 +f 1053//971 1022//969 1054//976 +f 1053//971 1054//976 1089//977 +f 948//972 933//917 949//919 +f 948//972 949//919 970//978 +f 969//973 948//972 970//978 +f 969//973 970//978 997//979 +f 996//974 969//973 997//979 +f 996//974 997//979 1024//980 +f 1023//975 996//974 1024//980 +f 1023//975 1024//980 1055//981 +f 1054//976 1023//975 1055//981 +f 1054//976 1055//981 1090//982 +f 1089//977 1054//976 1090//982 +f 1089//977 1090//982 1109//983 +f 970//978 949//919 971//921 +f 970//978 971//921 998//984 +f 997//979 970//978 998//984 +f 997//979 998//984 1025//985 +f 1024//980 997//979 1025//985 +f 1024//980 1025//985 1056//986 +f 1055//981 1024//980 1056//986 +f 1055//981 1056//986 1091//987 +f 1090//982 1055//981 1091//987 +f 1090//982 1091//987 1124//988 +f 1109//983 1090//982 1124//988 +f 1109//983 1124//988 1122//989 +f 998//984 971//921 999//923 +f 998//984 999//923 1026//990 +f 1025//985 998//984 1026//990 +f 1025//985 1026//990 1057//991 +f 1056//986 1025//985 1057//991 +f 1056//986 1057//991 1092//992 +f 1091//987 1056//986 1092//992 +f 1091//987 1092//992 1125//993 +f 1124//988 1091//987 1125//993 +f 1124//988 1125//993 1156//994 +f 1122//989 1124//988 1156//994 +f 1122//989 1156//994 1142//995 +f 1026//990 999//923 1027//925 +f 1026//990 1027//925 1058//996 +f 1057//991 1026//990 1058//996 +f 1057//991 1058//996 1093//997 +f 1092//992 1057//991 1093//997 +f 1092//992 1093//997 1126//998 +f 1125//993 1092//992 1126//998 +f 1125//993 1126//998 1159//999 +f 1156//994 1125//993 1159//999 +f 1156//994 1159//999 1176//1000 +f 1142//995 1156//994 1176//1000 +f 1142//995 1176//1000 1157//1001 +f 1058//996 1027//925 1059//927 +f 1058//996 1059//927 1094//1002 +f 1093//997 1058//996 1094//1002 +f 1093//997 1094//1002 1127//1003 +f 1126//998 1093//997 1127//1003 +f 1126//998 1127//1003 1160//1004 +f 1159//999 1126//998 1160//1004 +f 1159//999 1160//1004 1192//1005 +f 1176//1000 1159//999 1192//1005 +f 1176//1000 1192//1005 1189//1006 +f 1157//1001 1176//1000 1189//1006 +f 1157//1001 1189//1006 1178//1007 +f 1094//1002 1059//927 1095//929 +f 1094//1002 1095//929 1128//1008 +f 1127//1003 1094//1002 1128//1008 +f 1127//1003 1128//1008 1161//1009 +f 1160//1004 1127//1003 1161//1009 +f 1160//1004 1161//1009 1193//1010 +f 1192//1005 1160//1004 1193//1010 +f 1192//1005 1193//1010 1215//1011 +f 1189//1006 1192//1005 1215//1011 +f 1189//1006 1215//1011 1207//1012 +f 1178//1007 1189//1006 1207//1012 +f 1178//1007 1207//1012 1191//1013 +f 1128//1008 1095//929 1129//931 +f 1128//1008 1129//931 1162//1014 +f 1161//1009 1128//1008 1162//1014 +f 1161//1009 1162//1014 1194//1015 +f 1193//1010 1161//1009 1194//1015 +f 1193//1010 1194//1015 1217//1016 +f 1215//1011 1193//1010 1217//1016 +f 1215//1011 1217//1016 1227//1017 +f 1207//1012 1215//1011 1227//1017 +f 1207//1012 1227//1017 1216//1018 +f 1191//1013 1207//1012 1216//1018 +f 1191//1013 1216//1018 1209//1019 +f 1162//1014 1129//931 1163//933 +f 1162//1014 1163//933 1195//1020 +f 1194//1015 1162//1014 1195//1020 +f 1194//1015 1195//1020 1218//1021 +f 1217//1016 1194//1015 1218//1021 +f 1217//1016 1218//1021 1230//1022 +f 1227//1017 1217//1016 1230//1022 +f 1227//1017 1230//1022 1229//1023 +f 1216//1018 1227//1017 1229//1023 +f 1216//1018 1229//1023 1225//1024 +f 1209//1019 1216//1018 1225//1024 +f 1209//1019 1225//1024 1203//1025 +f 1195//1020 1163//933 1196//935 +f 1195//1020 1196//935 1219//1026 +f 1218//1021 1195//1020 1219//1026 +f 1218//1021 1219//1026 1231//1027 +f 1230//1022 1218//1021 1231//1027 +f 1230//1022 1231//1027 1232//1028 +f 1229//1023 1230//1022 1232//1028 +f 1229//1023 1232//1028 1228//1029 +f 1225//1024 1229//1023 1228//1029 +f 1225//1024 1228//1029 1214//1030 +f 1203//1025 1225//1024 1214//1030 +f 1203//1025 1214//1030 1184//1031 +f 1219//1026 1196//935 1220//937 +f 1219//1026 1220//937 1224//1032 +f 1231//1027 1219//1026 1224//1032 +f 1231//1027 1224//1032 1223//1033 +f 1232//1028 1231//1027 1223//1033 +f 1232//1028 1223//1033 1222//1034 +f 1228//1029 1232//1028 1222//1034 +f 1228//1029 1222//1034 1221//1035 +f 1214//1030 1228//1029 1221//1035 +f 1214//1030 1221//1035 1204//1036 +f 1184//1031 1214//1030 1204//1036 +f 1184//1031 1204//1036 1171//1037 +f 1224//1032 1220//937 1201//939 +f 1224//1032 1201//939 1200//1038 +f 1223//1033 1224//1032 1200//1038 +f 1223//1033 1200//1038 1199//1039 +f 1222//1034 1223//1033 1199//1039 +f 1222//1034 1199//1039 1198//1040 +f 1221//1035 1222//1034 1198//1040 +f 1221//1035 1198//1040 1197//1041 +f 1204//1036 1221//1035 1197//1041 +f 1204//1036 1197//1041 1185//1042 +f 1171//1037 1204//1036 1185//1042 +f 1171//1037 1185//1042 1151//1043 +f 1200//1038 1201//939 1169//941 +f 1200//1038 1169//941 1168//1044 +f 1199//1039 1200//1038 1168//1044 +f 1199//1039 1168//1044 1167//1045 +f 1198//1040 1199//1039 1167//1045 +f 1198//1040 1167//1045 1166//1046 +f 1197//1041 1198//1040 1166//1046 +f 1197//1041 1166//1046 1165//1047 +f 1185//1042 1197//1041 1165//1047 +f 1185//1042 1165//1047 1164//1048 +f 1151//1043 1185//1042 1164//1048 +f 1151//1043 1164//1048 1137//1049 +f 1168//1044 1169//941 1135//943 +f 1168//1044 1135//943 1134//1050 +f 1167//1045 1168//1044 1134//1050 +f 1167//1045 1134//1050 1133//1051 +f 1166//1046 1167//1045 1133//1051 +f 1166//1046 1133//1051 1132//1052 +f 1165//1047 1166//1046 1132//1052 +f 1165//1047 1132//1052 1131//1053 +f 1164//1048 1165//1047 1131//1053 +f 1164//1048 1131//1053 1130//1054 +f 1137//1049 1164//1048 1130//1054 +f 1137//1049 1130//1054 1117//1055 +f 1134//1050 1135//943 1102//945 +f 1134//1050 1102//945 1101//1056 +f 1133//1051 1134//1050 1101//1056 +f 1133//1051 1101//1056 1100//1057 +f 1132//1052 1133//1051 1100//1057 +f 1132//1052 1100//1057 1099//1058 +f 1131//1053 1132//1052 1099//1058 +f 1131//1053 1099//1058 1098//1059 +f 1130//1054 1131//1053 1098//1059 +f 1130//1054 1098//1059 1097//1060 +f 1117//1055 1130//1054 1097//1060 +f 1117//1055 1097//1060 1096//1061 +f 1101//1056 1102//945 1065//947 +f 1101//1056 1065//947 1064//1062 +f 1100//1057 1101//1056 1064//1062 +f 1100//1057 1064//1062 1063//1063 +f 1099//1058 1100//1057 1063//1063 +f 1099//1058 1063//1063 1062//1064 +f 1098//1059 1099//1058 1062//1064 +f 1098//1059 1062//1064 1061//1065 +f 1097//1060 1098//1059 1061//1065 +f 1097//1060 1061//1065 1060//1066 +f 1096//1061 1097//1060 1060//1066 +f 1096//1061 1060//1066 1066//1067 +f 1064//1062 1065//947 1032//949 +f 1064//1062 1032//949 1031//1068 +f 1063//1063 1064//1062 1031//1068 +f 1063//1063 1031//1068 1030//1069 +f 1062//1064 1063//1063 1030//1069 +f 1062//1064 1030//1069 1029//1070 +f 1061//1065 1062//1064 1029//1070 +f 1061//1065 1029//1070 1028//1071 +f 1060//1066 1061//1065 1028//1071 +f 1060//1066 1028//1071 1033//1072 +f 1066//1067 1060//1066 1033//1072 +f 1066//1067 1033//1072 1050//1073 +f 1031//1068 1032//949 1003//951 +f 1031//1068 1003//951 1002//1074 +f 1030//1069 1031//1068 1002//1074 +f 1030//1069 1002//1074 1001//1075 +f 1029//1070 1030//1069 1001//1075 +f 1029//1070 1001//1075 1000//1076 +f 1028//1071 1029//1070 1000//1076 +f 1028//1071 1000//1076 1004//1077 +f 1033//1072 1028//1071 1004//1077 +f 1033//1072 1004//1077 1021//1078 +f 1050//1073 1033//1072 1021//1078 +f 1050//1073 1021//1078 1041//1079 +f 1002//1074 1003//951 974//953 +f 1002//1074 974//953 973//1080 +f 1001//1075 1002//1074 973//1080 +f 1001//1075 973//1080 972//1081 +f 1000//1076 1001//1075 972//1081 +f 1000//1076 972//1081 975//1082 +f 1004//1077 1000//1076 975//1082 +f 1004//1077 975//1082 992//1083 +f 1021//1078 1004//1077 992//1083 +f 1021//1078 992//1083 1010//1084 +f 1041//1079 1021//1078 1010//1084 +f 1041//1079 1010//1084 1040//1085 +f 973//1080 974//953 951//955 +f 973//1080 951//955 950//1086 +f 972//1081 973//1080 950//1086 +f 972//1081 950//1086 952//1087 +f 975//1082 972//1081 952//1087 +f 975//1082 952//1087 965//1088 +f 992//1083 975//1082 965//1088 +f 992//1083 965//1088 983//1089 +f 1010//1084 992//1083 983//1089 +f 1010//1084 983//1089 1009//1090 +f 1040//1085 1010//1084 1009//1090 +f 1040//1085 1009//1090 1039//1091 +f 950//1086 951//955 934//957 +f 950//1086 934//957 935//1092 +f 952//1087 950//1086 935//1092 +f 952//1087 935//1092 944//1093 +f 965//1088 952//1087 944//1093 +f 965//1088 944//1093 958//1094 +f 983//1089 965//1088 958//1094 +f 983//1089 958//1094 982//1095 +f 1009//1090 983//1089 982//1095 +f 1009//1090 982//1095 1008//1096 +f 1039//1091 1009//1090 1008//1096 +f 1039//1091 1008//1096 1038//1097 +f 935//1092 934//957 924//959 +f 935//1092 924//959 929//1098 +f 944//1093 935//1092 929//1098 +f 944//1093 929//1098 939//1099 +f 958//1094 944//1093 939//1099 +f 958//1094 939//1099 957//1100 +f 982//1095 958//1094 957//1100 +f 982//1095 957//1100 981//1101 +f 1008//1096 982//1095 981//1101 +f 1008//1096 981//1101 1007//1102 +f 1038//1097 1008//1096 1007//1102 +f 1038//1097 1007//1102 1037//1103 +f 924//959 920//912 929//1098 +f 929//1098 920//912 926//960 +f 939//1099 929//1098 926//960 +f 939//1099 926//960 938//962 +f 957//1100 939//1099 938//962 +f 957//1100 938//962 956//964 +f 981//1101 957//1100 956//964 +f 981//1101 956//964 980//966 +f 1007//1102 981//1101 980//966 +f 1007//1102 980//966 1006//968 +f 1037//1103 1007//1102 1006//968 +f 1037//1103 1006//968 1036//970 +f 993//1104 1005//1105 976//1106 +f 966//1107 993//1104 976//1106 +f 966//1107 976//1106 953//1108 +f 945//1109 966//1107 953//1108 +f 945//1109 953//1108 936//1110 +f 930//1111 945//1109 936//1110 +f 930//1111 936//1110 925//1112 +f 921//913 930//1111 925//1112 +f 921//913 925//1112 922//914 +f 976//1106 1005//1105 977//1113 +f 953//1108 976//1106 977//1113 +f 953//1108 977//1113 954//1114 +f 936//1110 953//1108 954//1114 +f 936//1110 954//1114 937//1115 +f 925//1112 936//1110 937//1115 +f 925//1112 937//1115 931//1116 +f 922//914 925//1112 931//1116 +f 922//914 931//1116 927//916 +f 977//1113 1005//1105 978//1117 +f 954//1114 977//1113 978//1117 +f 954//1114 978//1117 955//1118 +f 937//1115 954//1114 955//1118 +f 937//1115 955//1118 946//1119 +f 931//1116 937//1115 946//1119 +f 931//1116 946//1119 941//1120 +f 927//916 931//1116 941//1120 +f 927//916 941//1120 940//918 +f 978//1117 1005//1105 979//1121 +f 955//1118 978//1117 979//1121 +f 955//1118 979//1121 967//1122 +f 946//1119 955//1118 967//1122 +f 946//1119 967//1122 961//1123 +f 941//1120 946//1119 961//1123 +f 941//1120 961//1123 960//1124 +f 940//918 941//1120 960//1124 +f 940//918 960//1124 959//920 +f 979//1121 1005//1105 994//1125 +f 967//1122 979//1121 994//1125 +f 967//1122 994//1125 987//1126 +f 961//1123 967//1122 987//1126 +f 961//1123 987//1126 986//1127 +f 960//1124 961//1123 986//1127 +f 960//1124 986//1127 985//1128 +f 959//920 960//1124 985//1128 +f 959//920 985//1128 984//922 +f 994//1125 1005//1105 1015//1129 +f 987//1126 994//1125 1015//1129 +f 987//1126 1015//1129 1014//1130 +f 986//1127 987//1126 1014//1130 +f 986//1127 1014//1130 1013//1131 +f 985//1128 986//1127 1013//1131 +f 985//1128 1013//1131 1012//1132 +f 984//922 985//1128 1012//1132 +f 984//922 1012//1132 1011//924 +f 1015//1129 1005//1105 1035//1133 +f 1014//1130 1015//1129 1035//1133 +f 1014//1130 1035//1133 1045//1134 +f 1013//1131 1014//1130 1045//1134 +f 1013//1131 1045//1134 1044//1135 +f 1012//1132 1013//1131 1044//1135 +f 1012//1132 1044//1135 1043//1136 +f 1011//924 1012//1132 1043//1136 +f 1011//924 1043//1136 1042//926 +f 1035//1133 1005//1105 1052//1137 +f 1045//1134 1035//1133 1052//1137 +f 1045//1134 1052//1137 1080//1138 +f 1044//1135 1045//1134 1080//1138 +f 1044//1135 1080//1138 1079//1139 +f 1043//1136 1044//1135 1079//1139 +f 1043//1136 1079//1139 1078//1140 +f 1042//926 1043//1136 1078//1140 +f 1042//926 1078//1140 1077//928 +f 1052//1137 1005//1105 1068//1141 +f 1080//1138 1052//1137 1068//1141 +f 1080//1138 1068//1141 1106//1142 +f 1079//1139 1080//1138 1106//1142 +f 1079//1139 1106//1142 1112//1143 +f 1078//1140 1079//1139 1112//1143 +f 1078//1140 1112//1143 1111//1144 +f 1077//928 1078//1140 1111//1144 +f 1077//928 1111//1144 1110//930 +f 1068//1141 1005//1105 1087//1145 +f 1106//1142 1068//1141 1087//1145 +f 1106//1142 1087//1145 1120//1146 +f 1112//1143 1106//1142 1120//1146 +f 1112//1143 1120//1146 1146//1147 +f 1111//1144 1112//1143 1146//1147 +f 1111//1144 1146//1147 1145//1148 +f 1110//930 1111//1144 1145//1148 +f 1110//930 1145//1148 1144//932 +f 1087//1145 1005//1105 1107//1149 +f 1120//1146 1087//1145 1107//1149 +f 1120//1146 1107//1149 1140//1150 +f 1146//1147 1120//1146 1140//1150 +f 1146//1147 1140//1150 1174//1151 +f 1145//1148 1146//1147 1174//1151 +f 1145//1148 1174//1151 1180//1152 +f 1144//932 1145//1148 1180//1152 +f 1144//932 1180//1152 1179//934 +f 1107//1149 1005//1105 1121//1153 +f 1140//1150 1107//1149 1121//1153 +f 1140//1150 1121//1153 1154//1154 +f 1174//1151 1140//1150 1154//1154 +f 1174//1151 1154//1154 1188//1155 +f 1180//1152 1174//1151 1188//1155 +f 1180//1152 1188//1155 1211//1156 +f 1179//934 1180//1152 1211//1156 +f 1179//934 1211//1156 1210//936 +f 1121//1153 1005//1105 1141//1157 +f 1154//1154 1121//1153 1141//1157 +f 1154//1154 1141//1157 1175//1158 +f 1188//1155 1154//1154 1175//1158 +f 1188//1155 1175//1158 1206//1159 +f 1211//1156 1188//1155 1206//1159 +f 1211//1156 1206//1159 1226//1160 +f 1210//936 1211//1156 1226//1160 +f 1210//936 1226//1160 1212//938 +f 1141//1157 1005//1105 1155//1161 +f 1175//1158 1141//1157 1155//1161 +f 1175//1158 1155//1161 1187//1162 +f 1206//1159 1175//1158 1187//1162 +f 1206//1159 1187//1162 1205//1163 +f 1226//1160 1206//1159 1205//1163 +f 1226//1160 1205//1163 1213//1164 +f 1212//938 1226//1160 1213//1164 +f 1212//938 1213//1164 1181//940 +f 1155//1161 1005//1105 1153//1165 +f 1187//1162 1155//1161 1153//1165 +f 1187//1162 1153//1165 1173//1166 +f 1205//1163 1187//1162 1173//1166 +f 1205//1163 1173//1166 1186//1167 +f 1213//1164 1205//1163 1186//1167 +f 1213//1164 1186//1167 1182//1168 +f 1181//940 1213//1164 1182//1168 +f 1181//940 1182//1168 1147//942 +f 1153//1165 1005//1105 1139//1169 +f 1173//1166 1153//1165 1139//1169 +f 1173//1166 1139//1169 1152//1170 +f 1186//1167 1173//1166 1152//1170 +f 1186//1167 1152//1170 1172//1171 +f 1182//1168 1186//1167 1172//1171 +f 1182//1168 1172//1171 1148//1172 +f 1147//942 1182//1168 1148//1172 +f 1147//942 1148//1172 1113//944 +f 1139//1169 1005//1105 1119//1173 +f 1152//1170 1139//1169 1119//1173 +f 1152//1170 1119//1173 1138//1174 +f 1172//1171 1152//1170 1138//1174 +f 1172//1171 1138//1174 1149//1175 +f 1148//1172 1172//1171 1149//1175 +f 1148//1172 1149//1175 1114//1176 +f 1113//944 1148//1172 1114//1176 +f 1113//944 1114//1176 1081//946 +f 1119//1173 1005//1105 1105//1177 +f 1138//1174 1119//1173 1105//1177 +f 1138//1174 1105//1177 1118//1178 +f 1149//1175 1138//1174 1118//1178 +f 1149//1175 1118//1178 1115//1179 +f 1114//1176 1149//1175 1115//1179 +f 1114//1176 1115//1179 1082//1180 +f 1081//946 1114//1176 1082//1180 +f 1081//946 1082//1180 1046//948 +f 1105//1177 1005//1105 1086//1181 +f 1118//1178 1105//1177 1086//1181 +f 1118//1178 1086//1181 1104//1182 +f 1115//1179 1118//1178 1104//1182 +f 1115//1179 1104//1182 1083//1183 +f 1082//1180 1115//1179 1083//1183 +f 1082//1180 1083//1183 1047//1184 +f 1046//948 1082//1180 1047//1184 +f 1046//948 1047//1184 1016//950 +f 1086//1181 1005//1105 1067//1185 +f 1104//1182 1086//1181 1067//1185 +f 1104//1182 1067//1185 1084//1186 +f 1083//1183 1104//1182 1084//1186 +f 1083//1183 1084//1186 1048//1187 +f 1047//1184 1083//1183 1048//1187 +f 1047//1184 1048//1187 1017//1188 +f 1016//950 1047//1184 1017//1188 +f 1016//950 1017//1188 988//952 +f 1067//1185 1005//1105 1051//1189 +f 1084//1186 1067//1185 1051//1189 +f 1084//1186 1051//1189 1049//1190 +f 1048//1187 1084//1186 1049//1190 +f 1048//1187 1049//1190 1018//1191 +f 1017//1188 1048//1187 1018//1191 +f 1017//1188 1018//1191 989//1192 +f 988//952 1017//1188 989//1192 +f 988//952 989//1192 962//954 +f 1051//1189 1005//1105 1034//1193 +f 1049//1190 1051//1189 1034//1193 +f 1049//1190 1034//1193 1019//1194 +f 1018//1191 1049//1190 1019//1194 +f 1018//1191 1019//1194 990//1195 +f 989//1192 1018//1191 990//1195 +f 989//1192 990//1195 963//1196 +f 962//954 989//1192 963//1196 +f 962//954 963//1196 942//956 +f 1034//1193 1005//1105 1020//1197 +f 1019//1194 1034//1193 1020//1197 +f 1019//1194 1020//1197 991//1198 +f 990//1195 1019//1194 991//1198 +f 990//1195 991//1198 964//1199 +f 963//1196 990//1195 964//1199 +f 963//1196 964//1199 943//1200 +f 942//956 963//1196 943//1200 +f 942//956 943//1200 928//958 +f 1020//1197 1005//1105 993//1104 +f 991//1198 1020//1197 993//1104 +f 991//1198 993//1104 966//1107 +f 964//1199 991//1198 966//1107 +f 964//1199 966//1107 945//1109 +f 943//1200 964//1199 945//1109 +f 943//1200 945//1109 930//1111 +f 928//958 943//1200 930//1111 +f 928//958 930//1111 921//913 +f 1151//1043 1137//1049 1150//1201 +f 1142//995 1143//1202 1122//989 +f 1053//971 1089//977 1069//1203 +f 1122//989 1123//1204 1109//983 +f 1096//1061 1103//1205 1117//1055 +f 1171//1037 1170//1206 1184//1031 +f 1191//1013 1209//1019 1190//1207 +f 1036//970 1053//971 1070//1208 +f 1036//970 1070//1208 1037//1103 +f 1203//1025 1202//1209 1209//1019 +f 1066//1067 1085//1210 1096//1061 +f 1050//1073 1076//1211 1066//1067 +f 1184//1031 1183//1212 1203//1025 +f 1041//1079 1040//1085 1075//1213 +f 1171//1037 1151//1043 1170//1206 +f 1157//1001 1158//1214 1142//995 +f 1137//1049 1117//1055 1136//1215 +f 1038//1097 1072//1216 1039//1091 +f 1178//1007 1191//1013 1177//1217 +f 1089//977 1109//983 1088//1218 +f 1037//1103 1071//1219 1038//1097 +f 1050//1073 1041//1079 1076//1211 +f 1157//1001 1178//1007 1158//1214 +f 1040//1085 1039//1091 1074//1220 +f 1170//1206 1150//1201 452//1221 +f 1264//1222 1071//1219 1263//1223 +f 1261//1224 1262//1225 1076//1211 +f 1085//1210 1076//1211 1262//1225 +f 1190//1207 1208//1226 405//1227 +f 509//176 526//519 1260//1228 +f 1260//1228 526//519 556//523 +f 167//201 556//523 595//202 +f 595//202 621//526 1255//200 +f 172//192 163//182 1254//199 +f 8//49 18//42 3//1229 +f 3//1229 18//42 1288//1230 +f 15//75 7//66 1240//82 +f 1250//50 8//49 3//1229 +f 1//32 1283//40 566//33 +f 593//3 566//33 9//41 +f 19//1231 20//34 33//25 +f 1243//2 636//89 593//3 +f 64//18 40//6 36//17 +f 1244//24 64//18 36//17 +f 641//579 614//582 1237//1232 +f 1250//50 1239//1233 4//48 +f 7//66 4//48 1239//1233 +f 5//74 14//73 11//81 +f 1240//82 7//66 1239//1233 +f 1//32 553//31 565//56 +f 593//3 9//41 1289//83 +f 18//42 20//34 1288//1230 +f 40//6 27//5 1252//16 +f 1249//58 6//65 565//56 +f 14//73 15//75 11//81 +f 592//57 1234//130 1233//58 +f 1237//1232 614//582 588//586 +f 1237//1232 588//586 605//592 +f 539//175 159//177 1259//1234 +f 164//257 1257//1235 168//251 +f 509//176 1256//1236 159//177 +f 1258//250 585//249 1259//1234 +f 169//1237 164//257 174//242 +f 191//236 208//230 185//1238 +f 1290//1239 207//229 640//777 +f 621//526 1292//1240 1255//200 +f 163//182 160//178 157//180 +f 1284//1241 1292//1240 648//227 +f 1252//16 27//5 12//95 +f 119//124 116//129 104//161 +f 116//129 88//135 1242//136 +f 87//159 666//713 715//160 +f 87//159 1241//1242 666//713 +f 1253//1243 47//150 631//152 +f 631//152 666//713 1253//1243 +f 86//142 74//144 60//143 +f 640//777 1291//1244 1290//1239 +f 1291//1244 640//777 613//248 +f 208//230 219//220 200//1245 +f 665//778 640//777 207//229 +f 1285//226 200//1245 219//220 +f 648//227 207//229 1284//1241 +f 691//228 665//778 207//229 +f 605//592 1236//1246 1245//1246 +f 1235//151 605//592 631//152 +f 1248//145 48//153 37//167 +f 667//708 1251//1247 1247//158 +f 605//592 1235//151 1236//1246 +f 641//579 1238//1248 1246//1249 +f 641//579 1237//1232 1238//1248 +f 404//412 391//405 1267//904 +f 1265//911 453//433 436//426 +f 328//351 327//350 331//910 +f 443//445 462//439 469//1250 +f 342//370 1275//1251 344//1252 +f 342//370 334//363 1275//1251 +f 372//480 385//473 384//906 +f 351//377 1271//1253 361//384 +f 351//377 350//1254 1271//1253 +f 337//1255 335//508 345//501 +f 384//906 385//473 396//466 +f 361//384 368//1256 369//391 +f 361//384 1271//1253 368//1256 +f 352//494 1276//1257 346//908 +f 397//1258 396//466 411//459 +f 342//370 350//1254 351//377 +f 342//370 344//1252 350//1254 +f 380//398 369//391 368//1256 +f 334//363 328//351 332//1259 +f 404//412 418//1260 419//419 +f 404//412 1268//905 418//1260 +f 426//452 1286//1261 1282//1262 +f 1282//1262 411//459 426//452 +f 352//494 362//487 1277//1263 +f 1277//1263 1276//1257 352//494 +f 391//405 380//398 381//1264 +f 426//452 443//445 444//1265 +f 444//1265 1286//1261 426//452 +f 362//487 372//480 373//907 +f 373//907 1277//1263 362//487 +f 1202//1209 1183//1212 1270//1266 +f 1116//1267 428//1268 1136//1215 +f 428//1268 1287//1269 1136//1215 +f 1073//1270 353//1271 1074//1220 +f 353//1271 363//1272 1074//1220 +f 353//1271 1073//1270 1279//1273 +f 1070//1208 1069//1203 1263//1223 +f 1274//1274 1069//1203 1088//1218 +f 1177//1217 1273//1275 1272//1276 +f 1272//1276 1158//1214 1177//1217 +f 428//1268 1116//1267 427//1277 +f 1088//1218 1108//1278 343//1279 +f 1103//1205 1085//1210 1278//1280 +f 1108//1278 1123//1204 1280//1281 +f 1123//1204 1281//1282 1280//1281 +f 1143//1202 1158//1214 360//1283 +f 1158//1214 1272//1276 360//1283 +f 1075//1213 1261//1224 1076//1211 +f 1085//1210 1262//1225 1278//1280 +f 1123//1204 1143//1202 1281//1282 +f 1143//1202 360//1283 1281//1282 +f 1074//1220 363//1272 1075//1213 +f 363//1272 1261//1224 1075//1213 +f 1270//1266 1183//1212 452//1221 +f 1266//1284 1150//1201 1136//1215 +f 1273//1275 1177//1217 1190//1207 +f 1208//1226 1202//1209 406//1285 +f 1202//1209 1269//1286 406//1285 +f 1072//1216 1071//1219 1264//1222 +f 1241//1242 1253//1243 666//713 +f 71//137 86//142 60//143 +f 88//135 86//142 71//137 +f 1245//1246 1237//1232 605//592 +f 119//124 104//161 90//119 +f 667//708 1246//1249 1251//1247 +f 621//526 648//227 1292//1240 +f 208//230 200//1245 185//1238 +f 174//242 191//236 169//1237 +f 1258//250 1291//1244 613//248 +f 1244//24 19//1231 33//25 +f 1288//1230 20//34 19//1231 +f 199//208 182//198 178//1287 +f 206//1288 218//214 190//1289 +f 1260//1228 556//523 167//201 +f 157//180 1254//199 163//182 +f 178//1287 182//198 1254//199 +f 218//214 206//1288 1285//226 +f 161//258 1257//1235 158//179 +f 324//345 312//274 323//336 +f 303//317 302//323 316//338 +f 305//305 304//311 318//340 +f 304//311 303//317 317//339 +f 322//347 309//281 321//341 +f 320//346 307//293 319//342 +f 301//329 311//335 314//344 +f 302//323 301//329 315//337 +f 311//335 312//274 313//343 +f 319//342 306//299 318//340 +f 321//341 308//287 320//346 +f 323//336 310//275 322//347 +f 418//1260 435//909 419//419 +f 337//1255 331//910 335//508 +f 469//1250 462//439 1265//911 +f 1137//1049 1136//1215 1150//1201 +f 1143//1202 1123//1204 1122//989 +f 1089//977 1088//1218 1069//1203 +f 1123//1204 1108//1278 1109//983 +f 1103//1205 1116//1267 1117//1055 +f 1170//1206 1183//1212 1184//1031 +f 1209//1019 1208//1226 1190//1207 +f 1053//971 1069//1203 1070//1208 +f 1070//1208 1071//1219 1037//1103 +f 1202//1209 1208//1226 1209//1019 +f 1085//1210 1103//1205 1096//1061 +f 1076//1211 1085//1210 1066//1067 +f 1183//1212 1202//1209 1203//1025 +f 1040//1085 1074//1220 1075//1213 +f 1151//1043 1150//1201 1170//1206 +f 1158//1214 1143//1202 1142//995 +f 1117//1055 1116//1267 1136//1215 +f 1072//1216 1073//1270 1039//1091 +f 1191//1013 1190//1207 1177//1217 +f 1109//983 1108//1278 1088//1218 +f 1071//1219 1072//1216 1038//1097 +f 1041//1079 1075//1213 1076//1211 +f 1178//1007 1177//1217 1158//1214 +f 1039//1091 1073//1270 1074//1220 +f 1150//1201 1266//1284 452//1221 +f 1071//1219 1070//1208 1263//1223 +f 1208//1226 406//1285 405//1227 +f 1256//1236 509//176 1260//1228 +f 1257//1235 161//258 168//251 +f 585//249 539//175 1259//1234 +f 715//160 667//708 1247//158 +f 667//708 641//579 1246//1249 +f 435//909 1265//911 436//426 +f 332//1259 328//351 331//910 +f 444//1265 443//445 469//1250 +f 346//908 337//1255 345//501 +f 397//1258 384//906 396//466 +f 1282//1262 397//1258 411//459 +f 381//1264 380//398 368//1256 +f 1275//1251 334//363 332//1259 +f 1267//904 391//405 381//1264 +f 1269//1286 1202//1209 1270//1266 +f 1073//1270 1072//1216 1279//1273 +f 1069//1203 1274//1274 1263//1223 +f 343//1279 1274//1274 1088//1218 +f 1116//1267 1103//1205 427//1277 +f 1108//1278 1280//1281 343//1279 +f 427//1277 1103//1205 1278//1280 +f 1183//1212 1170//1206 452//1221 +f 1287//1269 1266//1284 1136//1215 +f 405//1227 1273//1275 1190//1207 +f 1279//1273 1072//1216 1264//1222 +f 191//236 185//1238 169//1237 +f 190//1289 199//208 178//1287 +f 218//214 199//208 190//1289 diff --git a/L00(old)/src/GLSL.cpp b/L00(old)/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L00(old)/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L00(old)/src/GLSL.h b/L00(old)/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L00(old)/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L00(old)/src/MatrixStack.cpp b/L00(old)/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/L00(old)/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/L00(old)/src/MatrixStack.h b/L00(old)/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/L00(old)/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/L00(old)/src/Program.cpp b/L00(old)/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/L00(old)/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/L00(old)/src/Program.h b/L00(old)/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/L00(old)/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/L00(old)/src/Shape.cpp b/L00(old)/src/Shape.cpp new file mode 100644 index 0000000..a559ba5 --- /dev/null +++ b/L00(old)/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("vertPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("vertNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("vertTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/L00(old)/src/Shape.h b/L00(old)/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/L00(old)/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/L00(old)/src/main.cpp b/L00(old)/src/main.cpp new file mode 100644 index 0000000..17dd855 --- /dev/null +++ b/L00(old)/src/main.cpp @@ -0,0 +1,152 @@ +#define _USE_MATH_DEFINES +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Program.h" +#include "Shape.h" + +using namespace std; + +GLFWwindow *window; // Main application window +string RES_DIR = ""; // Where data files live +shared_ptr prog; +shared_ptr shape; + +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +static void init() +{ + GLSL::checkVersion(); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // Initialize mesh. + shape = make_shared(); + shape->loadMesh(RES_DIR + "teapot.obj"); + shape->init(); + + // Initialize the GLSL program. + prog = make_shared(); + prog->setVerbose(false); // Set this to true when debugging. + prog->setShaderNames(RES_DIR + "simple_vert.glsl", RES_DIR + "simple_frag.glsl"); + prog->init(); + prog->addUniform("P"); + prog->addUniform("MV"); + prog->addAttribute("vertPos"); + prog->addAttribute("vertNor"); + + // If there were any OpenGL errors, this will print something. + // You can intersperse this line in your code to find the exact location + // of your OpenGL error. + GLSL::checkError(GET_FILE_LINE); +} + +static void render() +{ + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + glViewport(0, 0, width, height); + + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Create matrix stacks. + auto P = make_shared(); + auto MV = make_shared(); + // Apply projection. + P->pushMatrix(); + P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f)); + // Apply camera transform. + MV->pushMatrix(); + MV->translate(glm::vec3(0, -0.5, -3)); + + // Draw mesh using GLSL. + prog->bind(); + glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]); + glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]); + shape->draw(prog); + prog->unbind(); + + // Pop matrix stacks. + MV->popMatrix(); + P->popMatrix(); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RES_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L00(old)/src/tiny_obj_loader.h b/L00(old)/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L00(old)/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L00.zip b/L00.zip new file mode 100644 index 0000000000000000000000000000000000000000..5d88ccce80afb5bd891423f4b548e461e55b0466 GIT binary patch literal 58868 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 GXa57|nkz&A literal 0 HcmV?d00001 diff --git a/L00/.gitignore b/L00/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L00/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L00/CMakeLists.txt b/L00/CMakeLists.txt new file mode 100644 index 0000000..f6a10e7 --- /dev/null +++ b/L00/CMakeLists.txt @@ -0,0 +1,118 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L00) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Use glob to get the list of all source files. +FILE(GLOB_RECURSE SOURCES "src/*.cpp") + +# We don't really need to include header and resource files to build, but it's +# nice to have them show up in IDEs. +FILE(GLOB_RECURSE HEADERS "src/*.h") +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L00/resources/simple_frag.glsl b/L00/resources/simple_frag.glsl new file mode 100644 index 0000000..fc76efb --- /dev/null +++ b/L00/resources/simple_frag.glsl @@ -0,0 +1,11 @@ +#version 120 + +varying vec3 vNor; + +void main() +{ + vec3 normal = normalize(vNor); + // Map normal in the range [-1, 1] to color in range [0, 1]; + vec3 color = 0.5*normal + 0.5; + gl_FragColor = vec4(color, 1.0); +} diff --git a/L00/resources/simple_vert.glsl b/L00/resources/simple_vert.glsl new file mode 100644 index 0000000..5ace583 --- /dev/null +++ b/L00/resources/simple_vert.glsl @@ -0,0 +1,12 @@ +#version 120 +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vNor; + +void main() +{ + gl_Position = P * MV * aPos; + vNor = (MV * vec4(aNor, 0.0)).xyz; +} diff --git a/L00/resources/teapot.obj b/L00/resources/teapot.obj new file mode 100644 index 0000000..6fed453 --- /dev/null +++ b/L00/resources/teapot.obj @@ -0,0 +1,5049 @@ +# Blender v2.65 (sub 0) OBJ File +# www.blender.org +o teapot.005 +v -0.498530 0.712498 -0.039883 +v -0.501666 0.699221 -0.063813 +v -0.501255 0.717792 0.000000 +v -0.624036 0.711938 -0.039883 +v -0.526706 0.651362 -0.039883 +v -0.508714 0.682112 -0.071712 +v -0.622039 0.698704 -0.063813 +v -0.624834 0.717232 0.000000 +v -0.498530 0.712498 0.039883 +v -0.638129 0.287158 0.000000 +v -0.517593 0.664661 -0.063813 +v -0.534329 0.646030 0.000000 +v -0.614850 0.651067 -0.039883 +v -0.616848 0.664299 -0.063813 +v -0.619445 0.681503 -0.071790 +v -0.741245 0.707456 -0.039883 +v -0.744483 0.712577 0.000000 +v -0.624036 0.711938 0.039883 +v -0.501667 0.699221 0.063813 +v -0.622039 0.698704 0.063813 +v -0.712095 0.661370 -0.063813 +v -0.733150 0.694655 -0.063813 +v -0.741245 0.707456 0.039883 +v -0.733150 0.694655 0.063813 +v -0.631184 0.277569 -0.039883 +v -0.526706 0.651362 0.039883 +v -0.614053 0.645774 0.000000 +v -0.704000 0.648569 -0.039883 +v -0.722621 0.678012 -0.071790 +v -0.832523 0.695296 -0.039883 +v -0.837545 0.699948 0.000000 +v -0.832523 0.695296 0.039883 +v -0.619445 0.681503 0.071790 +v -0.508714 0.682112 0.071712 +v -0.722621 0.678012 0.071790 +v -0.517593 0.664661 0.063813 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.710066 0.328372 0.000000 +v -0.614850 0.651067 0.039883 +v -0.787321 0.653419 -0.063813 +v -0.803644 0.668539 -0.071790 +v -0.819967 0.683663 -0.063813 +v -0.819967 0.683663 0.063813 +v -0.803644 0.668539 0.071790 +v -0.711425 0.307332 -0.063813 +v -0.615553 0.216807 -0.063813 +v -0.712688 0.287795 -0.071790 +v -0.631184 0.277569 0.039883 +v -0.710455 0.322361 -0.039883 +v -0.710455 0.322361 0.039883 +v -0.700762 0.643448 0.000000 +v -0.774766 0.641786 -0.039883 +v -0.897800 0.671612 -0.039883 +v -0.904015 0.675354 0.000000 +v -0.897800 0.671612 0.039883 +v -0.882265 0.662257 0.063813 +v -0.712095 0.661370 0.063813 +v -0.787321 0.653419 0.063813 +v -0.608884 0.198682 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.766936 0.377559 0.000000 +v -0.769651 0.372307 0.039883 +v -0.616848 0.664299 0.063813 +v -0.704000 0.648569 0.039883 +v -0.841868 0.637931 -0.063813 +v -0.862065 0.650094 -0.071790 +v -0.882265 0.662257 -0.063813 +v -0.862065 0.650094 0.071790 +v -0.841868 0.637931 0.063813 +v -0.611709 0.194244 0.000000 +v -0.776434 0.359177 -0.063813 +v -0.769651 0.372307 -0.039883 +v -0.713952 0.268259 -0.063813 +v -0.711425 0.307332 0.063813 +v -0.776434 0.359177 0.063813 +v -0.769743 0.637131 0.000000 +v -0.826329 0.628576 -0.039883 +v -0.937016 0.632565 -0.039883 +v -0.943899 0.634805 0.000000 +v -0.937016 0.632565 0.039883 +v -0.919812 0.626965 0.063813 +v -0.897443 0.619684 0.071790 +v -0.774766 0.641786 0.039883 +v -0.826329 0.628576 0.039883 +v -0.714922 0.253231 -0.039883 +v -0.608883 0.198681 0.039883 +v -0.715311 0.247220 0.000000 +v -0.785253 0.342107 -0.071790 +v -0.619922 0.238069 0.071790 +v -0.712688 0.287795 0.071790 +v -0.809626 0.430737 0.000000 +v -0.814205 0.426194 0.039883 +v -0.825653 0.414838 0.063813 +v -0.875076 0.612403 -0.063813 +v -0.897443 0.619684 -0.071790 +v -0.919812 0.626965 -0.063813 +v -0.875076 0.612403 0.063813 +v -0.857869 0.606800 0.039883 +v -0.794072 0.325038 -0.063813 +v -0.800855 0.311909 -0.039883 +v -0.825653 0.414838 -0.063813 +v -0.814205 0.426194 -0.039883 +v -0.615480 0.216617 0.063578 +v -0.785253 0.342107 0.071790 +v -0.840534 0.400078 0.071790 +v -0.820114 0.624834 0.000000 +v -0.857869 0.606800 -0.039883 +v -0.950104 0.574316 -0.039883 +v -0.957194 0.574316 0.000000 +v -0.950104 0.574316 0.039883 +v -0.932377 0.574316 0.063813 +v -0.909334 0.574316 0.071790 +v -0.886292 0.574316 0.063813 +v -0.850987 0.604560 0.000000 +v -0.714922 0.253231 0.039883 +v -0.803571 0.306656 0.000000 +v -0.840534 0.400078 -0.071790 +v -0.713952 0.268259 0.063813 +v -0.794072 0.325038 0.063813 +v -0.839022 0.483916 0.000000 +v -0.844976 0.480304 0.039883 +v -0.859854 0.471278 0.063813 +v -0.879202 0.459542 0.071790 +v -0.886292 0.574316 -0.063813 +v -0.909334 0.574316 -0.071790 +v -0.932377 0.574316 -0.063813 +v -0.868564 0.574316 0.039883 +v -0.861474 0.574316 0.000000 +v -0.855419 0.385315 -0.063813 +v -0.866867 0.373960 -0.039883 +v -0.859854 0.471278 -0.063813 +v -0.844976 0.480304 -0.039883 +v -0.855419 0.385315 0.063813 +v -0.898547 0.447807 0.063813 +v -0.868564 0.574316 -0.039883 +v -0.941014 0.505765 -0.039883 +v -0.947813 0.503580 0.000000 +v -0.941014 0.505765 0.039883 +v -0.924011 0.511234 0.063813 +v -0.901913 0.518343 0.071790 +v -0.879811 0.525448 0.063813 +v -0.862808 0.530917 0.039883 +v -0.800855 0.311909 0.039883 +v -0.871445 0.369416 0.000000 +v -0.879202 0.459542 -0.071790 +v -0.866867 0.373960 0.039883 +v -0.856009 0.533103 0.000000 +v -0.879811 0.525448 -0.063813 +v -0.901913 0.518343 -0.071790 +v -0.924011 0.511234 -0.063813 +v -0.862808 0.530917 -0.039883 +v -0.898547 0.447807 -0.063813 +v -0.913428 0.438781 -0.039883 +v -0.913428 0.438781 0.039883 +v -0.919378 0.435169 0.000000 +v 0.600960 0.444810 0.085753 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.656890 0.471064 0.000000 +v 0.661223 0.454734 -0.083705 +v 0.730696 0.501576 -0.073611 +v 0.661223 0.454734 0.083705 +v 0.605101 0.399712 -0.137265 +v 0.746455 0.470391 -0.117778 +v 0.724395 0.514048 0.000000 +v 0.605100 0.399712 0.137265 +v 0.672055 0.413907 -0.133928 +v 0.613258 0.341675 -0.154354 +v 0.786583 0.544847 -0.096783 +v 0.768856 0.565896 -0.060489 +v 0.672055 0.413907 0.133928 +v 0.730696 0.501576 0.073611 +v 0.686135 0.360830 -0.150669 +v 0.809626 0.517481 -0.108881 +v 0.766935 0.429850 -0.132501 +v 0.761767 0.574316 0.000000 +v 0.613258 0.341675 0.154354 +v 0.813417 0.626247 -0.075788 +v 0.839021 0.611098 -0.085261 +v 0.793721 0.637899 -0.047367 +v 0.686135 0.360830 0.150669 +v 0.768856 0.565896 0.060489 +v 0.746455 0.470391 0.117778 +v 0.619427 0.283145 -0.137236 +v 0.864627 0.595949 -0.075788 +v 0.832669 0.490118 -0.096783 +v 0.787419 0.389310 -0.117778 +v 0.785843 0.642561 0.000000 +v 0.619427 0.283145 0.137236 +v 0.700219 0.307756 -0.133928 +v 0.847933 0.703560 -0.059638 +v 0.879938 0.698065 -0.067092 +v 0.911944 0.692571 -0.059638 +v 0.823314 0.707784 -0.037273 +v 0.766935 0.429850 0.132501 +v 0.793721 0.637899 0.047367 +v 0.786583 0.544847 0.096783 +v 0.700219 0.307756 0.133928 +v 0.617684 0.235930 -0.085941 +v 0.936563 0.688344 -0.037273 +v 0.884319 0.584297 -0.047367 +v 0.850396 0.469070 -0.060489 +v 0.803175 0.358128 -0.073611 +v 0.813468 0.709475 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v 0.711051 0.266929 -0.083705 +v 0.911107 0.765755 -0.053178 +v 0.957193 0.765755 -0.059825 +v 1.003279 0.765755 -0.053178 +v 1.038733 0.765755 -0.033236 +v 0.875654 0.765755 -0.033236 +v 0.809626 0.517481 0.108881 +v 0.787419 0.389310 0.117778 +v 0.823314 0.707784 0.037273 +v 0.813417 0.626247 0.075788 +v 0.711051 0.266929 0.083705 +v 0.715384 0.250599 0.000000 +v 1.052913 0.765755 0.000000 +v 0.946409 0.686653 0.000000 +v 0.892200 0.579635 0.000000 +v 0.857486 0.460650 0.000000 +v 0.809479 0.345652 0.000000 +v 0.861474 0.765755 0.000000 +v 0.929990 0.776479 -0.051602 +v 0.979075 0.777181 -0.058052 +v 1.028157 0.777879 -0.051602 +v 1.065915 0.778419 -0.032251 +v 1.081016 0.778632 0.000000 +v 0.892235 0.775943 -0.032251 +v 0.839021 0.611098 0.085261 +v 0.832669 0.490118 0.096783 +v 0.803175 0.358128 0.073611 +v 0.875654 0.765755 0.033236 +v 0.847933 0.703560 0.059638 +v 1.065915 0.778419 0.032174 +v 1.038733 0.765755 0.033236 +v 0.936563 0.688344 0.037273 +v 0.884319 0.584297 0.047367 +v 0.850396 0.469070 0.060489 +v 0.877131 0.775726 0.000000 +v 0.943713 0.783087 -0.047663 +v 0.992645 0.784366 -0.053621 +v 1.041577 0.785649 -0.047663 +v 1.079216 0.786631 -0.029789 +v 1.094273 0.787027 0.000000 +v 1.079216 0.786631 0.029174 +v 0.906073 0.782101 -0.029789 +v 0.879938 0.698065 0.067092 +v 0.864627 0.595949 0.075788 +v 0.892235 0.775943 0.032236 +v 0.911107 0.765755 0.053178 +v 1.041577 0.785649 0.046875 +v 1.028157 0.777879 0.051503 +v 1.003279 0.765755 0.053178 +v 0.911944 0.692571 0.059638 +v 0.891016 0.781708 0.000000 +v 0.951249 0.785448 -0.042542 +v 0.997575 0.787068 -0.047860 +v 1.043903 0.788686 -0.042542 +v 1.079539 0.789934 -0.026589 +v 1.093795 0.790431 0.000000 +v 1.079539 0.789934 0.024511 +v 1.043903 0.788686 0.039883 +v 0.915613 0.784200 -0.026589 +v 0.957193 0.765755 0.059825 +v 0.906073 0.782101 0.029666 +v 0.929990 0.776479 0.051553 +v 0.997575 0.787068 0.045616 +v 0.992645 0.784366 0.052956 +v 0.979075 0.777181 0.057969 +v 0.901357 0.783702 0.000000 +v 0.951569 0.783431 -0.037421 +v 0.993532 0.785033 -0.042099 +v 1.035492 0.786631 -0.037421 +v 1.067772 0.787863 -0.023388 +v 1.080684 0.788354 0.000000 +v 1.067772 0.787863 0.018464 +v 1.035492 0.786631 0.031119 +v 0.993532 0.785033 0.036781 +v 0.919292 0.782200 -0.023388 +v 0.915613 0.784200 0.026173 +v 0.943713 0.783087 0.047269 +v 0.951569 0.783431 0.034270 +v 0.951249 0.785448 0.041213 +v 0.906379 0.781708 0.000000 +v 0.943653 0.776909 -0.033482 +v 0.980182 0.778010 -0.037667 +v 1.016712 0.779111 -0.033482 +v 1.044812 0.779957 -0.020926 +v 1.056052 0.780295 0.000000 +v 1.044812 0.779957 0.011310 +v 1.016712 0.779111 0.021172 +v 0.980182 0.778010 0.027281 +v 0.943653 0.776909 0.027327 +v 0.915553 0.776064 -0.020926 +v 0.919292 0.782200 0.022403 +v 0.915553 0.776064 0.019003 +v 0.904312 0.775726 0.000000 +v 0.926468 0.765755 -0.031906 +v 0.957193 0.765755 -0.035895 +v 0.987920 0.765755 -0.031906 +v 1.011552 0.765755 -0.019942 +v 1.021006 0.765755 0.000000 +v 1.011552 0.765755 0.003324 +v 0.987920 0.765755 0.010635 +v 0.957193 0.765755 0.017947 +v 0.926468 0.765755 0.021271 +v 0.902834 0.765755 0.016618 +v 0.902834 0.765755 -0.019942 +v 0.893380 0.765755 0.000000 +v 0.886428 0.750924 -0.019014 +v 0.908324 0.750924 -0.030099 +v 0.936793 0.750924 -0.033795 +v 0.965261 0.750924 -0.030099 +v 0.987158 0.750924 -0.019014 +v 0.995918 0.750924 -0.000537 +v 0.987158 0.750924 0.002542 +v 0.965261 0.750924 0.009317 +v 0.936793 0.750924 0.016092 +v 0.908324 0.750924 0.019171 +v 0.886428 0.750924 0.014860 +v 0.877668 0.750924 -0.000537 +v 0.936793 0.750924 -0.007312 +v 0.440746 0.783205 0.000000 +v 0.446690 0.765755 0.000000 +v 0.430973 0.765755 0.119945 +v 0.425236 0.783205 0.118348 +v 0.425236 0.783205 -0.118348 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 0.121642 +v 0.441668 0.793673 0.000000 +v 0.386470 0.765755 0.226985 +v 0.430973 0.765755 -0.119945 +v 0.426127 0.793673 -0.118596 +v 0.437073 0.750009 -0.121642 +v 0.426127 0.793673 0.118596 +v 0.381327 0.783205 0.223964 +v 0.381327 0.783205 -0.223964 +v 0.382124 0.793673 -0.224433 +v 0.317150 0.765755 0.317150 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 0.321639 +v 0.386470 0.765755 -0.226985 +v 0.391939 0.750009 -0.230197 +v 0.447686 0.797164 0.000000 +v 0.431936 0.797164 -0.120212 +v 0.387332 0.797164 -0.227491 +v 0.230197 0.750009 0.391940 +v 0.226984 0.765755 0.386470 +v 0.317150 0.765755 -0.317150 +v 0.321638 0.750009 -0.321639 +v 0.431936 0.797164 0.120212 +v 0.382124 0.793673 0.224433 +v 0.312929 0.783205 0.312929 +v 0.313584 0.793673 -0.313584 +v 0.312929 0.783205 -0.312929 +v 0.317858 0.797164 -0.317858 +v 0.121642 0.750009 0.437072 +v 0.119944 0.765755 0.430973 +v 0.226984 0.765755 -0.386470 +v 0.230197 0.750009 -0.391940 +v 0.457031 0.793673 0.000000 +v 0.440950 0.793673 -0.122721 +v 0.395416 0.793673 -0.232239 +v 0.324491 0.793673 -0.324492 +v -0.000000 0.750009 0.453012 +v -0.000000 0.765755 0.446690 +v 0.223963 0.783205 0.381327 +v 0.223963 0.783205 -0.381327 +v 0.119944 0.765755 -0.430973 +v 0.121642 0.750009 -0.437072 +v 0.440950 0.793673 0.122721 +v 0.387332 0.797164 0.227491 +v 0.313584 0.793673 0.313584 +v 0.227491 0.797164 -0.387332 +v 0.224433 0.793673 -0.382125 +v 0.232239 0.793673 -0.395417 +v -0.119945 0.765755 0.430973 +v -0.121642 0.750009 0.437072 +v 0.118348 0.783205 0.425237 +v 0.118348 0.783205 -0.425237 +v -0.000000 0.750009 -0.453012 +v -0.000000 0.765755 -0.446690 +v 0.467924 0.783205 0.000000 +v 0.451460 0.783205 -0.125646 +v 0.404842 0.783205 -0.237775 +v 0.332226 0.783205 -0.332226 +v 0.237775 0.783205 -0.404842 +v -0.226985 0.765755 0.386470 +v -0.000000 0.783205 0.440746 +v 0.224433 0.793673 0.382125 +v 0.118596 0.793673 -0.426127 +v -0.000000 0.783205 -0.440746 +v -0.119945 0.765755 -0.430973 +v -0.121642 0.750009 -0.437072 +v 0.451460 0.783205 0.125646 +v 0.395416 0.793673 0.232239 +v 0.317858 0.797164 0.317858 +v 0.122721 0.793673 -0.440950 +v 0.120212 0.797164 -0.431937 +v 0.125646 0.783205 -0.451460 +v -0.317150 0.765755 0.317150 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.118348 0.783205 0.425237 +v 0.118596 0.793673 0.426127 +v -0.000000 0.793673 -0.441668 +v -0.118348 0.783205 -0.425237 +v -0.226985 0.765755 -0.386470 +v 0.478596 0.765755 0.000000 +v 0.461756 0.765755 -0.128512 +v 0.414076 0.765755 -0.243198 +v 0.339803 0.765755 -0.339804 +v 0.243198 0.765755 -0.414076 +v 0.128512 0.765755 -0.461757 +v -0.391940 0.750009 0.230197 +v -0.386470 0.765755 0.226985 +v -0.223964 0.783205 0.381327 +v -0.000000 0.793673 0.441668 +v 0.227491 0.797164 0.387332 +v -0.000000 0.797164 -0.447686 +v -0.118596 0.793673 -0.426127 +v -0.223964 0.783205 -0.381327 +v -0.317150 0.765755 -0.317150 +v -0.230198 0.750009 -0.391939 +v -0.321639 0.750009 -0.321639 +v 0.461756 0.765755 0.128512 +v 0.404842 0.783205 0.237775 +v 0.324491 0.793673 0.324492 +v -0.000000 0.783205 -0.467924 +v -0.000000 0.793673 -0.457031 +v -0.000000 0.765755 -0.478597 +v -0.437073 0.750009 0.121642 +v -0.430974 0.765755 0.119945 +v -0.312929 0.783205 0.312929 +v -0.118596 0.793673 0.426127 +v 0.120212 0.797164 0.431937 +v -0.120212 0.797164 -0.431937 +v -0.224433 0.793673 -0.382125 +v -0.312929 0.783205 -0.312929 +v -0.386470 0.765755 -0.226985 +v -0.391940 0.750009 -0.230197 +v 0.518110 0.682112 0.000000 +v 0.499881 0.682112 -0.139122 +v 0.448260 0.682112 -0.263277 +v 0.367859 0.682112 -0.367859 +v 0.263277 0.682112 -0.448260 +v 0.139122 0.682112 -0.499882 +v -0.000000 0.682112 -0.518110 +v -0.453012 0.750009 0.000000 +v -0.446690 0.765755 0.000000 +v -0.381327 0.783205 0.223964 +v -0.224433 0.793673 0.382125 +v -0.000000 0.797164 0.447686 +v 0.232239 0.793673 0.395417 +v -0.122721 0.793673 -0.440950 +v -0.227491 0.797164 -0.387332 +v -0.313584 0.793673 -0.313584 +v -0.381327 0.783205 -0.223964 +v -0.430974 0.765755 -0.119945 +v 0.499881 0.682112 0.139122 +v 0.414076 0.765755 0.243198 +v 0.332226 0.783205 0.332226 +v -0.128513 0.765755 -0.461757 +v -0.125646 0.783205 -0.451460 +v -0.139123 0.682112 -0.499882 +v -0.437073 0.750009 -0.121642 +v -0.425237 0.783205 0.118348 +v -0.313584 0.793673 0.313584 +v -0.120212 0.797164 0.431937 +v 0.122721 0.793673 0.440950 +v -0.232240 0.793673 -0.395417 +v -0.317859 0.797164 -0.317858 +v -0.382125 0.793673 -0.224433 +v -0.425237 0.783205 -0.118348 +v 0.555408 0.599133 0.000000 +v 0.535865 0.599133 -0.149137 +v 0.480530 0.599133 -0.282230 +v 0.394341 0.599133 -0.394341 +v 0.282230 0.599133 -0.480530 +v 0.149137 0.599133 -0.535866 +v -0.000000 0.599133 -0.555408 +v -0.149138 0.599133 -0.535866 +v -0.440746 0.783205 0.000000 +v -0.382125 0.793673 0.224433 +v -0.227491 0.797164 0.387332 +v -0.000000 0.793673 0.457031 +v 0.237775 0.783205 0.404842 +v -0.237775 0.783205 -0.404842 +v -0.324492 0.793673 -0.324492 +v -0.387332 0.797164 -0.227491 +v -0.426127 0.793673 -0.118596 +v 0.535865 0.599133 0.149137 +v 0.448260 0.682112 0.263277 +v 0.339803 0.765755 0.339804 +v -0.263278 0.682112 -0.448260 +v -0.243198 0.765755 -0.414076 +v -0.282230 0.599133 -0.480530 +v -0.426127 0.793673 0.118596 +v -0.317859 0.797164 0.317858 +v -0.122721 0.793673 0.440950 +v 0.125646 0.783205 0.451460 +v -0.332226 0.783205 -0.332226 +v -0.395417 0.793673 -0.232239 +v -0.431937 0.797164 -0.120212 +v -0.441668 0.793673 0.000000 +v 0.588275 0.517481 0.000000 +v 0.567578 0.517481 -0.157963 +v 0.508969 0.517485 -0.298931 +v 0.417675 0.517481 -0.417675 +v 0.298931 0.517485 -0.508969 +v 0.157963 0.517485 -0.567578 +v -0.000000 0.517481 -0.588275 +v -0.157963 0.517481 -0.567578 +v -0.298931 0.517485 -0.508969 +v -0.387332 0.797164 0.227491 +v -0.232240 0.793673 0.395417 +v -0.000000 0.783205 0.467924 +v 0.243198 0.765755 0.414076 +v -0.339804 0.765755 -0.339804 +v -0.404842 0.783205 -0.237775 +v -0.440950 0.793673 -0.122721 +v -0.447686 0.797164 0.000000 +v 0.567578 0.517485 0.157963 +v 0.480530 0.599133 0.282230 +v 0.367859 0.682112 0.367859 +v -0.394341 0.599133 -0.394341 +v -0.367859 0.682112 -0.367859 +v -0.417675 0.517481 -0.417675 +v -0.431937 0.797164 0.120212 +v -0.324492 0.793673 0.324492 +v -0.125646 0.783205 0.451460 +v 0.128512 0.765755 0.461757 +v -0.414076 0.765755 -0.243198 +v -0.451461 0.783205 -0.125646 +v -0.457031 0.793673 0.000000 +v 0.592873 0.437827 -0.165003 +v 0.531651 0.437827 -0.312254 +v 0.436292 0.437827 -0.436292 +v 0.312254 0.437827 -0.531651 +v 0.165003 0.437827 -0.592873 +v -0.000000 0.437827 -0.614496 +v -0.165004 0.437827 -0.592873 +v -0.312255 0.437827 -0.531651 +v -0.436292 0.437827 -0.436292 +v -0.395417 0.793673 0.232239 +v -0.237775 0.783205 0.404842 +v -0.000000 0.765755 0.478597 +v 0.263277 0.682112 0.448260 +v -0.448260 0.682112 -0.263277 +v -0.461757 0.765755 -0.128512 +v -0.467924 0.783205 0.000000 +v -0.440950 0.793673 0.122721 +v 0.592873 0.437827 0.165003 +v 0.508969 0.517485 0.298931 +v 0.394341 0.599133 0.394341 +v -0.508969 0.517485 -0.298931 +v -0.480530 0.599133 -0.282230 +v -0.531651 0.437827 -0.312254 +v -0.332226 0.783205 0.332226 +v -0.128513 0.765755 0.461757 +v 0.139122 0.682112 0.499882 +v -0.499882 0.682112 -0.139122 +v -0.478597 0.765755 0.000000 +v -0.451461 0.783205 0.125646 +v 0.546669 0.360830 -0.321075 +v 0.448614 0.360830 -0.448614 +v 0.321074 0.360830 -0.546669 +v 0.169664 0.360830 -0.609621 +v -0.000000 0.360830 -0.631850 +v -0.169664 0.360830 -0.609621 +v -0.321075 0.360830 -0.546669 +v -0.448615 0.360830 -0.448614 +v -0.546669 0.360830 -0.321075 +v -0.404842 0.783205 0.237775 +v -0.243198 0.765755 0.414076 +v -0.000000 0.682112 0.518110 +v 0.282230 0.599133 0.480530 +v -0.535866 0.599133 -0.149137 +v -0.461757 0.765755 0.128512 +v 0.531651 0.437827 0.312254 +v 0.417675 0.517481 0.417675 +v 0.609621 0.360830 -0.169664 +v -0.592873 0.437827 -0.165003 +v -0.567578 0.517485 -0.157963 +v -0.609621 0.360830 -0.169664 +v -0.339804 0.765755 0.339804 +v -0.139123 0.682112 0.499882 +v 0.149137 0.599133 0.535866 +v -0.555408 0.599133 0.000000 +v -0.499882 0.682112 0.139122 +v -0.414076 0.765755 0.243198 +v 0.609621 0.360830 0.169664 +v 0.552100 0.287158 -0.324265 +v 0.453072 0.287158 -0.453072 +v 0.324265 0.287158 -0.552100 +v 0.171349 0.287158 -0.615677 +v -0.000000 0.287158 -0.638129 +v -0.171350 0.287158 -0.615677 +v -0.324265 0.287158 -0.552100 +v -0.453072 0.287158 -0.453072 +v -0.552100 0.287158 -0.324265 +v -0.615677 0.287158 -0.171349 +v -0.263278 0.682112 0.448260 +v -0.000000 0.599133 0.555408 +v 0.298931 0.517485 0.508969 +v -0.588275 0.517481 0.000000 +v -0.448260 0.682112 0.263277 +v 0.546669 0.360830 0.321075 +v 0.436292 0.437827 0.436292 +v 0.615677 0.287158 -0.171349 +v -0.631850 0.360830 0.000000 +v -0.614496 0.437827 0.000000 +v -0.367859 0.682112 0.367859 +v -0.149138 0.599133 0.535866 +v 0.157963 0.517481 0.567578 +v -0.567578 0.517481 0.157963 +v -0.480530 0.599133 0.282230 +v 0.615677 0.287158 0.171349 +v 0.541877 0.221240 -0.318259 +v 0.444680 0.221240 -0.444680 +v 0.318259 0.221240 -0.541877 +v 0.168176 0.221240 -0.604276 +v -0.000000 0.221240 -0.626311 +v -0.168177 0.221240 -0.604276 +v -0.318259 0.221240 -0.541877 +v -0.444680 0.221240 -0.444680 +v -0.541877 0.221240 -0.318259 +v -0.604277 0.221240 -0.168176 +v -0.282230 0.599133 0.480530 +v -0.000000 0.517481 0.588275 +v 0.312254 0.437827 0.531651 +v -0.592873 0.437827 0.165003 +v -0.535866 0.599133 0.149137 +v -0.394341 0.599133 0.394341 +v 0.552100 0.287158 0.324265 +v 0.448614 0.360830 0.448614 +v 0.604276 0.221240 -0.168176 +v -0.615677 0.287158 0.171349 +v -0.609621 0.360830 0.169664 +v -0.157963 0.517485 0.567578 +v 0.165003 0.437827 0.592873 +v -0.531651 0.437827 0.312254 +v -0.508969 0.517485 0.298931 +v -0.417675 0.517481 0.417675 +v 0.604276 0.221240 0.168176 +v 0.516317 0.166623 -0.303247 +v 0.423705 0.166623 -0.423705 +v 0.303247 0.166623 -0.516317 +v 0.160243 0.166623 -0.575771 +v -0.000000 0.166623 -0.596769 +v -0.160244 0.166623 -0.575771 +v -0.303247 0.166623 -0.516317 +v -0.423705 0.166623 -0.423705 +v -0.516317 0.166623 -0.303247 +v -0.575771 0.166623 -0.160243 +v -0.298931 0.517485 0.508969 +v -0.000000 0.437827 0.614496 +v 0.321074 0.360830 0.546669 +v -0.546669 0.360830 0.321075 +v 0.541877 0.221240 0.318259 +v 0.453072 0.287158 0.453072 +v 0.575771 0.166623 -0.160243 +v -0.596769 0.166623 0.000000 +v -0.604277 0.221240 0.168176 +v -0.552100 0.287158 0.324265 +v -0.165004 0.437827 0.592873 +v 0.169664 0.360830 0.609621 +v -0.448615 0.360830 0.448614 +v -0.436292 0.437827 0.436292 +v -0.312255 0.437827 0.531651 +v 0.575771 0.166623 0.160243 +v 0.483086 0.122640 -0.283731 +v 0.396438 0.122640 -0.396438 +v 0.283731 0.122640 -0.483086 +v 0.149931 0.122640 -0.538718 +v -0.000000 0.122640 -0.558363 +v -0.149931 0.122640 -0.538718 +v -0.283731 0.122640 -0.483086 +v -0.396438 0.122640 -0.396438 +v -0.483087 0.122640 -0.283731 +v -0.538718 0.122640 -0.149931 +v -0.558363 0.122640 0.000000 +v -0.541877 0.221240 0.318259 +v -0.000000 0.360830 0.631850 +v 0.324265 0.287158 0.552100 +v -0.453072 0.287158 0.453072 +v 0.516317 0.166623 0.303247 +v 0.596768 0.166623 0.000000 +v 0.444680 0.221240 0.444680 +v 0.538718 0.122640 -0.149931 +v -0.538718 0.122640 0.149931 +v -0.516317 0.166623 0.303247 +v -0.444680 0.221240 0.444680 +v -0.169664 0.360830 0.609621 +v 0.171349 0.287158 0.615677 +v -0.324265 0.287158 0.552100 +v -0.321075 0.360830 0.546669 +v 0.538718 0.122640 0.149931 +v 0.558363 0.122640 0.000000 +v 0.449858 0.088629 -0.264215 +v 0.369171 0.088629 -0.369171 +v 0.264215 0.088629 -0.449859 +v 0.139618 0.088629 -0.501662 +v -0.000000 0.088629 -0.519957 +v -0.139618 0.088629 -0.501662 +v -0.264215 0.088629 -0.449859 +v -0.369171 0.088629 -0.369171 +v -0.449859 0.088629 -0.264215 +v -0.501662 0.088629 -0.139618 +v -0.519957 0.088629 0.000000 +v -0.501662 0.088629 0.139618 +v -0.575771 0.166623 0.160243 +v -0.423705 0.166623 0.423705 +v -0.000000 0.287158 0.638129 +v 0.318259 0.221240 0.541877 +v -0.318259 0.221240 0.541877 +v 0.483086 0.122640 0.283731 +v 0.423705 0.166623 0.423705 +v 0.501662 0.088629 -0.139618 +v -0.449859 0.088629 0.264215 +v -0.483087 0.122640 0.283731 +v -0.396438 0.122640 0.396438 +v -0.303247 0.166623 0.516317 +v -0.171350 0.287158 0.615677 +v 0.168176 0.221240 0.604276 +v -0.168177 0.221240 0.604276 +v 0.501662 0.088629 0.139618 +v 0.519957 0.088629 0.000000 +v 0.424299 0.063924 -0.249203 +v 0.348195 0.063924 -0.348195 +v 0.249203 0.063924 -0.424298 +v 0.131685 0.063924 -0.473160 +v -0.000000 0.063924 -0.490415 +v -0.131686 0.063924 -0.473160 +v -0.249203 0.063924 -0.424298 +v -0.348196 0.063924 -0.348195 +v -0.424299 0.063924 -0.249203 +v -0.473160 0.063924 -0.131685 +v -0.490415 0.063924 0.000000 +v -0.473160 0.063924 0.131685 +v -0.424299 0.063924 0.249203 +v -0.283731 0.122640 0.483086 +v -0.000000 0.221240 0.626311 +v 0.303247 0.166623 0.516317 +v -0.160244 0.166623 0.575771 +v 0.449858 0.088629 0.264215 +v 0.396438 0.122640 0.396438 +v 0.473160 0.063924 -0.131685 +v -0.348196 0.063924 0.348195 +v -0.369171 0.088629 0.369171 +v -0.264215 0.088629 0.449859 +v -0.149931 0.122640 0.538718 +v 0.160243 0.166623 0.575771 +v -0.000000 0.166623 0.596769 +v 0.473160 0.063924 0.131685 +v 0.490415 0.063924 0.000000 +v 0.414076 0.047860 -0.243198 +v 0.339803 0.047860 -0.339804 +v 0.243198 0.047860 -0.414076 +v 0.128512 0.047860 -0.461757 +v -0.000000 0.047860 -0.478597 +v -0.128513 0.047860 -0.461757 +v -0.243198 0.047860 -0.414076 +v -0.339804 0.047860 -0.339804 +v -0.414076 0.047860 -0.243198 +v -0.461757 0.047860 -0.128512 +v -0.478597 0.047860 0.000000 +v -0.461757 0.047860 0.128512 +v -0.414076 0.047860 0.243198 +v -0.339804 0.047860 0.339804 +v -0.139618 0.088629 0.501662 +v 0.283731 0.122640 0.483086 +v -0.000000 0.122640 0.558363 +v 0.424299 0.063924 0.249203 +v 0.369171 0.088629 0.369171 +v 0.461756 0.047860 -0.128512 +v -0.243198 0.047860 0.414076 +v -0.249203 0.063924 0.424298 +v -0.131686 0.063924 0.473160 +v -0.000000 0.088629 0.519957 +v 0.149931 0.122640 0.538718 +v 0.461756 0.047860 0.128512 +v 0.478596 0.047860 0.000000 +v 0.410719 0.036005 -0.241228 +v 0.337050 0.036005 -0.337050 +v 0.241227 0.036005 -0.410719 +v 0.127471 0.036005 -0.458017 +v -0.000000 0.036005 -0.474720 +v -0.127471 0.036005 -0.458017 +v -0.241228 0.036005 -0.410719 +v -0.337051 0.036005 -0.337050 +v -0.410719 0.036005 -0.241228 +v -0.458017 0.036005 -0.127471 +v -0.474721 0.036005 0.000000 +v -0.458017 0.036005 0.127471 +v -0.410719 0.036005 0.241228 +v -0.337051 0.036005 0.337050 +v -0.241228 0.036005 0.410719 +v -0.000000 0.063924 0.490415 +v 0.264215 0.088629 0.449859 +v 0.139618 0.088629 0.501662 +v 0.414076 0.047860 0.243198 +v 0.348195 0.063924 0.348195 +v 0.458017 0.036005 -0.127471 +v -0.127471 0.036005 0.458017 +v -0.128513 0.047860 0.461757 +v -0.000000 0.047860 0.478597 +v 0.131685 0.063924 0.473160 +v 0.458017 0.036005 0.127471 +v 0.474720 0.036005 0.000000 +v 0.394137 0.024816 -0.231489 +v 0.323442 0.024816 -0.323442 +v 0.231489 0.024816 -0.394137 +v 0.122324 0.024816 -0.439524 +v -0.000000 0.024816 -0.455554 +v -0.122325 0.024816 -0.439524 +v -0.231489 0.024816 -0.394137 +v -0.323442 0.024816 -0.323442 +v -0.394137 0.024816 -0.231489 +v -0.439524 0.024816 -0.122325 +v -0.455554 0.024816 0.000000 +v -0.439524 0.024816 0.122325 +v -0.394137 0.024816 0.231489 +v -0.323442 0.024816 0.323442 +v -0.231489 0.024816 0.394137 +v -0.122325 0.024816 0.439524 +v 0.128512 0.047860 0.461757 +v 0.249203 0.063924 0.424298 +v 0.410719 0.036005 0.241228 +v 0.339803 0.047860 0.339804 +v 0.439524 0.024816 -0.122325 +v -0.000000 0.036005 0.474720 +v -0.000000 0.024816 0.455554 +v 0.127471 0.036005 0.458017 +v 0.243198 0.047860 0.414076 +v 0.439524 0.024816 0.122325 +v 0.455554 0.024816 0.000000 +v 0.354551 0.014956 -0.208238 +v 0.290957 0.014956 -0.290957 +v 0.208238 0.014956 -0.354551 +v 0.110038 0.014956 -0.395378 +v -0.000000 0.014956 -0.409797 +v -0.110038 0.014956 -0.395378 +v -0.208239 0.014956 -0.354551 +v -0.290957 0.014956 -0.290957 +v -0.354551 0.014956 -0.208238 +v -0.395378 0.014956 -0.110038 +v -0.409797 0.014956 0.000000 +v -0.395378 0.014956 0.110038 +v -0.354551 0.014956 0.208238 +v -0.290957 0.014956 0.290957 +v -0.208239 0.014956 0.354551 +v -0.110038 0.014956 0.395378 +v -0.000000 0.014956 0.409797 +v 0.241227 0.036005 0.410719 +v 0.337050 0.036005 0.337050 +v 0.394137 0.024816 0.231489 +v 0.395378 0.014956 -0.110038 +v 0.122324 0.024816 0.439524 +v 0.110038 0.014956 0.395378 +v 0.231489 0.024816 0.394137 +v 0.395378 0.014956 0.110038 +v 0.409797 0.014956 0.000000 +v 0.282184 0.007090 -0.165735 +v 0.231570 0.007090 -0.231570 +v 0.165735 0.007090 -0.282185 +v 0.087579 0.007090 -0.314679 +v -0.000000 0.007090 -0.326154 +v -0.087579 0.007090 -0.314679 +v -0.165735 0.007090 -0.282185 +v -0.231570 0.007090 -0.231570 +v -0.282184 0.007090 -0.165735 +v -0.314679 0.007090 -0.087579 +v -0.326155 0.007090 0.000000 +v -0.314679 0.007090 0.087579 +v -0.282184 0.007090 0.165735 +v -0.231570 0.007090 0.231570 +v -0.165735 0.007090 0.282185 +v -0.087579 0.007090 0.314679 +v -0.000000 0.007090 0.326154 +v 0.087579 0.007090 0.314679 +v 0.323442 0.024816 0.323442 +v 0.354551 0.014956 0.208238 +v 0.314679 0.007090 -0.087579 +v 0.208238 0.014956 0.354551 +v 0.165735 0.007090 0.282185 +v 0.290957 0.014956 0.290957 +v 0.314679 0.007090 0.087579 +v 0.326154 0.007090 0.000000 +v 0.167259 0.001883 -0.098236 +v 0.137258 0.001883 -0.137259 +v 0.098236 0.001883 -0.167259 +v 0.051910 0.001883 -0.186520 +v -0.000000 0.001883 -0.193322 +v -0.051911 0.001883 -0.186520 +v -0.098237 0.001883 -0.167259 +v -0.137259 0.001883 -0.137259 +v -0.167259 0.001883 -0.098236 +v -0.186520 0.001883 -0.051911 +v -0.193323 0.001883 0.000000 +v -0.186520 0.001883 0.051911 +v -0.167259 0.001883 0.098236 +v -0.137259 0.001883 0.137259 +v -0.098237 0.001883 0.167259 +v -0.051911 0.001883 0.186520 +v -0.000000 0.001883 0.193322 +v 0.051910 0.001883 0.186520 +v 0.098236 0.001883 0.167259 +v 0.282184 0.007090 0.165735 +v 0.186520 0.001883 -0.051911 +v 0.231570 0.007090 0.231570 +v 0.137258 0.001883 0.137259 +v 0.186520 0.001883 0.051911 +v 0.193322 0.001883 0.000000 +v -0.000000 0.000000 0.000000 +v 0.167259 0.001883 0.098236 +v 0.063813 0.861474 0.000000 +v 0.054654 0.888729 0.000000 +v 0.052734 0.888729 0.014691 +v 0.061568 0.861474 0.017135 +v 0.061568 0.861474 -0.017135 +v 0.072979 0.919969 0.020357 +v 0.111968 0.841089 0.000000 +v 0.047296 0.888729 0.027792 +v 0.052734 0.888729 -0.014691 +v 0.108028 0.841089 -0.030065 +v 0.075630 0.919969 0.000000 +v 0.065466 0.919969 0.038494 +v 0.108028 0.841089 0.030065 +v 0.055210 0.861474 0.032427 +v 0.055210 0.861474 -0.032427 +v 0.096873 0.841089 -0.056896 +v 0.100064 0.951211 0.027927 +v 0.089769 0.951211 0.052799 +v 0.183167 0.826023 0.000000 +v 0.176722 0.826023 -0.049184 +v 0.038821 0.888729 0.038821 +v 0.053751 0.919969 0.053751 +v 0.047296 0.888729 -0.027792 +v 0.072979 0.919969 -0.020357 +v 0.158473 0.826023 -0.093076 +v 0.103696 0.951211 0.000000 +v 0.073714 0.951211 0.073714 +v 0.176722 0.826023 0.049184 +v 0.096873 0.841089 0.056896 +v 0.045307 0.861474 0.045307 +v 0.079497 0.841089 -0.079497 +v 0.045307 0.861474 -0.045307 +v 0.130048 0.826023 -0.130048 +v 0.111754 0.978466 0.031195 +v 0.100259 0.978466 0.058974 +v 0.082330 0.978466 0.082330 +v 0.263228 0.813615 0.000000 +v 0.253966 0.813615 -0.070682 +v 0.227741 0.813615 -0.133759 +v 0.027792 0.888729 0.047296 +v 0.038494 0.919969 0.065466 +v 0.052799 0.951211 0.089769 +v 0.038821 0.888729 -0.038821 +v 0.065466 0.919969 -0.038494 +v 0.100064 0.951211 -0.027927 +v 0.186892 0.813615 -0.186892 +v 0.115809 0.978466 0.000000 +v 0.058974 0.978466 0.100259 +v 0.253966 0.813615 0.070682 +v 0.158473 0.826023 0.093076 +v 0.079497 0.841089 0.079497 +v 0.032426 0.861474 0.055210 +v 0.093076 0.826023 -0.158473 +v 0.056896 0.841089 -0.096873 +v 0.032426 0.861474 -0.055210 +v 0.133759 0.813615 -0.227741 +v 0.085811 0.997741 0.023955 +v 0.076985 0.997741 0.045285 +v 0.063219 0.997741 0.063219 +v 0.045285 0.997741 0.076986 +v 0.337972 0.801206 0.000000 +v 0.326081 0.801206 -0.090752 +v 0.292408 0.801206 -0.171740 +v 0.239960 0.801206 -0.239960 +v 0.014691 0.888729 0.052735 +v 0.020357 0.919969 0.072979 +v 0.027927 0.951211 0.100064 +v 0.031195 0.978466 0.111754 +v 0.027792 0.888729 -0.047296 +v 0.053751 0.919969 -0.053751 +v 0.089769 0.951211 -0.052799 +v 0.111754 0.978466 -0.031195 +v 0.171740 0.801206 -0.292408 +v 0.088924 0.997741 0.000000 +v 0.023955 0.997741 0.085811 +v 0.326081 0.801206 0.090752 +v 0.227741 0.813615 0.133759 +v 0.130048 0.826023 0.130048 +v 0.056896 0.841089 0.096873 +v 0.017135 0.861474 0.061568 +v 0.070682 0.813615 -0.253966 +v 0.049184 0.826023 -0.176722 +v 0.030065 0.841089 -0.108029 +v 0.017135 0.861474 -0.061568 +v 0.090752 0.801206 -0.326081 +v -0.000000 1.005054 0.000000 +v 0.393218 0.786140 0.000000 +v 0.379380 0.786140 -0.105586 +v 0.340206 0.786140 -0.199813 +v 0.279184 0.786140 -0.279184 +v 0.199813 0.786140 -0.340206 +v -0.000000 0.888729 0.054654 +v -0.000000 0.919969 0.075630 +v -0.000000 0.951211 0.103696 +v -0.000000 0.978466 0.115809 +v -0.000000 0.997741 0.088925 +v 0.014691 0.888729 -0.052735 +v 0.038494 0.919969 -0.065466 +v 0.073714 0.951211 -0.073714 +v 0.100259 0.978466 -0.058974 +v 0.085811 0.997741 -0.023955 +v 0.105586 0.786140 -0.379381 +v 0.379380 0.786140 0.105586 +v 0.292408 0.801206 0.171740 +v 0.186892 0.813615 0.186892 +v 0.093076 0.826023 0.158473 +v 0.030065 0.841089 0.108029 +v -0.000000 0.861474 0.063813 +v -0.000000 0.801206 -0.337972 +v -0.000000 0.813615 -0.263228 +v -0.000000 0.826023 -0.183167 +v -0.000000 0.841089 -0.111968 +v -0.000000 0.861474 -0.063813 +v -0.000000 0.786140 -0.393218 +v 0.076985 0.997741 -0.045285 +v -0.023955 0.997741 0.085811 +v 0.414784 0.765755 0.000000 +v 0.400190 0.765755 -0.111377 +v 0.358865 0.765755 -0.210772 +v 0.294497 0.765755 -0.294497 +v 0.210772 0.765755 -0.358865 +v 0.111377 0.765755 -0.400190 +v -0.014691 0.888729 0.052735 +v -0.020357 0.919969 0.072979 +v -0.027927 0.951211 0.100064 +v -0.031195 0.978466 0.111754 +v -0.000000 0.888729 -0.054654 +v 0.020357 0.919969 -0.072979 +v 0.052799 0.951211 -0.089769 +v 0.082330 0.978466 -0.082330 +v -0.000000 0.765755 -0.414784 +v 0.063219 0.997741 -0.063219 +v -0.045285 0.997741 0.076986 +v 0.400190 0.765755 0.111377 +v 0.340206 0.786140 0.199813 +v 0.239960 0.801206 0.239960 +v 0.133759 0.813615 0.227741 +v 0.049184 0.826023 0.176722 +v -0.000000 0.841089 0.111968 +v -0.017135 0.861474 0.061568 +v -0.105586 0.786140 -0.379381 +v -0.090752 0.801206 -0.326081 +v -0.070682 0.813615 -0.253966 +v -0.049184 0.826023 -0.176722 +v -0.030066 0.841089 -0.108029 +v -0.017135 0.861474 -0.061568 +v -0.111377 0.765755 -0.400190 +v 0.045285 0.997741 -0.076986 +v -0.063220 0.997741 0.063219 +v 0.414952 0.750806 0.115486 +v 0.430085 0.750806 0.000000 +v 0.414952 0.750806 -0.115486 +v 0.372103 0.750806 -0.218547 +v 0.305360 0.750806 -0.305360 +v 0.218547 0.750806 -0.372103 +v 0.115486 0.750806 -0.414952 +v -0.000000 0.750806 -0.430085 +v -0.027793 0.888729 0.047296 +v -0.038494 0.919969 0.065466 +v -0.052799 0.951211 0.089769 +v -0.058974 0.978466 0.100259 +v -0.014691 0.888729 -0.052735 +v -0.000000 0.919969 -0.075630 +v 0.027927 0.951211 -0.100064 +v 0.058974 0.978466 -0.100259 +v -0.115486 0.750806 -0.414952 +v 0.023955 0.997741 -0.085811 +v -0.076986 0.997741 0.045285 +v 0.372103 0.750806 0.218547 +v 0.358865 0.765755 0.210772 +v 0.279184 0.786140 0.279184 +v 0.171740 0.801206 0.292408 +v 0.070682 0.813615 0.253966 +v -0.000000 0.826023 0.183167 +v -0.030066 0.841089 0.108029 +v -0.032427 0.861474 0.055210 +v -0.210772 0.765755 -0.358865 +v -0.199813 0.786140 -0.340206 +v -0.171740 0.801206 -0.292408 +v -0.133759 0.813615 -0.227741 +v -0.093076 0.826023 -0.158473 +v -0.056896 0.841089 -0.096873 +v -0.032427 0.861474 -0.055210 +v -0.218547 0.750806 -0.372103 +v 0.031195 0.978466 -0.111754 +v -0.000000 0.997741 -0.088925 +v -0.082331 0.978466 0.082330 +v -0.085811 0.997741 0.023955 +v 0.305360 0.750806 0.305360 +v 0.294497 0.765755 0.294497 +v -0.038821 0.888729 0.038821 +v -0.053751 0.919969 0.053751 +v -0.073714 0.951211 0.073714 +v -0.027793 0.888729 -0.047296 +v -0.020357 0.919969 -0.072979 +v -0.000000 0.951211 -0.103696 +v -0.305360 0.750806 -0.305360 +v -0.294497 0.765755 -0.294497 +v -0.000000 0.978466 -0.115809 +v -0.023955 0.997741 -0.085811 +v -0.100259 0.978466 0.058974 +v -0.088925 0.997741 0.000000 +v 0.210772 0.765755 0.358865 +v 0.218547 0.750806 0.372103 +v 0.199813 0.786140 0.340206 +v 0.090752 0.801206 0.326081 +v -0.000000 0.813615 0.263228 +v -0.049184 0.826023 0.176722 +v -0.056896 0.841089 0.096873 +v -0.045307 0.861474 0.045307 +v -0.279185 0.786140 -0.279184 +v -0.239960 0.801206 -0.239960 +v -0.186892 0.813615 -0.186892 +v -0.130049 0.826023 -0.130048 +v -0.079497 0.841089 -0.079497 +v -0.045307 0.861474 -0.045307 +v -0.372103 0.750806 -0.218547 +v -0.358865 0.765755 -0.210772 +v -0.031195 0.978466 -0.111754 +v -0.045285 0.997741 -0.076986 +v -0.111754 0.978466 0.031195 +v -0.085811 0.997741 -0.023955 +v 0.111377 0.765755 0.400190 +v 0.115486 0.750806 0.414952 +v -0.047296 0.888729 0.027792 +v -0.065466 0.919969 0.038494 +v -0.089770 0.951211 0.052799 +v -0.038821 0.888729 -0.038821 +v -0.038494 0.919969 -0.065466 +v -0.027927 0.951211 -0.100064 +v -0.414952 0.750806 -0.115486 +v -0.400190 0.765755 -0.111377 +v -0.058974 0.978466 -0.100259 +v -0.063220 0.997741 -0.063219 +v -0.115809 0.978466 0.000000 +v -0.076986 0.997741 -0.045285 +v 0.105586 0.786140 0.379381 +v -0.000000 0.765755 0.414784 +v -0.000000 0.750806 0.430085 +v -0.000000 0.801206 0.337972 +v -0.070682 0.813615 0.253966 +v -0.093076 0.826023 0.158473 +v -0.079497 0.841089 0.079497 +v -0.055210 0.861474 0.032427 +v -0.340206 0.786140 -0.199813 +v -0.292408 0.801206 -0.171740 +v -0.227741 0.813615 -0.133759 +v -0.158473 0.826023 -0.093076 +v -0.096873 0.841089 -0.056896 +v -0.055210 0.861474 -0.032427 +v -0.430085 0.750806 0.000000 +v -0.414784 0.765755 0.000000 +v -0.052799 0.951211 -0.089769 +v -0.082331 0.978466 -0.082330 +v -0.100064 0.951211 0.027927 +v -0.111754 0.978466 -0.031195 +v -0.000000 0.786140 0.393218 +v -0.115486 0.750806 0.414952 +v -0.111377 0.765755 0.400190 +v -0.052735 0.888729 0.014691 +v -0.072979 0.919969 0.020357 +v -0.047296 0.888729 -0.027792 +v -0.053751 0.919969 -0.053751 +v -0.414952 0.750806 0.115486 +v -0.400190 0.765755 0.111377 +v -0.379381 0.786140 -0.105586 +v -0.073714 0.951211 -0.073714 +v -0.100259 0.978466 -0.058974 +v -0.103696 0.951211 0.000000 +v -0.105586 0.786140 0.379381 +v -0.218547 0.750806 0.372103 +v -0.210772 0.765755 0.358865 +v -0.090752 0.801206 0.326081 +v -0.133759 0.813615 0.227741 +v -0.130049 0.826023 0.130048 +v -0.096873 0.841089 0.056896 +v -0.061568 0.861474 0.017135 +v -0.326081 0.801206 -0.090752 +v -0.253966 0.813615 -0.070682 +v -0.176722 0.826023 -0.049184 +v -0.108029 0.841089 -0.030065 +v -0.061568 0.861474 -0.017135 +v -0.372103 0.750806 0.218547 +v -0.358865 0.765755 0.210772 +v -0.393219 0.786140 0.000000 +v -0.089770 0.951211 -0.052799 +v -0.100064 0.951211 -0.027927 +v -0.199813 0.786140 0.340206 +v -0.305360 0.750806 0.305360 +v -0.294497 0.765755 0.294497 +v -0.054655 0.888729 0.000000 +v -0.075630 0.919969 0.000000 +v -0.052735 0.888729 -0.014691 +v -0.065466 0.919969 -0.038494 +v -0.379381 0.786140 0.105586 +v -0.171740 0.801206 0.292408 +v -0.279185 0.786140 0.279184 +v -0.186892 0.813615 0.186892 +v -0.158473 0.826023 0.093076 +v -0.108029 0.841089 0.030065 +v -0.063813 0.861474 0.000000 +v -0.337972 0.801206 0.000000 +v -0.263228 0.813615 0.000000 +v -0.183167 0.826023 0.000000 +v -0.111968 0.841089 0.000000 +v -0.340206 0.786140 0.199813 +v -0.072979 0.919969 -0.020357 +v -0.239960 0.801206 0.239960 +v -0.326081 0.801206 0.090752 +v -0.292408 0.801206 0.171740 +v -0.227741 0.813615 0.133759 +v -0.176722 0.826023 0.049184 +v -0.253966 0.813615 0.070682 +v -0.526706 0.651362 -0.039883 +v -0.534329 0.646030 0.000000 +v -0.619922 0.238069 -0.071790 +v -0.624826 0.259599 -0.063813 +v -0.638129 0.287158 0.000000 +v -0.631184 0.277569 0.039883 +v -0.501666 0.699221 -0.063813 +v -0.508714 0.682112 -0.071712 +v -0.611709 0.194244 0.000000 +v -0.608883 0.198681 0.039883 +v -0.517593 0.664661 0.063813 +v -0.508714 0.682112 0.071712 +v -0.631184 0.277569 -0.039883 +v -0.624828 0.259599 0.063813 +v -0.615480 0.216617 0.063578 +v -0.615553 0.216807 -0.063813 +v -0.517593 0.664661 -0.063813 +v -0.498530 0.712498 -0.039883 +v -0.619922 0.238069 0.071790 +v -0.526706 0.651362 0.039883 +v -0.608884 0.198682 -0.039883 +v 0.605100 0.399712 0.137265 +v 0.613258 0.341675 0.154354 +v 0.605956 0.463769 0.000000 +v 0.600959 0.444810 -0.085753 +v 0.613258 0.341675 -0.154354 +v 0.605101 0.399712 -0.137265 +v 0.600960 0.444810 0.085753 +v 0.121642 0.750009 -0.437072 +v -0.000000 0.750009 -0.453012 +v 0.453011 0.750009 0.000000 +v 0.437073 0.750009 -0.121642 +v -0.453012 0.750009 0.000000 +v -0.437073 0.750009 -0.121642 +v -0.230198 0.750009 0.391939 +v -0.321639 0.750009 0.321639 +v -0.391940 0.750009 0.230197 +v -0.437073 0.750009 0.121642 +v 0.121642 0.750009 0.437072 +v -0.000000 0.750009 0.453012 +v -0.121642 0.750009 0.437072 +v 0.437073 0.750009 0.121642 +v 0.391939 0.750009 0.230197 +v 0.321638 0.750009 -0.321639 +v 0.230197 0.750009 -0.391940 +v -0.121642 0.750009 -0.437072 +v 0.391939 0.750009 -0.230197 +v 0.321638 0.750009 0.321639 +v 0.230197 0.750009 0.391940 +v -0.230198 0.750009 -0.391939 +v -0.501255 0.717792 0.000000 +v 0.617684 0.235930 0.085941 +v 0.625577 0.219883 0.000000 +v -0.321639 0.750009 -0.321639 +v -0.391940 0.750009 -0.230197 +v -0.498530 0.712498 0.039883 +v -0.501667 0.699221 0.063813 +v 0.617684 0.235930 -0.085941 +v 0.619427 0.283145 -0.137236 +v 0.619427 0.283145 0.137236 +vn -0.901883 0.415418 0.118168 +vn -0.905637 0.407056 0.118656 +vn -0.877041 0.418744 0.235298 +vn 0.058443 -0.998260 0.000732 +vn 0.015107 -0.999878 0.000183 +vn 0.014557 -0.949278 0.314035 +vn 0.056703 -0.947539 0.314524 +vn 0.162053 -0.986755 0.002014 +vn 0.157933 -0.933592 0.321604 +vn 0.392376 -0.919767 0.004334 +vn 0.378307 -0.856655 0.350688 +vn 0.783776 -0.620991 0.005249 +vn 0.726829 -0.553880 0.406079 +vn 0.994812 -0.101627 0.001984 +vn 0.908139 -0.082766 0.410321 +vn 0.003082 -0.939787 0.341685 +vn 0.002167 -0.619495 0.784967 +vn 0.011536 -0.679403 0.733634 +vn 0.044679 -0.675588 0.735923 +vn 0.123325 -0.652272 0.747856 +vn 0.275399 -0.556871 0.783593 +vn 0.460067 -0.316263 0.829615 +vn 0.563036 -0.041200 0.825373 +vn -0.000427 0.122166 0.992492 +vn 0.000397 0.003632 0.999969 +vn 0.002869 0.011841 0.999908 +vn 0.004852 0.029298 0.999542 +vn -0.008179 0.053499 0.998505 +vn -0.046510 0.041536 0.998047 +vn -0.039155 0.003113 0.999207 +vn -0.850551 0.473769 -0.228217 +vn -0.897885 0.424177 -0.117649 +vn -0.880886 0.473281 0.000000 +vn -0.013611 0.682394 0.730827 +vn -0.053896 0.680441 0.730796 +vn -0.147557 0.656789 0.739464 +vn -0.325968 0.560564 0.761223 +vn -0.537645 0.315806 0.781762 +vn -0.611530 0.029939 0.790613 +vn -0.904172 0.427137 0.000000 +vn -0.897885 0.424146 0.117618 +vn -0.020112 0.949461 0.313150 +vn -0.081820 0.945433 0.315287 +vn -0.227699 0.916379 0.329173 +vn -0.504196 0.785302 0.359203 +vn -0.810633 0.443220 0.382611 +vn -0.921232 0.039705 0.386944 +vn -0.020569 0.949400 -0.313334 +vn -0.021729 0.999756 -0.000092 +vn -0.004242 0.950468 -0.310770 +vn -0.088260 0.996094 -0.000488 +vn -0.246895 0.969024 -0.001343 +vn -0.549730 0.835322 -0.002350 +vn -0.880673 0.473647 -0.001984 +vn -0.999084 0.042146 -0.000610 +vn -0.877041 0.418744 -0.235298 +vn -0.920286 0.391156 0.000000 +vn -0.905637 0.407056 -0.118656 +vn -0.083132 0.945006 -0.316202 +vn -0.230201 0.914823 -0.331797 +vn -0.505570 0.782800 -0.362743 +vn -0.808710 0.444960 -0.384625 +vn -0.920835 0.042055 -0.387646 +vn -0.897885 0.424146 -0.117618 +vn -0.901883 0.415448 -0.118168 +vn -0.014161 0.682394 -0.730796 +vn -0.055361 0.680074 -0.731010 +vn -0.150029 0.655660 -0.739982 +vn -0.327616 0.560594 -0.760491 +vn -0.537431 0.320933 -0.779809 +vn -0.611988 0.033387 -0.790155 +vn 0.015168 -0.949339 -0.313852 +vn 0.011902 -0.679403 -0.733634 +vn 0.003265 -0.939817 -0.341594 +vn 0.000183 0.004212 -0.999969 +vn 0.003510 0.014008 -0.999878 +vn 0.005921 0.035951 -0.999329 +vn -0.010132 0.064333 -0.997864 +vn -0.051576 0.048463 -0.997467 +vn -0.041597 0.003998 -0.999115 +vn 0.003082 -0.620106 -0.784478 +vn -0.000031 0.122440 -0.992462 +vn -0.897885 0.424177 0.117649 +vn 0.046449 -0.674398 -0.736869 +vn 0.125980 -0.648946 -0.750298 +vn 0.275430 -0.552477 -0.786676 +vn 0.455519 -0.320536 -0.830500 +vn 0.561693 -0.046480 -0.826014 +vn -0.888668 0.391644 0.238441 +vn 0.058046 -0.947630 -0.314005 +vn 0.159948 -0.933836 -0.319865 +vn 0.380169 -0.857753 -0.345927 +vn 0.725547 -0.560930 -0.398602 +vn 0.908597 -0.089236 -0.407971 +vn 0.003235 -0.999969 0.000031 +vn 0.973144 0.230110 0.000824 +vn 0.890896 0.211737 0.401776 +vn 0.912900 0.408094 0.002533 +vn 0.836970 0.380932 0.392834 +vn 0.829035 0.559160 0.003784 +vn 0.764519 0.528550 0.368969 +vn 0.718650 0.695334 0.003937 +vn 0.668294 0.663717 0.335917 +vn 0.579577 0.814905 0.002838 +vn 0.542650 0.779687 0.312357 +vn 0.495163 0.868770 0.002258 +vn 0.458052 0.820643 0.341624 +vn 0.561205 0.137028 0.816218 +vn 0.532029 0.253456 0.807886 +vn 0.497543 0.363445 0.787591 +vn 0.449538 0.472060 0.758293 +vn 0.373669 0.563555 0.736686 +vn 0.289041 0.531114 0.796442 +vn -0.023225 -0.005249 0.999695 +vn -0.016785 -0.010254 0.999786 +vn -0.011444 -0.012940 0.999847 +vn -0.009796 -0.013276 0.999847 +vn -0.014801 -0.013916 0.999786 +vn -0.089755 -0.176122 0.980255 +vn -0.585772 -0.152379 0.795984 +vn -0.538896 -0.288766 0.791314 +vn -0.484146 -0.407910 0.774071 +vn -0.424635 -0.509781 0.748161 +vn -0.355907 -0.584765 0.728935 +vn -0.889828 -0.237159 0.389782 +vn -0.808740 -0.446852 0.382366 +vn -0.702475 -0.613269 0.361095 +vn -0.590625 -0.734855 0.333293 +vn -0.483291 -0.816767 0.315104 +vn -0.912076 0.409955 0.000000 +vn -0.965606 -0.259987 -0.000458 +vn -0.872433 -0.488693 -0.001465 +vn -0.748436 -0.663167 -0.002197 +vn -0.621601 -0.783288 -0.002136 +vn -0.507065 -0.861873 -0.001251 +vn -0.438215 -0.854366 0.279183 +vn -0.456130 -0.889889 -0.000732 +vn -0.889126 -0.238868 -0.390332 +vn -0.807001 -0.448531 -0.384075 +vn -0.700980 -0.613392 -0.363750 +vn -0.590442 -0.733757 -0.336039 +vn -0.484787 -0.815332 -0.316477 +vn -0.440962 -0.852931 -0.279305 +vn -0.359691 -0.584185 -0.727531 +vn -0.358074 -0.682241 -0.637410 +vn -0.585467 -0.154668 -0.795770 +vn -0.538499 -0.291696 -0.790490 +vn -0.484512 -0.409772 -0.772851 +vn -0.426496 -0.510056 -0.746910 +vn -0.909543 -0.399274 -0.115207 +vn -0.971191 -0.204688 -0.121891 +vn -0.912931 -0.326609 -0.244606 +vn -0.020478 -0.017853 -0.999603 +vn -0.024537 -0.005737 -0.999664 +vn -0.020844 -0.012207 -0.999695 +vn -0.017548 -0.016846 -0.999695 +vn -0.016724 -0.018097 -0.999695 +vn -0.909116 -0.400311 0.115055 +vn -0.873775 -0.472610 0.114475 +vn -0.795892 -0.566485 0.213538 +vn -0.353069 -0.684103 0.638203 +vn 0.559679 0.139714 -0.816828 +vn 0.528581 0.255501 -0.809473 +vn 0.494217 0.362987 -0.789911 +vn 0.449049 0.469283 -0.760308 +vn 0.378246 0.560869 -0.736412 +vn -0.091983 -0.174383 -0.980346 +vn 0.295267 0.530625 -0.794488 +vn 0.890500 0.214759 -0.401044 +vn 0.836634 0.384075 -0.390515 +vn 0.765191 0.530198 -0.365123 +vn 0.671041 0.663228 -0.331339 +vn 0.547929 0.777642 -0.308206 +vn 0.464522 0.818842 -0.337199 +vn 0.931486 0.265572 -0.248543 +vn 0.939543 0.342357 0.000000 +vn 0.947539 0.295114 -0.122684 +vn -0.351421 0.936186 0.001953 +vn -0.144444 0.989502 0.003174 +vn -0.126743 0.878811 0.459975 +vn -0.716758 0.697287 -0.000946 +vn -0.299997 0.838313 0.455214 +vn -0.621876 0.660207 0.421155 +vn -0.901822 0.432081 -0.004517 +vn -0.807031 0.443434 0.389904 +vn -0.930204 0.366863 -0.008484 +vn -0.824549 0.383312 0.416059 +vn -0.850673 0.525529 -0.011628 +vn -0.722465 0.508988 0.467910 +vn -0.668447 0.743645 -0.011139 +vn -0.531449 0.686514 0.496170 +vn -0.116459 0.505448 0.854946 +vn -0.258400 0.470656 0.843593 +vn -0.407605 0.396985 0.822321 +vn -0.450270 0.352367 0.820399 +vn -0.385876 0.395734 0.833338 +vn -0.270669 0.487838 0.829890 +vn 0.141606 -0.001190 0.989898 +vn -0.067690 0.525346 0.848170 +vn 0.989593 0.100253 0.103122 +vn 0.970244 0.213324 0.114475 +vn 0.960418 0.152654 0.232917 +vn 0.241829 0.092502 0.965880 +vn 0.209296 0.170660 0.962828 +vn 0.096194 0.178625 0.979186 +vn 0.009552 0.154332 0.987945 +vn -0.000122 0.151952 0.988372 +vn 0.361248 -0.477279 0.801019 +vn 0.607929 -0.282540 0.741997 +vn 0.679220 -0.106754 0.726096 +vn 0.583911 -0.078524 0.807978 +vn 0.402722 -0.205237 0.891995 +vn 0.279519 -0.338694 0.898404 +vn 0.488601 -0.768700 0.412671 +vn 0.784570 -0.501511 0.364544 +vn 0.893918 -0.279611 0.350291 +vn 0.861415 -0.285287 0.420179 +vn 0.679373 -0.540452 0.496323 +vn 0.458327 -0.754540 0.469588 +vn 0.524155 -0.851588 -0.000153 +vn 0.827143 -0.561968 0.001679 +vn 0.943205 -0.332133 0.003479 +vn 0.933256 -0.359081 0.005737 +vn 0.756859 -0.653493 0.006470 +vn 0.492843 -0.870083 0.004120 +vn 0.322489 -0.946562 -0.001129 +vn 0.912839 -0.326609 0.244942 +vn 0.824396 -0.565996 0.000000 +vn 0.894162 -0.447676 0.000000 +vn 0.486557 -0.770501 -0.411756 +vn 0.783990 -0.504074 -0.362285 +vn 0.895199 -0.281899 -0.345134 +vn 0.863735 -0.289010 -0.412824 +vn 0.682119 -0.544267 -0.488296 +vn 0.461928 -0.758202 -0.460128 +vn 0.357463 -0.479141 -0.801599 +vn 0.605884 -0.285867 -0.742393 +vn 0.679739 -0.108646 -0.725333 +vn 0.583636 -0.077883 -0.808222 +vn 0.401440 -0.199225 -0.893918 +vn 0.281961 -0.330638 -0.900632 +vn 0.135228 -0.002380 -0.990783 +vn 0.235755 0.091128 -0.967498 +vn 0.200720 0.170629 -0.964660 +vn 0.086123 0.184576 -0.979003 +vn 0.000671 0.174322 -0.984680 +vn -0.007141 0.169012 -0.985565 +vn 0.966613 -0.042848 -0.252602 +vn 0.960418 0.152654 -0.232917 +vn 0.989593 0.100223 -0.103092 +vn -0.119297 0.503342 -0.855770 +vn -0.261269 0.472793 -0.841517 +vn -0.414075 0.399792 -0.817713 +vn -0.459700 0.357036 -0.813105 +vn -0.394024 0.408490 -0.823298 +vn -0.277871 0.487381 -0.827754 +vn -0.072207 0.520127 -0.851009 +vn -0.298654 0.840297 -0.452376 +vn -0.617512 0.663961 -0.421613 +vn -0.801324 0.450209 -0.393872 +vn -0.819422 0.389691 -0.420270 +vn -0.721274 0.506912 -0.471969 +vn -0.538347 0.670644 -0.510239 +vn -0.482009 0.876125 -0.005127 +vn -0.394635 0.815363 0.423536 +vn -0.321909 0.946745 -0.002594 +vn -0.255287 0.921995 0.291086 +vn 0.004242 0.999969 0.000397 +vn -0.002960 0.999939 -0.010102 +vn 0.853450 0.521073 -0.007050 +vn 0.392041 0.688986 -0.609546 +vn 0.805170 -0.592517 -0.023621 +vn 0.588763 -0.206122 -0.781579 +vn 0.681478 -0.731040 -0.033296 +vn 0.485031 -0.441237 -0.754967 +vn -0.206824 0.638203 0.741539 +vn -0.129490 0.862056 0.489944 +vn -0.033418 0.999176 0.022340 +vn 0.047700 0.864040 -0.501114 +vn 0.099307 0.538743 -0.836573 +vn 0.053560 0.251839 -0.966277 +vn 0.020112 0.322611 0.946287 +vn 0.021943 0.748894 0.662282 +vn -0.025941 0.995605 0.089908 +vn -0.059175 0.930876 -0.360424 +vn -0.080172 0.784448 -0.614948 +vn -0.142582 0.557604 -0.817743 +vn 0.281747 -0.174993 0.943388 +vn 0.303903 0.444136 0.842830 +vn 0.034333 0.983764 0.175970 +vn -0.113865 0.956420 -0.268777 +vn -0.155339 0.858852 -0.488021 +vn -0.207404 0.641865 -0.738182 +vn 0.467238 -0.683187 0.561144 +vn 0.699515 0.004364 0.714560 +vn 0.355296 0.891934 0.279641 +vn -0.170354 0.971465 -0.164861 +vn -0.245552 0.901181 -0.357097 +vn -0.248726 0.651082 -0.717063 +vn 0.494430 -0.869167 0.006317 +vn 0.933134 -0.358898 0.019868 +vn 0.703146 0.710685 0.021790 +vn -0.203650 0.978942 -0.012574 +vn -0.326456 0.942869 -0.066073 +vn -0.397595 0.857082 -0.327525 +vn 0.460616 -0.712546 -0.529221 +vn 0.695486 -0.098544 -0.711722 +vn 0.397534 0.853816 -0.336070 +vn -0.198248 0.963439 0.180151 +vn -0.306833 0.888516 0.341075 +vn -0.393689 0.807672 0.438887 +vn 0.276559 -0.211951 -0.937315 +vn 0.294626 0.366161 -0.882656 +vn 0.046632 0.973235 -0.224982 +vn -0.146733 0.912168 0.382611 +vn -0.202643 0.700797 0.683950 +vn -0.232673 0.506485 0.830226 +vn 0.011689 0.309397 -0.950835 +vn 0.013245 0.708640 -0.705435 +vn -0.027589 0.995758 -0.087680 +vn -0.047395 0.829371 0.556658 +vn -0.015259 0.386608 0.922086 +vn 0.004639 0.119510 0.992798 +vn -0.211035 0.631001 -0.746513 +vn -0.138768 0.848781 -0.510147 +vn -0.024995 0.999664 -0.001190 +vn 0.120426 0.724570 0.678579 +vn 0.260750 0.006531 0.965361 +vn 0.272500 -0.255898 0.927488 +vn -0.395581 0.809961 -0.432905 +vn -0.258827 0.918851 -0.297800 +vn 0.004730 0.999878 0.013031 +vn 0.466628 0.599780 0.649983 +vn 0.621937 -0.400861 0.672628 +vn 0.551042 -0.592181 0.587878 +vn 0.649068 0.384991 -0.656087 +vn 0.055971 0.691214 0.720450 +vn -0.115940 0.804590 0.582354 +vn -0.262185 0.897946 0.353435 +vn -0.341655 0.885006 -0.316263 +vn -0.081423 0.793085 -0.603626 +vn -0.155675 0.857753 -0.489883 +vn 0.728690 0.365978 0.578784 +vn 0.318674 0.539384 0.779382 +vn 0.953551 0.300150 -0.024415 +vn -0.133976 0.836818 -0.530808 +vn 0.095401 0.667959 -0.738029 +vn 0.000000 0.999969 0.000000 +vn -0.992523 -0.122013 0.000000 +vn -0.937346 -0.348338 0.000000 +vn -0.905148 -0.348827 -0.242836 +vn -0.958617 -0.122227 -0.257057 +vn -0.832057 0.554674 0.000000 +vn -0.803217 0.555376 -0.215339 +vn -0.048616 0.998810 0.000000 +vn -0.046236 0.998840 -0.012726 +vn 0.544267 0.838893 0.000000 +vn 0.525376 0.839106 0.140843 +vn 0.783471 0.621387 0.000000 +vn 0.756371 0.621845 0.202918 +vn 0.880886 0.473281 0.000000 +vn 0.850551 0.473769 0.228217 +vn -0.810907 -0.349376 -0.469375 +vn -0.859004 -0.122410 -0.497085 +vn -0.719657 0.555559 -0.416425 +vn -0.041749 0.998810 -0.024415 +vn 0.470077 0.839625 0.272011 +vn 0.677236 0.622608 0.391980 +vn 0.761803 0.474471 0.440962 +vn -0.662465 -0.349620 -0.662465 +vn -0.701773 -0.122440 -0.701773 +vn -0.587878 0.555650 -0.587878 +vn -0.034272 0.998810 -0.034272 +vn 0.383831 0.839808 0.383831 +vn 0.553148 0.622913 0.553148 +vn 0.622303 0.474776 0.622303 +vn -0.469375 -0.349376 -0.810907 +vn -0.497085 -0.122379 -0.859004 +vn -0.416425 0.555559 -0.719657 +vn -0.024415 0.998810 -0.041749 +vn 0.272011 0.839625 0.470077 +vn 0.391980 0.622608 0.677236 +vn 0.440962 0.474471 0.761834 +vn -0.242836 -0.348827 -0.905148 +vn -0.257057 -0.122227 -0.958617 +vn -0.215339 0.555376 -0.803217 +vn -0.012726 0.998840 -0.046205 +vn 0.140843 0.839106 0.525376 +vn 0.202918 0.621845 0.756371 +vn 0.228217 0.473769 0.850551 +vn 0.000000 -0.348338 -0.937346 +vn 0.000000 -0.122013 -0.992523 +vn 0.000000 0.554674 -0.832057 +vn 0.000000 0.998810 -0.048616 +vn 0.000000 0.838893 0.544267 +vn 0.000000 0.621387 0.783471 +vn 0.000000 0.473281 0.880886 +vn 0.242836 -0.348827 -0.905148 +vn 0.257057 -0.122227 -0.958617 +vn 0.215308 0.555376 -0.803217 +vn 0.012726 0.998840 -0.046205 +vn -0.140843 0.839106 0.525376 +vn -0.202918 0.621845 0.756340 +vn -0.228217 0.473769 0.850551 +vn 0.469375 -0.349376 -0.810907 +vn 0.497085 -0.122379 -0.859004 +vn 0.416425 0.555559 -0.719657 +vn 0.024415 0.998810 -0.041749 +vn -0.272011 0.839625 0.470077 +vn -0.391980 0.622608 0.677236 +vn -0.440962 0.474502 0.761803 +vn 0.662465 -0.349620 -0.662465 +vn 0.701773 -0.122471 -0.701773 +vn 0.587878 0.555650 -0.587878 +vn 0.034272 0.998810 -0.034272 +vn -0.383831 0.839808 0.383831 +vn -0.553148 0.622913 0.553148 +vn -0.622303 0.474776 0.622303 +vn 0.810907 -0.349406 -0.469375 +vn 0.859004 -0.122379 -0.497085 +vn 0.719657 0.555559 -0.416425 +vn 0.041749 0.998810 -0.024415 +vn -0.470077 0.839625 0.272011 +vn -0.677236 0.622608 0.391980 +vn -0.761803 0.474471 0.440962 +vn 0.905148 -0.348827 -0.242836 +vn 0.958617 -0.122227 -0.257057 +vn 0.803217 0.555376 -0.215339 +vn 0.046205 0.998840 -0.012726 +vn -0.525376 0.839106 0.140843 +vn -0.756340 0.621876 0.202918 +vn -0.850551 0.473769 0.228217 +vn 0.937346 -0.348338 0.000000 +vn 0.992523 -0.122013 0.000000 +vn 0.832026 0.554674 0.000000 +vn 0.048616 0.998810 0.000000 +vn -0.544267 0.838893 0.000000 +vn -0.783471 0.621387 0.000000 +vn 0.905148 -0.348827 0.242836 +vn 0.958617 -0.122227 0.257057 +vn 0.803217 0.555376 0.215308 +vn 0.046205 0.998840 0.012726 +vn -0.525376 0.839106 -0.140843 +vn -0.756340 0.621876 -0.202918 +vn 0.810907 -0.349406 0.469375 +vn 0.859004 -0.122379 0.497085 +vn 0.719657 0.555559 0.416425 +vn 0.041749 0.998810 0.024415 +vn -0.470077 0.839625 -0.272011 +vn -0.677236 0.622608 -0.391980 +vn -0.761803 0.474471 -0.440962 +vn 0.662465 -0.349620 0.662465 +vn 0.701773 -0.122471 0.701773 +vn 0.587878 0.555650 0.587878 +vn 0.034272 0.998810 0.034272 +vn -0.383831 0.839808 -0.383831 +vn -0.553148 0.622913 -0.553148 +vn -0.622303 0.474776 -0.622303 +vn 0.469375 -0.349376 0.810907 +vn 0.497085 -0.122379 0.859004 +vn 0.416425 0.555559 0.719657 +vn 0.024415 0.998810 0.041749 +vn -0.272011 0.839625 -0.470077 +vn -0.391980 0.622608 -0.677236 +vn -0.440962 0.474471 -0.761803 +vn 0.242836 -0.348827 0.905148 +vn 0.257057 -0.122227 0.958617 +vn 0.215339 0.555376 0.803217 +vn 0.012726 0.998840 0.046205 +vn -0.140843 0.839106 -0.525376 +vn -0.202918 0.621845 -0.756371 +vn -0.228217 0.473769 -0.850551 +vn 0.000000 -0.348338 0.937346 +vn 0.000000 -0.122013 0.992523 +vn 0.000000 0.554674 0.832057 +vn 0.000000 0.998810 0.048616 +vn 0.000000 0.838893 -0.544267 +vn 0.000000 0.621387 -0.783471 +vn 0.000000 0.473281 -0.880886 +vn -0.242836 -0.348827 0.905148 +vn -0.257057 -0.122227 0.958617 +vn -0.215308 0.555376 0.803217 +vn -0.012726 0.998840 0.046205 +vn 0.140843 0.839106 -0.525376 +vn 0.202918 0.621845 -0.756371 +vn 0.228217 0.473769 -0.850551 +vn -0.469375 -0.349376 0.810907 +vn -0.497085 -0.122379 0.859004 +vn -0.416425 0.555559 0.719657 +vn -0.024415 0.998810 0.041749 +vn 0.272011 0.839625 -0.470077 +vn 0.391980 0.622608 -0.677236 +vn 0.440962 0.474471 -0.761803 +vn -0.662465 -0.349620 0.662465 +vn -0.701773 -0.122440 0.701773 +vn -0.587878 0.555650 0.587878 +vn -0.034272 0.998810 0.034272 +vn 0.383831 0.839808 -0.383831 +vn 0.553148 0.622913 -0.553148 +vn 0.622303 0.474776 -0.622303 +vn -0.810907 -0.349376 0.469375 +vn -0.859004 -0.122410 0.497085 +vn -0.719657 0.555528 0.416425 +vn -0.041749 0.998810 0.024415 +vn 0.470077 0.839625 -0.272011 +vn 0.677236 0.622639 -0.391980 +vn 0.761803 0.474471 -0.440962 +vn -0.905148 -0.348827 0.242836 +vn -0.958617 -0.122227 0.257057 +vn -0.803217 0.555376 0.215339 +vn -0.046236 0.998840 0.012726 +vn 0.525376 0.839106 -0.140843 +vn 0.756371 0.621845 -0.202918 +vn 0.850551 0.473769 -0.228217 +vn 0.908292 0.418256 0.000000 +vn 0.877041 0.418744 0.235298 +vn 0.920286 0.391156 0.000000 +vn 0.888668 0.391644 0.238441 +vn 0.907315 0.342753 0.243446 +vn 0.785638 0.419416 0.454756 +vn 0.796075 0.392285 0.460799 +vn 0.812830 0.343333 0.470504 +vn 0.931486 0.265542 0.248543 +vn 0.834162 0.266366 0.482864 +vn 0.855312 0.152379 0.495132 +vn 0.966613 -0.042848 0.252602 +vn 0.864498 -0.045808 0.500504 +vn 0.641804 0.419691 0.641804 +vn 0.650349 0.392499 0.650349 +vn 0.664052 0.343577 0.664052 +vn 0.681509 0.266579 0.681509 +vn 0.698813 0.152501 0.698813 +vn 0.706351 -0.045869 0.706351 +vn 0.454756 0.419416 0.785638 +vn 0.460799 0.392285 0.796075 +vn 0.470504 0.343333 0.812830 +vn 0.482864 0.266366 0.834162 +vn 0.495132 0.152409 0.855312 +vn 0.500504 -0.045808 0.864498 +vn 0.235298 0.418744 0.877041 +vn 0.238441 0.391644 0.888668 +vn 0.243446 0.342753 0.907315 +vn 0.249855 0.265908 0.931028 +vn 0.256172 0.152104 0.954558 +vn 0.258980 -0.045717 0.964782 +vn 0.000000 0.418256 0.908292 +vn 0.000000 0.391156 0.920286 +vn 0.000000 0.342357 0.939543 +vn 0.000000 0.265542 0.964080 +vn 0.000000 0.151891 0.988372 +vn 0.000000 -0.045656 0.998932 +vn -0.235298 0.418744 0.877041 +vn -0.238441 0.391644 0.888668 +vn -0.243446 0.342753 0.907315 +vn -0.249855 0.265877 0.931028 +vn -0.256172 0.152104 0.954558 +vn -0.258980 -0.045717 0.964782 +vn -0.454756 0.419416 0.785638 +vn -0.460799 0.392285 0.796075 +vn -0.470504 0.343333 0.812830 +vn -0.482864 0.266366 0.834162 +vn -0.495132 0.152379 0.855312 +vn -0.500504 -0.045808 0.864498 +vn -0.641804 0.419691 0.641804 +vn -0.650349 0.392499 0.650349 +vn -0.664052 0.343577 0.664052 +vn -0.681509 0.266579 0.681509 +vn -0.698813 0.152501 0.698813 +vn -0.706351 -0.045869 0.706351 +vn -0.785638 0.419416 0.454756 +vn -0.796075 0.392285 0.460799 +vn -0.812830 0.343364 0.470504 +vn -0.834162 0.266366 0.482864 +vn -0.855312 0.152379 0.495132 +vn -0.864498 -0.045808 0.500504 +vn -0.907315 0.342753 0.243446 +vn -0.931028 0.265908 0.249855 +vn -0.954558 0.152104 0.256172 +vn -0.964782 -0.045717 0.258980 +vn -0.939543 0.342357 0.000000 +vn -0.964080 0.265542 0.000000 +vn -0.988372 0.151891 0.000000 +vn -0.888668 0.391644 -0.238441 +vn -0.907315 0.342753 -0.243446 +vn -0.931028 0.265877 -0.249855 +vn -0.954558 0.152104 -0.256172 +vn -0.785638 0.419416 -0.454756 +vn -0.796075 0.392285 -0.460799 +vn -0.812830 0.343333 -0.470504 +vn -0.834162 0.266366 -0.482864 +vn -0.855312 0.152379 -0.495132 +vn -0.964782 -0.045717 -0.258980 +vn -0.864498 -0.045808 -0.500504 +vn -0.641804 0.419691 -0.641804 +vn -0.650349 0.392499 -0.650349 +vn -0.664052 0.343577 -0.664052 +vn -0.681509 0.266579 -0.681509 +vn -0.698813 0.152501 -0.698813 +vn -0.706351 -0.045869 -0.706351 +vn -0.454756 0.419416 -0.785638 +vn -0.460799 0.392285 -0.796075 +vn -0.470504 0.343333 -0.812830 +vn -0.482864 0.266366 -0.834162 +vn -0.495132 0.152379 -0.855312 +vn -0.500504 -0.045808 -0.864498 +vn -0.235298 0.418744 -0.877041 +vn -0.238441 0.391644 -0.888668 +vn -0.243446 0.342753 -0.907315 +vn -0.249855 0.265908 -0.931028 +vn -0.256172 0.152104 -0.954558 +vn -0.258980 -0.045717 -0.964782 +vn 0.000000 0.418256 -0.908292 +vn 0.000000 0.391156 -0.920286 +vn 0.000000 0.342357 -0.939543 +vn 0.000000 0.265542 -0.964080 +vn 0.000000 0.151891 -0.988372 +vn 0.000000 -0.045656 -0.998932 +vn 0.235298 0.418744 -0.877041 +vn 0.238441 0.391644 -0.888668 +vn 0.243446 0.342753 -0.907315 +vn 0.249855 0.265877 -0.931028 +vn 0.256172 0.152104 -0.954558 +vn 0.258980 -0.045717 -0.964782 +vn 0.454756 0.419416 -0.785638 +vn 0.460799 0.392285 -0.796075 +vn 0.470504 0.343333 -0.812830 +vn 0.482864 0.266366 -0.834162 +vn 0.495132 0.152379 -0.855312 +vn 0.500504 -0.045808 -0.864498 +vn 0.641804 0.419691 -0.641804 +vn 0.650349 0.392499 -0.650349 +vn 0.664052 0.343577 -0.664052 +vn 0.681509 0.266579 -0.681509 +vn 0.698813 0.152501 -0.698813 +vn 0.706351 -0.045869 -0.706351 +vn 0.785638 0.419416 -0.454756 +vn 0.796075 0.392285 -0.460799 +vn 0.812830 0.343364 -0.470504 +vn 0.834162 0.266366 -0.482864 +vn 0.855312 0.152379 -0.495132 +vn 0.864498 -0.045808 -0.500504 +vn 0.877041 0.418744 -0.235298 +vn 0.888668 0.391644 -0.238441 +vn 0.907315 0.342753 -0.243446 +vn 0.795892 -0.566485 0.213538 +vn 0.712180 -0.701987 0.000000 +vn 0.687399 -0.702445 0.184393 +vn 0.652974 -0.757347 0.000000 +vn 0.630146 -0.757805 0.169012 +vn 0.724021 -0.689749 0.000000 +vn 0.698752 -0.690329 0.187414 +vn 0.886410 -0.462874 0.000000 +vn 0.855861 -0.463454 0.229530 +vn 0.817774 -0.327158 0.473434 +vn 0.712729 -0.567248 0.412549 +vn 0.615345 -0.703146 0.356151 +vn 0.564043 -0.758446 0.326456 +vn 0.625660 -0.690939 0.362102 +vn 0.766625 -0.464125 0.443678 +vn 0.668111 -0.327403 0.668111 +vn 0.582171 -0.567522 0.582171 +vn 0.502579 -0.703421 0.502579 +vn 0.460646 -0.758660 0.460646 +vn 0.510971 -0.691183 0.510971 +vn 0.626209 -0.464370 0.626240 +vn 0.473434 -0.327158 0.817774 +vn 0.412549 -0.567248 0.712729 +vn 0.356151 -0.703146 0.615375 +vn 0.326456 -0.758446 0.564043 +vn 0.362102 -0.690939 0.625660 +vn 0.443678 -0.464125 0.766625 +vn 0.245003 -0.326609 0.912839 +vn 0.213538 -0.566485 0.795892 +vn 0.184393 -0.702445 0.687399 +vn 0.169012 -0.757805 0.630146 +vn 0.187414 -0.690329 0.698752 +vn 0.229530 -0.463454 0.855831 +vn 0.000000 -0.326243 0.945250 +vn 0.000000 -0.565996 0.824396 +vn 0.000000 -0.701987 0.712180 +vn 0.000000 -0.757347 0.652974 +vn 0.000000 -0.689749 0.724021 +vn 0.000000 -0.462905 0.886380 +vn -0.245003 -0.326609 0.912839 +vn -0.213538 -0.566485 0.795892 +vn -0.184393 -0.702445 0.687399 +vn -0.169012 -0.757805 0.630146 +vn -0.187414 -0.690329 0.698752 +vn -0.229530 -0.463454 0.855861 +vn -0.473434 -0.327158 0.817774 +vn -0.412549 -0.567248 0.712729 +vn -0.356151 -0.703146 0.615375 +vn -0.326456 -0.758446 0.564043 +vn -0.362102 -0.690939 0.625660 +vn -0.443678 -0.464125 0.766625 +vn -0.668111 -0.327403 0.668111 +vn -0.582171 -0.567522 0.582171 +vn -0.502579 -0.703421 0.502579 +vn -0.460646 -0.758660 0.460646 +vn -0.510971 -0.691183 0.510971 +vn -0.626209 -0.464370 0.626209 +vn -0.817774 -0.327158 0.473434 +vn -0.712729 -0.567248 0.412549 +vn -0.615375 -0.703146 0.356151 +vn -0.564043 -0.758446 0.326456 +vn -0.625660 -0.690939 0.362102 +vn -0.766625 -0.464125 0.443678 +vn -0.912931 -0.326609 0.244575 +vn -0.687399 -0.702445 0.184393 +vn -0.630146 -0.757805 0.169012 +vn -0.698752 -0.690329 0.187414 +vn -0.855831 -0.463485 0.229530 +vn -0.824396 -0.565996 0.000000 +vn -0.712180 -0.701987 0.000000 +vn -0.652974 -0.757347 0.000000 +vn -0.724021 -0.689749 0.000000 +vn -0.886410 -0.462874 0.000000 +vn -0.795892 -0.566485 -0.213538 +vn -0.687399 -0.702445 -0.184393 +vn -0.630146 -0.757805 -0.169012 +vn -0.698752 -0.690329 -0.187414 +vn -0.855831 -0.463454 -0.229530 +vn -0.817774 -0.327158 -0.473434 +vn -0.712729 -0.567217 -0.412549 +vn -0.615375 -0.703146 -0.356151 +vn -0.564043 -0.758446 -0.326456 +vn -0.625660 -0.690939 -0.362102 +vn -0.766625 -0.464125 -0.443678 +vn -0.668111 -0.327403 -0.668111 +vn -0.582171 -0.567522 -0.582171 +vn -0.502579 -0.703421 -0.502579 +vn -0.460646 -0.758660 -0.460646 +vn -0.510971 -0.691183 -0.510971 +vn -0.626209 -0.464370 -0.626209 +vn -0.473434 -0.327158 -0.817774 +vn -0.412549 -0.567248 -0.712729 +vn -0.356151 -0.703146 -0.615375 +vn -0.326456 -0.758446 -0.564043 +vn -0.362102 -0.690939 -0.625660 +vn -0.443678 -0.464125 -0.766625 +vn -0.245003 -0.326609 -0.912839 +vn -0.213538 -0.566485 -0.795892 +vn -0.184393 -0.702445 -0.687399 +vn -0.169012 -0.757805 -0.630146 +vn -0.187414 -0.690329 -0.698752 +vn -0.229530 -0.463454 -0.855831 +vn 0.000000 -0.326243 -0.945250 +vn 0.000000 -0.565996 -0.824396 +vn 0.000000 -0.701987 -0.712180 +vn 0.000000 -0.757347 -0.652974 +vn 0.000000 -0.689749 -0.724021 +vn 0.000000 -0.462905 -0.886380 +vn 0.245003 -0.326609 -0.912839 +vn 0.213538 -0.566485 -0.795892 +vn 0.184393 -0.702445 -0.687399 +vn 0.169012 -0.757805 -0.630146 +vn 0.187445 -0.690329 -0.698752 +vn 0.229530 -0.463454 -0.855861 +vn 0.473434 -0.327158 -0.817774 +vn 0.412549 -0.567248 -0.712729 +vn 0.356151 -0.703146 -0.615375 +vn 0.326456 -0.758446 -0.564043 +vn 0.362102 -0.690939 -0.625660 +vn 0.443678 -0.464125 -0.766625 +vn 0.668111 -0.327403 -0.668111 +vn 0.582171 -0.567522 -0.582171 +vn 0.502579 -0.703421 -0.502579 +vn 0.460646 -0.758660 -0.460646 +vn 0.510971 -0.691183 -0.510971 +vn 0.626209 -0.464370 -0.626209 +vn 0.817774 -0.327158 -0.473434 +vn 0.712729 -0.567248 -0.412549 +vn 0.615375 -0.703146 -0.356151 +vn 0.564043 -0.758446 -0.326456 +vn 0.625660 -0.690939 -0.362102 +vn 0.766625 -0.464125 -0.443678 +vn 0.912839 -0.326609 -0.244942 +vn 0.795892 -0.566485 -0.213538 +vn 0.687399 -0.702445 -0.184393 +vn 0.630146 -0.757805 -0.169012 +vn 0.698752 -0.690329 -0.187414 +vn 0.855861 -0.463454 -0.229530 +vn 0.025666 -0.999664 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.024781 -0.999664 -0.006623 +vn 0.068667 -0.997620 0.000000 +vn 0.066256 -0.997620 -0.017731 +vn 0.157170 -0.987548 0.000000 +vn 0.151677 -0.987579 -0.040620 +vn 0.373150 -0.927763 0.000000 +vn 0.360118 -0.927885 -0.096469 +vn 0.789148 -0.614154 0.000000 +vn 0.762017 -0.614399 -0.204505 +vn 0.022156 -0.999664 -0.012787 +vn 0.059236 -0.997650 -0.034272 +vn 0.135624 -0.987640 -0.078463 +vn 0.322153 -0.928129 -0.186377 +vn 0.682333 -0.615131 -0.394971 +vn 0.018067 -0.999664 -0.018067 +vn 0.048341 -0.997650 -0.048341 +vn 0.110691 -0.987640 -0.110691 +vn 0.262947 -0.928251 -0.262947 +vn 0.557329 -0.615375 -0.557329 +vn 0.012787 -0.999664 -0.022156 +vn 0.034272 -0.997650 -0.059236 +vn 0.078463 -0.987640 -0.135624 +vn 0.186377 -0.928129 -0.322153 +vn 0.394971 -0.615131 -0.682302 +vn 0.006623 -0.999664 -0.024781 +vn 0.017731 -0.997620 -0.066256 +vn 0.040620 -0.987579 -0.151677 +vn 0.096469 -0.927885 -0.360118 +vn 0.204474 -0.614399 -0.762017 +vn 0.000000 -0.999664 -0.025666 +vn 0.000000 -0.997620 -0.068667 +vn 0.000000 -0.987548 -0.157170 +vn 0.000000 -0.927763 -0.373150 +vn 0.000000 -0.614154 -0.789148 +vn -0.006623 -0.999664 -0.024781 +vn -0.017731 -0.997620 -0.066256 +vn -0.040620 -0.987579 -0.151677 +vn -0.096469 -0.927885 -0.360118 +vn -0.204474 -0.614399 -0.762017 +vn -0.012787 -0.999664 -0.022156 +vn -0.034272 -0.997650 -0.059236 +vn -0.078463 -0.987640 -0.135624 +vn -0.186377 -0.928129 -0.322153 +vn -0.394971 -0.615131 -0.682333 +vn -0.018067 -0.999664 -0.018067 +vn -0.048341 -0.997650 -0.048341 +vn -0.110691 -0.987640 -0.110691 +vn -0.262947 -0.928251 -0.262947 +vn -0.557329 -0.615375 -0.557329 +vn -0.022156 -0.999664 -0.012787 +vn -0.059236 -0.997650 -0.034272 +vn -0.135624 -0.987640 -0.078463 +vn -0.322153 -0.928129 -0.186377 +vn -0.682302 -0.615131 -0.394971 +vn -0.024781 -0.999664 -0.006623 +vn -0.066256 -0.997620 -0.017731 +vn -0.151677 -0.987579 -0.040620 +vn -0.360118 -0.927885 -0.096469 +vn -0.762017 -0.614399 -0.204474 +vn -0.025666 -0.999664 0.000000 +vn -0.068667 -0.997620 0.000000 +vn -0.157170 -0.987548 0.000000 +vn -0.373150 -0.927763 0.000000 +vn -0.789148 -0.614154 0.000000 +vn -0.024781 -0.999664 0.006623 +vn -0.066256 -0.997620 0.017731 +vn -0.151677 -0.987579 0.040620 +vn -0.360149 -0.927885 0.096469 +vn -0.762017 -0.614399 0.204474 +vn -0.022156 -0.999664 0.012787 +vn -0.059236 -0.997650 0.034272 +vn -0.135624 -0.987640 0.078463 +vn -0.322153 -0.928129 0.186377 +vn -0.682333 -0.615131 0.394971 +vn -0.018067 -0.999664 0.018067 +vn -0.048341 -0.997650 0.048341 +vn -0.110691 -0.987640 0.110691 +vn -0.262947 -0.928251 0.262947 +vn -0.557329 -0.615375 0.557329 +vn -0.012787 -0.999664 0.022156 +vn -0.034272 -0.997650 0.059236 +vn -0.078463 -0.987640 0.135624 +vn -0.186377 -0.928129 0.322153 +vn -0.394971 -0.615131 0.682302 +vn -0.006623 -0.999664 0.024781 +vn -0.017731 -0.997620 0.066256 +vn -0.040620 -0.987579 0.151677 +vn -0.096469 -0.927885 0.360118 +vn -0.204474 -0.614399 0.762017 +vn 0.000000 -0.999664 0.025666 +vn 0.000000 -0.997620 0.068667 +vn 0.000000 -0.987548 0.157170 +vn 0.000000 -0.927763 0.373150 +vn 0.000000 -0.614154 0.789148 +vn 0.006623 -0.999664 0.024781 +vn 0.017731 -0.997620 0.066256 +vn 0.040620 -0.987579 0.151677 +vn 0.096469 -0.927885 0.360149 +vn 0.204474 -0.614399 0.762017 +vn 0.012787 -0.999664 0.022156 +vn 0.034272 -0.997650 0.059236 +vn 0.078463 -0.987640 0.135624 +vn 0.186377 -0.928129 0.322153 +vn 0.394971 -0.615131 0.682333 +vn 0.018067 -0.999664 0.018067 +vn 0.048341 -0.997650 0.048341 +vn 0.110691 -0.987640 0.110691 +vn 0.262947 -0.928251 0.262947 +vn 0.557329 -0.615375 0.557329 +vn 0.022156 -0.999664 0.012787 +vn 0.059236 -0.997650 0.034272 +vn 0.135624 -0.987640 0.078463 +vn 0.322153 -0.928129 0.186346 +vn 0.682302 -0.615131 0.394971 +vn 0.024781 -0.999664 0.006623 +vn 0.066256 -0.997620 0.017731 +vn 0.151677 -0.987579 0.040620 +vn 0.360118 -0.927885 0.096469 +vn 0.762017 -0.614399 0.204474 +vn 0.464827 -0.373638 -0.802667 +vn 0.655812 -0.373882 -0.655812 +vn 0.000000 -0.372539 0.927976 +vn -0.240699 -0.373028 0.896023 +vn -0.802667 -0.373608 0.464827 +vn 0.896023 -0.372997 -0.240699 +vn -0.927976 -0.372539 0.000000 +vn 0.927976 -0.372539 0.000000 +vn 0.717063 0.696982 0.000000 +vn 0.990387 -0.138310 -0.000061 +vn 0.956694 -0.138737 0.255806 +vn 0.692129 0.697470 0.185583 +vn 0.857326 -0.139317 0.495529 +vn 0.620045 0.697653 0.358837 +vn 0.700125 -0.139531 0.700217 +vn 0.506516 0.697714 0.506546 +vn 0.495468 -0.139286 0.857356 +vn 0.358776 0.697714 0.620014 +vn 0.255867 -0.138737 0.956694 +vn 0.185583 0.697531 0.692068 +vn 0.000061 -0.138310 0.990387 +vn 0.000000 0.696982 0.717063 +vn -0.255806 -0.138737 0.956694 +vn -0.185583 0.697470 0.692129 +vn -0.495529 -0.139317 0.857326 +vn -0.358837 0.697653 0.620045 +vn -0.700217 -0.139531 0.700156 +vn -0.506546 0.697714 0.506516 +vn -0.857356 -0.139286 0.495468 +vn -0.620014 0.697714 0.358776 +vn -0.956694 -0.138737 0.255867 +vn -0.692068 0.697531 0.185583 +vn -0.990387 -0.138310 0.000061 +vn -0.717063 0.696982 0.000000 +vn -0.956694 -0.138737 -0.255806 +vn -0.692129 0.697470 -0.185583 +vn -0.857326 -0.139317 -0.495529 +vn -0.620045 0.697653 -0.358837 +vn -0.700125 -0.139531 -0.700217 +vn -0.506516 0.697714 -0.506546 +vn -0.495468 -0.139286 -0.857356 +vn -0.358776 0.697714 -0.620014 +vn -0.255867 -0.138737 -0.956694 +vn -0.185583 0.697531 -0.692068 +vn -0.000061 -0.138310 -0.990387 +vn 0.000000 0.696982 -0.717063 +vn 0.255806 -0.138737 -0.956694 +vn 0.185583 0.697470 -0.692129 +vn 0.495529 -0.139317 -0.857326 +vn 0.358837 0.697653 -0.620045 +vn 0.700217 -0.139531 -0.700156 +vn 0.506546 0.697714 -0.506516 +vn 0.857356 -0.139286 -0.495468 +vn 0.620014 0.697714 -0.358776 +vn 0.956694 -0.138737 -0.255867 +vn 0.692068 0.697531 -0.185583 +vn 0.292520 0.956236 0.000000 +vn 0.282083 0.956389 0.075686 +vn 0.177953 0.984008 0.000000 +vn 0.171606 0.984069 0.046022 +vn 0.158879 0.987274 0.000000 +vn 0.153264 0.987304 0.041078 +vn 0.217719 0.975982 0.000000 +vn 0.210059 0.976043 0.056276 +vn 0.504715 0.863277 0.000000 +vn 0.487197 0.863460 0.130558 +vn 0.693258 0.720664 0.000000 +vn 0.669057 0.721183 0.179449 +vn 0.252388 0.956511 0.146092 +vn 0.153508 0.984130 0.088839 +vn 0.137059 0.987365 0.079318 +vn 0.187872 0.976135 0.108676 +vn 0.435926 0.863887 0.252205 +vn 0.598956 0.721824 0.346660 +vn 0.206091 0.956572 0.206091 +vn 0.125340 0.984161 0.125340 +vn 0.111911 0.987396 0.111911 +vn 0.153356 0.976196 0.153356 +vn 0.355907 0.864071 0.355907 +vn 0.489151 0.722098 0.489151 +vn 0.146092 0.956511 0.252388 +vn 0.088839 0.984130 0.153508 +vn 0.079318 0.987365 0.137059 +vn 0.108676 0.976135 0.187872 +vn 0.252205 0.863887 0.435926 +vn 0.346660 0.721824 0.598956 +vn 0.075686 0.956389 0.282083 +vn 0.046022 0.984069 0.171606 +vn 0.041078 0.987304 0.153264 +vn 0.056276 0.976043 0.210059 +vn 0.130558 0.863460 0.487197 +vn 0.179449 0.721183 0.669057 +vn 0.000000 0.956236 0.292520 +vn 0.000000 0.984008 0.177953 +vn 0.000000 0.987274 0.158879 +vn 0.000000 0.975982 0.217719 +vn 0.000000 0.863277 0.504715 +vn 0.000000 0.720664 0.693258 +vn -0.075686 0.956389 0.282083 +vn -0.046022 0.984069 0.171606 +vn -0.041078 0.987304 0.153264 +vn -0.056276 0.976043 0.210059 +vn -0.130558 0.863460 0.487197 +vn -0.179449 0.721183 0.669057 +vn -0.146092 0.956511 0.252388 +vn -0.088839 0.984130 0.153508 +vn -0.079318 0.987365 0.137059 +vn -0.108676 0.976135 0.187872 +vn -0.252205 0.863887 0.435926 +vn -0.346660 0.721824 0.598956 +vn -0.206091 0.956572 0.206091 +vn -0.125340 0.984161 0.125340 +vn -0.111911 0.987396 0.111911 +vn -0.153356 0.976196 0.153356 +vn -0.355907 0.864071 0.355907 +vn -0.489151 0.722098 0.489151 +vn -0.252388 0.956511 0.146092 +vn -0.153508 0.984130 0.088839 +vn -0.137059 0.987365 0.079318 +vn -0.187872 0.976135 0.108676 +vn -0.435926 0.863887 0.252205 +vn -0.598956 0.721824 0.346660 +vn -0.282083 0.956389 0.075686 +vn -0.171606 0.984069 0.046022 +vn -0.153264 0.987304 0.041078 +vn -0.210059 0.976043 0.056276 +vn -0.487197 0.863460 0.130558 +vn -0.669057 0.721183 0.179449 +vn -0.292520 0.956236 0.000000 +vn -0.177953 0.984008 0.000000 +vn -0.158879 0.987274 0.000000 +vn -0.217719 0.975982 0.000000 +vn -0.504715 0.863277 0.000000 +vn -0.693258 0.720664 0.000000 +vn -0.282083 0.956389 -0.075686 +vn -0.171606 0.984069 -0.046022 +vn -0.153264 0.987304 -0.041078 +vn -0.210059 0.976043 -0.056276 +vn -0.487197 0.863460 -0.130558 +vn -0.669057 0.721183 -0.179449 +vn -0.252388 0.956511 -0.146092 +vn -0.153508 0.984130 -0.088839 +vn -0.137059 0.987365 -0.079318 +vn -0.187872 0.976135 -0.108676 +vn -0.435926 0.863887 -0.252205 +vn -0.598956 0.721824 -0.346660 +vn -0.206091 0.956572 -0.206091 +vn -0.125340 0.984161 -0.125340 +vn -0.111911 0.987396 -0.111911 +vn -0.153356 0.976196 -0.153356 +vn -0.355907 0.864071 -0.355907 +vn -0.489151 0.722098 -0.489151 +vn -0.146092 0.956511 -0.252388 +vn -0.088839 0.984130 -0.153508 +vn -0.079318 0.987365 -0.137059 +vn -0.108676 0.976135 -0.187872 +vn -0.252205 0.863887 -0.435926 +vn -0.346660 0.721824 -0.598956 +vn -0.075686 0.956389 -0.282083 +vn -0.046022 0.984069 -0.171606 +vn -0.041078 0.987304 -0.153264 +vn -0.056276 0.976043 -0.210059 +vn -0.130558 0.863460 -0.487197 +vn -0.179449 0.721183 -0.669057 +vn 0.000000 0.956236 -0.292520 +vn 0.000000 0.984008 -0.177953 +vn 0.000000 0.987274 -0.158879 +vn 0.000000 0.975982 -0.217719 +vn 0.000000 0.863277 -0.504715 +vn 0.000000 0.720664 -0.693258 +vn 0.075686 0.956389 -0.282083 +vn 0.046022 0.984069 -0.171606 +vn 0.041078 0.987304 -0.153264 +vn 0.056276 0.976043 -0.210059 +vn 0.130558 0.863460 -0.487197 +vn 0.179449 0.721183 -0.669057 +vn 0.146092 0.956511 -0.252388 +vn 0.088839 0.984130 -0.153508 +vn 0.079318 0.987365 -0.137059 +vn 0.108676 0.976135 -0.187872 +vn 0.252205 0.863887 -0.435926 +vn 0.346660 0.721824 -0.598956 +vn 0.206091 0.956572 -0.206091 +vn 0.125340 0.984161 -0.125340 +vn 0.111911 0.987396 -0.111911 +vn 0.153356 0.976196 -0.153356 +vn 0.355907 0.864071 -0.355907 +vn 0.489151 0.722098 -0.489151 +vn 0.252388 0.956511 -0.146092 +vn 0.153508 0.984130 -0.088839 +vn 0.137059 0.987365 -0.079318 +vn 0.187872 0.976135 -0.108676 +vn 0.435926 0.863887 -0.252205 +vn 0.598956 0.721824 -0.346660 +vn 0.282083 0.956389 -0.075686 +vn 0.171606 0.984069 -0.046022 +vn 0.153264 0.987304 -0.041078 +vn 0.210059 0.976043 -0.056276 +vn 0.487197 0.863460 -0.130558 +vn 0.669057 0.721183 -0.179449 +vn 0.363842 0.931455 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.351451 0.931516 0.093509 +vn 0.968261 0.249916 0.000000 +vn 0.935423 0.249763 0.250130 +vn 0.842860 -0.538102 0.000000 +vn 0.813959 -0.538713 0.217292 +vn 0.786767 -0.617206 -0.000031 +vn 0.759514 -0.618000 0.202857 +vn 0.314432 0.931791 0.181280 +vn 0.838404 0.249855 0.484359 +vn 0.729026 -0.539720 0.420911 +vn 0.680013 -0.619068 0.392743 +vn 0.256386 0.931913 0.256417 +vn 0.684652 0.249886 0.684652 +vn 0.595050 -0.540147 0.595050 +vn 0.555010 -0.619526 0.555040 +vn 0.181280 0.931791 0.314432 +vn 0.484359 0.249825 0.838404 +vn 0.420881 -0.539720 0.729026 +vn 0.392712 -0.619098 0.680013 +vn 0.093509 0.931516 0.351451 +vn 0.250160 0.249763 0.935423 +vn 0.217322 -0.538713 0.813959 +vn 0.202887 -0.618030 0.759484 +vn 0.000000 0.931455 0.363842 +vn 0.000000 0.249916 0.968261 +vn 0.000000 -0.538102 0.842860 +vn 0.000031 -0.617206 0.786767 +vn -0.093509 0.931516 0.351451 +vn -0.250130 0.249763 0.935423 +vn -0.217292 -0.538682 0.813959 +vn -0.202857 -0.618000 0.759514 +vn -0.181280 0.931791 0.314432 +vn -0.484359 0.249855 0.838404 +vn -0.420911 -0.539720 0.729026 +vn -0.392743 -0.619068 0.680013 +vn -0.256417 0.931913 0.256386 +vn -0.684652 0.249886 0.684652 +vn -0.595050 -0.540147 0.595050 +vn -0.555040 -0.619526 0.555010 +vn -0.314432 0.931791 0.181280 +vn -0.838404 0.249825 0.484359 +vn -0.729026 -0.539720 0.420881 +vn -0.680013 -0.619098 0.392712 +vn -0.351451 0.931516 0.093509 +vn -0.935423 0.249763 0.250160 +vn -0.813959 -0.538713 0.217292 +vn -0.759484 -0.618030 0.202887 +vn -0.363842 0.931455 0.000000 +vn -0.968261 0.249916 0.000000 +vn -0.842860 -0.538102 0.000000 +vn -0.786767 -0.617206 0.000031 +vn -0.351451 0.931516 -0.093509 +vn -0.935423 0.249763 -0.250130 +vn -0.813959 -0.538713 -0.217292 +vn -0.759514 -0.618000 -0.202857 +vn -0.314432 0.931791 -0.181280 +vn -0.838404 0.249855 -0.484359 +vn -0.729026 -0.539720 -0.420911 +vn -0.680013 -0.619068 -0.392743 +vn -0.256386 0.931913 -0.256417 +vn -0.684652 0.249886 -0.684652 +vn -0.595050 -0.540147 -0.595050 +vn -0.555010 -0.619526 -0.555040 +vn -0.181280 0.931791 -0.314432 +vn -0.484359 0.249825 -0.838404 +vn -0.420881 -0.539720 -0.729026 +vn -0.392712 -0.619098 -0.680013 +vn -0.093509 0.931516 -0.351451 +vn -0.250160 0.249763 -0.935423 +vn -0.217322 -0.538713 -0.813959 +vn -0.202887 -0.618030 -0.759484 +vn 0.000000 0.931455 -0.363842 +vn 0.000000 0.249916 -0.968261 +vn 0.000000 -0.538102 -0.842860 +vn -0.000031 -0.617206 -0.786767 +vn 0.093509 0.931516 -0.351451 +vn 0.250130 0.249763 -0.935423 +vn 0.217292 -0.538682 -0.813959 +vn 0.202857 -0.618000 -0.759514 +vn 0.181280 0.931791 -0.314432 +vn 0.484359 0.249855 -0.838404 +vn 0.420911 -0.539720 -0.729026 +vn 0.392743 -0.619068 -0.680013 +vn 0.256417 0.931913 -0.256386 +vn 0.684652 0.249886 -0.684652 +vn 0.595050 -0.540147 -0.595050 +vn 0.555040 -0.619526 -0.555010 +vn 0.314432 0.931791 -0.181280 +vn 0.838404 0.249825 -0.484359 +vn 0.729026 -0.539720 -0.420881 +vn 0.680013 -0.619098 -0.392712 +vn 0.351451 0.931516 -0.093509 +vn 0.935423 0.249763 -0.250160 +vn 0.813959 -0.538713 -0.217292 +vn 0.759484 -0.618030 -0.202887 +vn -0.354198 0.930296 -0.095187 +vn 0.095187 0.930296 0.354198 +vn 0.354198 0.930296 0.095187 +vn 0.183721 0.930387 0.317179 +vn -0.183721 0.930387 -0.317179 +vn -0.367443 0.930021 0.000000 +vn -0.183721 0.930387 0.317179 +vn 0.367412 0.930021 0.000000 +vn -0.317179 0.930387 0.183721 +vn -0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 -0.367443 +vn -0.354198 0.930296 0.095187 +vn 0.095187 0.930296 -0.354198 +vn 0.000000 0.930021 0.367443 +vn -0.317179 0.930387 -0.183721 +vn 0.317179 0.930387 -0.183721 +vn -0.095187 0.930296 0.354198 +vn 0.317179 0.930387 0.183721 +vn 0.354198 0.930296 -0.095187 +vn 0.183721 0.930387 -0.317179 +vn -0.034730 0.999390 0.000000 +vn 0.033479 0.999390 -0.009003 +vn 0.034730 0.999390 0.000000 +vn 0.009003 0.999390 -0.033479 +vn 0.000000 0.999390 -0.034730 +vn -0.259163 0.930387 0.259163 +vn -0.017335 0.999390 0.029939 +vn 0.947539 0.295083 0.122654 +vn -0.004486 0.999969 0.000000 +vn -0.004151 0.950468 0.310739 +vn -0.003021 0.719291 0.694662 +vn -0.998688 0.050722 0.000000 +vn -0.003143 0.719321 -0.694632 +vn 0.970214 0.213324 -0.114505 +vn -0.136235 0.879482 -0.455947 +vn 0.949858 0.312662 0.000000 +vn 0.055757 -0.017579 -0.998260 +vn 0.201300 -0.540880 -0.816645 +vn 0.974456 -0.186071 -0.125645 +vn 0.988098 -0.096286 0.119938 +vn 0.974456 -0.186041 0.125614 +vn -0.879574 -0.475723 0.000000 +vn -0.873775 -0.472610 -0.114475 +vn 0.988067 -0.096286 -0.119938 +vn 0.295480 -0.855464 -0.425214 +vn -0.976196 -0.174993 -0.127903 +vn -0.971007 -0.205725 0.121677 +vn -0.976196 -0.174963 0.127903 +vn -0.976196 -0.174993 0.127903 +vn 0.896054 -0.372997 0.240699 +vn -0.802667 -0.373638 -0.464827 +vn -0.655812 -0.373852 -0.655812 +vn -0.240699 -0.373028 -0.896023 +vn -0.464827 -0.373638 -0.802667 +vn -0.896023 -0.373028 0.240699 +vn 0.000000 -0.372539 -0.927976 +vn -0.655812 -0.373852 0.655812 +vn 0.240699 -0.373028 0.896023 +vn -0.896023 -0.373028 -0.240699 +vn 0.802667 -0.373638 -0.464827 +vn 0.655812 -0.373882 0.655812 +vn 0.464827 -0.373638 0.802667 +vn -0.464827 -0.373638 0.802667 +vn 0.240699 -0.373028 -0.896023 +vn 0.802667 -0.373638 0.464827 +vn -0.033479 0.999390 0.009003 +vn -0.259163 0.930387 -0.259163 +vn -0.024445 0.999390 -0.024445 +vn -0.029939 0.999390 -0.017335 +vn 0.259163 0.930387 -0.259163 +vn 0.024445 0.999390 -0.024445 +vn 0.017335 0.999390 -0.029939 +vn 0.029939 0.999390 -0.017335 +vn 0.033479 0.999390 0.009003 +vn -0.009003 0.999390 0.033479 +vn 0.000000 0.999390 0.034730 +vn -0.017335 0.999390 -0.029939 +vn 0.259163 0.930387 0.259163 +vn 0.029939 0.999390 0.017335 +vn -0.009003 0.999390 -0.033479 +vn 0.024445 0.999390 0.024445 +vn 0.017335 0.999390 0.029939 +vn 0.009003 0.999390 0.033479 +vn -0.033479 0.999390 -0.009003 +vn -0.024445 0.999390 0.024445 +vn -0.029939 0.999390 0.017335 +vn 0.055757 -0.017579 0.998260 +vn 0.294198 -0.855403 0.426252 +vn 0.201300 -0.540880 0.816614 +s 1 +f 34//1 1243//2 593//3 +f 52//4 27//5 40//6 +f 52//4 40//6 65//7 +f 77//8 52//4 65//7 +f 77//8 65//7 84//9 +f 107//10 77//8 84//9 +f 107//10 84//9 85//11 +f 115//12 107//10 85//11 +f 115//12 85//11 99//13 +f 129//14 115//12 99//13 +f 129//14 99//13 128//15 +f 1252//16 36//17 40//6 +f 65//7 40//6 64//18 +f 65//7 64//18 58//19 +f 84//9 65//7 58//19 +f 84//9 58//19 59//20 +f 85//11 84//9 59//20 +f 85//11 59//20 70//21 +f 99//13 85//11 70//21 +f 99//13 70//21 98//22 +f 128//15 99//13 98//22 +f 128//15 98//22 114//23 +f 1244//24 33//25 64//18 +f 58//19 64//18 33//25 +f 58//19 33//25 35//26 +f 59//20 58//19 35//26 +f 59//20 35//26 45//27 +f 70//21 59//20 45//27 +f 70//21 45//27 69//28 +f 98//22 70//21 69//28 +f 98//22 69//28 83//29 +f 114//23 98//22 83//29 +f 114//23 83//29 113//30 +f 553//31 1//32 566//33 +f 35//26 33//25 20//34 +f 35//26 20//34 24//35 +f 45//27 35//26 24//35 +f 45//27 24//35 44//36 +f 69//28 45//27 44//36 +f 69//28 44//36 57//37 +f 83//29 69//28 57//37 +f 83//29 57//37 82//38 +f 113//30 83//29 82//38 +f 113//30 82//38 112//39 +f 566//33 1283//40 9//41 +f 24//35 20//34 18//42 +f 24//35 18//42 23//43 +f 44//36 24//35 23//43 +f 44//36 23//43 32//44 +f 57//37 44//36 32//44 +f 57//37 32//44 56//45 +f 82//38 57//37 56//45 +f 82//38 56//45 81//46 +f 112//39 82//38 81//46 +f 112//39 81//46 111//47 +f 4//48 8//49 1250//50 +f 23//43 18//42 8//49 +f 23//43 8//49 17//51 +f 32//44 23//43 17//51 +f 32//44 17//51 31//52 +f 56//45 32//44 31//52 +f 56//45 31//52 55//53 +f 81//46 56//45 55//53 +f 81//46 55//53 80//54 +f 111//47 81//46 80//54 +f 111//47 80//54 110//55 +f 565//56 592//57 1233//58 +f 17//51 8//49 4//48 +f 17//51 4//48 16//59 +f 31//52 17//51 16//59 +f 31//52 16//59 30//60 +f 55//53 31//52 30//60 +f 55//53 30//60 54//61 +f 80//54 55//53 54//61 +f 80//54 54//61 79//62 +f 110//55 80//54 79//62 +f 110//55 79//62 109//63 +f 1//32 565//56 2//64 +f 6//65 2//64 565//56 +f 16//59 4//48 7//66 +f 16//59 7//66 22//67 +f 30//60 16//59 22//67 +f 30//60 22//67 43//68 +f 54//61 30//60 43//68 +f 54//61 43//68 68//69 +f 79//62 54//61 68//69 +f 79//62 68//69 97//70 +f 109//63 79//62 97//70 +f 109//63 97//70 127//71 +f 565//56 1233//58 1249//58 +f 13//72 14//73 5//74 +f 22//67 7//66 15//75 +f 22//67 15//75 29//76 +f 43//68 22//67 29//76 +f 43//68 29//76 42//77 +f 68//69 43//68 42//77 +f 68//69 42//77 67//78 +f 97//70 68//69 67//78 +f 97//70 67//78 96//79 +f 127//71 97//70 96//79 +f 127//71 96//79 126//80 +f 11//81 15//75 1240//82 +f 1289//83 34//1 593//3 +f 29//76 15//75 14//73 +f 29//76 14//73 21//84 +f 42//77 29//76 21//84 +f 42//77 21//84 41//85 +f 67//78 42//77 41//85 +f 67//78 41//85 66//86 +f 96//79 67//78 66//86 +f 96//79 66//86 95//87 +f 126//80 96//79 95//87 +f 126//80 95//87 125//88 +f 636//89 1243//2 26//2 +f 636//89 26//2 592//57 +f 21//84 14//73 13//72 +f 21//84 13//72 28//90 +f 41//85 21//84 28//90 +f 41//85 28//90 53//91 +f 66//86 41//85 53//91 +f 66//86 53//91 78//92 +f 95//87 66//86 78//92 +f 95//87 78//92 108//93 +f 125//88 95//87 108//93 +f 125//88 108//93 136//94 +f 12//95 13//72 5//74 +f 28//90 13//72 27//5 +f 28//90 27//5 52//4 +f 53//91 28//90 52//4 +f 53//91 52//4 77//8 +f 78//92 53//91 77//8 +f 78//92 77//8 107//10 +f 108//93 78//92 107//10 +f 108//93 107//10 115//12 +f 136//94 108//93 115//12 +f 136//94 115//12 129//14 +f 148//96 129//14 128//15 +f 148//96 128//15 143//97 +f 121//98 148//96 143//97 +f 121//98 143//97 122//99 +f 92//100 121//98 122//99 +f 92//100 122//99 93//101 +f 62//102 92//100 93//101 +f 62//102 93//101 63//103 +f 39//104 62//102 63//103 +f 39//104 63//103 51//105 +f 10//106 39//104 51//105 +f 10//106 51//105 49//107 +f 143//97 128//15 114//23 +f 143//97 114//23 142//108 +f 122//99 143//97 142//108 +f 122//99 142//108 123//109 +f 93//101 122//99 123//109 +f 93//101 123//109 94//110 +f 63//103 93//101 94//110 +f 63//103 94//110 76//111 +f 51//105 63//103 76//111 +f 51//105 76//111 75//112 +f 49//107 51//105 75//112 +f 49//107 75//112 61//113 +f 142//108 114//23 113//30 +f 142//108 113//30 141//114 +f 123//109 142//108 141//114 +f 123//109 141//114 124//115 +f 94//110 123//109 124//115 +f 94//110 124//115 106//116 +f 76//111 94//110 106//116 +f 76//111 106//116 105//117 +f 75//112 76//111 105//117 +f 75//112 105//117 91//118 +f 61//113 75//112 91//118 +f 61//113 91//118 90//119 +f 141//114 113//30 112//39 +f 141//114 112//39 140//120 +f 124//115 141//114 140//120 +f 124//115 140//120 135//121 +f 106//116 124//115 135//121 +f 106//116 135//121 134//122 +f 105//117 106//116 134//122 +f 105//117 134//122 120//123 +f 91//118 105//117 120//123 +f 91//118 120//123 119//124 +f 90//119 91//118 119//124 +f 140//120 112//39 111//47 +f 140//120 111//47 139//125 +f 135//121 140//120 139//125 +f 135//121 139//125 155//126 +f 134//122 135//121 155//126 +f 134//122 155//126 147//127 +f 120//123 134//122 147//127 +f 120//123 147//127 144//128 +f 119//124 120//123 144//128 +f 119//124 144//128 116//129 +f 26//2 1234//130 592//57 +f 139//125 111//47 110//55 +f 139//125 110//55 138//131 +f 155//126 139//125 138//131 +f 155//126 138//131 156//132 +f 147//127 155//126 156//132 +f 147//127 156//132 145//133 +f 144//128 147//127 145//133 +f 144//128 145//133 117//134 +f 116//129 144//128 117//134 +f 116//129 117//134 88//135 +f 27//5 13//72 12//95 +f 1242//136 88//135 71//137 +f 138//131 110//55 109//63 +f 138//131 109//63 137//138 +f 156//132 138//131 137//138 +f 156//132 137//138 154//139 +f 145//133 156//132 154//139 +f 145//133 154//139 131//140 +f 117//134 145//133 131//140 +f 117//134 131//140 101//141 +f 88//135 117//134 101//141 +f 88//135 101//141 86//142 +f 60//143 74//144 1248//145 +f 137//138 109//63 127//71 +f 137//138 127//71 151//146 +f 154//139 137//138 151//146 +f 154//139 151//146 153//147 +f 131//140 154//139 153//147 +f 131//140 153//147 130//148 +f 101//141 131//140 130//148 +f 101//141 130//148 100//149 +f 86//142 101//141 100//149 +f 86//142 100//149 74//144 +f 47//150 1235//151 631//152 +f 74//144 48//153 1248//145 +f 151//146 127//71 126//80 +f 151//146 126//80 150//154 +f 153//147 151//146 150//154 +f 153//147 150//154 146//155 +f 130//148 153//147 146//155 +f 130//148 146//155 118//156 +f 100//149 130//148 118//156 +f 100//149 118//156 89//157 +f 74//144 100//149 89//157 +f 74//144 89//157 48//153 +f 1247//158 87//159 715//160 +f 104//161 116//129 1242//136 +f 150//154 126//80 125//88 +f 150//154 125//88 149//162 +f 146//155 150//154 149//162 +f 146//155 149//162 132//163 +f 118//156 146//155 132//163 +f 118//156 132//163 102//164 +f 89//157 118//156 102//164 +f 89//157 102//164 72//165 +f 48//153 89//157 72//165 +f 48//153 72//165 46//166 +f 37//167 48//153 46//166 +f 37//167 46//166 38//168 +f 149//162 125//88 136//94 +f 149//162 136//94 152//169 +f 132//163 149//162 152//169 +f 132//163 152//169 133//170 +f 102//164 132//163 133//170 +f 102//164 133//170 103//171 +f 72//165 102//164 103//171 +f 72//165 103//171 73//172 +f 46//166 72//165 73//172 +f 46//166 73//172 50//173 +f 38//168 46//166 50//173 +f 38//168 50//173 25//174 +f 152//169 136//94 129//14 +f 152//169 129//14 148//96 +f 133//170 152//169 148//96 +f 133//170 148//96 121//98 +f 103//171 133//170 121//98 +f 103//171 121//98 92//100 +f 73//172 103//171 92//100 +f 73//172 92//100 62//102 +f 50//173 73//172 62//102 +f 50//173 62//102 39//104 +f 25//174 50//173 39//104 +f 39//104 10//106 25//174 +f 539//175 509//176 159//177 +f 160//178 158//179 157//180 +f 166//181 160//178 163//182 +f 166//181 163//182 173//183 +f 177//184 166//181 173//183 +f 177//184 173//183 183//185 +f 189//186 177//184 183//185 +f 189//186 183//185 197//187 +f 205//188 189//186 197//187 +f 205//188 197//187 216//189 +f 225//190 205//188 216//189 +f 225//190 216//189 235//191 +f 173//183 163//182 172//192 +f 173//183 172//192 184//193 +f 183//185 173//183 184//193 +f 183//185 184//193 198//194 +f 197//187 183//185 198//194 +f 197//187 198//194 217//195 +f 216//189 197//187 217//195 +f 216//189 217//195 236//196 +f 235//191 216//189 236//196 +f 235//191 236//196 253//197 +f 182//198 172//192 1254//199 +f 1255//200 167//201 595//202 +f 184//193 172//192 182//198 +f 184//193 182//198 196//203 +f 198//194 184//193 196//203 +f 198//194 196//203 214//204 +f 217//195 198//194 214//204 +f 217//195 214//204 232//205 +f 236//196 217//195 232//205 +f 236//196 232//205 250//206 +f 253//197 236//196 250//206 +f 253//197 250//206 267//207 +f 196//203 182//198 199//208 +f 196//203 199//208 215//209 +f 214//204 196//203 215//209 +f 214//204 215//209 233//210 +f 232//205 214//204 233//210 +f 232//205 233//210 251//211 +f 250//206 232//205 251//211 +f 250//206 251//211 257//212 +f 267//207 250//206 257//212 +f 267//207 257//212 256//213 +f 215//209 199//208 218//214 +f 215//209 218//214 234//215 +f 233//210 215//209 234//215 +f 233//210 234//215 241//216 +f 251//211 233//210 241//216 +f 251//211 241//216 240//217 +f 257//212 251//211 240//217 +f 257//212 240//217 239//218 +f 256//213 257//212 239//218 +f 256//213 239//218 238//219 +f 234//215 218//214 219//220 +f 234//215 219//220 224//221 +f 241//216 234//215 224//221 +f 241//216 224//221 223//222 +f 240//217 241//216 223//222 +f 240//217 223//222 222//223 +f 239//218 240//217 222//223 +f 239//218 222//223 221//224 +f 238//219 239//218 221//224 +f 238//219 221//224 220//225 +f 219//220 218//214 1285//226 +f 648//227 691//228 207//229 +f 224//221 219//220 208//230 +f 224//221 208//230 204//231 +f 223//222 224//221 204//231 +f 223//222 204//231 203//232 +f 222//223 223//222 203//232 +f 222//223 203//232 202//233 +f 221//224 222//223 202//233 +f 221//224 202//233 201//234 +f 220//225 221//224 201//234 +f 220//225 201//234 212//235 +f 204//231 208//230 191//236 +f 204//231 191//236 188//237 +f 203//232 204//231 188//237 +f 203//232 188//237 187//238 +f 202//233 203//232 187//238 +f 202//233 187//238 186//239 +f 201//234 202//233 186//239 +f 201//234 186//239 194//240 +f 212//235 201//234 194//240 +f 212//235 194//240 211//241 +f 188//237 191//236 174//242 +f 188//237 174//242 176//243 +f 187//238 188//237 176//243 +f 187//238 176//243 175//244 +f 186//239 187//238 175//244 +f 186//239 175//244 180//245 +f 194//240 186//239 180//245 +f 194//240 180//245 193//246 +f 211//241 194//240 193//246 +f 211//241 193//246 210//247 +f 613//248 585//249 1258//250 +f 176//243 174//242 168//251 +f 176//243 168//251 165//252 +f 175//244 176//243 165//252 +f 175//244 165//252 170//253 +f 180//245 175//244 170//253 +f 180//245 170//253 179//254 +f 193//246 180//245 179//254 +f 193//246 179//254 192//255 +f 210//247 193//246 192//255 +f 210//247 192//255 209//256 +f 168//251 174//242 164//257 +f 165//252 168//251 161//258 +f 165//252 161//258 162//259 +f 170//253 165//252 162//259 +f 170//253 162//259 171//260 +f 179//254 170//253 171//260 +f 179//254 171//260 181//261 +f 192//255 179//254 181//261 +f 192//255 181//261 195//262 +f 209//256 192//255 195//262 +f 209//256 195//262 213//263 +f 160//178 161//258 158//179 +f 161//258 160//178 162//259 +f 162//259 160//178 166//181 +f 171//260 162//259 166//181 +f 171//260 166//181 177//184 +f 181//261 171//260 177//184 +f 181//261 177//184 189//186 +f 195//262 181//261 189//186 +f 195//262 189//186 205//188 +f 213//263 195//262 205//188 +f 213//263 205//188 225//190 +f 242//264 225//190 235//191 +f 242//264 235//191 252//265 +f 258//266 242//264 252//265 +f 258//266 252//265 268//267 +f 273//268 258//266 268//267 +f 273//268 268//267 283//269 +f 287//270 273//268 283//269 +f 287//270 283//269 298//271 +f 300//272 287//270 298//271 +f 300//272 298//271 299//273 +f 312//274 300//272 299//273 +f 312//274 299//273 310//275 +f 252//265 235//191 253//197 +f 252//265 253//197 269//276 +f 268//267 252//265 269//276 +f 268//267 269//276 284//277 +f 283//269 268//267 284//277 +f 283//269 284//277 286//278 +f 298//271 283//269 286//278 +f 298//271 286//278 285//279 +f 299//273 298//271 285//279 +f 299//273 285//279 296//280 +f 310//275 299//273 296//280 +f 310//275 296//280 309//281 +f 269//276 253//197 267//207 +f 269//276 267//207 272//282 +f 284//277 269//276 272//282 +f 284//277 272//282 271//283 +f 286//278 284//277 271//283 +f 286//278 271//283 270//284 +f 285//279 286//278 270//284 +f 285//279 270//284 281//285 +f 296//280 285//279 281//285 +f 296//280 281//285 295//286 +f 309//281 296//280 295//286 +f 309//281 295//286 308//287 +f 272//282 267//207 256//213 +f 272//282 256//213 255//288 +f 271//283 272//282 255//288 +f 271//283 255//288 254//289 +f 270//284 271//283 254//289 +f 270//284 254//289 265//290 +f 281//285 270//284 265//290 +f 281//285 265//290 280//291 +f 295//286 281//285 280//291 +f 295//286 280//291 294//292 +f 308//287 295//286 294//292 +f 308//287 294//292 307//293 +f 255//288 256//213 238//219 +f 255//288 238//219 237//294 +f 254//289 255//288 237//294 +f 254//289 237//294 248//295 +f 265//290 254//289 248//295 +f 265//290 248//295 264//296 +f 280//291 265//290 264//296 +f 280//291 264//296 279//297 +f 294//292 280//291 279//297 +f 294//292 279//297 293//298 +f 307//293 294//292 293//298 +f 307//293 293//298 306//299 +f 237//294 238//219 220//225 +f 237//294 220//225 230//300 +f 248//295 237//294 230//300 +f 248//295 230//300 247//301 +f 264//296 248//295 247//301 +f 264//296 247//301 263//302 +f 279//297 264//296 263//302 +f 279//297 263//302 278//303 +f 293//298 279//297 278//303 +f 293//298 278//303 292//304 +f 306//299 293//298 292//304 +f 306//299 292//304 305//305 +f 230//300 220//225 212//235 +f 230//300 212//235 229//306 +f 247//301 230//300 229//306 +f 247//301 229//306 246//307 +f 263//302 247//301 246//307 +f 263//302 246//307 262//308 +f 278//303 263//302 262//308 +f 278//303 262//308 277//309 +f 292//304 278//303 277//309 +f 292//304 277//309 291//310 +f 305//305 292//304 291//310 +f 305//305 291//310 304//311 +f 229//306 212//235 211//241 +f 229//306 211//241 228//312 +f 246//307 229//306 228//312 +f 246//307 228//312 245//313 +f 262//308 246//307 245//313 +f 262//308 245//313 261//314 +f 277//309 262//308 261//314 +f 277//309 261//314 276//315 +f 291//310 277//309 276//315 +f 291//310 276//315 290//316 +f 304//311 291//310 290//316 +f 304//311 290//316 303//317 +f 228//312 211//241 210//247 +f 228//312 210//247 227//318 +f 245//313 228//312 227//318 +f 245//313 227//318 244//319 +f 261//314 245//313 244//319 +f 261//314 244//319 260//320 +f 276//315 261//314 260//320 +f 276//315 260//320 275//321 +f 290//316 276//315 275//321 +f 290//316 275//321 289//322 +f 303//317 290//316 289//322 +f 303//317 289//322 302//323 +f 227//318 210//247 209//256 +f 227//318 209//256 226//324 +f 244//319 227//318 226//324 +f 244//319 226//324 243//325 +f 260//320 244//319 243//325 +f 260//320 243//325 259//326 +f 275//321 260//320 259//326 +f 275//321 259//326 274//327 +f 289//322 275//321 274//327 +f 289//322 274//327 288//328 +f 302//323 289//322 288//328 +f 302//323 288//328 301//329 +f 226//324 209//256 213//263 +f 226//324 213//263 231//330 +f 243//325 226//324 231//330 +f 243//325 231//330 249//331 +f 259//326 243//325 249//331 +f 259//326 249//331 266//332 +f 274//327 259//326 266//332 +f 274//327 266//332 282//333 +f 288//328 274//327 282//333 +f 288//328 282//333 297//334 +f 301//329 288//328 297//334 +f 301//329 297//334 311//335 +f 231//330 213//263 225//190 +f 231//330 225//190 242//264 +f 249//331 231//330 242//264 +f 249//331 242//264 258//266 +f 266//332 249//331 258//266 +f 266//332 258//266 273//268 +f 282//333 266//332 273//268 +f 282//333 273//268 287//270 +f 297//334 282//333 287//270 +f 297//334 287//270 300//272 +f 311//335 297//334 300//272 +f 311//335 300//272 312//274 +f 312//274 310//275 323//336 +f 302//323 315//337 316//338 +f 304//311 317//339 318//340 +f 303//317 316//338 317//339 +f 309//281 308//287 321//341 +f 307//293 306//299 319//342 +f 311//335 313//343 314//344 +f 301//329 314//344 315//337 +f 312//274 324//345 313//343 +f 306//299 305//305 318//340 +f 308//287 307//293 320//346 +f 310//275 309//281 322//347 +f 322//347 321//341 325//348 +f 314//344 313//343 325//348 +f 323//336 322//347 325//348 +f 319//342 318//340 325//348 +f 315//337 314//344 325//348 +f 321//341 320//346 325//348 +f 324//345 323//336 325//348 +f 320//346 319//342 325//348 +f 317//339 316//338 325//348 +f 316//338 315//337 325//348 +f 313//343 324//345 325//348 +f 318//340 317//339 325//348 +f 326//349 327//350 328//351 +f 326//349 328//351 329//352 +f 333//353 326//349 329//352 +f 333//353 329//352 338//354 +f 347//355 333//353 338//354 +f 347//355 338//354 354//356 +f 364//357 347//355 354//356 +f 364//357 354//356 374//358 +f 386//359 364//357 374//358 +f 386//359 374//358 398//360 +f 412//361 386//359 398//360 +f 412//361 398//360 429//362 +f 329//352 328//351 334//363 +f 329//352 334//363 339//364 +f 338//354 329//352 339//364 +f 338//354 339//364 355//365 +f 354//356 338//354 355//365 +f 354//356 355//365 375//366 +f 374//358 354//356 375//366 +f 374//358 375//366 399//367 +f 398//360 374//358 399//367 +f 398//360 399//367 430//368 +f 429//362 398//360 430//368 +f 429//362 430//368 464//369 +f 339//364 334//363 342//370 +f 339//364 342//370 356//371 +f 355//365 339//364 356//371 +f 355//365 356//371 376//372 +f 375//366 355//365 376//372 +f 375//366 376//372 400//373 +f 399//367 375//366 400//373 +f 399//367 400//373 431//374 +f 430//368 399//367 431//374 +f 430//368 431//374 465//375 +f 464//369 430//368 465//375 +f 464//369 465//375 497//376 +f 356//371 342//370 351//377 +f 356//371 351//377 370//378 +f 376//372 356//371 370//378 +f 376//372 370//378 393//379 +f 400//373 376//372 393//379 +f 400//373 393//379 422//380 +f 431//374 400//373 422//380 +f 431//374 422//380 457//381 +f 465//375 431//374 457//381 +f 465//375 457//381 490//382 +f 497//376 465//375 490//382 +f 497//376 490//382 521//383 +f 370//378 351//377 361//384 +f 370//378 361//384 382//385 +f 393//379 370//378 382//385 +f 393//379 382//385 408//386 +f 422//380 393//379 408//386 +f 422//380 408//386 439//387 +f 457//381 422//380 439//387 +f 457//381 439//387 473//388 +f 490//382 457//381 473//388 +f 490//382 473//388 504//389 +f 521//383 490//382 504//389 +f 521//383 504//389 535//390 +f 382//385 361//384 369//391 +f 382//385 369//391 392//392 +f 408//386 382//385 392//392 +f 408//386 392//392 421//393 +f 439//387 408//386 421//393 +f 439//387 421//393 456//394 +f 473//388 439//387 456//394 +f 473//388 456//394 489//395 +f 504//389 473//388 489//395 +f 504//389 489//395 520//396 +f 535//390 504//389 520//396 +f 535//390 520//396 550//397 +f 392//392 369//391 380//398 +f 392//392 380//398 407//399 +f 421//393 392//392 407//399 +f 421//393 407//399 438//400 +f 456//394 421//393 438//400 +f 456//394 438//400 472//401 +f 489//395 456//394 472//401 +f 489//395 472//401 503//402 +f 520//396 489//395 503//402 +f 520//396 503//402 534//403 +f 550//397 520//396 534//403 +f 550//397 534//403 563//404 +f 407//399 380//398 391//405 +f 407//399 391//405 420//406 +f 438//400 407//399 420//406 +f 438//400 420//406 455//407 +f 472//401 438//400 455//407 +f 472//401 455//407 488//408 +f 503//402 472//401 488//408 +f 503//402 488//408 519//409 +f 534//403 503//402 519//409 +f 534//403 519//409 549//410 +f 563//404 534//403 549//410 +f 563//404 549//410 578//411 +f 420//406 391//405 404//412 +f 420//406 404//412 437//413 +f 455//407 420//406 437//413 +f 455//407 437//413 471//414 +f 488//408 455//407 471//414 +f 488//408 471//414 502//415 +f 519//409 488//408 502//415 +f 519//409 502//415 533//416 +f 549//410 519//409 533//416 +f 549//410 533//416 562//417 +f 578//411 549//410 562//417 +f 578//411 562//417 589//418 +f 437//413 404//412 419//419 +f 437//413 419//419 454//420 +f 471//414 437//413 454//420 +f 471//414 454//420 487//421 +f 502//415 471//414 487//421 +f 502//415 487//421 518//422 +f 533//416 502//415 518//422 +f 533//416 518//422 548//423 +f 562//417 533//416 548//423 +f 562//417 548//423 577//424 +f 589//418 562//417 577//424 +f 589//418 577//424 594//425 +f 454//420 419//419 436//426 +f 454//420 436//426 470//427 +f 487//421 454//420 470//427 +f 487//421 470//427 501//428 +f 518//422 487//421 501//428 +f 518//422 501//428 532//429 +f 548//423 518//422 532//429 +f 548//423 532//429 555//430 +f 577//424 548//423 555//430 +f 577//424 555//430 567//431 +f 594//425 577//424 567//431 +f 594//425 567//431 582//432 +f 470//427 436//426 453//433 +f 470//427 453//433 486//434 +f 501//428 470//427 486//434 +f 501//428 486//434 508//435 +f 532//429 501//428 508//435 +f 532//429 508//435 525//436 +f 555//430 532//429 525//436 +f 555//430 525//436 538//437 +f 567//431 555//430 538//437 +f 567//431 538//437 554//438 +f 582//432 567//431 554//438 +f 582//432 554//438 566//33 +f 486//434 453//433 462//439 +f 486//434 462//439 477//440 +f 508//435 486//434 477//440 +f 508//435 477//440 494//441 +f 525//436 508//435 494//441 +f 525//436 494//441 507//442 +f 538//437 525//436 507//442 +f 538//437 507//442 524//443 +f 554//438 538//437 524//443 +f 554//438 524//443 537//444 +f 566//33 554//438 537//444 +f 566//33 537//444 553//31 +f 477//440 462//439 443//445 +f 477//440 443//445 461//446 +f 494//441 477//440 461//446 +f 494//441 461//446 476//447 +f 507//442 494//441 476//447 +f 507//442 476//447 493//448 +f 524//443 507//442 493//448 +f 524//443 493//448 506//449 +f 537//444 524//443 506//449 +f 537//444 506//449 523//450 +f 553//31 537//444 523//450 +f 553//31 523//450 536//451 +f 461//446 443//445 426//452 +f 461//446 426//452 442//453 +f 476//447 461//446 442//453 +f 476//447 442//453 460//454 +f 493//448 476//447 460//454 +f 493//448 460//454 475//455 +f 506//449 493//448 475//455 +f 506//449 475//455 492//456 +f 523//450 506//449 492//456 +f 523//450 492//456 505//457 +f 536//451 523//450 505//457 +f 536//451 505//457 522//458 +f 442//453 426//452 411//459 +f 442//453 411//459 425//460 +f 460//454 442//453 425//460 +f 460//454 425//460 441//461 +f 475//455 460//454 441//461 +f 475//455 441//461 459//462 +f 492//456 475//455 459//462 +f 492//456 459//462 474//463 +f 505//457 492//456 474//463 +f 505//457 474//463 491//464 +f 522//458 505//457 491//464 +f 522//458 491//464 499//465 +f 425//460 411//459 396//466 +f 425//460 396//466 410//467 +f 441//461 425//460 410//467 +f 441//461 410//467 424//468 +f 459//462 441//461 424//468 +f 459//462 424//468 440//469 +f 474//463 459//462 440//469 +f 474//463 440//469 458//470 +f 491//464 474//463 458//470 +f 491//464 458//470 467//471 +f 499//465 491//464 467//471 +f 499//465 467//471 466//472 +f 410//467 396//466 385//473 +f 410//467 385//473 395//474 +f 424//468 410//467 395//474 +f 424//468 395//474 409//475 +f 440//469 424//468 409//475 +f 440//469 409//475 423//476 +f 458//470 440//469 423//476 +f 458//470 423//476 433//477 +f 467//471 458//470 433//477 +f 467//471 433//477 432//478 +f 466//472 467//471 432//478 +f 466//472 432//478 434//479 +f 395//474 385//473 372//480 +f 395//474 372//480 383//481 +f 409//475 395//474 383//481 +f 409//475 383//481 394//482 +f 423//476 409//475 394//482 +f 423//476 394//482 402//483 +f 433//477 423//476 402//483 +f 433//477 402//483 401//484 +f 432//478 433//477 401//484 +f 432//478 401//484 403//485 +f 434//479 432//478 403//485 +f 434//479 403//485 417//486 +f 383//481 372//480 362//487 +f 383//481 362//487 371//488 +f 394//482 383//481 371//488 +f 394//482 371//488 378//489 +f 402//483 394//482 378//489 +f 402//483 378//489 377//490 +f 401//484 402//483 377//490 +f 401//484 377//490 379//491 +f 403//485 401//484 379//491 +f 403//485 379//491 390//492 +f 417//486 403//485 390//492 +f 417//486 390//492 416//493 +f 371//488 362//487 352//494 +f 371//488 352//494 358//495 +f 378//489 371//488 358//495 +f 378//489 358//495 357//496 +f 377//490 378//489 357//496 +f 377//490 357//496 359//497 +f 379//491 377//490 359//497 +f 379//491 359//497 367//498 +f 390//492 379//491 367//498 +f 390//492 367//498 389//499 +f 416//493 390//492 389//499 +f 416//493 389//499 415//500 +f 358//495 352//494 345//501 +f 358//495 345//501 340//502 +f 357//496 358//495 340//502 +f 357//496 340//502 341//503 +f 359//497 357//496 341//503 +f 359//497 341//503 349//504 +f 367//498 359//497 349//504 +f 367//498 349//504 366//505 +f 389//499 367//498 366//505 +f 389//499 366//505 388//506 +f 415//500 389//499 388//506 +f 415//500 388//506 414//507 +f 340//502 345//501 335//508 +f 340//502 335//508 330//509 +f 341//503 340//502 330//509 +f 341//503 330//509 336//510 +f 349//504 341//503 336//510 +f 349//504 336//510 348//511 +f 366//505 349//504 348//511 +f 366//505 348//511 365//512 +f 388//506 366//505 365//512 +f 388//506 365//512 387//513 +f 414//507 388//506 387//513 +f 414//507 387//513 413//514 +f 330//509 335//508 327//350 +f 327//350 326//349 330//509 +f 330//509 326//349 336//510 +f 336//510 326//349 333//353 +f 348//511 336//510 333//353 +f 348//511 333//353 347//355 +f 365//512 348//511 347//355 +f 365//512 347//355 364//357 +f 387//513 365//512 364//357 +f 387//513 364//357 386//359 +f 413//514 387//513 386//359 +f 413//514 386//359 412//361 +f 445//515 412//361 429//362 +f 445//515 429//362 463//516 +f 478//517 445//515 463//516 +f 478//517 463//516 495//518 +f 509//176 478//517 495//518 +f 509//176 495//518 526//519 +f 463//516 429//362 464//369 +f 463//516 464//369 496//520 +f 495//518 463//516 496//520 +f 495//518 496//520 527//521 +f 526//519 495//518 527//521 +f 526//519 527//521 557//522 +f 556//523 526//519 557//522 +f 556//523 557//522 583//524 +f 595//202 556//523 583//524 +f 595//202 583//524 611//525 +f 621//526 595//202 611//525 +f 621//526 611//525 638//527 +f 496//520 464//369 497//376 +f 496//520 497//376 528//528 +f 527//521 496//520 528//528 +f 527//521 528//528 558//529 +f 557//522 527//521 558//529 +f 557//522 558//529 584//530 +f 583//524 557//522 584//530 +f 583//524 584//530 612//531 +f 611//525 583//524 612//531 +f 611//525 612//531 639//532 +f 638//527 611//525 639//532 +f 638//527 639//532 664//533 +f 528//528 497//376 521//383 +f 528//528 521//383 551//534 +f 558//529 528//528 551//534 +f 558//529 551//534 580//535 +f 584//530 558//529 580//535 +f 584//530 580//535 608//536 +f 612//531 584//530 608//536 +f 612//531 608//536 634//537 +f 639//532 612//531 634//537 +f 639//532 634//537 661//538 +f 664//533 639//532 661//538 +f 664//533 661//538 688//539 +f 551//534 521//383 535//390 +f 551//534 535//390 564//540 +f 580//535 551//534 564//540 +f 580//535 564//540 591//541 +f 608//536 580//535 591//541 +f 608//536 591//541 618//542 +f 634//537 608//536 618//542 +f 634//537 618//542 644//543 +f 661//538 634//537 644//543 +f 661//538 644//543 670//544 +f 688//539 661//538 670//544 +f 688//539 670//544 698//545 +f 564//540 535//390 550//397 +f 564//540 550//397 579//546 +f 591//541 564//540 579//546 +f 591//541 579//546 607//547 +f 618//542 591//541 607//547 +f 618//542 607//547 633//548 +f 644//543 618//542 633//548 +f 644//543 633//548 660//549 +f 670//544 644//543 660//549 +f 670//544 660//549 687//550 +f 698//545 670//544 687//550 +f 698//545 687//550 717//551 +f 579//546 550//397 563//404 +f 579//546 563//404 590//552 +f 607//547 579//546 590//552 +f 607//547 590//552 617//553 +f 633//548 607//547 617//553 +f 633//548 617//553 643//554 +f 660//549 633//548 643//554 +f 660//549 643//554 669//555 +f 687//550 660//549 669//555 +f 687//550 669//555 697//556 +f 717//551 687//550 697//556 +f 717//551 697//556 727//557 +f 590//552 563//404 578//411 +f 590//552 578//411 606//558 +f 617//553 590//552 606//558 +f 617//553 606//558 632//559 +f 643//554 617//553 632//559 +f 643//554 632//559 659//560 +f 669//555 643//554 659//560 +f 669//555 659//560 673//561 +f 697//556 669//555 673//561 +f 697//556 673//561 700//562 +f 727//557 697//556 700//562 +f 727//557 700//562 699//563 +f 606//558 578//411 589//418 +f 606//558 589//418 616//564 +f 632//559 606//558 616//564 +f 632//559 616//564 637//565 +f 659//560 632//559 637//565 +f 659//560 637//565 647//566 +f 673//561 659//560 647//566 +f 673//561 647//566 672//567 +f 700//562 673//561 672//567 +f 700//562 672//567 671//568 +f 699//563 700//562 671//568 +f 699//563 671//568 689//569 +f 616//564 589//418 594//425 +f 616//564 594//425 610//570 +f 637//565 616//564 610//570 +f 637//565 610//570 620//571 +f 647//566 637//565 620//571 +f 647//566 620//571 646//572 +f 672//567 647//566 646//572 +f 672//567 646//572 645//573 +f 671//568 672//567 645//573 +f 671//568 645//573 662//574 +f 689//569 671//568 662//574 +f 689//569 662//574 668//575 +f 610//570 594//425 582//432 +f 610//570 582//432 593//3 +f 620//571 610//570 593//3 +f 620//571 593//3 636//89 +f 646//572 620//571 636//89 +f 646//572 636//89 619//576 +f 645//573 646//572 619//576 +f 645//573 619//576 635//577 +f 662//574 645//573 635//577 +f 662//574 635//577 642//578 +f 668//575 662//574 642//578 +f 668//575 642//578 641//579 +f 593//3 582//432 566//33 +f 619//576 636//89 592//57 +f 619//576 592//57 609//580 +f 635//577 619//576 609//580 +f 635//577 609//580 615//581 +f 642//578 635//577 615//581 +f 642//578 615//581 614//582 +f 641//579 642//578 614//582 +f 592//57 565//56 581//583 +f 609//580 592//57 581//583 +f 609//580 581//583 587//584 +f 615//581 609//580 587//584 +f 615//581 587//584 586//585 +f 614//582 615//581 586//585 +f 614//582 586//585 588//586 +f 565//56 553//31 536//451 +f 565//56 536//451 552//587 +f 581//583 565//56 552//587 +f 581//583 552//587 560//588 +f 587//584 581//583 560//588 +f 587//584 560//588 559//589 +f 586//585 587//584 559//589 +f 586//585 559//589 561//590 +f 588//586 586//585 561//590 +f 588//586 561//590 576//591 +f 605//592 588//586 576//591 +f 605//592 576//591 604//593 +f 552//587 536//451 522//458 +f 552//587 522//458 530//594 +f 560//588 552//587 530//594 +f 560//588 530//594 529//595 +f 559//589 560//588 529//595 +f 559//589 529//595 531//596 +f 561//590 559//589 531//596 +f 561//590 531//596 547//597 +f 576//591 561//590 547//597 +f 576//591 547//597 575//598 +f 604//593 576//591 575//598 +f 604//593 575//598 603//599 +f 530//594 522//458 499//465 +f 530//594 499//465 498//600 +f 529//595 530//594 498//600 +f 529//595 498//600 500//601 +f 531//596 529//595 500//601 +f 531//596 500//601 517//602 +f 547//597 531//596 517//602 +f 547//597 517//602 546//603 +f 575//598 547//597 546//603 +f 575//598 546//603 574//604 +f 603//599 575//598 574//604 +f 603//599 574//604 602//605 +f 498//600 499//465 466//472 +f 498//600 466//472 468//606 +f 500//601 498//600 468//606 +f 500//601 468//606 485//607 +f 517//602 500//601 485//607 +f 517//602 485//607 516//608 +f 546//603 517//602 516//608 +f 546//603 516//608 545//609 +f 574//604 546//603 545//609 +f 574//604 545//609 573//610 +f 602//605 574//604 573//610 +f 602//605 573//610 601//611 +f 468//606 466//472 434//479 +f 468//606 434//479 451//612 +f 485//607 468//606 451//612 +f 485//607 451//612 484//613 +f 516//608 485//607 484//613 +f 516//608 484//613 515//614 +f 545//609 516//608 515//614 +f 545//609 515//614 544//615 +f 573//610 545//609 544//615 +f 573//610 544//615 572//616 +f 601//611 573//610 572//616 +f 601//611 572//616 600//617 +f 451//612 434//479 417//486 +f 451//612 417//486 450//618 +f 484//613 451//612 450//618 +f 484//613 450//618 483//619 +f 515//614 484//613 483//619 +f 515//614 483//619 514//620 +f 544//615 515//614 514//620 +f 544//615 514//620 543//621 +f 572//616 544//615 543//621 +f 572//616 543//621 571//622 +f 600//617 572//616 571//622 +f 600//617 571//622 599//623 +f 450//618 417//486 416//493 +f 450//618 416//493 449//624 +f 483//619 450//618 449//624 +f 483//619 449//624 482//625 +f 514//620 483//619 482//625 +f 514//620 482//625 513//626 +f 543//621 514//620 513//626 +f 543//621 513//626 542//627 +f 571//622 543//621 542//627 +f 571//622 542//627 570//628 +f 599//623 571//622 570//628 +f 599//623 570//628 598//629 +f 449//624 416//493 415//500 +f 449//624 415//500 448//630 +f 482//625 449//624 448//630 +f 482//625 448//630 481//631 +f 513//626 482//625 481//631 +f 513//626 481//631 512//632 +f 542//627 513//626 512//632 +f 542//627 512//632 541//633 +f 570//628 542//627 541//633 +f 570//628 541//633 569//634 +f 598//629 570//628 569//634 +f 598//629 569//634 597//635 +f 448//630 415//500 414//507 +f 448//630 414//507 447//636 +f 481//631 448//630 447//636 +f 481//631 447//636 480//637 +f 512//632 481//631 480//637 +f 512//632 480//637 511//638 +f 541//633 512//632 511//638 +f 541//633 511//638 540//639 +f 569//634 541//633 540//639 +f 569//634 540//639 568//640 +f 597//635 569//634 568//640 +f 597//635 568//640 596//641 +f 447//636 414//507 413//514 +f 447//636 413//514 446//642 +f 480//637 447//636 446//642 +f 480//637 446//642 479//643 +f 511//638 480//637 479//643 +f 511//638 479//643 510//644 +f 540//639 511//638 510//644 +f 540//639 510//644 539//175 +f 568//640 540//639 539//175 +f 568//640 539//175 585//249 +f 596//641 568//640 585//249 +f 596//641 585//249 613//248 +f 446//642 413//514 412//361 +f 446//642 412//361 445//515 +f 479//643 446//642 445//515 +f 479//643 445//515 478//517 +f 510//644 479//643 478//517 +f 510//644 478//517 509//176 +f 539//175 510//644 509//176 +f 691//228 648//227 674//645 +f 702//646 691//228 674//645 +f 702//646 674//645 701//647 +f 731//648 702//646 701//647 +f 731//648 701//647 730//649 +f 759//650 731//648 730//649 +f 759//650 730//649 758//651 +f 786//652 759//650 758//651 +f 786//652 758//651 785//653 +f 648//227 621//526 638//527 +f 648//227 638//527 663//654 +f 674//645 648//227 663//654 +f 674//645 663//654 690//655 +f 701//647 674//645 690//655 +f 701//647 690//655 720//656 +f 730//649 701//647 720//656 +f 730//649 720//656 749//657 +f 758//651 730//649 749//657 +f 758//651 749//657 777//658 +f 785//653 758//651 777//658 +f 785//653 777//658 805//659 +f 663//654 638//527 664//533 +f 663//654 664//533 692//660 +f 690//655 663//654 692//660 +f 690//655 692//660 721//661 +f 720//656 690//655 721//661 +f 720//656 721//661 750//662 +f 749//657 720//656 750//662 +f 749//657 750//662 778//663 +f 777//658 749//657 778//663 +f 777//658 778//663 806//664 +f 805//659 777//658 806//664 +f 805//659 806//664 833//665 +f 692//660 664//533 688//539 +f 692//660 688//539 718//666 +f 721//661 692//660 718//666 +f 721//661 718//666 747//667 +f 750//662 721//661 747//667 +f 750//662 747//667 775//668 +f 778//663 750//662 775//668 +f 778//663 775//668 803//669 +f 806//664 778//663 803//669 +f 806//664 803//669 831//670 +f 833//665 806//664 831//670 +f 833//665 831//670 838//671 +f 718//666 688//539 698//545 +f 718//666 698//545 728//672 +f 747//667 718//666 728//672 +f 747//667 728//672 756//673 +f 775//668 747//667 756//673 +f 775//668 756//673 784//674 +f 803//669 775//668 784//674 +f 803//669 784//674 804//675 +f 831//670 803//669 804//675 +f 831//670 804//675 811//676 +f 838//671 831//670 811//676 +f 838//671 811//676 830//677 +f 728//672 698//545 717//551 +f 728//672 717//551 746//678 +f 756//673 728//672 746//678 +f 756//673 746//678 757//679 +f 784//674 756//673 757//679 +f 784//674 757//679 776//680 +f 804//675 784//674 776//680 +f 804//675 776//680 783//681 +f 811//676 804//675 783//681 +f 811//676 783//681 802//682 +f 830//677 811//676 802//682 +f 830//677 802//682 810//683 +f 746//678 717//551 727//557 +f 746//678 727//557 729//684 +f 757//679 746//678 729//684 +f 757//679 729//684 748//685 +f 776//680 757//679 748//685 +f 776//680 748//685 755//686 +f 783//681 776//680 755//686 +f 783//681 755//686 774//687 +f 802//682 783//681 774//687 +f 802//682 774//687 782//688 +f 810//683 802//682 782//688 +f 810//683 782//688 809//689 +f 729//684 727//557 699//563 +f 729//684 699//563 719//690 +f 748//685 729//684 719//690 +f 748//685 719//690 726//691 +f 755//686 748//685 726//691 +f 755//686 726//691 745//692 +f 774//687 755//686 745//692 +f 774//687 745//692 754//693 +f 782//688 774//687 754//693 +f 782//688 754//693 781//694 +f 809//689 782//688 781//694 +f 809//689 781//694 780//695 +f 719//690 699//563 689//569 +f 719//690 689//569 696//696 +f 726//691 719//690 696//696 +f 726//691 696//696 716//697 +f 745//692 726//691 716//697 +f 745//692 716//697 725//698 +f 754//693 745//692 725//698 +f 754//693 725//698 753//699 +f 781//694 754//693 753//699 +f 781//694 753//699 752//700 +f 780//695 781//694 752//700 +f 780//695 752//700 773//701 +f 696//696 689//569 668//575 +f 696//696 668//575 686//702 +f 716//697 696//696 686//702 +f 716//697 686//702 695//703 +f 725//698 716//697 695//703 +f 725//698 695//703 724//704 +f 753//699 725//698 724//704 +f 753//699 724//704 723//705 +f 752//700 753//699 723//705 +f 752//700 723//705 744//706 +f 773//701 752//700 744//706 +f 773//701 744//706 772//707 +f 686//702 668//575 641//579 +f 686//702 641//579 667//708 +f 695//703 686//702 667//708 +f 695//703 667//708 715//160 +f 724//704 695//703 715//160 +f 724//704 715//160 694//709 +f 723//705 724//704 694//709 +f 723//705 694//709 714//710 +f 744//706 723//705 714//710 +f 744//706 714//710 743//711 +f 772//707 744//706 743//711 +f 772//707 743//711 771//712 +f 694//709 715//160 666//713 +f 694//709 666//713 685//714 +f 714//710 694//709 685//714 +f 714//710 685//714 713//715 +f 743//711 714//710 713//715 +f 743//711 713//715 742//716 +f 771//712 743//711 742//716 +f 771//712 742//716 770//717 +f 666//713 631//152 658//718 +f 685//714 666//713 658//718 +f 685//714 658//718 684//719 +f 713//715 685//714 684//719 +f 713//715 684//719 712//720 +f 742//716 713//715 712//720 +f 742//716 712//720 741//721 +f 770//717 742//716 741//721 +f 770//717 741//721 769//722 +f 631//152 605//592 604//593 +f 631//152 604//593 630//723 +f 658//718 631//152 630//723 +f 658//718 630//723 657//724 +f 684//719 658//718 657//724 +f 684//719 657//724 683//725 +f 712//720 684//719 683//725 +f 712//720 683//725 711//726 +f 741//721 712//720 711//726 +f 741//721 711//726 740//727 +f 769//722 741//721 740//727 +f 769//722 740//727 768//728 +f 630//723 604//593 603//599 +f 630//723 603//599 629//729 +f 657//724 630//723 629//729 +f 657//724 629//729 656//730 +f 683//725 657//724 656//730 +f 683//725 656//730 682//731 +f 711//726 683//725 682//731 +f 711//726 682//731 710//732 +f 740//727 711//726 710//732 +f 740//727 710//732 739//733 +f 768//728 740//727 739//733 +f 768//728 739//733 767//734 +f 629//729 603//599 602//605 +f 629//729 602//605 628//735 +f 656//730 629//729 628//735 +f 656//730 628//735 655//736 +f 682//731 656//730 655//736 +f 682//731 655//736 681//737 +f 710//732 682//731 681//737 +f 710//732 681//737 709//738 +f 739//733 710//732 709//738 +f 739//733 709//738 738//739 +f 767//734 739//733 738//739 +f 767//734 738//739 766//740 +f 628//735 602//605 601//611 +f 628//735 601//611 627//741 +f 655//736 628//735 627//741 +f 655//736 627//741 654//742 +f 681//737 655//736 654//742 +f 681//737 654//742 680//743 +f 709//738 681//737 680//743 +f 709//738 680//743 708//744 +f 738//739 709//738 708//744 +f 738//739 708//744 737//745 +f 766//740 738//739 737//745 +f 766//740 737//745 765//746 +f 627//741 601//611 600//617 +f 627//741 600//617 626//747 +f 654//742 627//741 626//747 +f 654//742 626//747 653//748 +f 680//743 654//742 653//748 +f 680//743 653//748 679//749 +f 708//744 680//743 679//749 +f 708//744 679//749 707//750 +f 737//745 708//744 707//750 +f 737//745 707//750 736//751 +f 765//746 737//745 736//751 +f 765//746 736//751 764//752 +f 626//747 600//617 599//623 +f 626//747 599//623 625//753 +f 653//748 626//747 625//753 +f 653//748 625//753 652//754 +f 679//749 653//748 652//754 +f 679//749 652//754 678//755 +f 707//750 679//749 678//755 +f 707//750 678//755 706//756 +f 736//751 707//750 706//756 +f 736//751 706//756 735//757 +f 764//752 736//751 735//757 +f 764//752 735//757 763//758 +f 625//753 599//623 598//629 +f 625//753 598//629 624//759 +f 652//754 625//753 624//759 +f 652//754 624//759 651//760 +f 678//755 652//754 651//760 +f 678//755 651//760 677//761 +f 706//756 678//755 677//761 +f 706//756 677//761 705//762 +f 735//757 706//756 705//762 +f 735//757 705//762 734//763 +f 763//758 735//757 734//763 +f 763//758 734//763 762//764 +f 624//759 598//629 597//635 +f 624//759 597//635 623//765 +f 651//760 624//759 623//765 +f 651//760 623//765 650//766 +f 677//761 651//760 650//766 +f 677//761 650//766 676//767 +f 705//762 677//761 676//767 +f 705//762 676//767 704//768 +f 734//763 705//762 704//768 +f 734//763 704//768 733//769 +f 762//764 734//763 733//769 +f 762//764 733//769 761//770 +f 623//765 597//635 596//641 +f 623//765 596//641 622//771 +f 650//766 623//765 622//771 +f 650//766 622//771 649//772 +f 676//767 650//766 649//772 +f 676//767 649//772 675//773 +f 704//768 676//767 675//773 +f 704//768 675//773 703//774 +f 733//769 704//768 703//774 +f 733//769 703//774 732//775 +f 761//770 733//769 732//775 +f 761//770 732//775 760//776 +f 622//771 596//641 613//248 +f 622//771 613//248 640//777 +f 649//772 622//771 640//777 +f 649//772 640//777 665//778 +f 675//773 649//772 665//778 +f 675//773 665//778 693//779 +f 703//774 675//773 693//779 +f 703//774 693//779 722//780 +f 732//775 703//774 722//780 +f 732//775 722//780 751//781 +f 760//776 732//775 751//781 +f 760//776 751//781 779//782 +f 693//779 665//778 691//228 +f 693//779 691//228 702//646 +f 722//780 693//779 702//646 +f 722//780 702//646 731//648 +f 751//781 722//780 731//648 +f 751//781 731//648 759//650 +f 779//782 751//781 759//650 +f 779//782 759//650 786//652 +f 917//783 918//784 913//785 +f 892//786 917//783 913//785 +f 892//786 913//785 887//787 +f 866//788 892//786 887//787 +f 866//788 887//787 861//789 +f 840//790 866//788 861//789 +f 840//790 861//789 834//791 +f 813//792 840//790 834//791 +f 813//792 834//791 807//793 +f 786//652 813//792 807//793 +f 786//652 807//793 779//782 +f 913//785 918//784 893//794 +f 887//787 913//785 893//794 +f 887//787 893//794 867//795 +f 861//789 887//787 867//795 +f 861//789 867//795 841//796 +f 834//791 861//789 841//796 +f 834//791 841//796 814//797 +f 807//793 834//791 814//797 +f 807//793 814//797 787//798 +f 779//782 807//793 787//798 +f 779//782 787//798 760//776 +f 893//794 918//784 894//799 +f 867//795 893//794 894//799 +f 867//795 894//799 868//800 +f 841//796 867//795 868//800 +f 841//796 868//800 842//801 +f 814//797 841//796 842//801 +f 814//797 842//801 815//802 +f 787//798 814//797 815//802 +f 787//798 815//802 788//803 +f 760//776 787//798 788//803 +f 760//776 788//803 761//770 +f 894//799 918//784 895//804 +f 868//800 894//799 895//804 +f 868//800 895//804 869//805 +f 842//801 868//800 869//805 +f 842//801 869//805 843//806 +f 815//802 842//801 843//806 +f 815//802 843//806 816//807 +f 788//803 815//802 816//807 +f 788//803 816//807 789//808 +f 761//770 788//803 789//808 +f 761//770 789//808 762//764 +f 895//804 918//784 896//809 +f 869//805 895//804 896//809 +f 869//805 896//809 870//810 +f 843//806 869//805 870//810 +f 843//806 870//810 844//811 +f 816//807 843//806 844//811 +f 816//807 844//811 817//812 +f 789//808 816//807 817//812 +f 789//808 817//812 790//813 +f 762//764 789//808 790//813 +f 762//764 790//813 763//758 +f 896//809 918//784 897//814 +f 870//810 896//809 897//814 +f 870//810 897//814 871//815 +f 844//811 870//810 871//815 +f 844//811 871//815 845//816 +f 817//812 844//811 845//816 +f 817//812 845//816 818//817 +f 790//813 817//812 818//817 +f 790//813 818//817 791//818 +f 763//758 790//813 791//818 +f 763//758 791//818 764//752 +f 897//814 918//784 898//819 +f 871//815 897//814 898//819 +f 871//815 898//819 872//820 +f 845//816 871//815 872//820 +f 845//816 872//820 846//821 +f 818//817 845//816 846//821 +f 818//817 846//821 819//822 +f 791//818 818//817 819//822 +f 791//818 819//822 792//823 +f 764//752 791//818 792//823 +f 764//752 792//823 765//746 +f 898//819 918//784 899//824 +f 872//820 898//819 899//824 +f 872//820 899//824 873//825 +f 846//821 872//820 873//825 +f 846//821 873//825 847//826 +f 819//822 846//821 847//826 +f 819//822 847//826 820//827 +f 792//823 819//822 820//827 +f 792//823 820//827 793//828 +f 765//746 792//823 793//828 +f 765//746 793//828 766//740 +f 899//824 918//784 900//829 +f 873//825 899//824 900//829 +f 873//825 900//829 874//830 +f 847//826 873//825 874//830 +f 847//826 874//830 848//831 +f 820//827 847//826 848//831 +f 820//827 848//831 821//832 +f 793//828 820//827 821//832 +f 793//828 821//832 794//833 +f 766//740 793//828 794//833 +f 766//740 794//833 767//734 +f 900//829 918//784 901//834 +f 874//830 900//829 901//834 +f 874//830 901//834 875//835 +f 848//831 874//830 875//835 +f 848//831 875//835 849//836 +f 821//832 848//831 849//836 +f 821//832 849//836 822//837 +f 794//833 821//832 822//837 +f 794//833 822//837 795//838 +f 767//734 794//833 795//838 +f 767//734 795//838 768//728 +f 901//834 918//784 902//839 +f 875//835 901//834 902//839 +f 875//835 902//839 876//840 +f 849//836 875//835 876//840 +f 849//836 876//840 850//841 +f 822//837 849//836 850//841 +f 822//837 850//841 823//842 +f 795//838 822//837 823//842 +f 795//838 823//842 796//843 +f 768//728 795//838 796//843 +f 768//728 796//843 769//722 +f 902//839 918//784 903//844 +f 876//840 902//839 903//844 +f 876//840 903//844 877//845 +f 850//841 876//840 877//845 +f 850//841 877//845 851//846 +f 823//842 850//841 851//846 +f 823//842 851//846 824//847 +f 796//843 823//842 824//847 +f 796//843 824//847 797//848 +f 769//722 796//843 797//848 +f 769//722 797//848 770//717 +f 903//844 918//784 904//849 +f 877//845 903//844 904//849 +f 877//845 904//849 878//850 +f 851//846 877//845 878//850 +f 851//846 878//850 852//851 +f 824//847 851//846 852//851 +f 824//847 852//851 825//852 +f 797//848 824//847 825//852 +f 797//848 825//852 798//853 +f 770//717 797//848 798//853 +f 770//717 798//853 771//712 +f 904//849 918//784 905//854 +f 878//850 904//849 905//854 +f 878//850 905//854 879//855 +f 852//851 878//850 879//855 +f 852//851 879//855 853//856 +f 825//852 852//851 853//856 +f 825//852 853//856 826//857 +f 798//853 825//852 826//857 +f 798//853 826//857 799//858 +f 771//712 798//853 799//858 +f 771//712 799//858 772//707 +f 905//854 918//784 906//859 +f 879//855 905//854 906//859 +f 879//855 906//859 880//860 +f 853//856 879//855 880//860 +f 853//856 880//860 854//861 +f 826//857 853//856 854//861 +f 826//857 854//861 827//862 +f 799//858 826//857 827//862 +f 799//858 827//862 800//863 +f 772//707 799//858 800//863 +f 772//707 800//863 773//701 +f 906//859 918//784 907//864 +f 880//860 906//859 907//864 +f 880//860 907//864 881//865 +f 854//861 880//860 881//865 +f 854//861 881//865 855//866 +f 827//862 854//861 855//866 +f 827//862 855//866 828//867 +f 800//863 827//862 828//867 +f 800//863 828//867 801//868 +f 773//701 800//863 801//868 +f 773//701 801//868 780//695 +f 907//864 918//784 908//869 +f 881//865 907//864 908//869 +f 881//865 908//869 882//870 +f 855//866 881//865 882//870 +f 855//866 882//870 856//871 +f 828//867 855//866 856//871 +f 828//867 856//871 829//872 +f 801//868 828//867 829//872 +f 801//868 829//872 808//873 +f 780//695 801//868 808//873 +f 780//695 808//873 809//689 +f 908//869 918//784 909//874 +f 882//870 908//869 909//874 +f 882//870 909//874 883//875 +f 856//871 882//870 883//875 +f 856//871 883//875 857//876 +f 829//872 856//871 857//876 +f 829//872 857//876 836//877 +f 808//873 829//872 836//877 +f 808//873 836//877 835//878 +f 809//689 808//873 835//878 +f 809//689 835//878 810//683 +f 909//874 918//784 910//879 +f 883//875 909//874 910//879 +f 883//875 910//879 884//880 +f 857//876 883//875 884//880 +f 857//876 884//880 863//881 +f 836//877 857//876 863//881 +f 836//877 863//881 862//882 +f 835//878 836//877 862//882 +f 835//878 862//882 837//883 +f 810//683 835//878 837//883 +f 810//683 837//883 830//677 +f 910//879 918//784 911//884 +f 884//880 910//879 911//884 +f 884//880 911//884 889//885 +f 863//881 884//880 889//885 +f 863//881 889//885 888//886 +f 862//882 863//881 888//886 +f 862//882 888//886 864//887 +f 837//883 862//882 864//887 +f 837//883 864//887 858//888 +f 830//677 837//883 858//888 +f 830//677 858//888 838//671 +f 911//884 918//784 915//889 +f 889//885 911//884 915//889 +f 889//885 915//889 914//890 +f 888//886 889//885 914//890 +f 888//886 914//890 890//891 +f 864//887 888//886 890//891 +f 864//887 890//891 885//892 +f 858//888 864//887 885//892 +f 858//888 885//892 859//893 +f 838//671 858//888 859//893 +f 838//671 859//893 833//665 +f 915//889 918//784 919//894 +f 914//890 915//889 919//894 +f 914//890 919//894 912//895 +f 890//891 914//890 912//895 +f 890//891 912//895 886//896 +f 885//892 890//891 886//896 +f 885//892 886//896 860//897 +f 859//893 885//892 860//897 +f 859//893 860//897 832//898 +f 833//665 859//893 832//898 +f 833//665 832//898 805//659 +f 919//894 918//784 916//899 +f 912//895 919//894 916//899 +f 912//895 916//899 891//900 +f 886//896 912//895 891//900 +f 886//896 891//900 865//901 +f 860//897 886//896 865//901 +f 860//897 865//901 839//902 +f 832//898 860//897 839//902 +f 832//898 839//902 812//903 +f 805//659 832//898 812//903 +f 805//659 812//903 785//653 +f 916//899 918//784 917//783 +f 891//900 916//899 917//783 +f 891//900 917//783 892//786 +f 865//901 891//900 892//786 +f 865//901 892//786 866//788 +f 839//902 865//901 866//788 +f 839//902 866//788 840//790 +f 812//903 839//902 840//790 +f 812//903 840//790 813//792 +f 785//653 812//903 813//792 +f 785//653 813//792 786//652 +f 404//412 1267//904 1268//905 +f 384//906 373//907 372//480 +f 346//908 345//501 352//494 +f 435//909 436//426 419//419 +f 331//910 327//350 335//508 +f 462//439 453//433 1265//911 +f 920//912 921//913 922//914 +f 920//912 922//914 923//915 +f 923//915 922//914 927//916 +f 923//915 927//916 933//917 +f 933//917 927//916 940//918 +f 933//917 940//918 949//919 +f 949//919 940//918 959//920 +f 949//919 959//920 971//921 +f 971//921 959//920 984//922 +f 971//921 984//922 999//923 +f 999//923 984//922 1011//924 +f 999//923 1011//924 1027//925 +f 1027//925 1011//924 1042//926 +f 1027//925 1042//926 1059//927 +f 1059//927 1042//926 1077//928 +f 1059//927 1077//928 1095//929 +f 1095//929 1077//928 1110//930 +f 1095//929 1110//930 1129//931 +f 1129//931 1110//930 1144//932 +f 1129//931 1144//932 1163//933 +f 1163//933 1144//932 1179//934 +f 1163//933 1179//934 1196//935 +f 1196//935 1179//934 1210//936 +f 1196//935 1210//936 1220//937 +f 1220//937 1210//936 1212//938 +f 1220//937 1212//938 1201//939 +f 1201//939 1212//938 1181//940 +f 1201//939 1181//940 1169//941 +f 1169//941 1181//940 1147//942 +f 1169//941 1147//942 1135//943 +f 1135//943 1147//942 1113//944 +f 1135//943 1113//944 1102//945 +f 1102//945 1113//944 1081//946 +f 1102//945 1081//946 1065//947 +f 1065//947 1081//946 1046//948 +f 1065//947 1046//948 1032//949 +f 1032//949 1046//948 1016//950 +f 1032//949 1016//950 1003//951 +f 1003//951 1016//950 988//952 +f 1003//951 988//952 974//953 +f 974//953 988//952 962//954 +f 974//953 962//954 951//955 +f 951//955 962//954 942//956 +f 951//955 942//956 934//957 +f 934//957 942//956 928//958 +f 934//957 928//958 924//959 +f 924//959 928//958 921//913 +f 921//913 920//912 924//959 +f 926//960 920//912 923//915 +f 926//960 923//915 932//961 +f 938//962 926//960 932//961 +f 938//962 932//961 947//963 +f 956//964 938//962 947//963 +f 956//964 947//963 968//965 +f 980//966 956//964 968//965 +f 980//966 968//965 995//967 +f 1006//968 980//966 995//967 +f 1006//968 995//967 1022//969 +f 1036//970 1006//968 1022//969 +f 1036//970 1022//969 1053//971 +f 932//961 923//915 933//917 +f 932//961 933//917 948//972 +f 947//963 932//961 948//972 +f 947//963 948//972 969//973 +f 968//965 947//963 969//973 +f 968//965 969//973 996//974 +f 995//967 968//965 996//974 +f 995//967 996//974 1023//975 +f 1022//969 995//967 1023//975 +f 1022//969 1023//975 1054//976 +f 1053//971 1022//969 1054//976 +f 1053//971 1054//976 1089//977 +f 948//972 933//917 949//919 +f 948//972 949//919 970//978 +f 969//973 948//972 970//978 +f 969//973 970//978 997//979 +f 996//974 969//973 997//979 +f 996//974 997//979 1024//980 +f 1023//975 996//974 1024//980 +f 1023//975 1024//980 1055//981 +f 1054//976 1023//975 1055//981 +f 1054//976 1055//981 1090//982 +f 1089//977 1054//976 1090//982 +f 1089//977 1090//982 1109//983 +f 970//978 949//919 971//921 +f 970//978 971//921 998//984 +f 997//979 970//978 998//984 +f 997//979 998//984 1025//985 +f 1024//980 997//979 1025//985 +f 1024//980 1025//985 1056//986 +f 1055//981 1024//980 1056//986 +f 1055//981 1056//986 1091//987 +f 1090//982 1055//981 1091//987 +f 1090//982 1091//987 1124//988 +f 1109//983 1090//982 1124//988 +f 1109//983 1124//988 1122//989 +f 998//984 971//921 999//923 +f 998//984 999//923 1026//990 +f 1025//985 998//984 1026//990 +f 1025//985 1026//990 1057//991 +f 1056//986 1025//985 1057//991 +f 1056//986 1057//991 1092//992 +f 1091//987 1056//986 1092//992 +f 1091//987 1092//992 1125//993 +f 1124//988 1091//987 1125//993 +f 1124//988 1125//993 1156//994 +f 1122//989 1124//988 1156//994 +f 1122//989 1156//994 1142//995 +f 1026//990 999//923 1027//925 +f 1026//990 1027//925 1058//996 +f 1057//991 1026//990 1058//996 +f 1057//991 1058//996 1093//997 +f 1092//992 1057//991 1093//997 +f 1092//992 1093//997 1126//998 +f 1125//993 1092//992 1126//998 +f 1125//993 1126//998 1159//999 +f 1156//994 1125//993 1159//999 +f 1156//994 1159//999 1176//1000 +f 1142//995 1156//994 1176//1000 +f 1142//995 1176//1000 1157//1001 +f 1058//996 1027//925 1059//927 +f 1058//996 1059//927 1094//1002 +f 1093//997 1058//996 1094//1002 +f 1093//997 1094//1002 1127//1003 +f 1126//998 1093//997 1127//1003 +f 1126//998 1127//1003 1160//1004 +f 1159//999 1126//998 1160//1004 +f 1159//999 1160//1004 1192//1005 +f 1176//1000 1159//999 1192//1005 +f 1176//1000 1192//1005 1189//1006 +f 1157//1001 1176//1000 1189//1006 +f 1157//1001 1189//1006 1178//1007 +f 1094//1002 1059//927 1095//929 +f 1094//1002 1095//929 1128//1008 +f 1127//1003 1094//1002 1128//1008 +f 1127//1003 1128//1008 1161//1009 +f 1160//1004 1127//1003 1161//1009 +f 1160//1004 1161//1009 1193//1010 +f 1192//1005 1160//1004 1193//1010 +f 1192//1005 1193//1010 1215//1011 +f 1189//1006 1192//1005 1215//1011 +f 1189//1006 1215//1011 1207//1012 +f 1178//1007 1189//1006 1207//1012 +f 1178//1007 1207//1012 1191//1013 +f 1128//1008 1095//929 1129//931 +f 1128//1008 1129//931 1162//1014 +f 1161//1009 1128//1008 1162//1014 +f 1161//1009 1162//1014 1194//1015 +f 1193//1010 1161//1009 1194//1015 +f 1193//1010 1194//1015 1217//1016 +f 1215//1011 1193//1010 1217//1016 +f 1215//1011 1217//1016 1227//1017 +f 1207//1012 1215//1011 1227//1017 +f 1207//1012 1227//1017 1216//1018 +f 1191//1013 1207//1012 1216//1018 +f 1191//1013 1216//1018 1209//1019 +f 1162//1014 1129//931 1163//933 +f 1162//1014 1163//933 1195//1020 +f 1194//1015 1162//1014 1195//1020 +f 1194//1015 1195//1020 1218//1021 +f 1217//1016 1194//1015 1218//1021 +f 1217//1016 1218//1021 1230//1022 +f 1227//1017 1217//1016 1230//1022 +f 1227//1017 1230//1022 1229//1023 +f 1216//1018 1227//1017 1229//1023 +f 1216//1018 1229//1023 1225//1024 +f 1209//1019 1216//1018 1225//1024 +f 1209//1019 1225//1024 1203//1025 +f 1195//1020 1163//933 1196//935 +f 1195//1020 1196//935 1219//1026 +f 1218//1021 1195//1020 1219//1026 +f 1218//1021 1219//1026 1231//1027 +f 1230//1022 1218//1021 1231//1027 +f 1230//1022 1231//1027 1232//1028 +f 1229//1023 1230//1022 1232//1028 +f 1229//1023 1232//1028 1228//1029 +f 1225//1024 1229//1023 1228//1029 +f 1225//1024 1228//1029 1214//1030 +f 1203//1025 1225//1024 1214//1030 +f 1203//1025 1214//1030 1184//1031 +f 1219//1026 1196//935 1220//937 +f 1219//1026 1220//937 1224//1032 +f 1231//1027 1219//1026 1224//1032 +f 1231//1027 1224//1032 1223//1033 +f 1232//1028 1231//1027 1223//1033 +f 1232//1028 1223//1033 1222//1034 +f 1228//1029 1232//1028 1222//1034 +f 1228//1029 1222//1034 1221//1035 +f 1214//1030 1228//1029 1221//1035 +f 1214//1030 1221//1035 1204//1036 +f 1184//1031 1214//1030 1204//1036 +f 1184//1031 1204//1036 1171//1037 +f 1224//1032 1220//937 1201//939 +f 1224//1032 1201//939 1200//1038 +f 1223//1033 1224//1032 1200//1038 +f 1223//1033 1200//1038 1199//1039 +f 1222//1034 1223//1033 1199//1039 +f 1222//1034 1199//1039 1198//1040 +f 1221//1035 1222//1034 1198//1040 +f 1221//1035 1198//1040 1197//1041 +f 1204//1036 1221//1035 1197//1041 +f 1204//1036 1197//1041 1185//1042 +f 1171//1037 1204//1036 1185//1042 +f 1171//1037 1185//1042 1151//1043 +f 1200//1038 1201//939 1169//941 +f 1200//1038 1169//941 1168//1044 +f 1199//1039 1200//1038 1168//1044 +f 1199//1039 1168//1044 1167//1045 +f 1198//1040 1199//1039 1167//1045 +f 1198//1040 1167//1045 1166//1046 +f 1197//1041 1198//1040 1166//1046 +f 1197//1041 1166//1046 1165//1047 +f 1185//1042 1197//1041 1165//1047 +f 1185//1042 1165//1047 1164//1048 +f 1151//1043 1185//1042 1164//1048 +f 1151//1043 1164//1048 1137//1049 +f 1168//1044 1169//941 1135//943 +f 1168//1044 1135//943 1134//1050 +f 1167//1045 1168//1044 1134//1050 +f 1167//1045 1134//1050 1133//1051 +f 1166//1046 1167//1045 1133//1051 +f 1166//1046 1133//1051 1132//1052 +f 1165//1047 1166//1046 1132//1052 +f 1165//1047 1132//1052 1131//1053 +f 1164//1048 1165//1047 1131//1053 +f 1164//1048 1131//1053 1130//1054 +f 1137//1049 1164//1048 1130//1054 +f 1137//1049 1130//1054 1117//1055 +f 1134//1050 1135//943 1102//945 +f 1134//1050 1102//945 1101//1056 +f 1133//1051 1134//1050 1101//1056 +f 1133//1051 1101//1056 1100//1057 +f 1132//1052 1133//1051 1100//1057 +f 1132//1052 1100//1057 1099//1058 +f 1131//1053 1132//1052 1099//1058 +f 1131//1053 1099//1058 1098//1059 +f 1130//1054 1131//1053 1098//1059 +f 1130//1054 1098//1059 1097//1060 +f 1117//1055 1130//1054 1097//1060 +f 1117//1055 1097//1060 1096//1061 +f 1101//1056 1102//945 1065//947 +f 1101//1056 1065//947 1064//1062 +f 1100//1057 1101//1056 1064//1062 +f 1100//1057 1064//1062 1063//1063 +f 1099//1058 1100//1057 1063//1063 +f 1099//1058 1063//1063 1062//1064 +f 1098//1059 1099//1058 1062//1064 +f 1098//1059 1062//1064 1061//1065 +f 1097//1060 1098//1059 1061//1065 +f 1097//1060 1061//1065 1060//1066 +f 1096//1061 1097//1060 1060//1066 +f 1096//1061 1060//1066 1066//1067 +f 1064//1062 1065//947 1032//949 +f 1064//1062 1032//949 1031//1068 +f 1063//1063 1064//1062 1031//1068 +f 1063//1063 1031//1068 1030//1069 +f 1062//1064 1063//1063 1030//1069 +f 1062//1064 1030//1069 1029//1070 +f 1061//1065 1062//1064 1029//1070 +f 1061//1065 1029//1070 1028//1071 +f 1060//1066 1061//1065 1028//1071 +f 1060//1066 1028//1071 1033//1072 +f 1066//1067 1060//1066 1033//1072 +f 1066//1067 1033//1072 1050//1073 +f 1031//1068 1032//949 1003//951 +f 1031//1068 1003//951 1002//1074 +f 1030//1069 1031//1068 1002//1074 +f 1030//1069 1002//1074 1001//1075 +f 1029//1070 1030//1069 1001//1075 +f 1029//1070 1001//1075 1000//1076 +f 1028//1071 1029//1070 1000//1076 +f 1028//1071 1000//1076 1004//1077 +f 1033//1072 1028//1071 1004//1077 +f 1033//1072 1004//1077 1021//1078 +f 1050//1073 1033//1072 1021//1078 +f 1050//1073 1021//1078 1041//1079 +f 1002//1074 1003//951 974//953 +f 1002//1074 974//953 973//1080 +f 1001//1075 1002//1074 973//1080 +f 1001//1075 973//1080 972//1081 +f 1000//1076 1001//1075 972//1081 +f 1000//1076 972//1081 975//1082 +f 1004//1077 1000//1076 975//1082 +f 1004//1077 975//1082 992//1083 +f 1021//1078 1004//1077 992//1083 +f 1021//1078 992//1083 1010//1084 +f 1041//1079 1021//1078 1010//1084 +f 1041//1079 1010//1084 1040//1085 +f 973//1080 974//953 951//955 +f 973//1080 951//955 950//1086 +f 972//1081 973//1080 950//1086 +f 972//1081 950//1086 952//1087 +f 975//1082 972//1081 952//1087 +f 975//1082 952//1087 965//1088 +f 992//1083 975//1082 965//1088 +f 992//1083 965//1088 983//1089 +f 1010//1084 992//1083 983//1089 +f 1010//1084 983//1089 1009//1090 +f 1040//1085 1010//1084 1009//1090 +f 1040//1085 1009//1090 1039//1091 +f 950//1086 951//955 934//957 +f 950//1086 934//957 935//1092 +f 952//1087 950//1086 935//1092 +f 952//1087 935//1092 944//1093 +f 965//1088 952//1087 944//1093 +f 965//1088 944//1093 958//1094 +f 983//1089 965//1088 958//1094 +f 983//1089 958//1094 982//1095 +f 1009//1090 983//1089 982//1095 +f 1009//1090 982//1095 1008//1096 +f 1039//1091 1009//1090 1008//1096 +f 1039//1091 1008//1096 1038//1097 +f 935//1092 934//957 924//959 +f 935//1092 924//959 929//1098 +f 944//1093 935//1092 929//1098 +f 944//1093 929//1098 939//1099 +f 958//1094 944//1093 939//1099 +f 958//1094 939//1099 957//1100 +f 982//1095 958//1094 957//1100 +f 982//1095 957//1100 981//1101 +f 1008//1096 982//1095 981//1101 +f 1008//1096 981//1101 1007//1102 +f 1038//1097 1008//1096 1007//1102 +f 1038//1097 1007//1102 1037//1103 +f 924//959 920//912 929//1098 +f 929//1098 920//912 926//960 +f 939//1099 929//1098 926//960 +f 939//1099 926//960 938//962 +f 957//1100 939//1099 938//962 +f 957//1100 938//962 956//964 +f 981//1101 957//1100 956//964 +f 981//1101 956//964 980//966 +f 1007//1102 981//1101 980//966 +f 1007//1102 980//966 1006//968 +f 1037//1103 1007//1102 1006//968 +f 1037//1103 1006//968 1036//970 +f 993//1104 1005//1105 976//1106 +f 966//1107 993//1104 976//1106 +f 966//1107 976//1106 953//1108 +f 945//1109 966//1107 953//1108 +f 945//1109 953//1108 936//1110 +f 930//1111 945//1109 936//1110 +f 930//1111 936//1110 925//1112 +f 921//913 930//1111 925//1112 +f 921//913 925//1112 922//914 +f 976//1106 1005//1105 977//1113 +f 953//1108 976//1106 977//1113 +f 953//1108 977//1113 954//1114 +f 936//1110 953//1108 954//1114 +f 936//1110 954//1114 937//1115 +f 925//1112 936//1110 937//1115 +f 925//1112 937//1115 931//1116 +f 922//914 925//1112 931//1116 +f 922//914 931//1116 927//916 +f 977//1113 1005//1105 978//1117 +f 954//1114 977//1113 978//1117 +f 954//1114 978//1117 955//1118 +f 937//1115 954//1114 955//1118 +f 937//1115 955//1118 946//1119 +f 931//1116 937//1115 946//1119 +f 931//1116 946//1119 941//1120 +f 927//916 931//1116 941//1120 +f 927//916 941//1120 940//918 +f 978//1117 1005//1105 979//1121 +f 955//1118 978//1117 979//1121 +f 955//1118 979//1121 967//1122 +f 946//1119 955//1118 967//1122 +f 946//1119 967//1122 961//1123 +f 941//1120 946//1119 961//1123 +f 941//1120 961//1123 960//1124 +f 940//918 941//1120 960//1124 +f 940//918 960//1124 959//920 +f 979//1121 1005//1105 994//1125 +f 967//1122 979//1121 994//1125 +f 967//1122 994//1125 987//1126 +f 961//1123 967//1122 987//1126 +f 961//1123 987//1126 986//1127 +f 960//1124 961//1123 986//1127 +f 960//1124 986//1127 985//1128 +f 959//920 960//1124 985//1128 +f 959//920 985//1128 984//922 +f 994//1125 1005//1105 1015//1129 +f 987//1126 994//1125 1015//1129 +f 987//1126 1015//1129 1014//1130 +f 986//1127 987//1126 1014//1130 +f 986//1127 1014//1130 1013//1131 +f 985//1128 986//1127 1013//1131 +f 985//1128 1013//1131 1012//1132 +f 984//922 985//1128 1012//1132 +f 984//922 1012//1132 1011//924 +f 1015//1129 1005//1105 1035//1133 +f 1014//1130 1015//1129 1035//1133 +f 1014//1130 1035//1133 1045//1134 +f 1013//1131 1014//1130 1045//1134 +f 1013//1131 1045//1134 1044//1135 +f 1012//1132 1013//1131 1044//1135 +f 1012//1132 1044//1135 1043//1136 +f 1011//924 1012//1132 1043//1136 +f 1011//924 1043//1136 1042//926 +f 1035//1133 1005//1105 1052//1137 +f 1045//1134 1035//1133 1052//1137 +f 1045//1134 1052//1137 1080//1138 +f 1044//1135 1045//1134 1080//1138 +f 1044//1135 1080//1138 1079//1139 +f 1043//1136 1044//1135 1079//1139 +f 1043//1136 1079//1139 1078//1140 +f 1042//926 1043//1136 1078//1140 +f 1042//926 1078//1140 1077//928 +f 1052//1137 1005//1105 1068//1141 +f 1080//1138 1052//1137 1068//1141 +f 1080//1138 1068//1141 1106//1142 +f 1079//1139 1080//1138 1106//1142 +f 1079//1139 1106//1142 1112//1143 +f 1078//1140 1079//1139 1112//1143 +f 1078//1140 1112//1143 1111//1144 +f 1077//928 1078//1140 1111//1144 +f 1077//928 1111//1144 1110//930 +f 1068//1141 1005//1105 1087//1145 +f 1106//1142 1068//1141 1087//1145 +f 1106//1142 1087//1145 1120//1146 +f 1112//1143 1106//1142 1120//1146 +f 1112//1143 1120//1146 1146//1147 +f 1111//1144 1112//1143 1146//1147 +f 1111//1144 1146//1147 1145//1148 +f 1110//930 1111//1144 1145//1148 +f 1110//930 1145//1148 1144//932 +f 1087//1145 1005//1105 1107//1149 +f 1120//1146 1087//1145 1107//1149 +f 1120//1146 1107//1149 1140//1150 +f 1146//1147 1120//1146 1140//1150 +f 1146//1147 1140//1150 1174//1151 +f 1145//1148 1146//1147 1174//1151 +f 1145//1148 1174//1151 1180//1152 +f 1144//932 1145//1148 1180//1152 +f 1144//932 1180//1152 1179//934 +f 1107//1149 1005//1105 1121//1153 +f 1140//1150 1107//1149 1121//1153 +f 1140//1150 1121//1153 1154//1154 +f 1174//1151 1140//1150 1154//1154 +f 1174//1151 1154//1154 1188//1155 +f 1180//1152 1174//1151 1188//1155 +f 1180//1152 1188//1155 1211//1156 +f 1179//934 1180//1152 1211//1156 +f 1179//934 1211//1156 1210//936 +f 1121//1153 1005//1105 1141//1157 +f 1154//1154 1121//1153 1141//1157 +f 1154//1154 1141//1157 1175//1158 +f 1188//1155 1154//1154 1175//1158 +f 1188//1155 1175//1158 1206//1159 +f 1211//1156 1188//1155 1206//1159 +f 1211//1156 1206//1159 1226//1160 +f 1210//936 1211//1156 1226//1160 +f 1210//936 1226//1160 1212//938 +f 1141//1157 1005//1105 1155//1161 +f 1175//1158 1141//1157 1155//1161 +f 1175//1158 1155//1161 1187//1162 +f 1206//1159 1175//1158 1187//1162 +f 1206//1159 1187//1162 1205//1163 +f 1226//1160 1206//1159 1205//1163 +f 1226//1160 1205//1163 1213//1164 +f 1212//938 1226//1160 1213//1164 +f 1212//938 1213//1164 1181//940 +f 1155//1161 1005//1105 1153//1165 +f 1187//1162 1155//1161 1153//1165 +f 1187//1162 1153//1165 1173//1166 +f 1205//1163 1187//1162 1173//1166 +f 1205//1163 1173//1166 1186//1167 +f 1213//1164 1205//1163 1186//1167 +f 1213//1164 1186//1167 1182//1168 +f 1181//940 1213//1164 1182//1168 +f 1181//940 1182//1168 1147//942 +f 1153//1165 1005//1105 1139//1169 +f 1173//1166 1153//1165 1139//1169 +f 1173//1166 1139//1169 1152//1170 +f 1186//1167 1173//1166 1152//1170 +f 1186//1167 1152//1170 1172//1171 +f 1182//1168 1186//1167 1172//1171 +f 1182//1168 1172//1171 1148//1172 +f 1147//942 1182//1168 1148//1172 +f 1147//942 1148//1172 1113//944 +f 1139//1169 1005//1105 1119//1173 +f 1152//1170 1139//1169 1119//1173 +f 1152//1170 1119//1173 1138//1174 +f 1172//1171 1152//1170 1138//1174 +f 1172//1171 1138//1174 1149//1175 +f 1148//1172 1172//1171 1149//1175 +f 1148//1172 1149//1175 1114//1176 +f 1113//944 1148//1172 1114//1176 +f 1113//944 1114//1176 1081//946 +f 1119//1173 1005//1105 1105//1177 +f 1138//1174 1119//1173 1105//1177 +f 1138//1174 1105//1177 1118//1178 +f 1149//1175 1138//1174 1118//1178 +f 1149//1175 1118//1178 1115//1179 +f 1114//1176 1149//1175 1115//1179 +f 1114//1176 1115//1179 1082//1180 +f 1081//946 1114//1176 1082//1180 +f 1081//946 1082//1180 1046//948 +f 1105//1177 1005//1105 1086//1181 +f 1118//1178 1105//1177 1086//1181 +f 1118//1178 1086//1181 1104//1182 +f 1115//1179 1118//1178 1104//1182 +f 1115//1179 1104//1182 1083//1183 +f 1082//1180 1115//1179 1083//1183 +f 1082//1180 1083//1183 1047//1184 +f 1046//948 1082//1180 1047//1184 +f 1046//948 1047//1184 1016//950 +f 1086//1181 1005//1105 1067//1185 +f 1104//1182 1086//1181 1067//1185 +f 1104//1182 1067//1185 1084//1186 +f 1083//1183 1104//1182 1084//1186 +f 1083//1183 1084//1186 1048//1187 +f 1047//1184 1083//1183 1048//1187 +f 1047//1184 1048//1187 1017//1188 +f 1016//950 1047//1184 1017//1188 +f 1016//950 1017//1188 988//952 +f 1067//1185 1005//1105 1051//1189 +f 1084//1186 1067//1185 1051//1189 +f 1084//1186 1051//1189 1049//1190 +f 1048//1187 1084//1186 1049//1190 +f 1048//1187 1049//1190 1018//1191 +f 1017//1188 1048//1187 1018//1191 +f 1017//1188 1018//1191 989//1192 +f 988//952 1017//1188 989//1192 +f 988//952 989//1192 962//954 +f 1051//1189 1005//1105 1034//1193 +f 1049//1190 1051//1189 1034//1193 +f 1049//1190 1034//1193 1019//1194 +f 1018//1191 1049//1190 1019//1194 +f 1018//1191 1019//1194 990//1195 +f 989//1192 1018//1191 990//1195 +f 989//1192 990//1195 963//1196 +f 962//954 989//1192 963//1196 +f 962//954 963//1196 942//956 +f 1034//1193 1005//1105 1020//1197 +f 1019//1194 1034//1193 1020//1197 +f 1019//1194 1020//1197 991//1198 +f 990//1195 1019//1194 991//1198 +f 990//1195 991//1198 964//1199 +f 963//1196 990//1195 964//1199 +f 963//1196 964//1199 943//1200 +f 942//956 963//1196 943//1200 +f 942//956 943//1200 928//958 +f 1020//1197 1005//1105 993//1104 +f 991//1198 1020//1197 993//1104 +f 991//1198 993//1104 966//1107 +f 964//1199 991//1198 966//1107 +f 964//1199 966//1107 945//1109 +f 943//1200 964//1199 945//1109 +f 943//1200 945//1109 930//1111 +f 928//958 943//1200 930//1111 +f 928//958 930//1111 921//913 +f 1151//1043 1137//1049 1150//1201 +f 1142//995 1143//1202 1122//989 +f 1053//971 1089//977 1069//1203 +f 1122//989 1123//1204 1109//983 +f 1096//1061 1103//1205 1117//1055 +f 1171//1037 1170//1206 1184//1031 +f 1191//1013 1209//1019 1190//1207 +f 1036//970 1053//971 1070//1208 +f 1036//970 1070//1208 1037//1103 +f 1203//1025 1202//1209 1209//1019 +f 1066//1067 1085//1210 1096//1061 +f 1050//1073 1076//1211 1066//1067 +f 1184//1031 1183//1212 1203//1025 +f 1041//1079 1040//1085 1075//1213 +f 1171//1037 1151//1043 1170//1206 +f 1157//1001 1158//1214 1142//995 +f 1137//1049 1117//1055 1136//1215 +f 1038//1097 1072//1216 1039//1091 +f 1178//1007 1191//1013 1177//1217 +f 1089//977 1109//983 1088//1218 +f 1037//1103 1071//1219 1038//1097 +f 1050//1073 1041//1079 1076//1211 +f 1157//1001 1178//1007 1158//1214 +f 1040//1085 1039//1091 1074//1220 +f 1170//1206 1150//1201 452//1221 +f 1264//1222 1071//1219 1263//1223 +f 1261//1224 1262//1225 1076//1211 +f 1085//1210 1076//1211 1262//1225 +f 1190//1207 1208//1226 405//1227 +f 509//176 526//519 1260//1228 +f 1260//1228 526//519 556//523 +f 167//201 556//523 595//202 +f 595//202 621//526 1255//200 +f 172//192 163//182 1254//199 +f 8//49 18//42 3//1229 +f 3//1229 18//42 1288//1230 +f 15//75 7//66 1240//82 +f 1250//50 8//49 3//1229 +f 1//32 1283//40 566//33 +f 593//3 566//33 9//41 +f 19//1231 20//34 33//25 +f 1243//2 636//89 593//3 +f 64//18 40//6 36//17 +f 1244//24 64//18 36//17 +f 641//579 614//582 1237//1232 +f 1250//50 1239//1233 4//48 +f 7//66 4//48 1239//1233 +f 5//74 14//73 11//81 +f 1240//82 7//66 1239//1233 +f 1//32 553//31 565//56 +f 593//3 9//41 1289//83 +f 18//42 20//34 1288//1230 +f 40//6 27//5 1252//16 +f 1249//58 6//65 565//56 +f 14//73 15//75 11//81 +f 592//57 1234//130 1233//58 +f 1237//1232 614//582 588//586 +f 1237//1232 588//586 605//592 +f 539//175 159//177 1259//1234 +f 164//257 1257//1235 168//251 +f 509//176 1256//1236 159//177 +f 1258//250 585//249 1259//1234 +f 169//1237 164//257 174//242 +f 191//236 208//230 185//1238 +f 1290//1239 207//229 640//777 +f 621//526 1292//1240 1255//200 +f 163//182 160//178 157//180 +f 1284//1241 1292//1240 648//227 +f 1252//16 27//5 12//95 +f 119//124 116//129 104//161 +f 116//129 88//135 1242//136 +f 87//159 666//713 715//160 +f 87//159 1241//1242 666//713 +f 1253//1243 47//150 631//152 +f 631//152 666//713 1253//1243 +f 86//142 74//144 60//143 +f 640//777 1291//1244 1290//1239 +f 1291//1244 640//777 613//248 +f 208//230 219//220 200//1245 +f 665//778 640//777 207//229 +f 1285//226 200//1245 219//220 +f 648//227 207//229 1284//1241 +f 691//228 665//778 207//229 +f 605//592 1236//1246 1245//1246 +f 1235//151 605//592 631//152 +f 1248//145 48//153 37//167 +f 667//708 1251//1247 1247//158 +f 605//592 1235//151 1236//1246 +f 641//579 1238//1248 1246//1249 +f 641//579 1237//1232 1238//1248 +f 404//412 391//405 1267//904 +f 1265//911 453//433 436//426 +f 328//351 327//350 331//910 +f 443//445 462//439 469//1250 +f 342//370 1275//1251 344//1252 +f 342//370 334//363 1275//1251 +f 372//480 385//473 384//906 +f 351//377 1271//1253 361//384 +f 351//377 350//1254 1271//1253 +f 337//1255 335//508 345//501 +f 384//906 385//473 396//466 +f 361//384 368//1256 369//391 +f 361//384 1271//1253 368//1256 +f 352//494 1276//1257 346//908 +f 397//1258 396//466 411//459 +f 342//370 350//1254 351//377 +f 342//370 344//1252 350//1254 +f 380//398 369//391 368//1256 +f 334//363 328//351 332//1259 +f 404//412 418//1260 419//419 +f 404//412 1268//905 418//1260 +f 426//452 1286//1261 1282//1262 +f 1282//1262 411//459 426//452 +f 352//494 362//487 1277//1263 +f 1277//1263 1276//1257 352//494 +f 391//405 380//398 381//1264 +f 426//452 443//445 444//1265 +f 444//1265 1286//1261 426//452 +f 362//487 372//480 373//907 +f 373//907 1277//1263 362//487 +f 1202//1209 1183//1212 1270//1266 +f 1116//1267 428//1268 1136//1215 +f 428//1268 1287//1269 1136//1215 +f 1073//1270 353//1271 1074//1220 +f 353//1271 363//1272 1074//1220 +f 353//1271 1073//1270 1279//1273 +f 1070//1208 1069//1203 1263//1223 +f 1274//1274 1069//1203 1088//1218 +f 1177//1217 1273//1275 1272//1276 +f 1272//1276 1158//1214 1177//1217 +f 428//1268 1116//1267 427//1277 +f 1088//1218 1108//1278 343//1279 +f 1103//1205 1085//1210 1278//1280 +f 1108//1278 1123//1204 1280//1281 +f 1123//1204 1281//1282 1280//1281 +f 1143//1202 1158//1214 360//1283 +f 1158//1214 1272//1276 360//1283 +f 1075//1213 1261//1224 1076//1211 +f 1085//1210 1262//1225 1278//1280 +f 1123//1204 1143//1202 1281//1282 +f 1143//1202 360//1283 1281//1282 +f 1074//1220 363//1272 1075//1213 +f 363//1272 1261//1224 1075//1213 +f 1270//1266 1183//1212 452//1221 +f 1266//1284 1150//1201 1136//1215 +f 1273//1275 1177//1217 1190//1207 +f 1208//1226 1202//1209 406//1285 +f 1202//1209 1269//1286 406//1285 +f 1072//1216 1071//1219 1264//1222 +f 1241//1242 1253//1243 666//713 +f 71//137 86//142 60//143 +f 88//135 86//142 71//137 +f 1245//1246 1237//1232 605//592 +f 119//124 104//161 90//119 +f 667//708 1246//1249 1251//1247 +f 621//526 648//227 1292//1240 +f 208//230 200//1245 185//1238 +f 174//242 191//236 169//1237 +f 1258//250 1291//1244 613//248 +f 1244//24 19//1231 33//25 +f 1288//1230 20//34 19//1231 +f 199//208 182//198 178//1287 +f 206//1288 218//214 190//1289 +f 1260//1228 556//523 167//201 +f 157//180 1254//199 163//182 +f 178//1287 182//198 1254//199 +f 218//214 206//1288 1285//226 +f 161//258 1257//1235 158//179 +f 324//345 312//274 323//336 +f 303//317 302//323 316//338 +f 305//305 304//311 318//340 +f 304//311 303//317 317//339 +f 322//347 309//281 321//341 +f 320//346 307//293 319//342 +f 301//329 311//335 314//344 +f 302//323 301//329 315//337 +f 311//335 312//274 313//343 +f 319//342 306//299 318//340 +f 321//341 308//287 320//346 +f 323//336 310//275 322//347 +f 418//1260 435//909 419//419 +f 337//1255 331//910 335//508 +f 469//1250 462//439 1265//911 +f 1137//1049 1136//1215 1150//1201 +f 1143//1202 1123//1204 1122//989 +f 1089//977 1088//1218 1069//1203 +f 1123//1204 1108//1278 1109//983 +f 1103//1205 1116//1267 1117//1055 +f 1170//1206 1183//1212 1184//1031 +f 1209//1019 1208//1226 1190//1207 +f 1053//971 1069//1203 1070//1208 +f 1070//1208 1071//1219 1037//1103 +f 1202//1209 1208//1226 1209//1019 +f 1085//1210 1103//1205 1096//1061 +f 1076//1211 1085//1210 1066//1067 +f 1183//1212 1202//1209 1203//1025 +f 1040//1085 1074//1220 1075//1213 +f 1151//1043 1150//1201 1170//1206 +f 1158//1214 1143//1202 1142//995 +f 1117//1055 1116//1267 1136//1215 +f 1072//1216 1073//1270 1039//1091 +f 1191//1013 1190//1207 1177//1217 +f 1109//983 1108//1278 1088//1218 +f 1071//1219 1072//1216 1038//1097 +f 1041//1079 1075//1213 1076//1211 +f 1178//1007 1177//1217 1158//1214 +f 1039//1091 1073//1270 1074//1220 +f 1150//1201 1266//1284 452//1221 +f 1071//1219 1070//1208 1263//1223 +f 1208//1226 406//1285 405//1227 +f 1256//1236 509//176 1260//1228 +f 1257//1235 161//258 168//251 +f 585//249 539//175 1259//1234 +f 715//160 667//708 1247//158 +f 667//708 641//579 1246//1249 +f 435//909 1265//911 436//426 +f 332//1259 328//351 331//910 +f 444//1265 443//445 469//1250 +f 346//908 337//1255 345//501 +f 397//1258 384//906 396//466 +f 1282//1262 397//1258 411//459 +f 381//1264 380//398 368//1256 +f 1275//1251 334//363 332//1259 +f 1267//904 391//405 381//1264 +f 1269//1286 1202//1209 1270//1266 +f 1073//1270 1072//1216 1279//1273 +f 1069//1203 1274//1274 1263//1223 +f 343//1279 1274//1274 1088//1218 +f 1116//1267 1103//1205 427//1277 +f 1108//1278 1280//1281 343//1279 +f 427//1277 1103//1205 1278//1280 +f 1183//1212 1170//1206 452//1221 +f 1287//1269 1266//1284 1136//1215 +f 405//1227 1273//1275 1190//1207 +f 1279//1273 1072//1216 1264//1222 +f 191//236 185//1238 169//1237 +f 190//1289 199//208 178//1287 +f 218//214 199//208 190//1289 diff --git a/L00/src/GLSL.cpp b/L00/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L00/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L00/src/GLSL.h b/L00/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L00/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L00/src/MatrixStack.cpp b/L00/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/L00/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/L00/src/MatrixStack.h b/L00/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/L00/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/L00/src/Program.cpp b/L00/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/L00/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/L00/src/Program.h b/L00/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/L00/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/L00/src/Shape.cpp b/L00/src/Shape.cpp new file mode 100644 index 0000000..cf80379 --- /dev/null +++ b/L00/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("aPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("aNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("aTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/L00/src/Shape.h b/L00/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/L00/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/L00/src/main.cpp b/L00/src/main.cpp new file mode 100644 index 0000000..f98680b --- /dev/null +++ b/L00/src/main.cpp @@ -0,0 +1,152 @@ +#define _USE_MATH_DEFINES +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Program.h" +#include "Shape.h" + +using namespace std; + +GLFWwindow *window; // Main application window +string RES_DIR = ""; // Where data files live +shared_ptr prog; +shared_ptr shape; + +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +static void init() +{ + GLSL::checkVersion(); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // Initialize mesh. + shape = make_shared(); + shape->loadMesh(RES_DIR + "teapot.obj"); + shape->init(); + + // Initialize the GLSL program. + prog = make_shared(); + prog->setVerbose(false); // Set this to true when debugging. + prog->setShaderNames(RES_DIR + "simple_vert.glsl", RES_DIR + "simple_frag.glsl"); + prog->init(); + prog->addUniform("P"); + prog->addUniform("MV"); + prog->addAttribute("aPos"); + prog->addAttribute("aNor"); + + // If there were any OpenGL errors, this will print something. + // You can intersperse this line in your code to find the exact location + // of your OpenGL error. + GLSL::checkError(GET_FILE_LINE); +} + +static void render() +{ + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + glViewport(0, 0, width, height); + + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Create matrix stacks. + auto P = make_shared(); + auto MV = make_shared(); + // Apply projection. + P->pushMatrix(); + P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f)); + // Apply camera transform. + MV->pushMatrix(); + MV->translate(glm::vec3(0, -0.5, -3)); + + // Draw mesh using GLSL. + prog->bind(); + glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]); + glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]); + shape->draw(prog); + prog->unbind(); + + // Pop matrix stacks. + MV->popMatrix(); + P->popMatrix(); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RES_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L00/src/tiny_obj_loader.h b/L00/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L00/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L01.zip b/L01.zip new file mode 100644 index 0000000000000000000000000000000000000000..cb546dda9873055ffdf2f8bdb7615303272a40d0 GIT binary patch literal 14255 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 literal 0 HcmV?d00001 diff --git a/L01/.gitignore b/L01/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L01/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L01/CMakeLists.txt b/L01/CMakeLists.txt new file mode 100644 index 0000000..15573f2 --- /dev/null +++ b/L01/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L01) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/L01/src/Image.cpp b/L01/src/Image.cpp new file mode 100644 index 0000000..7655b46 --- /dev/null +++ b/L01/src/Image.cpp @@ -0,0 +1,87 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); +} + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/L01/src/Image.h b/L01/src/Image.h new file mode 100644 index 0000000..748bb6d --- /dev/null +++ b/L01/src/Image.h @@ -0,0 +1,40 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; +}; + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/L01/src/main.cpp b/L01/src/main.cpp new file mode 100644 index 0000000..6f0a8d1 --- /dev/null +++ b/L01/src/main.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include "Image.h" + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 10) { + cout << "Usage: L01 filename width height x1 y1 x2 y2 x3 y3" << endl; + return 0; + } + // Output filename + string filename(argv[1]); + // Width of image + int width = atoi(argv[2]); + // Height of image + int height = atoi(argv[3]); + + // Initialize coordinate variables to make things easier + float x1 = atoi(argv[4]); + float y1 = atoi(argv[5]); + float x2 = atoi(argv[6]); + float y2 = atoi(argv[7]); + float x3 = atoi(argv[8]); + float y3 = atoi(argv[9]); + + // Vertex 1 + vertex v1; + v1.x = x1; + v1.y = y1; + v1.z = 0.0; + // Vertex 2 + vertex v2; + v2.x = x2; + v2.y = y2; + v2.z = 0.0; + // Vertex 3 + vertex v3; + v3.x = x3; + v3.y = y3; + v3.z = 0.0; + // Triangle + Tri t(v1, v2, v3); + +// Find xmin, xmax, ymin, ymax + float xmin = x1; + float xmax = x1; + float ymin = y1; + float ymax = y1; + if(x2 < xmin) + xmin = x2; + if(x3 < xmin) + xmin = x3; + if(x2 > xmax) + xmax = x2; + if(x3 > xmax) + xmax = x3; + if(y2 < ymin) + ymin = y2; + if(y3 < ymin) + ymin = y3; + if(y2 > ymax) + ymax = y2; + if(y3 > ymax) + ymax = y3; + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + // Draw a rectangle + for(int y = ymin; y < ymax; ++y) { + for(int x = xmin; x < xmax; ++x) { + unsigned char r = 255; + unsigned char g = 0; + unsigned char b = 0; + image->setPixel(x, y, r, g, b); + } + } + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/L01/src/stb_image_write.h b/L01/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/L01/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/L01/src/triangle.cpp b/L01/src/triangle.cpp new file mode 100644 index 0000000..a8029c6 --- /dev/null +++ b/L01/src/triangle.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include "triangle.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) : + v.push_back(one), + v.push_back(two), + v.push_back(three) +{ +} diff --git a/L01/src/triangle.h b/L01/src/triangle.h new file mode 100644 index 0000000..ee231b9 --- /dev/null +++ b/L01/src/triangle.h @@ -0,0 +1,23 @@ +#pragma once +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; +}; + +#endif diff --git a/L02/.gitignore b/L02/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L02/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake b/L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake new file mode 100644 index 0000000..fb36007 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CMakeCCompiler.cmake @@ -0,0 +1,68 @@ +set(CMAKE_C_COMPILER "/usr/lib/hardening-wrapper/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "6.3.1") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") +set(CMAKE_C_COMPILE_FEATURES "c_function_prototypes;c_restrict;c_variadic_macros;c_static_assert") +set(CMAKE_C90_COMPILE_FEATURES "c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_static_assert") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_SIMULATE_VERSION "") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/lib/hardening-wrapper/bin/ld") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake b/L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..929c256 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CMakeCXXCompiler.cmake @@ -0,0 +1,69 @@ +set(CMAKE_CXX_COMPILER "/usr/lib/hardening-wrapper/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "6.3.1") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_template_template_parameters;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_SIMULATE_VERSION "") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/lib/hardening-wrapper/bin/ld") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP) +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_C.bin b/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..b893f608f787a35d278c397656ddccf928aecd45 GIT binary patch literal 8616 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 PZ39187Awb7T}l24Q{$BW literal 0 HcmV?d00001 diff --git a/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_CXX.bin b/L02/CMakeFiles/3.7.2/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..e18e2ba907a1f0c2c26394cda9dff35b28b893ff GIT binary patch literal 8632 zcmeHMZ){W76~B%Xl8nT0XkY=l^2+EMit_3NNCOqC9mnB?I)sMMWu@WOv7N-!u`~Ob z1=Ojav}hg+jkZbKI;lh2hxS7?Z6DVC(X>J7I;5@=bYer4O%aSObg-o@WvNE-&bjX% z=lS}1tF{mO!i}7B&+q)X=iPVTefOOAbRgJO=5R1-PWD-boTt)6yh6~vLUe$5Sv#wS z|97#KY!UDk95dx!lYrE0^TIXJDuFwJmcy^T%mie5r_dux5hBI$O0{o%!juqYOyL09 zVXWtBISW+b9ilr#90P)q9kOUQC+y~g9nl#P7*V=Dyf*yx3x6{01Q|A>sEcjKWg~+9 z(Q3{X(G4cdh?3nSV25#j+~yXFePX;)^U@^ZCn_$N-5-w)wQaaR9%+up5}AqSiT1YU zwhd}JskZX#M*pb0b^9(p63wFm9LC%LKU@PSzw50>E~M+fv-jw)zF)oeUgO6boBuqF zGF*aahjiL~u!`N?P+e7CUi;;8=0yx|bv^v{R{MYVvrAul${#p;wPy1-7q?)K910b=5RneBrOZ{kscHN;ZsJv5~GSfjks z;70&oZR6(+z}&2nHM*4o>2;1TXC4XvQ0O;F_?v($Hh#_kzJ%50pZ9gZWBWP$>RBE0 zh;>No>>S{z{{ykmqo@pR7JhEFoXO+92sr9LA@l>N4DBNPmcSjHlNRmE9Is`H7#Ht9 zwpZY{gt^!nfpZZ5!8%MEk?^{8xc1tZu8)i*6MEVRr3_tX`nG*~UvwmvHlitiJd{pH z(@gK~@6jXClz{tt{PAQW+8-KWkCwftP5xd=CrY-Q07jdtK(b3)JFjIgYm@V?eM=#XVH80a)q}a2 zVXi-T5=R|Y>sCF(hXngW+)M%HMk6@8TR5vRotgHs zzk^#^K#gVY)h4(6qY`?%z@Jg09oe!3@Y&j2E;p;ezroilssM1jUmVX5DA%+~2bdLfNHFH6z{GoxRbWJsVsL(+l_b#7EBA zx?8!N_Utu7X?dIGGnjoRn7z>n9&!yAw8@hWZPOnz@8BBPJ?MMfH|X2r(@#z>4ER1Q z4en2@5(j@H;dPj;dwW;!<}^I-$zeS*Zlrd5+6Pg>@z79gH=M5!aIADbi0^D%qc44w z%N+!I3g`}?^AP4sKyltr0sRS3H>@LU_@2b(IMBx&6K==Kn#!taN2MEaJR6OJ58AU) z&t9LgH9}tjeg4e5++D85ZFP&kSapy+wBo`0)~{KO_UN+{ej3EY_iCTZeYnhDyQs_y zBb%}a$R|J^1H?&r!nT#ZMa0hcmW-r;KcYK7+V9A2ck+9xY}T;7zc-RJW7TumJ= z1@u6_!&SxO#J&C)__03!=<;^EJp;FA;D4I|dSBD~nY@W@CI2oaJ|+~1PfPqE!Pf{% z=QfcR<AaAObdTYC z7u#Z!z)9C^O9ds8KU0YFia5ToMsY}>IPjc{t=c4cfB(#x@d3*hSo z@4gWNT}cHnl}LzyhGDdlU)yT;{2?>dvesTVbc21jo z)5K|)LC$RWJeIR}bHo$Hhu99k18@hNQsnDW058LQR=QuS1%6DzF)KrTc^`flaEB#+ z+AkjCc=0?R5`Ji32bQ-f`0uc}UwF2%yRO%`ejW3Q`%e4gd4UfI+yy+gQuFf{kU3aA zo2CtzYcuu%$BX9;#dh(SrN`p+*#HybuvriHalEmp&d?@s+OI@7%nvwL4&-&)FK~IC zk8nT5>$V#99lQF;IOt=2L#|iUg1%i{y_(5Uhb#3F4PO-V!cSNUj?~-@%`N?{L6Ku%^bJc zZ?S5khFLgeq>aq*Fm!c&o4-#FcJJ(m!q7tfM>odwFjjz|GNeb6`ba!E6pHH+BbiF; zq09seC&$L)Q6m~r+cvd4V6VgrI(jIT3hmdU2_vi7EZ^=3RL|) zp(msMfdM}Z6pKewzK(7+JU-6!$AT?wvBYpvw7+gyN<^?0Rv0N3s4SuL z3LDcqKfm4A)9nWtuXZiewmwE3PA-snz1C{hzc14jR?e`ZXIr(CYHHR3oiy4){5JJA zUTWhtJf^1ij~SsMphn81qtuHfpvpMT)I`#Vs&EsVjnIhTMiLoyC=-Knc`U+IsL zSaYKhFeT13H5Z?0LH)g9Py^?ou~-;JP8#SQ5Ueq(Pl zH=2#kfkY`U5Mr)NeWag;AHHhIp3aLz6_8n*NFVZ03-qk^bgm@2Ca-CBWcyBlZ@^ie z#;5Zq(Z_{7?yB#6fn#o$o{wpkSOItpu(GQ zM=aX|JSl=3ecU%vil zz!tAbq;2`{2$Yw?NwT1c>B(bPpl7wGb9tWTHO&sy$%%eNvRA~pk0`}UZe;%JlD$XR z6Mav*VKgrJ`?h3H-$jVZ$9nntzbou%{^>gp(KZ@LP?-p zuS@pw{QVN-ct)i>n$B_b9aGjPp6DB3TW7JS^WlsrXpkPL@J2k*-vf%bh{mTpVfH`R zo8B0^03BSrWKVe#eP^B#_n+1`jZ638DA-!Zr+n%(UKBKsN%H^6p6F$eSncz9ml%Nd z8FD~&ME@q))Az|nVNY?&_Qd1;MPGFN^xd#Y7}7YTFQ$W7hTl06^W+h;L-z9eBYUFt zpiX03U3f$RtBe$dP-6Mm^z2yepAhj+h#U7Q5aPFBx*nQWd_L{QKex>EHXu2d$Nv|% C2D458 literal 0 HcmV?d00001 diff --git a/L02/CMakeFiles/3.7.2/CMakeSystem.cmake b/L02/CMakeFiles/3.7.2/CMakeSystem.cmake new file mode 100644 index 0000000..73db990 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-4.8.13-1-ARCH") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "4.8.13-1-ARCH") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-4.8.13-1-ARCH") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "4.8.13-1-ARCH") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c b/L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..512e360 --- /dev/null +++ b/L02/CMakeFiles/3.7.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,561 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(__ARMCC_VERSION) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(SDCC) +# define COMPILER_ID "SDCC" + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if !defined(__STDC__) +# if defined(_MSC_VER) && !defined(__clang__) +# define C_DIALECT "90" +# else +# define C_DIALECT +# endif +#elif __STDC_VERSION__ >= 201000L +# define C_DIALECT "11" +#elif __STDC_VERSION__ >= 199901L +# define C_DIALECT "99" +#else +# define C_DIALECT "90" +#endif +const char* info_language_dialect_default = + "INFO" ":" "dialect_default[" C_DIALECT "]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/L02/CMakeFiles/3.7.2/CompilerIdC/a.out b/L02/CMakeFiles/3.7.2/CompilerIdC/a.out new file mode 100755 index 0000000000000000000000000000000000000000..5f8674debeae8af53beafce8eef2eb550fd3c218 GIT binary patch literal 8776 zcmeHMU2Igx6`u8CY{0C|Uu&QZS2R&cTNc{^$0VZc`j2aBe&U#L4;8JNR;UdUAQC~7B2Wq2bLO6J zeed;k8s()gjJ11azBxbhb7uC;@i)49yQ?A*g%VX?RNR`bc9Dd1ytzs$L=vh^EuioF z)M_=K+RU1u50`}go}sryHE6B$M~Tj(Pg|7>1nH-Q4-_M0Dnk_%c&*y~OQr7l^R-f>7WbI-x zU3A4mg}3$gw0Br7@s{`|cZlMYs*2W_|CEA1lvZWv1XZcyG8dc=`1Q0nSp&|G@a-1d zXfQMaezeyGa3u^)0lZJ}wg5gVcp`uo1wU8s+T~&Jd{F-E!7*#@yXe8$4^b|AaGWjf zyY9ig_s=a4?md6z#I;)UMD;TZ4P_ob*o2pP9rHhEz0U#Wv+Zs-_b2Mh)tC~YffzW0oV4BKBvw+vE^6Py1ckt zE?+k3Yw-2zHwlQmH+wwCYG}|CTUBY%mA%C2j+^XnCVrmG6;@e3H+UsMyki>t=fF3F;jCcz94+i^Qd(mwKZstw@Ikq3 z9)HI%n*WOZ=$*XUJ9)E{G?bUWWlo%ln4AAry2`#YFqr&Waxl3!X`Pv#*}wPB(2QB1 z_AZ{kzeMOPe^}|+*}dzL;r#f4Og3E@pxb!R&+Y5C4yFsmOg=Zz#?GdP9lGvD>{8YlXePgc0QWS-C0+jq+4uM?d| zOVmqru2ZE_8M3^6$IlJXch#(GWq7rJ8V1)+XCNgOG|R>nM+1LJ6u3CnX*LEnGM?)ZpXv(ojf$EzPT1k%rvZezW!OZ#79__nlR z7vuVWQM_a4vXA&38-(~A@i^k|Z50a3Hh;%(&oUQ{QT7le&omJEBKoquTj`XKTfV7 z{^Q3NRQ$@1FH|@`eteNS0EhQ(+|U!5gwr^EjTZO@G7-foeJ#NTETTPiRvi)AZPyI zz56A?BWh;+xKF;S@!9KqO!VL$r=~7b^c@M=FODt4<~7%Rf3Ni{QLo@a)Y_H$qsC{i z19yk%|BIGeI?GS4YCW_4;XUCG`rCZHAhZ2;CE<|}KiNR|Qr;Kwe_Rt=2{*J2|JQ`Z zXZzIv;SKa_5cI3fgf9&_cS9QY>*m%m(G&FBlY|?y+0~B-UsBbmD)+JQ{DN^cbFOg> z{Z`|RDwtn+gK%Dl-Lej8(Q}Dt1NqzTzLD!g8Dbk!M~I6wO$2MKd;9#`ySrM`e{848Ayxp zKdtdb70gSiOfKWZht+VwDLSQ*5vp3&_KrTQx99PG%ThDxJj)rkhB=`}nK~<#w??!1 zAvo@lpbq$Uvfv6)wQ#e2J4O-b)S4nS)E_mncUISL0q05oxUW9 ze)+8~({i<$oqfvM*1M}c*=z0U?tZ+h-|A1c_ja)bo%9?omh?o$aNQ+SK zP_ZZ`bf#7dXYJf*$sVP}_vbRgld~43bFs{v=M7EN`cuUIiE5jYfN{si`4pw%#lz!{ zJw((gxO5D)OpemX2UI+lchd1>d(V2u9+lQ;t`r|CWhj52NvSxu#_Zylil+|eNS{lc zg4+Y5noSxO^%c@tn*~%{uUY&+)`^ei9Tj)dhv=JKm6-B+7vt$Man7+6iK69-x?bu^ zpuTUI*hslOo*AZL=`QZ9-e9S(I`~u?D%Kug8kcXZ> zP=CEg9`C3IaeVMW4ced=sDtMZ`*@c${ttQRdy6XUyO77b%n*6}e;fV{yYPdPB5PWMSK@_w-7)RRu=r3^cWE_`X;EsEi+R_ou0I1AQ>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(__ARMCC_VERSION) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if __cplusplus >= 201402L + "14" +#elif __cplusplus >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} diff --git a/L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out b/L02/CMakeFiles/3.7.2/CompilerIdCXX/a.out new file mode 100755 index 0000000000000000000000000000000000000000..4d7dcb7bca9d8b1af2488068b850a48cd757bf45 GIT binary patch literal 8784 zcmeHMUvN}c89$pPBtWuBC};qcEz&W_aM=wZ4Q-L#BpYt%hR_hO62s+YcayB$KXLai z4UAT3N}V*O;_y(~7kzNXKJ>xyPlqQB!c<3J(iy9r5o@NFnb4scr^tjU&H8=ke&6Qa zn;Y60AAFFL+5OJ>o$ufIyXX7zok+B!%;OPUyy7bYTT|sG5~7ajjZ^^=5-nmCe1Ab~ z5-XvNtReVd3CZt8I!~&ZR#Lwg=nD9>l$n5&evbHZdMf*YCo;c^Ui_z}LF)?^=exdl`HJ@GUNS1k6+3h{v{X$GK@1nl_ZqX0*Ja=L}5~ z+JTc=Phu#UHxjwFl%CHg@}I7pQ65?C7wWkwqpUcsj$N(1 z!e&Hq_W*PiABw|w&E^o)TA?<0o*9B4bdJAyTpfQ`9eZ!?P;Ydyd^NbQPF7!l(W#Sr ztAG^O-(KYxw`w-GOXvx-HCc}2h`McF9lx%Q&HGNS2RHr%eCWoi{^HD_2LD>&TS(T~Gly~Yov-dKviNcrE zvAsiBI|BNQDs^J-v(TEYE*6WkDtz_7QGO8s&xcF>d9VVU9@{4hYi=9|PSbC&f2YzM z%nejoobJC7f?lkTfBU97UYPl9h`?y$C&wXI{gMZ=qkB+||9lzZU8j9<#sbg0>>Yl$A-p4)D*B}0R zxIcV6tX(<3XzxSVN>ZO~SK+wL;(;@KuhMz2qx+FqHa(I|C31amTld?!ZT;HGL@uAq zX8HnVX;!GRiz~r?Atgpqx-po|rTe1z>p`HNiw*ZtJ)YE4iI@TR;GkYe8GXT~e&N~V zeKY{(@m$@yTP%JH=sK99DA4wWV)4g7uL8XavhVPZDzQFS^Rxc2)dj-+R{c?W>?$5yg(+u$Yi{D#3cDNE{ zanhs%&pX;@sa-|%3_WfrEE4Zkm>nCapWlO}lhPZG-iPG2P*<27>_-bt5Ik~aVSOJJP5%It ztZ@BGe;Y_1es*M==XZ|U_0)fd+H9B9|IY}=vCBEY?{Ys)48Obioz3s+{cUZJ_#5DT zu+87B1eKt_F%WDHv;-Q3t!J0n^Kc*-*t49;67Gc;I_CvSAXL2YX5o0+j(dgS@?+?Q zh?Dn|oxfc0KC zNY=e#J>*r~@XrX2)2u>X@mUB!-T3Q8y(_*!sIEBQLW|n*ysi-cDlQ^s4TtZBKLEG~ zUSZC0`2jBz)nd-EURwwc@C62KEEs7czw@4c9B_|V^q=pOV-jCF&u2*w-}}&%WfHzU zF6)JFN4Ifd&vmj5vfNG!uAzk z2Je=7mY&m5iQ81j#!JiS`8nWquwLe`5zehyezOe!HNb0K#(M*B+@sD?4g;?%t6y@C z>JSG#Av#}tP3$CozvJ9J1~|^=2+e1L3`I$gGrw~T@LJ3MXTJuC->R&ppbAY3tb97E+39LBb&=>dSO&xl$}Z#iMZ0dC-|^C6Q=Kynx4z) zr?f=I$ej{{IX#`w;)Qhj6o^<_8hU19ZR^sXO0+%sWE+L^opB{LG9t8N(O_dTGnnP@ z9rSecgu5bI&Kqus6HsMg)laX8Ye^@dxc5frkSkJ|y6 z{uEmK*A9leI@_R6rXpkcf*c>TKRHS2%wC2<*7W7QbEw^r^^7MoS|OhR$1vUMno@;j z(hc3rkb+Ov?5V?=21#0)Ejf`XJu_6$hhSaoX$;U3&u6t^Jrl=d?&7d{3S1ebtQfyPnR2|sMv&K9z6cGx;^4ZFh2N=6{e&~&`uf-w>F^u6Zqi#u{_5$Oq(41 z&iVhPLw<(rGQH)HXZINXHB@kq(zY+fN&Np+CqK8D{sCm+HCK}7cxr|cEzAcjvT&Q} zp8>`3vwe ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccNP9yHN.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-o] ==> ignore + arg [cmTC_89404] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o] ==> ignore + arg [-L/usr/lib/hardening-wrapper/bin] ==> dir [/usr/lib/hardening-wrapper/bin] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] + arg [CMakeFiles/cmTC_89404.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] ==> ignore + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + collapse library dir [/usr/lib/hardening-wrapper/bin] ==> [/usr/lib/hardening-wrapper/bin] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> [/usr/lib] + implicit libs: [c] + implicit dirs: [/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib] + implicit fwks: [] + + + + +Detecting C [-std=c11] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_82150/fast" +/usr/bin/make -f CMakeFiles/cmTC_82150.dir/build.make CMakeFiles/cmTC_82150.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_82150.dir/feature_tests.c.o +/usr/lib/hardening-wrapper/bin/cc -std=c11 -o CMakeFiles/cmTC_82150.dir/feature_tests.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_82150 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_82150.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_82150.dir/feature_tests.c.o -o cmTC_82150 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:1c_restrict + Feature record: C_FEATURE:1c_static_assert + Feature record: C_FEATURE:1c_variadic_macros + + +Detecting C [-std=c99] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_1c427/fast" +/usr/bin/make -f CMakeFiles/cmTC_1c427.dir/build.make CMakeFiles/cmTC_1c427.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_1c427.dir/feature_tests.c.o +/usr/lib/hardening-wrapper/bin/cc -std=c99 -o CMakeFiles/cmTC_1c427.dir/feature_tests.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_1c427 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_1c427.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_1c427.dir/feature_tests.c.o -o cmTC_1c427 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:1c_restrict + Feature record: C_FEATURE:0c_static_assert + Feature record: C_FEATURE:1c_variadic_macros + + +Detecting C [-std=c90] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_6a547/fast" +/usr/bin/make -f CMakeFiles/cmTC_6a547.dir/build.make CMakeFiles/cmTC_6a547.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_6a547.dir/feature_tests.c.o +/usr/lib/hardening-wrapper/bin/cc -std=c90 -o CMakeFiles/cmTC_6a547.dir/feature_tests.c.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_6a547 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_6a547.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/cc CMakeFiles/cmTC_6a547.dir/feature_tests.c.o -o cmTC_6a547 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:0c_restrict + Feature record: C_FEATURE:0c_static_assert + Feature record: C_FEATURE:0c_variadic_macros +Determining if the CXX compiler works passed with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_f3383/fast" +/usr/bin/make -f CMakeFiles/cmTC_f3383.dir/build.make CMakeFiles/cmTC_f3383.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_f3383.dir/testCXXCompiler.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -o CMakeFiles/cmTC_f3383.dir/testCXXCompiler.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx +Linking CXX executable cmTC_f3383 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_f3383.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_f3383.dir/testCXXCompiler.cxx.o -o cmTC_f3383 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_ad6b8/fast" +/usr/bin/make -f CMakeFiles/cmTC_ad6b8.dir/build.make CMakeFiles/cmTC_ad6b8.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o +/usr/lib/hardening-wrapper/bin/c++ -o CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.7/Modules/CMakeCXXCompilerABI.cpp +Linking CXX executable cmTC_ad6b8 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_ad6b8.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ -v CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_ad6b8 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper +Target: x86_64-pc-linux-gnu +Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release +Thread model: posix +gcc version 6.3.1 20170109 (GCC) +COMPILER_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ +LIBRARY_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_ad6b8' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJChkf9.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_ad6b8 /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o -L/usr/lib/hardening-wrapper/bin -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o +COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_ad6b8' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:"/usr/bin/make" "cmTC_ad6b8/fast"] + ignore line: [/usr/bin/make -f CMakeFiles/cmTC_ad6b8.dir/build.make CMakeFiles/cmTC_ad6b8.dir/build] + ignore line: [make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp'] + ignore line: [Building CXX object CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/lib/hardening-wrapper/bin/c++ -o CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.7/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Linking CXX executable cmTC_ad6b8] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_ad6b8.dir/link.txt --verbose=1] + ignore line: [/usr/lib/hardening-wrapper/bin/c++ -v CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_ad6b8 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] + ignore line: [Target: x86_64-pc-linux-gnu] + ignore line: [Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release] + ignore line: [Thread model: posix] + ignore line: [gcc version 6.3.1 20170109 (GCC) ] + ignore line: [COMPILER_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/hardening-wrapper/bin/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-B' '/usr/lib/hardening-wrapper/bin' '-fPIE' '-pie' '-fstack-check=specific' '-fstack-protector-strong' '-v' '-o' 'cmTC_ad6b8' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJChkf9.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_ad6b8 /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o -L/usr/lib/hardening-wrapper/bin -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccJChkf9.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-o] ==> ignore + arg [cmTC_ad6b8] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/Scrt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o] ==> ignore + arg [-L/usr/lib/hardening-wrapper/bin] ==> dir [/usr/lib/hardening-wrapper/bin] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] + arg [CMakeFiles/cmTC_ad6b8.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib/crtn.o] ==> ignore + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + collapse library dir [/usr/lib/hardening-wrapper/bin] ==> [/usr/lib/hardening-wrapper/bin] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] ==> [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;c] + implicit dirs: [/usr/lib/hardening-wrapper/bin;/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1;/usr/lib;/lib] + implicit fwks: [] + + + + +Detecting CXX [-std=c++14] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_e6959/fast" +/usr/bin/make -f CMakeFiles/cmTC_e6959.dir/build.make CMakeFiles/cmTC_e6959.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_e6959.dir/feature_tests.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -std=c++14 -o CMakeFiles/cmTC_e6959.dir/feature_tests.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.cxx +Linking CXX executable cmTC_e6959 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_e6959.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_e6959.dir/feature_tests.cxx.o -o cmTC_e6959 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: CXX_FEATURE:1cxx_aggregate_default_initializers + Feature record: CXX_FEATURE:1cxx_alias_templates + Feature record: CXX_FEATURE:1cxx_alignas + Feature record: CXX_FEATURE:1cxx_alignof + Feature record: CXX_FEATURE:1cxx_attributes + Feature record: CXX_FEATURE:1cxx_attribute_deprecated + Feature record: CXX_FEATURE:1cxx_auto_type + Feature record: CXX_FEATURE:1cxx_binary_literals + Feature record: CXX_FEATURE:1cxx_constexpr + Feature record: CXX_FEATURE:1cxx_contextual_conversions + Feature record: CXX_FEATURE:1cxx_decltype + Feature record: CXX_FEATURE:1cxx_decltype_auto + Feature record: CXX_FEATURE:1cxx_decltype_incomplete_return_types + Feature record: CXX_FEATURE:1cxx_default_function_template_args + Feature record: CXX_FEATURE:1cxx_defaulted_functions + Feature record: CXX_FEATURE:1cxx_defaulted_move_initializers + Feature record: CXX_FEATURE:1cxx_delegating_constructors + Feature record: CXX_FEATURE:1cxx_deleted_functions + Feature record: CXX_FEATURE:1cxx_digit_separators + Feature record: CXX_FEATURE:1cxx_enum_forward_declarations + Feature record: CXX_FEATURE:1cxx_explicit_conversions + Feature record: CXX_FEATURE:1cxx_extended_friend_declarations + Feature record: CXX_FEATURE:1cxx_extern_templates + Feature record: CXX_FEATURE:1cxx_final + Feature record: CXX_FEATURE:1cxx_func_identifier + Feature record: CXX_FEATURE:1cxx_generalized_initializers + Feature record: CXX_FEATURE:1cxx_generic_lambdas + Feature record: CXX_FEATURE:1cxx_inheriting_constructors + Feature record: CXX_FEATURE:1cxx_inline_namespaces + Feature record: CXX_FEATURE:1cxx_lambdas + Feature record: CXX_FEATURE:1cxx_lambda_init_captures + Feature record: CXX_FEATURE:1cxx_local_type_template_args + Feature record: CXX_FEATURE:1cxx_long_long_type + Feature record: CXX_FEATURE:1cxx_noexcept + Feature record: CXX_FEATURE:1cxx_nonstatic_member_init + Feature record: CXX_FEATURE:1cxx_nullptr + Feature record: CXX_FEATURE:1cxx_override + Feature record: CXX_FEATURE:1cxx_range_for + Feature record: CXX_FEATURE:1cxx_raw_string_literals + Feature record: CXX_FEATURE:1cxx_reference_qualified_functions + Feature record: CXX_FEATURE:1cxx_relaxed_constexpr + Feature record: CXX_FEATURE:1cxx_return_type_deduction + Feature record: CXX_FEATURE:1cxx_right_angle_brackets + Feature record: CXX_FEATURE:1cxx_rvalue_references + Feature record: CXX_FEATURE:1cxx_sizeof_member + Feature record: CXX_FEATURE:1cxx_static_assert + Feature record: CXX_FEATURE:1cxx_strong_enums + Feature record: CXX_FEATURE:1cxx_template_template_parameters + Feature record: CXX_FEATURE:1cxx_thread_local + Feature record: CXX_FEATURE:1cxx_trailing_return_types + Feature record: CXX_FEATURE:1cxx_unicode_literals + Feature record: CXX_FEATURE:1cxx_uniform_initialization + Feature record: CXX_FEATURE:1cxx_unrestricted_unions + Feature record: CXX_FEATURE:1cxx_user_literals + Feature record: CXX_FEATURE:1cxx_variable_templates + Feature record: CXX_FEATURE:1cxx_variadic_macros + Feature record: CXX_FEATURE:1cxx_variadic_templates + + +Detecting CXX [-std=c++11] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_990df/fast" +/usr/bin/make -f CMakeFiles/cmTC_990df.dir/build.make CMakeFiles/cmTC_990df.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_990df.dir/feature_tests.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -std=c++11 -o CMakeFiles/cmTC_990df.dir/feature_tests.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.cxx +Linking CXX executable cmTC_990df +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_990df.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_990df.dir/feature_tests.cxx.o -o cmTC_990df -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: CXX_FEATURE:0cxx_aggregate_default_initializers + Feature record: CXX_FEATURE:1cxx_alias_templates + Feature record: CXX_FEATURE:1cxx_alignas + Feature record: CXX_FEATURE:1cxx_alignof + Feature record: CXX_FEATURE:1cxx_attributes + Feature record: CXX_FEATURE:0cxx_attribute_deprecated + Feature record: CXX_FEATURE:1cxx_auto_type + Feature record: CXX_FEATURE:0cxx_binary_literals + Feature record: CXX_FEATURE:1cxx_constexpr + Feature record: CXX_FEATURE:0cxx_contextual_conversions + Feature record: CXX_FEATURE:1cxx_decltype + Feature record: CXX_FEATURE:0cxx_decltype_auto + Feature record: CXX_FEATURE:1cxx_decltype_incomplete_return_types + Feature record: CXX_FEATURE:1cxx_default_function_template_args + Feature record: CXX_FEATURE:1cxx_defaulted_functions + Feature record: CXX_FEATURE:1cxx_defaulted_move_initializers + Feature record: CXX_FEATURE:1cxx_delegating_constructors + Feature record: CXX_FEATURE:1cxx_deleted_functions + Feature record: CXX_FEATURE:0cxx_digit_separators + Feature record: CXX_FEATURE:1cxx_enum_forward_declarations + Feature record: CXX_FEATURE:1cxx_explicit_conversions + Feature record: CXX_FEATURE:1cxx_extended_friend_declarations + Feature record: CXX_FEATURE:1cxx_extern_templates + Feature record: CXX_FEATURE:1cxx_final + Feature record: CXX_FEATURE:1cxx_func_identifier + Feature record: CXX_FEATURE:1cxx_generalized_initializers + Feature record: CXX_FEATURE:0cxx_generic_lambdas + Feature record: CXX_FEATURE:1cxx_inheriting_constructors + Feature record: CXX_FEATURE:1cxx_inline_namespaces + Feature record: CXX_FEATURE:1cxx_lambdas + Feature record: CXX_FEATURE:0cxx_lambda_init_captures + Feature record: CXX_FEATURE:1cxx_local_type_template_args + Feature record: CXX_FEATURE:1cxx_long_long_type + Feature record: CXX_FEATURE:1cxx_noexcept + Feature record: CXX_FEATURE:1cxx_nonstatic_member_init + Feature record: CXX_FEATURE:1cxx_nullptr + Feature record: CXX_FEATURE:1cxx_override + Feature record: CXX_FEATURE:1cxx_range_for + Feature record: CXX_FEATURE:1cxx_raw_string_literals + Feature record: CXX_FEATURE:1cxx_reference_qualified_functions + Feature record: CXX_FEATURE:0cxx_relaxed_constexpr + Feature record: CXX_FEATURE:0cxx_return_type_deduction + Feature record: CXX_FEATURE:1cxx_right_angle_brackets + Feature record: CXX_FEATURE:1cxx_rvalue_references + Feature record: CXX_FEATURE:1cxx_sizeof_member + Feature record: CXX_FEATURE:1cxx_static_assert + Feature record: CXX_FEATURE:1cxx_strong_enums + Feature record: CXX_FEATURE:1cxx_template_template_parameters + Feature record: CXX_FEATURE:1cxx_thread_local + Feature record: CXX_FEATURE:1cxx_trailing_return_types + Feature record: CXX_FEATURE:1cxx_unicode_literals + Feature record: CXX_FEATURE:1cxx_uniform_initialization + Feature record: CXX_FEATURE:1cxx_unrestricted_unions + Feature record: CXX_FEATURE:1cxx_user_literals + Feature record: CXX_FEATURE:0cxx_variable_templates + Feature record: CXX_FEATURE:1cxx_variadic_macros + Feature record: CXX_FEATURE:1cxx_variadic_templates + + +Detecting CXX [-std=c++98] compiler features compiled with the following output: +Change Dir: /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_7a266/fast" +/usr/bin/make -f CMakeFiles/cmTC_7a266.dir/build.make CMakeFiles/cmTC_7a266.dir/build +make[1]: Entering directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_7a266.dir/feature_tests.cxx.o +/usr/lib/hardening-wrapper/bin/c++ -std=c++98 -o CMakeFiles/cmTC_7a266.dir/feature_tests.cxx.o -c /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/feature_tests.cxx +Linking CXX executable cmTC_7a266 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_7a266.dir/link.txt --verbose=1 +/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/cmTC_7a266.dir/feature_tests.cxx.o -o cmTC_7a266 -rdynamic +make[1]: Leaving directory '/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/CMakeTmp' + + + Feature record: CXX_FEATURE:0cxx_aggregate_default_initializers + Feature record: CXX_FEATURE:0cxx_alias_templates + Feature record: CXX_FEATURE:0cxx_alignas + Feature record: CXX_FEATURE:0cxx_alignof + Feature record: CXX_FEATURE:0cxx_attributes + Feature record: CXX_FEATURE:0cxx_attribute_deprecated + Feature record: CXX_FEATURE:0cxx_auto_type + Feature record: CXX_FEATURE:0cxx_binary_literals + Feature record: CXX_FEATURE:0cxx_constexpr + Feature record: CXX_FEATURE:0cxx_contextual_conversions + Feature record: CXX_FEATURE:0cxx_decltype + Feature record: CXX_FEATURE:0cxx_decltype_auto + Feature record: CXX_FEATURE:0cxx_decltype_incomplete_return_types + Feature record: CXX_FEATURE:0cxx_default_function_template_args + Feature record: CXX_FEATURE:0cxx_defaulted_functions + Feature record: CXX_FEATURE:0cxx_defaulted_move_initializers + Feature record: CXX_FEATURE:0cxx_delegating_constructors + Feature record: CXX_FEATURE:0cxx_deleted_functions + Feature record: CXX_FEATURE:0cxx_digit_separators + Feature record: CXX_FEATURE:0cxx_enum_forward_declarations + Feature record: CXX_FEATURE:0cxx_explicit_conversions + Feature record: CXX_FEATURE:0cxx_extended_friend_declarations + Feature record: CXX_FEATURE:0cxx_extern_templates + Feature record: CXX_FEATURE:0cxx_final + Feature record: CXX_FEATURE:0cxx_func_identifier + Feature record: CXX_FEATURE:0cxx_generalized_initializers + Feature record: CXX_FEATURE:0cxx_generic_lambdas + Feature record: CXX_FEATURE:0cxx_inheriting_constructors + Feature record: CXX_FEATURE:0cxx_inline_namespaces + Feature record: CXX_FEATURE:0cxx_lambdas + Feature record: CXX_FEATURE:0cxx_lambda_init_captures + Feature record: CXX_FEATURE:0cxx_local_type_template_args + Feature record: CXX_FEATURE:0cxx_long_long_type + Feature record: CXX_FEATURE:0cxx_noexcept + Feature record: CXX_FEATURE:0cxx_nonstatic_member_init + Feature record: CXX_FEATURE:0cxx_nullptr + Feature record: CXX_FEATURE:0cxx_override + Feature record: CXX_FEATURE:0cxx_range_for + Feature record: CXX_FEATURE:0cxx_raw_string_literals + Feature record: CXX_FEATURE:0cxx_reference_qualified_functions + Feature record: CXX_FEATURE:0cxx_relaxed_constexpr + Feature record: CXX_FEATURE:0cxx_return_type_deduction + Feature record: CXX_FEATURE:0cxx_right_angle_brackets + Feature record: CXX_FEATURE:0cxx_rvalue_references + Feature record: CXX_FEATURE:0cxx_sizeof_member + Feature record: CXX_FEATURE:0cxx_static_assert + Feature record: CXX_FEATURE:0cxx_strong_enums + Feature record: CXX_FEATURE:1cxx_template_template_parameters + Feature record: CXX_FEATURE:0cxx_thread_local + Feature record: CXX_FEATURE:0cxx_trailing_return_types + Feature record: CXX_FEATURE:0cxx_unicode_literals + Feature record: CXX_FEATURE:0cxx_uniform_initialization + Feature record: CXX_FEATURE:0cxx_unrestricted_unions + Feature record: CXX_FEATURE:0cxx_user_literals + Feature record: CXX_FEATURE:0cxx_variable_templates + Feature record: CXX_FEATURE:0cxx_variadic_macros + Feature record: CXX_FEATURE:0cxx_variadic_templates diff --git a/L02/CMakeFiles/L02.dir/CXX.includecache b/L02/CMakeFiles/L02.dir/CXX.includecache new file mode 100644 index 0000000..f341202 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/CXX.includecache @@ -0,0 +1,52 @@ +#IncludeRegexLine: ^[ ]*#[ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +/home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp +iostream +- +cassert +- +Image.h +/home/shadow8t4/Documents/CSCE441/L02/src/Image.h +stb_image_write.h +/home/shadow8t4/Documents/CSCE441/L02/src/stb_image_write.h + +/home/shadow8t4/Documents/CSCE441/L02/src/Image.h +string +- +vector +- + +/home/shadow8t4/Documents/CSCE441/L02/src/main.cpp +iostream +- +string +- +vector +- +memory +- +Image.h +/home/shadow8t4/Documents/CSCE441/L02/src/Image.h +math.h +- + +/home/shadow8t4/Documents/CSCE441/L02/src/stb_image_write.h +stdio.h +- +stdarg.h +- +stdlib.h +- +string.h +- +math.h +- +assert.h +- + diff --git a/L02/CMakeFiles/L02.dir/DependInfo.cmake b/L02/CMakeFiles/L02.dir/DependInfo.cmake new file mode 100644 index 0000000..fb18f92 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/DependInfo.cmake @@ -0,0 +1,21 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_CXX + "/home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp" "/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir/src/Image.cpp.o" + "/home/shadow8t4/Documents/CSCE441/L02/src/main.cpp" "/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir/src/main.cpp.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/L02/CMakeFiles/L02.dir/build.make b/L02/CMakeFiles/L02.dir/build.make new file mode 100644 index 0000000..5c29247 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/build.make @@ -0,0 +1,140 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/shadow8t4/Documents/CSCE441/L02 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/shadow8t4/Documents/CSCE441/L02/build + +# Include any dependencies generated for this target. +include CMakeFiles/L02.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/L02.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/L02.dir/flags.make + +CMakeFiles/L02.dir/src/Image.cpp.o: CMakeFiles/L02.dir/flags.make +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/Image.cpp + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/L02.dir/src/Image.cpp.o" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/L02.dir/src/Image.cpp.o -c /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp + +CMakeFiles/L02.dir/src/Image.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/L02.dir/src/Image.cpp.i" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp > CMakeFiles/L02.dir/src/Image.cpp.i + +CMakeFiles/L02.dir/src/Image.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/L02.dir/src/Image.cpp.s" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp -o CMakeFiles/L02.dir/src/Image.cpp.s + +CMakeFiles/L02.dir/src/Image.cpp.o.requires: + +.PHONY : CMakeFiles/L02.dir/src/Image.cpp.o.requires + +CMakeFiles/L02.dir/src/Image.cpp.o.provides: CMakeFiles/L02.dir/src/Image.cpp.o.requires + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/src/Image.cpp.o.provides.build +.PHONY : CMakeFiles/L02.dir/src/Image.cpp.o.provides + +CMakeFiles/L02.dir/src/Image.cpp.o.provides.build: CMakeFiles/L02.dir/src/Image.cpp.o + + +CMakeFiles/L02.dir/src/main.cpp.o: CMakeFiles/L02.dir/flags.make +CMakeFiles/L02.dir/src/main.cpp.o: ../src/main.cpp + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object CMakeFiles/L02.dir/src/main.cpp.o" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/L02.dir/src/main.cpp.o -c /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp + +CMakeFiles/L02.dir/src/main.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/L02.dir/src/main.cpp.i" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp > CMakeFiles/L02.dir/src/main.cpp.i + +CMakeFiles/L02.dir/src/main.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/L02.dir/src/main.cpp.s" + /usr/lib/hardening-wrapper/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp -o CMakeFiles/L02.dir/src/main.cpp.s + +CMakeFiles/L02.dir/src/main.cpp.o.requires: + +.PHONY : CMakeFiles/L02.dir/src/main.cpp.o.requires + +CMakeFiles/L02.dir/src/main.cpp.o.provides: CMakeFiles/L02.dir/src/main.cpp.o.requires + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/src/main.cpp.o.provides.build +.PHONY : CMakeFiles/L02.dir/src/main.cpp.o.provides + +CMakeFiles/L02.dir/src/main.cpp.o.provides.build: CMakeFiles/L02.dir/src/main.cpp.o + + +# Object files for target L02 +L02_OBJECTS = \ +"CMakeFiles/L02.dir/src/Image.cpp.o" \ +"CMakeFiles/L02.dir/src/main.cpp.o" + +# External object files for target L02 +L02_EXTERNAL_OBJECTS = + +L02: CMakeFiles/L02.dir/src/Image.cpp.o +L02: CMakeFiles/L02.dir/src/main.cpp.o +L02: CMakeFiles/L02.dir/build.make +L02: CMakeFiles/L02.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Linking CXX executable L02" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/L02.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/L02.dir/build: L02 + +.PHONY : CMakeFiles/L02.dir/build + +CMakeFiles/L02.dir/requires: CMakeFiles/L02.dir/src/Image.cpp.o.requires +CMakeFiles/L02.dir/requires: CMakeFiles/L02.dir/src/main.cpp.o.requires + +.PHONY : CMakeFiles/L02.dir/requires + +CMakeFiles/L02.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/L02.dir/cmake_clean.cmake +.PHONY : CMakeFiles/L02.dir/clean + +CMakeFiles/L02.dir/depend: + cd /home/shadow8t4/Documents/CSCE441/L02/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/shadow8t4/Documents/CSCE441/L02 /home/shadow8t4/Documents/CSCE441/L02 /home/shadow8t4/Documents/CSCE441/L02/build /home/shadow8t4/Documents/CSCE441/L02/build /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/L02.dir/depend + diff --git a/L02/CMakeFiles/L02.dir/cmake_clean.cmake b/L02/CMakeFiles/L02.dir/cmake_clean.cmake new file mode 100644 index 0000000..bf61c67 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/cmake_clean.cmake @@ -0,0 +1,11 @@ +file(REMOVE_RECURSE + "CMakeFiles/L02.dir/src/Image.cpp.o" + "CMakeFiles/L02.dir/src/main.cpp.o" + "L02.pdb" + "L02" +) + +# Per-language clean rules from dependency scanning. +foreach(lang CXX) + include(CMakeFiles/L02.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/L02/CMakeFiles/L02.dir/depend.internal b/L02/CMakeFiles/L02.dir/depend.internal new file mode 100644 index 0000000..f8165f0 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/depend.internal @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +CMakeFiles/L02.dir/src/Image.cpp.o + /home/shadow8t4/Documents/CSCE441/L02/src/Image.cpp + /home/shadow8t4/Documents/CSCE441/L02/src/Image.h + /home/shadow8t4/Documents/CSCE441/L02/src/stb_image_write.h +CMakeFiles/L02.dir/src/main.cpp.o + /home/shadow8t4/Documents/CSCE441/L02/src/Image.h + /home/shadow8t4/Documents/CSCE441/L02/src/main.cpp diff --git a/L02/CMakeFiles/L02.dir/depend.make b/L02/CMakeFiles/L02.dir/depend.make new file mode 100644 index 0000000..1d05299 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/depend.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/Image.cpp +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/Image.h +CMakeFiles/L02.dir/src/Image.cpp.o: ../src/stb_image_write.h + +CMakeFiles/L02.dir/src/main.cpp.o: ../src/Image.h +CMakeFiles/L02.dir/src/main.cpp.o: ../src/main.cpp + diff --git a/L02/CMakeFiles/L02.dir/flags.make b/L02/CMakeFiles/L02.dir/flags.make new file mode 100644 index 0000000..2607a0b --- /dev/null +++ b/L02/CMakeFiles/L02.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# compile CXX with /usr/lib/hardening-wrapper/bin/c++ +CXX_FLAGS = -std=c++11 -Wall -pedantic + +CXX_DEFINES = + +CXX_INCLUDES = + diff --git a/L02/CMakeFiles/L02.dir/link.txt b/L02/CMakeFiles/L02.dir/link.txt new file mode 100644 index 0000000..8fa74d4 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/link.txt @@ -0,0 +1 @@ +/usr/lib/hardening-wrapper/bin/c++ -std=c++11 -Wall -pedantic CMakeFiles/L02.dir/src/Image.cpp.o CMakeFiles/L02.dir/src/main.cpp.o -o L02 -rdynamic diff --git a/L02/CMakeFiles/L02.dir/progress.make b/L02/CMakeFiles/L02.dir/progress.make new file mode 100644 index 0000000..6a9dc74 --- /dev/null +++ b/L02/CMakeFiles/L02.dir/progress.make @@ -0,0 +1,4 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 + diff --git a/L02/CMakeFiles/L02.dir/src/Image.cpp.o b/L02/CMakeFiles/L02.dir/src/Image.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..1a1c40cbf36452b5d19c6a137fe2d61bd1a61ab0 GIT binary patch literal 81608 zcmdVD3w%_?**|_Z8z9_Fyp~pcjW+~QB-{i+4VTr85{y6;6%M&~vOC28TQY(6;P|K?MSM)qxoTghI&%Xri0$dYM4yU=C z=5d0O+z=5!6GcXL|9={=m@ z%jtcb-p}a|IDL@QwVeKt(;spA2&a#7`cqEpIem=N4V?a*(~X?|iqlP;KFR53PM_xV zSx&cbx|P%CIemfC7dd^2(;b{Pa=MGt-JI^>w29MZPG946FQ>0_`Ua;hoW8~B+nm0` z>3f{M&*=x89^mvNPFp$snA1->wIQ=uHZJf4q`YES}IsGfA9h`p7>6e^-#c3zf zY=8Jq{%~cdKV0774`;XeBfd_5Bpc@`eA?y@XC>9$^opRY-Eel}XUC5Ds|THJ`Eik& zVp)nkoP9XrJM7PG@kcTt!`HEc8izmJMD|*BuXZT`TFP6&)atJtPvnZt9~SnIyf$Pl zKL+KH=%ci{veQal+nBtyF)F*o)jCnA^du!zv!&jJem`t!fis#H`6G$v3>Vh;I@20q zLrd~jYjtDt>J}7@F8#Gx9#9gTyrZ$YGc7a>zg8Vr-I&_ZpEA3SM|O>0IYMf_Vkoh^11E>(VuuVoI5)q9Z+q`7Ah{moR zT<2mybGUqWIJ+^NxqU|1*Dy1jx!GaG9$)LRJ-$C$dwd@stFGK`-8K?RnqfjDyV0Nf zmcRB&_#}I?zjoa5)Rf4mX!D5p&|(upGw^HGfa*?9Xh?em0aD%ROFwbE6Df^ZJEzHglVXdFoLc9jBdpqgX5@7$!lm} zZ1T~t0pLKws{DxWfPY=`*13IJ=`2@h^Lv`5YR;U|rxiWph@GV0U)|^xnT^R$?Iikw zSMRK=tAD!{z(XgNHNsBF36$gfn+T23nb~!4YdszE)WS%~tY#G-s)GZt~DzoTAfe@`)Y3oaOjRE9}VYL#CLGAZ*L`3v?V{~+Z%?*55hrD z!I{Ec4b=OGeH}9~enu*XM>2;*vUf+y_km%5W_ah+Fh=U8w&tV9j#Y#4&}PE5{y&n9 zz77K^wKoh;9$#Dg?J%wzx3vBhT}SMYF8a3cb7zA&yq5ZuaP3h1o)KO%L?pE*A?ZoS z1_OtnlS%?PPDkU^!l~w3?(V8zBEeQg|LT`Wk#*aE2J%-sO*Um$NF88IS2(eou8b-*hiywN?cb0ko=9fvHIdAN*DM*nWCG<(&03PVWEzio$T@n= z66;ub%M#Dj@HbP#9pN{(!Rli>=of-XxVi0fD%hR7H^ax#G0(NR(Bvqby*HeRw&L53 zKH1q$(9yPF3b-GG6#`KVK@WdLHBs3R$=ppdoASMsmmy>M4KehVQ>!(&(antL$N)Dw zM+MQ<3+?YxYgrBLYZ@_AM7)lM8Ji=S+c7>w%6DsK_+dsEovC1JYTE=JbcToe2=~y8 z7WNHtujUe$k!xePd_y?9KAgE8_SI?OPGe_v<@$tBU;Iui?62#JCa?GpAEB>>Zx=;2Q3{U z-9{H`?xvzP@HO;Q?@o{S>P6?fySj3>m0WX%P`Mku>IVF*mpyBp>{;8Ie2pXuga2e? z*B-`LhVv+08~4CX=srQ$;izOh2BH8OnPDc3isiKLg?x^iBTAt9mofI~% z>P{ghV;x<|TQ6GjUXQP_Jqc~Rdg*RY`#b3ExC^hOhCRi-VY_ua`@dEH*J1Aewo+S( z{8#%wXz#ZFyAWpR{U3OG+W#5vp&i{G>bvF3

V|Etm)<;#}TDS2rf%JSBP5u4Mz6 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

i0h?`JOw2`8jdw F|9{f3xXb_m literal 0 HcmV?d00001 diff --git a/L02/CMakeFiles/L02.dir/src/main.cpp.o b/L02/CMakeFiles/L02.dir/src/main.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..c4edae31ada5c6132f847f7f5b1321abfabeced1 GIT binary patch literal 64144 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 literal 0 HcmV?d00001 diff --git a/L02/CMakeFiles/Makefile.cmake b/L02/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..ca445c6 --- /dev/null +++ b/L02/CMakeFiles/Makefile.cmake @@ -0,0 +1,45 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/3.7.2/CMakeCCompiler.cmake" + "CMakeFiles/3.7.2/CMakeCXXCompiler.cmake" + "CMakeFiles/3.7.2/CMakeSystem.cmake" + "/usr/share/cmake-3.7/Modules/CMakeCInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeCXXInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake-3.7/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake-3.7/Modules/CMakeLanguageInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake-3.7/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/share/cmake-3.7/Modules/Compiler/GNU-C.cmake" + "/usr/share/cmake-3.7/Modules/Compiler/GNU-CXX.cmake" + "/usr/share/cmake-3.7/Modules/Compiler/GNU.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux-GNU-C.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake-3.7/Modules/Platform/Linux.cmake" + "/usr/share/cmake-3.7/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/L02.dir/DependInfo.cmake" + ) diff --git a/L02/CMakeFiles/Makefile2 b/L02/CMakeFiles/Makefile2 new file mode 100644 index 0000000..0e148b4 --- /dev/null +++ b/L02/CMakeFiles/Makefile2 @@ -0,0 +1,108 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.7 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# The main recursive all target +all: + +.PHONY : all + +# The main recursive preinstall target +preinstall: + +.PHONY : preinstall + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/shadow8t4/Documents/CSCE441/L02 + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/shadow8t4/Documents/CSCE441/L02/build + +#============================================================================= +# Target rules for target CMakeFiles/L02.dir + +# All Build rule for target. +CMakeFiles/L02.dir/all: + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/depend + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles --progress-num=1,2,3 "Built target L02" +.PHONY : CMakeFiles/L02.dir/all + +# Include target in all. +all: CMakeFiles/L02.dir/all + +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/L02.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles 3 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/L02.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles 0 +.PHONY : CMakeFiles/L02.dir/rule + +# Convenience name for target. +L02: CMakeFiles/L02.dir/rule + +.PHONY : L02 + +# clean rule for target. +CMakeFiles/L02.dir/clean: + $(MAKE) -f CMakeFiles/L02.dir/build.make CMakeFiles/L02.dir/clean +.PHONY : CMakeFiles/L02.dir/clean + +# clean rule for target. +clean: CMakeFiles/L02.dir/clean + +.PHONY : clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/L02/CMakeFiles/TargetDirectories.txt b/L02/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..167cb32 --- /dev/null +++ b/L02/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/rebuild_cache.dir +/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/edit_cache.dir +/home/shadow8t4/Documents/CSCE441/L02/build/CMakeFiles/L02.dir diff --git a/L02/CMakeFiles/cmake.check_cache b/L02/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/L02/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/L02/CMakeFiles/feature_tests.bin b/L02/CMakeFiles/feature_tests.bin new file mode 100755 index 0000000000000000000000000000000000000000..5af7746092a42d6304628fa2a1421449c7e1626c GIT binary patch literal 12672 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 Xm&QYW#m6nE|LN;J`LFww`}_YN= 404 +"1" +#else +"0" +#endif +"c_function_prototypes\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +"1" +#else +"0" +#endif +"c_restrict\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L +"1" +#else +"0" +#endif +"c_static_assert\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +"1" +#else +"0" +#endif +"c_variadic_macros\n" + +}; + +int main(int argc, char** argv) { (void)argv; return features[argc]; } diff --git a/L02/CMakeFiles/feature_tests.cxx b/L02/CMakeFiles/feature_tests.cxx new file mode 100644 index 0000000..b93418c --- /dev/null +++ b/L02/CMakeFiles/feature_tests.cxx @@ -0,0 +1,405 @@ + + const char features[] = {"\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L +"1" +#else +"0" +#endif +"cxx_aggregate_default_initializers\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_alias_templates\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_alignas\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_alignof\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_attributes\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_attribute_deprecated\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_auto_type\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_binary_literals\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_constexpr\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_contextual_conversions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_decltype\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_decltype_auto\n" +"CXX_FEATURE:" +#if ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_decltype_incomplete_return_types\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_default_function_template_args\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_defaulted_functions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_defaulted_move_initializers\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_delegating_constructors\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_deleted_functions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_digit_separators\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_enum_forward_declarations\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_explicit_conversions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_extended_friend_declarations\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_extern_templates\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_final\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_func_identifier\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_generalized_initializers\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_generic_lambdas\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_inheriting_constructors\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_inline_namespaces\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_lambdas\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_lambda_init_captures\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_local_type_template_args\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_long_long_type\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_noexcept\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_nonstatic_member_init\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_nullptr\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_override\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_range_for\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_raw_string_literals\n" +"CXX_FEATURE:" +#if ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_reference_qualified_functions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L +"1" +#else +"0" +#endif +"cxx_relaxed_constexpr\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L +"1" +#else +"0" +#endif +"cxx_return_type_deduction\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_right_angle_brackets\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_rvalue_references\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_sizeof_member\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_static_assert\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_strong_enums\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && __cplusplus +"1" +#else +"0" +#endif +"cxx_template_template_parameters\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_thread_local\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_trailing_return_types\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_unicode_literals\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_uniform_initialization\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_unrestricted_unions\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L +"1" +#else +"0" +#endif +"cxx_user_literals\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L +"1" +#else +"0" +#endif +"cxx_variable_templates\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_variadic_macros\n" +"CXX_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && (__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)) +"1" +#else +"0" +#endif +"cxx_variadic_templates\n" + +}; + +int main(int argc, char** argv) { (void)argv; return features[argc]; } diff --git a/L02/CMakeFiles/progress.marks b/L02/CMakeFiles/progress.marks new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/L02/CMakeFiles/progress.marks @@ -0,0 +1 @@ +3 diff --git a/L02/CMakeLists.txt b/L02/CMakeLists.txt new file mode 100644 index 0000000..99e3d6d --- /dev/null +++ b/L02/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L02) + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS}) + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") +ENDIF() diff --git a/L02/src/Image.cpp b/L02/src/Image.cpp new file mode 100644 index 0000000..7655b46 --- /dev/null +++ b/L02/src/Image.cpp @@ -0,0 +1,87 @@ +#include +#include +#include "Image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +using namespace std; + +Tri::Tri() +{ + vertex v1; + v1.x = 0.0; + v1.y = 0.0; + v1.z = 0.0; + vertex v2; + v2.x = 0.0; + v2.y = 0.0; + v2.z = 0.0; + vertex v3; + v3.x = 0.0; + v3.y = 0.0; + v3.z = 0.0; + v.push_back(v1); + v.push_back(v2); + v.push_back(v3); +} + +Tri::Tri(vertex &one, vertex &two, vertex &three) +{ + v.push_back(one); + v.push_back(two); + v.push_back(three); +} + +Image::Image(int w, int h) : + width(w), + height(h), + comp(3), + pixels(width*height*comp, 0) +{ +} + +Image::~Image() +{ +} + +void Image::setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + // The pixel data is laid out row by row. Each row consists of 'width' + // columns, and each column consists of 3 unsigned chars. + + // First check for bounds + if(y < 0 || y >= height) { + cout << "Row " << y << " is out of bounds" << endl; + return; + } + if(x < 0 || x >= width) { + cout << "Col " << x << " is out of bounds" << endl; + return; + } + + // Since the origin (0, 0) of the image is the upper left corner, we need + // to flip the row to make the origin be the lower left corner. + y = height - y - 1; + // index corresponding to row and col, (assuming single component image) + int index = y*width + x; + // Multiply by 3 to get the index for the rgb components. + assert(index >= 0); + assert(3*index + 2 < (int)pixels.size()); + pixels[3*index + 0] = r; + pixels[3*index + 1] = g; + pixels[3*index + 2] = b; +} + +void Image::writeToFile(const string &filename) +{ + // The distance in bytes from the first byte of a row of pixels to the + // first byte of the next row of pixels + int stride_in_bytes = width*comp*sizeof(unsigned char); + int rc = stbi_write_png(filename.c_str(), width, height, comp, &pixels[0], stride_in_bytes); + if(rc) { + cout << "Wrote to " << filename << endl; + } else { + cout << "Couldn't write to " << filename << endl; + } +} diff --git a/L02/src/Image.h b/L02/src/Image.h new file mode 100644 index 0000000..8442ffb --- /dev/null +++ b/L02/src/Image.h @@ -0,0 +1,43 @@ +#pragma once +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include + +struct vertex +{ + float x = 0.0; + float y = 0.0; + float z = 0.0; + float r = 0.0; + float g = 0.0; + float b = 0.0; +}; + +class Tri +{ + public: + Tri(); + Tri(vertex &one, vertex &two, vertex &three); + std::vector v; +}; + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + void setPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b); + void writeToFile(const std::string &filename); + int getWidth() const { return width; } + int getHeight() const { return height; } + +private: + int width; + int height; + int comp; + std::vector pixels; +}; + +#endif diff --git a/L02/src/main.cpp b/L02/src/main.cpp new file mode 100644 index 0000000..d80c938 --- /dev/null +++ b/L02/src/main.cpp @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include "Image.h" +#include + +// This allows you to skip the `std::` in front of C++ standard library +// functions. You can also say `using std::cout` to be more selective. +// You should never do this in a header file. +using namespace std; + +int main(int argc, char **argv) +{ + if(argc < 19) { + cout << "Usage: L01 filename width height x1 y1 r1 g1 b1 x2 y2 r2 g2 b2 x3 y3 r3 g3 b3" << endl; + return 0; + } + // Output filename + string filename(argv[1]); + // Width of image + int width = atoi(argv[2]); + // Height of image + int height = atoi(argv[3]); + + // Initialize coordinate variables to make things easier + float x1 = atoi(argv[4]); + float y1 = atoi(argv[5]); + float x2 = atoi(argv[9]); + float y2 = atoi(argv[10]); + float x3 = atoi(argv[14]); + float y3 = atoi(argv[15]); + + // Initialize rgb values again to make things easier + float r1 = atoi(argv[6]); + float b1 = atoi(argv[7]); + float g1 = atoi(argv[8]); + float r2 = atoi(argv[11]); + float g2 = atoi(argv[12]); + float b2 = atoi(argv[13]); + float r3 = atoi(argv[16]); + float g3 = atoi(argv[17]); + float b3 = atoi(argv[18]); + + // Vertex 1 + vertex v1; + v1.x = x1; + v1.y = y1; + v1.z = 0.0; + v1.r = r1; + v1.g = g1; + v1.b = b1; + + // Vertex 2 + vertex v2; + v2.x = x2; + v2.y = y2; + v2.z = 0.0; + v2.r = r2; + v2.g = g2; + v2.b = b2; + + // Vertex 3 + vertex v3; + v3.x = x3; + v3.y = y3; + v3.z = 0.0; + v3.r = r3; + v3.g = g3; + v3.b = b3; + + // Triangle + Tri t(v1, v2, v3); + + // Find xmin, xmax, ymin, ymax + float xmin = x1; + float xmax = x1; + float ymin = y1; + float ymax = y1; + if(x2 < xmin) + xmin = x2; + if(x3 < xmin) + xmin = x3; + if(x2 > xmax) + xmax = x2; + if(x3 > xmax) + xmax = x3; + if(y2 < ymin) + ymin = y2; + if(y3 < ymin) + ymin = y3; + if(y2 > ymax) + ymax = y2; + if(y3 > ymax) + ymax = y3; + + // Find total area + float area = abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))/2.0); + + // Create the image. We're using a `shared_ptr`, a C++11 feature. + auto image = make_shared(width, height); + + // Initialize variables for holding area between points + float a1 = 0.0; + float a2 = 0.0; + float a3 = 0.0; + + // Initialize barycentric coordinate variables + float l1 = 0.0; + float l2 = 0.0; + float l3 = 0.0; + + // Draw a rectangle + for(int y = ymin; y < ymax; ++y) { + for(int x = xmin; x < xmax; ++x) { + + // Find area between point and two other vertices + a1 = abs(x1 * (y2 - y) + x2 * (y - y1) + x * (y1 - y2))/2.0; + a2 = abs(x1 * (y - y3) + x * (y3 - y1) + x3 * (y1 - y))/2.0; + a3 = abs(x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2))/2.0; + + // Assign barycentric coordinates + l1 = a1/area; + l2 = a2/area; + l3 = a3/area; + + unsigned char r = (a1*v1.r + a2*v2.r + a3*v3.r)/area; + unsigned char g = (a1*v1.g + a2*v2.g + a3*v3.g)/area; + unsigned char b = (a1*v1.b + a2*v2.b + a3*v3.b)/area; + + // Find if point is inside triangle + //if((l1 <= 0.0 || l1 >= 1.0) || (l2 <= 0.0 || l2 >= 1.0) || (l3 <= 0.0 || l3 >= 1.0)) + if(!(l1 + l2 + l3 <= 1.0001 && l1 + l2 + l3 >= 0.9999)) + { + continue; + } + else + { + image->setPixel(x, y, r, g, b); + } + } + } + // Write image to file + image->writeToFile(filename); + return 0; +} diff --git a/L02/src/stb_image_write.h b/L02/src/stb_image_write.h new file mode 100644 index 0000000..f07b625 --- /dev/null +++ b/L02/src/stb_image_write.h @@ -0,0 +1,1048 @@ +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 1: + s->func(s->context,d,1); + break; + case 2: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson +#ifndef STBI_WRITE_NO_STDIO + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ diff --git a/L03.zip b/L03.zip new file mode 100644 index 0000000000000000000000000000000000000000..17389309b8bf8c919627ba5b9553fb9b3aaaa13a GIT binary patch literal 20758 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 literal 0 HcmV?d00001 diff --git a/L03/.gitignore b/L03/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L03/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L03/CMakeLists.txt b/L03/CMakeLists.txt new file mode 100644 index 0000000..016f065 --- /dev/null +++ b/L03/CMakeLists.txt @@ -0,0 +1,126 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L03) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L03/resources/cube.obj b/L03/resources/cube.obj new file mode 100644 index 0000000..e81edd5 --- /dev/null +++ b/L03/resources/cube.obj @@ -0,0 +1,29 @@ +# Blender v2.71 (sub 0) OBJ File: '' +# www.blender.org +v 0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 -0.000000 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +s off +f 2//1 3//1 4//1 +f 8//2 7//2 6//2 +f 1//3 5//3 6//3 +f 2//4 6//4 7//4 +f 7//5 8//5 4//5 +f 1//6 4//6 8//6 +f 1//1 2//1 4//1 +f 5//2 8//2 6//2 +f 2//3 1//3 6//3 +f 3//4 2//4 7//4 +f 3//5 7//5 4//5 +f 5//6 1//6 8//6 diff --git a/L03/resources/frag.glsl b/L03/resources/frag.glsl new file mode 100644 index 0000000..9d07efa --- /dev/null +++ b/L03/resources/frag.glsl @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 vCol; + +void main() +{ + gl_FragColor = vec4(vCol.r, vCol.g, vCol.b, 1.0); +} diff --git a/L03/resources/vert.glsl b/L03/resources/vert.glsl new file mode 100644 index 0000000..3ecb3f4 --- /dev/null +++ b/L03/resources/vert.glsl @@ -0,0 +1,13 @@ +#version 120 + +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vCol; + +void main() +{ + gl_Position = P * MV * aPos; + vCol = 0.5*(aNor + 1.0); +} diff --git a/L03/src/GLSL.cpp b/L03/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L03/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L03/src/GLSL.h b/L03/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L03/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L03/src/main.cpp b/L03/src/main.cpp new file mode 100644 index 0000000..6f625a0 --- /dev/null +++ b/L03/src/main.cpp @@ -0,0 +1,449 @@ +#include +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include "GLSL.h" + +using namespace std; +using namespace glm; + +GLFWwindow *window; // Main application window +string RESOURCE_DIR = "./"; // Where the resources are loaded from + +GLuint progID; +map attrIDs; +map unifIDs; +map bufIDs; +int indCount; + +// This function is called when a GLFW error occurs +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +// This function is called when a key is pressed +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// This function is called when the mouse is clicked +static void mouse_callback(GLFWwindow *window, int button, int action, int mods) +{ + // Do nothing +} + +// If the window is resized, capture the new size and reset the viewport +static void resize_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +// This function is called once to initialize the scene and OpenGL +static void init() +{ + // + // General setup + // + + // Initialize time. + glfwSetTime(0.0); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // + // GLSL program setup + // + + // Create shader handles + GLuint vShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint fShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + string vShaderName = RESOURCE_DIR + "vert.glsl"; + string fShaderName = RESOURCE_DIR + "frag.glsl"; + const char *vShaderText = GLSL::textFileRead(vShaderName.c_str()); + const char *fShaderText = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(vShaderID, 1, &vShaderText, NULL); + glShaderSource(fShaderID, 1, &fShaderText, NULL); + + // Compile vertex shader + int rc; + glCompileShader(vShaderID); + glGetShaderiv(vShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(vShaderID); + cout << "Error compiling vertex shader " << vShaderName << endl; + return; + } + + // Compile fragment shader + glCompileShader(fShaderID); + glGetShaderiv(fShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(fShaderID); + cout << "Error compiling fragment shader " << fShaderName << endl; + return; + } + + // Create the program and link + progID = glCreateProgram(); + glAttachShader(progID, vShaderID); + glAttachShader(progID, fShaderID); + glLinkProgram(progID); + glGetProgramiv(progID, GL_LINK_STATUS, &rc); + if(!rc) { + GLSL::printProgramInfoLog(progID); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + return; + } + + // Get vertex attribute IDs + attrIDs["aPos"] = glGetAttribLocation(progID, "aPos"); + attrIDs["aNor"] = glGetAttribLocation(progID, "aNor"); + + // Get uniform IDs + unifIDs["P"] = glGetUniformLocation(progID, "P"); + unifIDs["MV"] = glGetUniformLocation(progID, "MV"); + + // + // Vertex buffer setup + // + + // Load OBJ geometry // Load OBJ geometry + vector posBuf; + vector norBuf; + // Some obj files contain material information. + // We'll ignore them for this assignment. + string meshName = RESOURCE_DIR + "cube.obj"; + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + indCount = posBuf.size()/3; // number of indices to be rendered + + // Generate 2 buffer IDs and put them in the bufIDs map. + GLuint tmp[2]; + glGenBuffers(2, tmp); + bufIDs["bPos"] = tmp[0]; + bufIDs["bNor"] = tmp[1]; + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + assert(norBuf.size() == posBuf.size()); + + + GLSL::checkError(GET_FILE_LINE); +} + +static void printMatrix(const float *A, const char *name = 0) +{ + // OpenGL uses col-major ordering: + // [ 0 4 8 12] + // [ 1 5 9 13] + // [ 2 6 10 14] + // [ 3 7 11 15] + // The (i,j)th element is A[i+4*j]. + if(name) { + printf("%s=[\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + printf("%- 5.2f ", A[i+4*j]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +// Sets M to be the zero matrix +static void createZeroMatrix(float *M) +{ + memset(M, 0, 16*sizeof(float)); +} + +// Sets M to be the identity matrix +static void createIdentityMatrix(float *M) +{ + // + // IMPLEMENT ME + // + createZeroMatrix(M); + M[0] = 1; + M[5] = 1; + M[10] = 1; + M[15] = 1; +} + +// Sets M to be a translation matrix +static void createTranslationMatrix(float *M, float x, float y, float z) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[12] +=x; + M[13] +=y; + M[14] +=z; +} + +// Sets M to be a scale matrix +static void createScaleMatrix(float *M, float x, float y, float z) +{ + // + // IMPLEMENT ME + // + M[0] *= x; + M[5] *= y; + M[10] *= z; +} + +// Sets M to be an X rotation matrix +static void createRotationXMatrix(float *M, float angle) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[5] = cos(angle); + M[6] = -sin(angle); + M[9] = sin(angle); + M[10] = cos(angle); +} + +// Sets M to be a Y rotation matrix +static void createRotationYMatrix(float *M, float angle) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[0] = cos(angle); + M[2] = sin(angle); + M[8] = -sin(angle); + M[10] = cos(angle); +} + +// Sets M to be a Z rotation matrix +static void createRotationZMatrix(float *M, float angle) +{ + // + // IMPLEMENT ME + // + createIdentityMatrix(M); + M[0] = cos(angle); + M[1] = -sin(angle); + M[4] = sin(angle); + M[5] = cos(angle); +} + +// Sets C = A*B +static void multMatrix(float *C, const float *A, const float *B) +{ + createZeroMatrix(C); + for(int k = 0; k < 4; ++k) { + // Process kth column of C + for(int i = 0; i < 4; ++i) { + // Process ith row of C. + // The (i,k)th element of C is the dot product + // of the ith row of A and kth col of B. + + // + // IMPLEMENT ME + // + + C[k*4+i] = (A[i]*B[k*4] + A[i + 4]*B[k*4 + 1] + A[i + 8]*B[k*4 + 2] + A[i + 12]*B[k*4 + 3]); + } + } +} + +// This function is called every frame to draw the scene. +static void render() +{ + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + + // Set up projection matrix (camera intrinsics) + mat4 P; + P = perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f); + + // Modelview matrix: camera and world + float M[16]; + + // Tell OpenGL which GLSL program to use + glUseProgram(progID); + // Pass in the current projection matrix + glUniformMatrix4fv(unifIDs["P"], 1, GL_FALSE, &P[0][0]); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aPos"]); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aNor"]); + // Bind the position buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aPos"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + // Bind the color buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aNor"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Send the modelview matrix and draw + createZeroMatrix(M); + // Implimented. + createIdentityMatrix(M); + // Testing + //printMatrix(A); + /* + float A[16], B[16], C[16]; + for(int i = 0; i < 16; ++i) { A[i] = i; } + for(int i = 0; i < 16; ++i) { B[i] = i*i; } + multMatrix(C, A, B); + printMatrix(A, "A"); + printMatrix(B, "B"); + printMatrix(C, "C"); + */ + float C[16]; + createRotationYMatrix(C, 30); + float I[16]; + createIdentityMatrix(I); + multMatrix(M, C, I); + M[14] += -5; + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, M); + glDrawArrays(GL_TRIANGLES, 0, indCount); + + // Unbind the buffer object + glBindBuffer(GL_ARRAY_BUFFER, 0); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aNor"]); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aPos"]); + // Unbind our GLSL program + glUseProgram(0); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RESOURCE_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + GLSL::checkVersion(); + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Set the mouse call back. + glfwSetMouseButtonCallback(window, mouse_callback); + // Set the window resize call back. + glfwSetFramebufferSizeCallback(window, resize_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L03/src/tiny_obj_loader.h b/L03/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L03/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_ diff --git a/L04.zip b/L04.zip new file mode 100644 index 0000000000000000000000000000000000000000..e63da6c4ed3e5eeb29a8bd87c44a767f9ffc85ef GIT binary patch literal 21810 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

_Z?qFCW7}DXW`|8oql2=OM0r^Tqg2NN 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

}MgoE0z5vSiN9rp*W;0d+KES6>^0V(p6e)z=%= zp>M{|PKoCcO3a=u^C?Evaa@#F8DC&;LW;Q7_)*mtg47lY61(mHtFaV z{EM8i?VJ-J3+D_9tCED6Tv$k&HTyI86N3}9`hw}K&G?%d2dXG3Qpoc)_##zsiMW<#xPngbB zo780?Z9~$(68hS=32$PWMqE;xcq*C>436rz}7iEb)g(9iFvRo^=N2>k5nwLId)k9cWQ#7 zhn#jpR+?GtM6|w$a*K>=%RK?$LR_Te?p2lOa2}0%grk~~-tq<~7sv0_T8FP!8{y_o zZYsuZ!2)4HC)iK3OAtdYNF$HT}-~bf_=<^4c^m zemgLi&^w&v69`l!{k z!st(tD~qU&xg6!d^()IFUu#pAztkZCpdmguPu%AD_6+tBuG~{;tR?F+s#V+dS~|_Rfx4-WRqtwL1>oDx~#N&4?qN&ZN*JG|7z= zYD;0(z-Kb5OdwhUoTyk+9haBkGRl;oD03>R^f9eM_)EGOh>KWKe7KLKl{t_zKOhTP zSqoPLP)QpDXv>lYuHs8z0eJe5emO4i--by4F!VUrf(^(F_PMEu{Ti~llaU3pg^jb# zUlZyNMA7`42|<|UnCOQFh9Rt+?2F6va*Txo19FhY*@;lCb);o6AMD{u=z7sSVqq(^1V zh-8Z~#`$dd#i=Nb{?mr;pJ&{?0ZD(F)I$K=UBWd~Ao*QrCYQk0f@9>#fJpoDX0K6O zZx_bkb0K|BN+N^Rpm-Unr(D9uUOjJov|EWnjT%B<8c&{De!^EauEI}>*5(ST8&I4x zp3RqSM`}`*g9AQ=zdhD{O(Fs8Z~y>IOasV%b#wKf(nN$?Y2tqf6K|RS%>;JK1OPAr zJ0gy-O4Y3w3`V-~g8eP&S2yN&E7;w1rTR`&sVtx?$Fq8{RKl3ygSUYx$RizZWL&5`zhEiTCQ0{~q{Nj zP2dLmdw=OJwg6V1xS7D;w3+@X@$G|jfBW8|ZyzK{MZldk@z>3|*~R}b+WVXMZq(4< zc)#{CEa%N${s->;1$LMFQR!~ZJL?PvzFBAg0KUI;?t+z-?}G2FAQ<>&1>FN9Am03- Q(P6JscmRM(<>uS}0sC|RyZ`_I literal 0 HcmV?d00001 diff --git a/L04/.gitignore b/L04/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/L04/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/L04/CMakeLists.txt b/L04/CMakeLists.txt new file mode 100644 index 0000000..ca58509 --- /dev/null +++ b/L04/CMakeLists.txt @@ -0,0 +1,126 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +# Name of the project +PROJECT(L04) + +# FOR LAB MACHINES ONLY! +# DO NOT EDIT +SET(DEF_DIR_GLM "C:\\c++\\glm") +SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1") +SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0") + +# Is this the solution? +# Override with `cmake -DSOL=ON ..` +OPTION(SOL "Solution" OFF) + +# Use glob to get the list of all source files. +# We don't really need to include header and resource files to build, but it's +# nice to have them also show up in IDEs. +IF(${SOL}) + FILE(GLOB_RECURSE SOURCES "src0/*.cpp") + FILE(GLOB_RECURSE HEADERS "src0/*.h") +ELSE() + FILE(GLOB_RECURSE SOURCES "src/*.cpp") + FILE(GLOB_RECURSE HEADERS "src/*.h") +ENDIF() +FILE(GLOB_RECURSE GLSL "resources/*.glsl") + +# Set the executable. +ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL}) + +# Get the GLM environment variable. Since GLM is a header-only library, we +# just need to add it to the include directory. +SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}") +IF(NOT GLM_INCLUDE_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}") + IF(IS_DIRECTORY ${DEF_DIR_GLM}) + MESSAGE(STATUS "Found!") + SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR}) + +# Get the GLFW environment variable. There should be a CMakeLists.txt in the +# specified directory. +SET(GLFW_DIR "$ENV{GLFW_DIR}") +IF(NOT GLFW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}") + IF(IS_DIRECTORY ${DEF_DIR_GLFW}) + MESSAGE(STATUS "Found!") + SET(GLFW_DIR ${DEF_DIR_GLFW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF) +OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF) +OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF) +IF(CMAKE_BUILD_TYPE MATCHES Release) + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release) +ELSE() + ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug) +ENDIF() +INCLUDE_DIRECTORIES(${GLFW_DIR}/include) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES}) + +# Get the GLEW environment variable. +SET(GLEW_DIR "$ENV{GLEW_DIR}") +IF(NOT GLEW_DIR) + # The environment variable was not set + SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.") + IF(WIN32) + # On Windows, try the default location + MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}") + IF(IS_DIRECTORY ${DEF_DIR_GLEW}) + MESSAGE(STATUS "Found!") + SET(GLEW_DIR ${DEF_DIR_GLEW}) + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR ${ERR_MSG}) + ENDIF() +ENDIF() +INCLUDE_DIRECTORIES(${GLEW_DIR}/include) +IF(WIN32) + # With prebuilt binaries + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib) +ELSE() + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a) +ENDIF() + +# OS specific options and libraries +IF(WIN32) + # c++11 is enabled by default. + # -Wall produces way too many warnings. + # -pedantic is not supported. + # Disable warning 4996. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib) +ELSE() + # Enable all pedantic warnings. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic") + IF(APPLE) + # Add required frameworks for GLFW. + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo") + ELSE() + #Link the Linux OpenGL library + TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL") + ENDIF() +ENDIF() diff --git a/L04/resources/cube.obj b/L04/resources/cube.obj new file mode 100644 index 0000000..e81edd5 --- /dev/null +++ b/L04/resources/cube.obj @@ -0,0 +1,29 @@ +# Blender v2.71 (sub 0) OBJ File: '' +# www.blender.org +v 0.500000 0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.500000 0.500000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 -0.000000 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +s off +f 2//1 3//1 4//1 +f 8//2 7//2 6//2 +f 1//3 5//3 6//3 +f 2//4 6//4 7//4 +f 7//5 8//5 4//5 +f 1//6 4//6 8//6 +f 1//1 2//1 4//1 +f 5//2 8//2 6//2 +f 2//3 1//3 6//3 +f 3//4 2//4 7//4 +f 3//5 7//5 4//5 +f 5//6 1//6 8//6 diff --git a/L04/resources/frag.glsl b/L04/resources/frag.glsl new file mode 100644 index 0000000..9d07efa --- /dev/null +++ b/L04/resources/frag.glsl @@ -0,0 +1,8 @@ +#version 120 + +varying vec3 vCol; + +void main() +{ + gl_FragColor = vec4(vCol.r, vCol.g, vCol.b, 1.0); +} diff --git a/L04/resources/vert.glsl b/L04/resources/vert.glsl new file mode 100644 index 0000000..3ecb3f4 --- /dev/null +++ b/L04/resources/vert.glsl @@ -0,0 +1,13 @@ +#version 120 + +attribute vec4 aPos; +attribute vec3 aNor; +uniform mat4 P; +uniform mat4 MV; +varying vec3 vCol; + +void main() +{ + gl_Position = P * MV * aPos; + vCol = 0.5*(aNor + 1.0); +} diff --git a/L04/src/GLSL.cpp b/L04/src/GLSL.cpp new file mode 100644 index 0000000..2969872 --- /dev/null +++ b/L04/src/GLSL.cpp @@ -0,0 +1,152 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#include "GLSL.h" +#include +#include +#include +#include + +using namespace std; + +namespace GLSL { + +const char * errorString(GLenum err) +{ + switch(err) { + case GL_NO_ERROR: + return "No error"; + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_STACK_OVERFLOW: + return "Stack overflow"; + case GL_STACK_UNDERFLOW: + return "Stack underflow"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + default: + return "No error"; + } +} + +void checkVersion() +{ + int major, minor; + major = minor = 0; + const char *verstr = (const char *)glGetString(GL_VERSION); + + if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) { + printf("Invalid GL_VERSION format %d.%d\n", major, minor); + } + if(major < 2) { + printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor); + exit(0); + } +} + +void checkError(const char *str) +{ + GLenum glErr = glGetError(); + if(glErr != GL_NO_ERROR) { + if(str) { + printf("%s: ", str); + } + printf("GL_ERROR = %s.\n", errorString(glErr)); + assert(false); + } +} + +void printShaderInfoLog(GLuint shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Shader InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +void printProgramInfoLog(GLuint program) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog = 0; + + checkError(GET_FILE_LINE); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength); + checkError(GET_FILE_LINE); + + if(infologLength > 0) { + infoLog = (GLchar *)malloc(infologLength); + if(infoLog == NULL) { + puts("ERROR: Could not allocate InfoLog buffer"); + exit(1); + } + glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog); + checkError(GET_FILE_LINE); + printf("Program InfoLog:\n%s\n\n", infoLog); + free(infoLog); + } +} + +char *textFileRead(const char *fn) +{ + FILE *fp; + char *content = NULL; + int count = 0; + if(fn != NULL) { + fp = fopen(fn,"rt"); + if(fp != NULL) { + fseek(fp, 0, SEEK_END); + count = (int)ftell(fp); + rewind(fp); + if(count > 0) { + content = (char *)malloc(sizeof(char) * (count+1)); + count = (int)fread(content,sizeof(char),count,fp); + content[count] = '\0'; + } + fclose(fp); + } else { + printf("error loading %s\n", fn); + } + } + return content; +} + +int textFileWrite(const char *fn, const char *s) +{ + FILE *fp; + int status = 0; + if(fn != NULL) { + fp = fopen(fn,"w"); + if(fp != NULL) { + if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) { + status = 1; + } + fclose(fp); + } + } + return(status); +} + +} diff --git a/L04/src/GLSL.h b/L04/src/GLSL.h new file mode 100644 index 0000000..f945fdd --- /dev/null +++ b/L04/src/GLSL.h @@ -0,0 +1,40 @@ +// +// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book +// Created by zwood on 2/21/10. +// Modified by sueda 10/15/15. +// + +#pragma once +#ifndef __GLSL__ +#define __GLSL__ + +#define GLEW_STATIC +#include + +/////////////////////////////////////////////////////////////////////////////// +// For printing out the current file and line number // +/////////////////////////////////////////////////////////////////////////////// +#include + +template +std::string NumberToString(T x) +{ + std::ostringstream ss; + ss << x; + return ss.str(); +} + +#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str() +/////////////////////////////////////////////////////////////////////////////// + +namespace GLSL { + + void checkVersion(); + void checkError(const char *str = 0); + void printProgramInfoLog(GLuint program); + void printShaderInfoLog(GLuint shader); + int textFileWrite(const char *filename, const char *s); + char *textFileRead(const char *filename); +} + +#endif diff --git a/L04/src/MatrixStack.cpp b/L04/src/MatrixStack.cpp new file mode 100644 index 0000000..eaa6e6c --- /dev/null +++ b/L04/src/MatrixStack.cpp @@ -0,0 +1,114 @@ +#include "MatrixStack.h" + +#include +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include + +using namespace std; + +MatrixStack::MatrixStack() +{ + mstack = make_shared< stack >(); + mstack->push(glm::mat4(1.0)); +} + +MatrixStack::~MatrixStack() +{ +} + +void MatrixStack::pushMatrix() +{ + const glm::mat4 &top = mstack->top(); + mstack->push(top); + assert(mstack->size() < 100); +} + +void MatrixStack::popMatrix() +{ + assert(!mstack->empty()); + mstack->pop(); + // There should always be one matrix left. + assert(!mstack->empty()); +} + +void MatrixStack::loadIdentity() +{ + glm::mat4 &top = mstack->top(); + top = glm::mat4(1.0); +} + +void MatrixStack::translate(const glm::vec3 &t) +{ + glm::mat4 &top = mstack->top(); + top *= glm::translate(t); +} + +void MatrixStack::translate(float x, float y, float z) +{ + translate(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(const glm::vec3 &s) +{ + glm::mat4 &top = mstack->top(); + top *= glm::scale(s); +} + +void MatrixStack::scale(float x, float y, float z) +{ + scale(glm::vec3(x, y, z)); +} + +void MatrixStack::scale(float s) +{ + scale(glm::vec3(s, s, s)); +} + +void MatrixStack::rotate(float angle, const glm::vec3 &axis) +{ + glm::mat4 &top = mstack->top(); + top *= glm::rotate(angle, axis); +} + +void MatrixStack::rotate(float angle, float x, float y, float z) +{ + rotate(angle, glm::vec3(x, y, z)); +} + +void MatrixStack::multMatrix(const glm::mat4 &matrix) +{ + glm::mat4 &top = mstack->top(); + top *= matrix; +} + +const glm::mat4 &MatrixStack::topMatrix() const +{ + return mstack->top(); +} + +void MatrixStack::print(const glm::mat4 &mat, const char *name) +{ + if(name) { + printf("%s = [\n", name); + } + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + // mat[j] returns the jth column + printf("%- 5.2f ", mat[j][i]); + } + printf("\n"); + } + if(name) { + printf("];"); + } + printf("\n"); +} + +void MatrixStack::print(const char *name) const +{ + print(mstack->top(), name); +} diff --git a/L04/src/MatrixStack.h b/L04/src/MatrixStack.h new file mode 100644 index 0000000..66278ce --- /dev/null +++ b/L04/src/MatrixStack.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef _MatrixStack_H_ +#define _MatrixStack_H_ + +#include +#include +#include + +class MatrixStack +{ +public: + MatrixStack(); + virtual ~MatrixStack(); + + // glPushMatrix(): Copies the current matrix and adds it to the top of the stack + void pushMatrix(); + // glPopMatrix(): Removes the top of the stack and sets the current matrix to be the matrix that is now on top + void popMatrix(); + + // glLoadIdentity(): Sets the top matrix to be the identity + void loadIdentity(); + // glMultMatrix(): Right multiplies the top matrix + void multMatrix(const glm::mat4 &matrix); + + // glTranslate(): Right multiplies the top matrix by a translation matrix + void translate(const glm::vec3 &trans); + void translate(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(const glm::vec3 &scale); + void scale(float x, float y, float z); + // glScale(): Right multiplies the top matrix by a scaling matrix + void scale(float size); + // glRotate(): Right multiplies the top matrix by a rotation matrix (angle in radians) + void rotate(float angle, const glm::vec3 &axis); + void rotate(float angle, float x, float y, float z); + + // glGet(GL_MODELVIEW_MATRIX): Gets the top matrix + const glm::mat4 &topMatrix() const; + + // Prints out the specified matrix + static void print(const glm::mat4 &mat, const char *name = 0); + // Prints out the top matrix + void print(const char *name = 0) const; + +private: + std::shared_ptr< std::stack > mstack; + +}; + +#endif diff --git a/L04/src/Program.cpp b/L04/src/Program.cpp new file mode 100644 index 0000000..1e85538 --- /dev/null +++ b/L04/src/Program.cpp @@ -0,0 +1,126 @@ +#include "Program.h" + +#include +#include + +#include "GLSL.h" + +using namespace std; + +Program::Program() : + vShaderName(""), + fShaderName(""), + pid(0), + verbose(true) +{ + +} + +Program::~Program() +{ + +} + +void Program::setShaderNames(const string &v, const string &f) +{ + vShaderName = v; + fShaderName = f; +} + +bool Program::init() +{ + GLint rc; + + // Create shader handles + GLuint VS = glCreateShader(GL_VERTEX_SHADER); + GLuint FS = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + const char *vshader = GLSL::textFileRead(vShaderName.c_str()); + const char *fshader = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(VS, 1, &vshader, NULL); + glShaderSource(FS, 1, &fshader, NULL); + + // Compile vertex shader + glCompileShader(VS); + glGetShaderiv(VS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(VS); + cout << "Error compiling vertex shader " << vShaderName << endl; + } + return false; + } + + // Compile fragment shader + glCompileShader(FS); + glGetShaderiv(FS, GL_COMPILE_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printShaderInfoLog(FS); + cout << "Error compiling fragment shader " << fShaderName << endl; + } + return false; + } + + // Create the program and link + pid = glCreateProgram(); + glAttachShader(pid, VS); + glAttachShader(pid, FS); + glLinkProgram(pid); + glGetProgramiv(pid, GL_LINK_STATUS, &rc); + if(!rc) { + if(isVerbose()) { + GLSL::printProgramInfoLog(pid); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + } + return false; + } + + GLSL::checkError(GET_FILE_LINE); + return true; +} + +void Program::bind() +{ + glUseProgram(pid); +} + +void Program::unbind() +{ + glUseProgram(0); +} + +void Program::addAttribute(const string &name) +{ + attributes[name] = glGetAttribLocation(pid, name.c_str()); +} + +void Program::addUniform(const string &name) +{ + uniforms[name] = glGetUniformLocation(pid, name.c_str()); +} + +GLint Program::getAttribute(const string &name) const +{ + map::const_iterator attribute = attributes.find(name.c_str()); + if(attribute == attributes.end()) { + if(isVerbose()) { + cout << name << " is not an attribute variable" << endl; + } + return -1; + } + return attribute->second; +} + +GLint Program::getUniform(const string &name) const +{ + map::const_iterator uniform = uniforms.find(name.c_str()); + if(uniform == uniforms.end()) { + if(isVerbose()) { + cout << name << " is not a uniform variable" << endl; + } + return -1; + } + return uniform->second; +} diff --git a/L04/src/Program.h b/L04/src/Program.h new file mode 100644 index 0000000..51e58bb --- /dev/null +++ b/L04/src/Program.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef __Program__ +#define __Program__ + +#include +#include + +#define GLEW_STATIC +#include + +/** + * An OpenGL Program (vertex and fragment shaders) + */ +class Program +{ +public: + Program(); + virtual ~Program(); + + void setVerbose(bool v) { verbose = v; } + bool isVerbose() const { return verbose; } + + void setShaderNames(const std::string &v, const std::string &f); + virtual bool init(); + virtual void bind(); + virtual void unbind(); + + void addAttribute(const std::string &name); + void addUniform(const std::string &name); + GLint getAttribute(const std::string &name) const; + GLint getUniform(const std::string &name) const; + +protected: + std::string vShaderName; + std::string fShaderName; + +private: + GLuint pid; + std::map attributes; + std::map uniforms; + bool verbose; +}; + +#endif diff --git a/L04/src/Shape.cpp b/L04/src/Shape.cpp new file mode 100644 index 0000000..cf80379 --- /dev/null +++ b/L04/src/Shape.cpp @@ -0,0 +1,135 @@ +#include "Shape.h" +#include + +#include "GLSL.h" +#include "Program.h" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +using namespace std; + +Shape::Shape() : + posBufID(0), + norBufID(0), + texBufID(0) +{ +} + +Shape::~Shape() +{ +} + +void Shape::loadMesh(const string &meshName) +{ + // Load geometry + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + bool rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + if(!attrib.texcoords.empty()) { + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+0]); + texBuf.push_back(attrib.texcoords[2*idx.texcoord_index+1]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } +} + +void Shape::init() +{ + // Send the position array to the GPU + glGenBuffers(1, &posBufID); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + // Send the normal array to the GPU + if(!norBuf.empty()) { + glGenBuffers(1, &norBufID); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + } + + // Send the texture array to the GPU + if(!texBuf.empty()) { + glGenBuffers(1, &texBufID); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glBufferData(GL_ARRAY_BUFFER, texBuf.size()*sizeof(float), &texBuf[0], GL_STATIC_DRAW); + } + + // Unbind the arrays + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} + +void Shape::draw(const shared_ptr prog) const +{ + // Bind position buffer + int h_pos = prog->getAttribute("aPos"); + glEnableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, posBufID); + glVertexAttribPointer(h_pos, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + + // Bind normal buffer + int h_nor = prog->getAttribute("aNor"); + if(h_nor != -1 && norBufID != 0) { + glEnableVertexAttribArray(h_nor); + glBindBuffer(GL_ARRAY_BUFFER, norBufID); + glVertexAttribPointer(h_nor, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Bind texcoords buffer + int h_tex = prog->getAttribute("aTex"); + if(h_tex != -1 && texBufID != 0) { + glEnableVertexAttribArray(h_tex); + glBindBuffer(GL_ARRAY_BUFFER, texBufID); + glVertexAttribPointer(h_tex, 2, GL_FLOAT, GL_FALSE, 0, (const void *)0); + } + + // Draw + int count = posBuf.size()/3; // number of indices to be rendered + glDrawArrays(GL_TRIANGLES, 0, count); + + // Disable and unbind + if(h_tex != -1) { + glDisableVertexAttribArray(h_tex); + } + if(h_nor != -1) { + glDisableVertexAttribArray(h_nor); + } + glDisableVertexAttribArray(h_pos); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLSL::checkError(GET_FILE_LINE); +} diff --git a/L04/src/Shape.h b/L04/src/Shape.h new file mode 100644 index 0000000..df2aea3 --- /dev/null +++ b/L04/src/Shape.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef _SHAPE_H_ +#define _SHAPE_H_ + +#include +#include +#include + +class Program; + +/** + * A shape defined by a list of triangles + * - posBuf should be of length 3*ntris + * - norBuf should be of length 3*ntris (if normals are available) + * - texBuf should be of length 2*ntris (if texture coords are available) + * posBufID, norBufID, and texBufID are OpenGL buffer identifiers. + */ +class Shape +{ +public: + Shape(); + virtual ~Shape(); + void loadMesh(const std::string &meshName); + void init(); + void draw(const std::shared_ptr prog) const; + +private: + std::vector posBuf; + std::vector norBuf; + std::vector texBuf; + unsigned posBufID; + unsigned norBufID; + unsigned texBufID; +}; + +#endif diff --git a/L04/src/main.cpp b/L04/src/main.cpp new file mode 100644 index 0000000..2d15242 --- /dev/null +++ b/L04/src/main.cpp @@ -0,0 +1,347 @@ +#include +#include +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#define GLEW_STATIC +#include +#include + +#define GLM_FORCE_RADIANS +#include +#include +#include + +#include "tiny_obj_loader.h" + +#include "GLSL.h" +#include "MatrixStack.h" +#include "Shape.h" +#include "Program.h" + +#define PI 3.14159 + +using namespace std; +using namespace glm; + +GLFWwindow *window; // Main application window +string RESOURCE_DIR = "./"; // Where the resources are loaded from + +GLuint progID; +map attrIDs; +map unifIDs; +map bufIDs; +int indCount; + +// This function is called when a GLFW error occurs +static void error_callback(int error, const char *description) +{ + cerr << description << endl; +} + +// This function is called when a key is pressed +static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GL_TRUE); + } +} + +// This function is called when the mouse is clicked +static void mouse_callback(GLFWwindow *window, int button, int action, int mods) +{ + // Do nothing +} + +// If the window is resized, capture the new size and reset the viewport +static void resize_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +// This function is called once to initialize the scene and OpenGL +static void init() +{ + // + // General setup + // + + // Initialize time. + glfwSetTime(0.0); + + // Set background color. + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + // Enable z-buffer test. + glEnable(GL_DEPTH_TEST); + + // + // GLSL program setup + // + + // Create shader handles + GLuint vShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint fShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read shader sources + string vShaderName = RESOURCE_DIR + "vert.glsl"; + string fShaderName = RESOURCE_DIR + "frag.glsl"; + const char *vShaderText = GLSL::textFileRead(vShaderName.c_str()); + const char *fShaderText = GLSL::textFileRead(fShaderName.c_str()); + glShaderSource(vShaderID, 1, &vShaderText, NULL); + glShaderSource(fShaderID, 1, &fShaderText, NULL); + + // Compile vertex shader + int rc; + glCompileShader(vShaderID); + glGetShaderiv(vShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(vShaderID); + cout << "Error compiling vertex shader " << vShaderName << endl; + return; + } + + // Compile fragment shader + glCompileShader(fShaderID); + glGetShaderiv(fShaderID, GL_COMPILE_STATUS, &rc); + if(!rc) { + GLSL::printShaderInfoLog(fShaderID); + cout << "Error compiling fragment shader " << fShaderName << endl; + return; + } + + // Create the program and link + progID = glCreateProgram(); + glAttachShader(progID, vShaderID); + glAttachShader(progID, fShaderID); + glLinkProgram(progID); + glGetProgramiv(progID, GL_LINK_STATUS, &rc); + if(!rc) { + GLSL::printProgramInfoLog(progID); + cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl; + return; + } + + // Get vertex attribute IDs + attrIDs["aPos"] = glGetAttribLocation(progID, "aPos"); + attrIDs["aNor"] = glGetAttribLocation(progID, "aNor"); + + // Get uniform IDs + unifIDs["P"] = glGetUniformLocation(progID, "P"); + unifIDs["MV"] = glGetUniformLocation(progID, "MV"); + + // + // Vertex buffer setup + // + + // Load OBJ geometry + vector posBuf; + vector norBuf; + // Some obj files contain material information. + // We'll ignore them for this assignment. + string meshName = RESOURCE_DIR + "cube.obj"; + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + string errStr; + rc = tinyobj::LoadObj(&attrib, &shapes, &materials, &errStr, meshName.c_str()); + if(!rc) { + cerr << errStr << endl; + } else { + // Some OBJ files have different indices for vertex positions, normals, + // and texture coordinates. For example, a cube corner vertex may have + // three different normals. Here, we are going to duplicate all such + // vertices. + // Loop over shapes + for(size_t s = 0; s < shapes.size(); s++) { + // Loop over faces (polygons) + size_t index_offset = 0; + for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { + size_t fv = shapes[s].mesh.num_face_vertices[f]; + // Loop over vertices in the face. + for(size_t v = 0; v < fv; v++) { + // access to vertex + tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; + posBuf.push_back(attrib.vertices[3*idx.vertex_index+0]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+1]); + posBuf.push_back(attrib.vertices[3*idx.vertex_index+2]); + if(!attrib.normals.empty()) { + norBuf.push_back(attrib.normals[3*idx.normal_index+0]); + norBuf.push_back(attrib.normals[3*idx.normal_index+1]); + norBuf.push_back(attrib.normals[3*idx.normal_index+2]); + } + } + index_offset += fv; + // per-face material (IGNORE) + shapes[s].mesh.material_ids[f]; + } + } + } + indCount = posBuf.size()/3; // number of indices to be rendered + + // Generate 2 buffer IDs and put them in the bufIDs map. + GLuint tmp[2]; + glGenBuffers(2, tmp); + bufIDs["bPos"] = tmp[0]; + bufIDs["bNor"] = tmp[1]; + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + glBufferData(GL_ARRAY_BUFFER, norBuf.size()*sizeof(float), &norBuf[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + assert(norBuf.size() == posBuf.size()); + + GLSL::checkError(GET_FILE_LINE); +} + +static void renderA(MatrixStack MV) +{ + MV.pushMatrix(); + MV.translate(-1, 0, 0); + MV.rotate(-(2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #1 + MV.pushMatrix(); + MV.scale(2, 0.5, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #2 + MV.pushMatrix(); + MV.translate(1, 0, 0); + MV.rotate((2*PI)/16, 0, 0, 1); + MV.scale(0.5, 4, 0.5); + glUniformMatrix4fv(unifIDs["MV"], 1, GL_FALSE, value_ptr(MV.topMatrix())); + glDrawArrays(GL_TRIANGLES, 0, indCount); + MV.popMatrix(); // This line undoes the transformation applied to #3 +} + +// This function is called every frame to draw the scene. +static void render() +{ + // Clear framebuffer. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Get current frame buffer size. + int width, height; + glfwGetFramebufferSize(window, &width, &height); + float aspect = width/(float)height; + + // Set up projection matrix (camera intrinsics) + mat4 P = perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f); + + // Modelview matrix: camera and world + MatrixStack MV; + + // Tell OpenGL which GLSL program to use + glUseProgram(progID); + // Pass in the current projection matrix + glUniformMatrix4fv(unifIDs["P"], 1, GL_FALSE, value_ptr(P)); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aPos"]); + // Enable the attribute + glEnableVertexAttribArray(attrIDs["aNor"]); + // Bind the position buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bPos"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aPos"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + // Bind the color buffer object to make it the currently active buffer + glBindBuffer(GL_ARRAY_BUFFER, bufIDs["bNor"]); + // Set the pointer -- the data is already on the GPU + glVertexAttribPointer(attrIDs["aNor"], 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + //MV.pushMatrix(); + // + // DO STUFF HERE + // + MV.loadIdentity(); + MV.pushMatrix(); + MV.translate(-2, 0, -10); + MV.rotate((-(2*PI/16)), 0, 1, 0); + MV.rotate((-(2*PI/16)), 1, 0, 0); + MV.pushMatrix(); + for(int i = 1; i <= 20; i++) + { + renderA(MV); + MV.translate(1.0, 0,-2); + MV.scale(0.75, 0.75, 0.75); + } + MV.popMatrix(); + MV.popMatrix(); + + + // Unbind the buffer object + glBindBuffer(GL_ARRAY_BUFFER, 0); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aNor"]); + // Disable the attribute + glDisableVertexAttribArray(attrIDs["aPos"]); + // Unbind our GLSL program + glUseProgram(0); + + GLSL::checkError(GET_FILE_LINE); +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + cout << "Please specify the resource directory." << endl; + return 0; + } + RESOURCE_DIR = argv[1] + string("/"); + + // Set error callback. + glfwSetErrorCallback(error_callback); + // Initialize the library. + if(!glfwInit()) { + return -1; + } + // Create a windowed mode window and its OpenGL context. + window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL); + if(!window) { + glfwTerminate(); + return -1; + } + // Make the window's context current. + glfwMakeContextCurrent(window); + // Initialize GLEW. + glewExperimental = true; + if(glewInit() != GLEW_OK) { + cerr << "Failed to initialize GLEW" << endl; + return -1; + } + glGetError(); // A bug in glewInit() causes an error that we can safely ignore. + cout << "OpenGL version: " << glGetString(GL_VERSION) << endl; + cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; + GLSL::checkVersion(); + // Set vsync. + glfwSwapInterval(1); + // Set keyboard callback. + glfwSetKeyCallback(window, key_callback); + // Set the mouse call back. + glfwSetMouseButtonCallback(window, mouse_callback); + // Set the window resize call back. + glfwSetFramebufferSizeCallback(window, resize_callback); + // Initialize scene. + init(); + // Loop until the user closes the window. + while(!glfwWindowShouldClose(window)) { + // Render scene. + render(); + // Swap front and back buffers. + glfwSwapBuffers(window); + // Poll for and process events. + glfwPollEvents(); + } + // Quit program. + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/L04/src/tiny_obj_loader.h b/L04/src/tiny_obj_loader.h new file mode 100644 index 0000000..b975601 --- /dev/null +++ b/L04/src/tiny_obj_loader.h @@ -0,0 +1,1922 @@ +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// +// version 1.0.3 : Support parsing texture options(#85) +// version 1.0.2 : Improve parsing speed by about a factor of 2 for large +// files(#105) +// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104) +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// + +// +// Use this in *one* .cc +// #define TINYOBJLOADER_IMPLEMENTATION +// #include "tiny_obj_loader.h" +// + +#ifndef TINY_OBJ_LOADER_H_ +#define TINY_OBJ_LOADER_H_ + +#include +#include +#include + +namespace tinyobj { + +// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ... +// +// -blendu on | off # set horizontal texture blending +// (default on) +// -blendv on | off # set vertical texture blending +// (default on) +// -boost float_value # boost mip-map sharpness +// -mm base_value gain_value # modify texture map values (default +// 0 1) +// # base_value = brightness, +// gain_value = contrast +// -o u [v [w]] # Origin offset (default +// 0 0 0) +// -s u [v [w]] # Scale (default +// 1 1 1) +// -t u [v [w]] # Turbulence (default +// 0 0 0) +// -texres resolution # texture resolution to create +// -clamp on | off # only render texels in the clamped +// 0-1 range (default off) +// # When unclamped, textures are +// repeated across a surface, +// # when clamped, only texels which +// fall within the 0-1 +// # range are rendered. +// -bm mult_value # bump multiplier (for bump maps +// only) +// +// -imfchan r | g | b | m | l | z # specifies which channel of the file +// is used to +// # create a scalar or bump texture. +// r:red, g:green, +// # b:blue, m:matte, l:luminance, +// z:z-depth.. +// # (the default for bump is 'l' and +// for decal is 'm') +// bump -imfchan r bumpmap.tga # says to use the red channel of +// bumpmap.tga as the bumpmap +// +// For reflection maps... +// +// -type sphere # specifies a sphere for a "refl" +// reflection map +// -type cube_top | cube_bottom | # when using a cube map, the texture +// file for each +// cube_front | cube_back | # side of the cube is specified +// separately +// cube_left | cube_right + +typedef enum { + TEXTURE_TYPE_NONE, // default + TEXTURE_TYPE_SPHERE, + TEXTURE_TYPE_CUBE_TOP, + TEXTURE_TYPE_CUBE_BOTTOM, + TEXTURE_TYPE_CUBE_FRONT, + TEXTURE_TYPE_CUBE_BACK, + TEXTURE_TYPE_CUBE_LEFT, + TEXTURE_TYPE_CUBE_RIGHT +} texture_type_t; + +typedef struct { + texture_type_t type; // -type (default TEXTURE_TYPE_NONE) + float sharpness; // -boost (default 1.0?) + float brightness; // base_value in -mm option (default 0) + float contrast; // gain_value in -mm option (default 1) + float origin_offset[3]; // -o u [v [w]] (default 0 0 0) + float scale[3]; // -s u [v [w]] (default 1 1 1) + float turbulence[3]; // -t u [v [w]] (default 0 0 0) + // int texture_resolution; // -texres resolution (default = ?) TODO + bool clamp; // -clamp (default false) + char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm') + bool blendu; // -blendu (default on) + bool blendv; // -blendv (default on) + float bump_multiplier; // -bm (for bump maps only, default 1.0) +} texture_option_t; + +typedef struct { + std::string name; + + float ambient[3]; + float diffuse[3]; + float specular[3]; + float transmittance[3]; + float emission[3]; + float shininess; + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent + // illumination model (see http://www.fileformat.info/format/material/) + int illum; + + int dummy; // Suppress padding warning. + + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d + + texture_option_t ambient_texopt; + texture_option_t diffuse_texopt; + texture_option_t specular_texopt; + texture_option_t specular_highlight_texopt; + texture_option_t bump_texopt; + texture_option_t displacement_texopt; + texture_option_t alpha_texopt; + + // PBR extension + // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr + float roughness; // [0, 1] default 0 + float metallic; // [0, 1] default 0 + float sheen; // [0, 1] default 0 + float clearcoat_thickness; // [0, 1] default 0 + float clearcoat_roughness; // [0, 1] default 0 + float anisotropy; // aniso. [0, 1] default 0 + float anisotropy_rotation; // anisor. [0, 1] default 0 + float pad0; + float pad1; + std::string roughness_texname; // map_Pr + std::string metallic_texname; // map_Pm + std::string sheen_texname; // map_Ps + std::string emissive_texname; // map_Ke + std::string normal_texname; // norm. For normal mapping. + + texture_option_t roughness_texopt; + texture_option_t metallic_texopt; + texture_option_t sheen_texopt; + texture_option_t emissive_texopt; + texture_option_t normal_texopt; + + int pad2; + + std::map unknown_parameter; +} material_t; + +typedef struct { + std::string name; + + std::vector intValues; + std::vector floatValues; + std::vector stringValues; +} tag_t; + +// Index struct to support different indices for vtx/normal/texcoord. +// -1 means not used. +typedef struct { + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; + std::vector num_face_vertices; // The number of vertices per + // face. 3 = polygon, 4 = quad, + // ... Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag +} mesh_t; + +typedef struct { + std::string name; + mesh_t mesh; +} shape_t; + +// Vertex attributes +typedef struct { + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' +} attrib_t; + +typedef struct callback_t_ { + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); + void (*normal_cb)(void *user_data, float x, float y, float z); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in + // `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); + + // called per 'f' line. num_indices is the number of face indices(e.g. 3 for + // triangle, 4 for quad) + // 0 will be passed for undefined index in index_t members. + void (*index_cb)(void *user_data, index_t *indices, int num_indices); + // `name` material name, `material_id` = the array index of material_t[]. -1 + // if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int material_id); + // `materials` = parsed material data. + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} +} callback_t; + +class MaterialReader { + public: + MaterialReader() {} + virtual ~MaterialReader(); + + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) = 0; +}; + +class MaterialFileReader : public MaterialReader { + public: + explicit MaterialFileReader(const std::string &mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::string m_mtlBaseDir; +}; + +class MaterialStreamReader : public MaterialReader { + public: + explicit MaterialStreamReader(std::istream &inStream) + : m_inStream(inStream) {} + virtual ~MaterialStreamReader() {} + virtual bool operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, std::string *err); + + private: + std::istream &m_inStream; +}; + +/// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data +/// 'shapes' will be filled with parsed shape data +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +/// 'mtl_basedir' is optional, and used for base directory for .mtl file. +/// In default(`NULL'), .mtl file is searched from an application's working directory. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir = NULL, + bool triangulate = true); + +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// See `examples/callback_api/` for how to use this function. +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data = NULL, + MaterialReader *readMatFn = NULL, + std::string *err = NULL); + +/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve +/// std::istream for materials. +/// Returns true when loading .obj become success. +/// Returns warning and error message into `err` +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn = NULL, + bool triangulate = true); + +/// Loads materials into std::map +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj + +#ifdef TINYOBJLOADER_IMPLEMENTATION +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tinyobj { + +MaterialReader::~MaterialReader() {} + +#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) + +struct vertex_index { + int v_idx, vt_idx, vn_idx; + vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} + explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} + vertex_index(int vidx, int vtidx, int vnidx) + : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} +}; + +struct tag_sizes { + tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} + int num_ints; + int num_floats; + int num_strings; +}; + +struct obj_shape { + std::vector v; + std::vector vn; + std::vector vt; +}; + +// See +// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf +static std::istream &safeGetline(std::istream &is, std::string &t) { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) is.setstate(std::ios::eofbit); + return is; + default: + t += static_cast(c); + } + } +} + +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) + +// Make index zero-base, and also support relative index. +static inline int fixIndex(int idx, int n) { + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative +} + +static inline std::string parseString(const char **token) { + std::string s; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; + return s; +} + +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); + return i; +} + +// Tries to parse a floating point number located at s. +// +// s_end should be a location in the string where reading should absolutely +// stop. For example at the end of the string, to prevent buffer overflows. +// +// Parses the following EBNF grammar: +// sign = "+" | "-" ; +// END = ? anything not in digit ? +// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; +// integer = [sign] , digit , {digit} ; +// decimal = integer , ["." , integer] ; +// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; +// +// Valid strings are for example: +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// +// If the parsing is a success, result is set to the parsed value and true +// is returned. +// +// The function is greedy and will parse until any of the following happens: +// - a non-conforming character is encountered. +// - s_end is reached. +// +// The following situations triggers a failure: +// - s >= s_end. +// - parse failure. +// +static bool tryParseDouble(const char *s, const char *s_end, double *result) { + if (s >= s_end) { + return false; + } + + double mantissa = 0.0; + // This exponent is base 2 rather than 10. + // However the exponent we parse is supposed to be one of ten, + // thus we must take care to convert the exponent/and or the + // mantissa to a * 2^E, where a is the mantissa and E is the + // exponent. + // To get the final double we will use ldexp, it requires the + // exponent to be in base 2. + int exponent = 0; + + // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED + // TO JUMP OVER DEFINITIONS. + char sign = '+'; + char exp_sign = '+'; + char const *curr = s; + + // How many characters were read in a loop. + int read = 0; + // Tells whether a loop terminated due to reaching s_end. + bool end_not_reached = false; + + /* + BEGIN PARSING. + */ + + // Find out what sign we've got. + if (*curr == '+' || *curr == '-') { + sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + goto fail; + } + + // Read the integer part. + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + mantissa *= 10; + mantissa += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + + // We must make sure we actually got something. + if (read == 0) goto fail; + // We allow numbers of form "#", "###" etc. + if (!end_not_reached) goto assemble; + + // Read the decimal part. + if (*curr == '.') { + curr++; + read = 1; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + static const double pow_lut[] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, + }; + const int lut_entries = sizeof pow_lut / sizeof pow_lut[0]; + + // NOTE: Don't use powf here, it will absolutely murder precision. + mantissa += static_cast(*curr - 0x30) * + (read < lut_entries ? pow_lut[read] : pow(10.0, -read)); + read++; + curr++; + end_not_reached = (curr != s_end); + } + } else if (*curr == 'e' || *curr == 'E') { + } else { + goto assemble; + } + + if (!end_not_reached) goto assemble; + + // Read the exponent part. + if (*curr == 'e' || *curr == 'E') { + curr++; + // Figure out if a sign is present and if it is. + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { + exp_sign = *curr; + curr++; + } else if (IS_DIGIT(*curr)) { /* Pass through. */ + } else { + // Empty E is not allowed. + goto fail; + } + + read = 0; + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { + exponent *= 10; + exponent += static_cast(*curr - 0x30); + curr++; + read++; + end_not_reached = (curr != s_end); + } + exponent *= (exp_sign == '+' ? 1 : -1); + if (read == 0) goto fail; + } + +assemble: + *result = + (sign == '+' ? 1 : -1) * + (exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa); + return true; +fail: + return false; +} + +static inline float parseFloat(const char **token, double default_value = 0.0) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + double val = default_value; + tryParseDouble((*token), end, &val); + float f = static_cast(val); + (*token) = end; + return f; +} + +static inline void parseFloat2(float *x, float *y, const char **token, + const double default_x = 0.0, + const double default_y = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); +} + +static inline void parseFloat3(float *x, float *y, float *z, const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); +} + +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token, const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0, + const double default_w = 1.0) { + (*x) = parseFloat(token, default_x); + (*y) = parseFloat(token, default_y); + (*z) = parseFloat(token, default_z); + (*w) = parseFloat(token, default_w); +} + +static inline bool parseOnOff(const char **token, bool default_value = true) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + + bool ret = default_value; + if ((0 == strncmp((*token), "on", 2))) { + ret = true; + } else if ((0 == strncmp((*token), "off", 3))) { + ret = false; + } + + (*token) = end; + return ret; +} + +static inline texture_type_t parseTextureType( + const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { + (*token) += strspn((*token), " \t"); + const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; + + if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { + ty = TEXTURE_TYPE_SPHERE; + } + + (*token) = end; + return ty; +} + +static tag_sizes parseTagTriple(const char **token) { + tag_sizes ts; + + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return ts; + } + (*token)++; + + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; + + return ts; +} + +// Parse triples with index offsets: i, i/j/k, i//k, i/j +static vertex_index parseTriple(const char **token, int vsize, int vnsize, + int vtsize) { + vertex_index vi(-1); + + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(static_cast(0)); // 0 is an invalid index in OBJ + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + +static bool ParseTextureNameAndOption(std::string *texname, + texture_option_t *texopt, + const char *linebuf, const bool is_bump) { + // @todo { write more robust lexer and parser. } + bool found_texname = false; + std::string texture_name; + + // Fill with default value for texopt. + if (is_bump) { + texopt->imfchan = 'l'; + } else { + texopt->imfchan = 'm'; + } + texopt->bump_multiplier = 1.0f; + texopt->clamp = false; + texopt->blendu = true; + texopt->blendv = true; + texopt->sharpness = 1.0f; + texopt->brightness = 0.0f; + texopt->contrast = 1.0f; + texopt->origin_offset[0] = 0.0f; + texopt->origin_offset[1] = 0.0f; + texopt->origin_offset[2] = 0.0f; + texopt->scale[0] = 1.0f; + texopt->scale[1] = 1.0f; + texopt->scale[2] = 1.0f; + texopt->turbulence[0] = 0.0f; + texopt->turbulence[1] = 0.0f; + texopt->turbulence[2] = 0.0f; + texopt->type = TEXTURE_TYPE_NONE; + + const char *token = linebuf; // Assume line ends with NULL + + while (!IS_NEW_LINE((*token))) { + if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { + token += 7; + texopt->sharpness = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { + token += 4; + texopt->bump_multiplier = parseFloat(&token, 1.0); + } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), + &token, 1.0, 1.0, 1.0); + } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { + token += 3; + parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { + token += 4; + parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { + // Assume texture filename + token += strspn(token, " \t"); // skip space + size_t len = strcspn(token, " \t\r"); // untile next space + texture_name = std::string(token, token + len); + token += len; + + token += strspn(token, " \t"); // skip space + + found_texname = true; + } + } + + if (found_texname) { + (*texname) = texture_name; + return true; + } else { + return false; + } +} + +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; + for (int i = 0; i < 3; i++) { + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; + } + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + + material->roughness = 0.f; + material->metallic = 0.f; + material->sheen = 0.f; + material->clearcoat_thickness = 0.f; + material->clearcoat_roughness = 0.f; + material->anisotropy_rotation = 0.f; + material->anisotropy = 0.f; + material->roughness_texname = ""; + material->metallic_texname = ""; + material->sheen_texname = ""; + material->emissive_texname = ""; + material->normal_texname = ""; + + material->unknown_parameter.clear(); +} + +static bool exportFaceGroupToShape( + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { + if (faceGroup.empty()) { + return false; + } + + // Flatten vertices and indices + for (size_t i = 0; i < faceGroup.size(); i++) { + const std::vector &face = faceGroup[i]; + + vertex_index i0 = face[0]; + vertex_index i1(-1); + vertex_index i2 = face[1]; + + size_t npolys = face.size(); + + if (triangulate) { + // Polygon -> triangle fan conversion + for (size_t k = 2; k < npolys; k++) { + i1 = i2; + i2 = face[k]; + + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); + + shape->mesh.num_face_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); + } + } else { + for (size_t k = 0; k < npolys; k++) { + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); + } + + shape->mesh.num_face_vertices.push_back( + static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face + } + } + + shape->name = name; + shape->mesh.tags = tags; + + return true; +} + +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { + // Create a default material anyway. + material_t material; + InitMaterial(&material); + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim trailing whitespace. + if (linebuf.size() > 0) { + linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); + } + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // new mtl + if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { + // flush previous material. + if (!material.name.empty()) { + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + // set new mtl name + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + material.name = namebuf; + continue; + } + + // ambient + if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || + (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { + token += 2; + material.ior = parseFloat(&token); + continue; + } + + // emission + if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { + token += 2; + float r, g, b; + parseFloat3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } + + // shininess + if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.shininess = parseFloat(&token); + continue; + } + + // illum model + if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { + token += 6; + material.illum = parseInt(&token); + continue; + } + + // dissolve + if ((token[0] == 'd' && IS_SPACE(token[1]))) { + token += 1; + material.dissolve = parseFloat(&token); + continue; + } + if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + // Invert value of Tr(assume Tr is in range [0, 1]) + material.dissolve = 1.0f - parseFloat(&token); + continue; + } + + // PBR: roughness + if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { + token += 2; + material.roughness = parseFloat(&token); + continue; + } + + // PBR: metallic + if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { + token += 2; + material.metallic = parseFloat(&token); + continue; + } + + // PBR: sheen + if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { + token += 2; + material.sheen = parseFloat(&token); + continue; + } + + // PBR: clearcoat thickness + if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { + token += 2; + material.clearcoat_thickness = parseFloat(&token); + continue; + } + + // PBR: clearcoat roughness + if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { + token += 4; + material.clearcoat_roughness = parseFloat(&token); + continue; + } + + // PBR: anisotropy + if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { + token += 6; + material.anisotropy = parseFloat(&token); + continue; + } + + // PBR: anisotropy rotation + if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { + token += 7; + material.anisotropy_rotation = parseFloat(&token); + continue; + } + + // ambient texture + if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } + + // diffuse texture + if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } + + // specular texture + if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } + + // specular highlight texture + if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } + + // bump texture + if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // bump texture + if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } + + // alpha texture + if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } + + // displacement texture + if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: roughness texture + if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: metallic texture + if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: sheen texture + if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: emissive texture + if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } + + // PBR: normal map texture + if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } + + // unknown parameter + const char *_space = strchr(token, ' '); + if (!_space) { + _space = strchr(token, '\t'); + } + if (_space) { + std::ptrdiff_t len = _space - token; + std::string key(token, static_cast(len)); + std::string value = _space + 1; + material.unknown_parameter.insert( + std::pair(key, value)); + } + } + // flush last material. + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); +} + +bool MaterialFileReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } else { + filepath = matId; + } + + std::ifstream matIStream(filepath.c_str()); + LoadMtl(matMap, materials, &matIStream); + if (!matIStream) { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath + << " ] not found. Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool MaterialStreamReader::operator()(const std::string &matId, + std::vector *materials, + std::map *matMap, + std::string *err) { + (void)matId; + LoadMtl(matMap, materials, &m_inStream); + if (!m_inStream) { + std::stringstream ss; + ss << "WARN: Material stream in error state." + << " Created a default material."; + if (err) { + (*err) += ss.str(); + } + } + return true; +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basedir, + bool trianglulate) { + attrib->vertices.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); + + std::stringstream errss; + + std::ifstream ifs(filename); + if (!ifs) { + errss << "Cannot open file [" << filename << "]" << std::endl; + if (err) { + (*err) = errss.str(); + } + return false; + } + + std::string baseDir; + if (mtl_basedir) { + baseDir = mtl_basedir; + } + MaterialFileReader matFileReader(baseDir); + + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); +} + +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn /*= NULL*/, + bool triangulate) { + std::stringstream errss; + + std::vector v; + std::vector vn; + std::vector vt; + std::vector tags; + std::vector > faceGroup; + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + std::string linebuf; + while (inStream->peek() != -1) { + safeGetline(*inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + v.push_back(x); + v.push_back(y); + v.push_back(z); + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + vn.push_back(x); + vn.push_back(y); + vn.push_back(z); + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + vt.push_back(x); + vt.push_back(y); + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2)); + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + // Create per-face material. Thus we don't add `shape` to `shapes` at + // this time. + // just clear `faceGroup` after `exportFaceGroupToShape()` call. + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + faceGroup.clear(); + material = newMaterialId; + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + faceGroup.clear(); // for safety + return false; + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + continue; + } + + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } + + // Ignore unknown command. + } + + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); + // exportFaceGroupToShape return false when `usemtl` is called in the last + // line. + // we also add `shape` to `shapes` when `shape.mesh` has already some + // faces(indices) + if (ret || shape.mesh.indices.size()) { + shapes->push_back(shape); + } + faceGroup.clear(); // for safety + + if (err) { + (*err) += errss.str(); + } + + attrib->vertices.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + + return true; +} + +bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, + void *user_data /*= NULL*/, + MaterialReader *readMatFn /*= NULL*/, + std::string *err /*= NULL*/) { + std::stringstream errss; + + // material + std::map material_map; + int material_id = -1; // -1 = invalid + + std::vector indices; + std::vector materials; + std::vector names; + names.reserve(2); + std::string name; + std::vector names_out; + + std::string linebuf; + while (inStream.peek() != -1) { + safeGetline(inStream, linebuf); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z, w); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y, z); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + indices.clear(); + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + + index_t idx; + idx.vertex_index = vi.v_idx; + idx.normal_index = vi.vn_idx; + idx.texcoord_index = vi.vt_idx; + + indices.push_back(idx); + size_t n = strspn(token, " \t\r"); + token += n; + } + + if (callback.index_cb && indices.size() > 0) { + callback.index_cb(user_data, &indices.at(0), + static_cast(indices.size())); + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, + static_cast(_countof(namebuf))); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material_id) { + material_id = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, namebuf, material_id); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + if (readMatFn) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + materials.clear(); + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + std::string object_name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} +} // namespace tinyobj + +#endif + +#endif // TINY_OBJ_LOADER_H_