Przeglądaj źródła

added meshoptimizer to 3rdparty

attilaz 6 lat temu
rodzic
commit
aca1b6c774
39 zmienionych plików z 23163 dodań i 0 usunięć
  1. 12 0
      3rdparty/meshoptimizer/.clang-format
  2. 2 0
      3rdparty/meshoptimizer/.gitignore
  3. 37 0
      3rdparty/meshoptimizer/.travis.yml
  4. 40 0
      3rdparty/meshoptimizer/CMakeLists.txt
  5. 54 0
      3rdparty/meshoptimizer/CONTRIBUTING.md
  6. 21 0
      3rdparty/meshoptimizer/LICENSE.md
  7. 97 0
      3rdparty/meshoptimizer/Makefile
  8. 264 0
      3rdparty/meshoptimizer/README.md
  9. 10 0
      3rdparty/meshoptimizer/codecov.yml
  10. 2 0
      3rdparty/meshoptimizer/demo/ansi.c
  11. 122 0
      3rdparty/meshoptimizer/demo/index.html
  12. 941 0
      3rdparty/meshoptimizer/demo/main.cpp
  13. 1197 0
      3rdparty/meshoptimizer/demo/miniz.cpp
  14. 298 0
      3rdparty/meshoptimizer/demo/miniz.h
  15. 11358 0
      3rdparty/meshoptimizer/demo/pirate.obj
  16. BIN
      3rdparty/meshoptimizer/demo/pirate.optmesh
  17. 280 0
      3rdparty/meshoptimizer/demo/tests.cpp
  18. 4 0
      3rdparty/meshoptimizer/js/decoder.js
  19. 7 0
      3rdparty/meshoptimizer/src/allocator.cpp
  20. 351 0
      3rdparty/meshoptimizer/src/clusterizer.cpp
  21. 582 0
      3rdparty/meshoptimizer/src/indexcodec.cpp
  22. 347 0
      3rdparty/meshoptimizer/src/indexgenerator.cpp
  23. 759 0
      3rdparty/meshoptimizer/src/meshoptimizer.h
  24. 230 0
      3rdparty/meshoptimizer/src/overdrawanalyzer.cpp
  25. 333 0
      3rdparty/meshoptimizer/src/overdrawoptimizer.cpp
  26. 1363 0
      3rdparty/meshoptimizer/src/simplifier.cpp
  27. 269 0
      3rdparty/meshoptimizer/src/stripifier.cpp
  28. 73 0
      3rdparty/meshoptimizer/src/vcacheanalyzer.cpp
  29. 453 0
      3rdparty/meshoptimizer/src/vcacheoptimizer.cpp
  30. 954 0
      3rdparty/meshoptimizer/src/vertexcodec.cpp
  31. 58 0
      3rdparty/meshoptimizer/src/vfetchanalyzer.cpp
  32. 74 0
      3rdparty/meshoptimizer/src/vfetchoptimizer.cpp
  33. 179 0
      3rdparty/meshoptimizer/tools/OptMeshLoader.js
  34. 630 0
      3rdparty/meshoptimizer/tools/lodviewer.cpp
  35. 255 0
      3rdparty/meshoptimizer/tools/meshencoder.cpp
  36. 383 0
      3rdparty/meshoptimizer/tools/objparser.cpp
  37. 42 0
      3rdparty/meshoptimizer/tools/objparser.h
  38. 495 0
      3rdparty/meshoptimizer/tools/vcachetester.cpp
  39. 587 0
      3rdparty/meshoptimizer/tools/vcachetuner.cpp

+ 12 - 0
3rdparty/meshoptimizer/.clang-format

@@ -0,0 +1,12 @@
+Standard: Cpp03
+UseTab: ForIndentation
+TabWidth: 4
+IndentWidth: 4
+AccessModifierOffset: -4
+BreakBeforeBraces: Allman
+IndentCaseLabels: false
+ColumnLimit: 0
+PointerAlignment: Left
+BreakConstructorInitializersBeforeComma: true
+NamespaceIndentation: None
+AlignEscapedNewlines: DontAlign

+ 2 - 0
3rdparty/meshoptimizer/.gitignore

@@ -0,0 +1,2 @@
+/build/
+/data/

+ 37 - 0
3rdparty/meshoptimizer/.travis.yml

@@ -0,0 +1,37 @@
+language: cpp
+
+matrix:
+  include:
+    - os: linux
+      compiler: gcc
+    - os: linux
+      compiler: clang
+    - os: osx
+      compiler: clang
+    - os: windows
+      compiler: cl
+      env:
+        - TARGET="Visual Studio 15 2017"
+    - os: windows
+      compiler: cl
+      env:
+        - TARGET="Visual Studio 15 2017 Win64"
+
+script:
+  - if [[ "$TRAVIS_COMPILER" == "gcc" ]]; then make config=coverage test; fi
+  - if [[ "$TRAVIS_COMPILER" == "clang" ]]; then make config=sanitize test; fi
+  - if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then make config=debug test; fi
+  - if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then make config=release test; fi
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then cmake -G "$TARGET" -DBUILD_DEMO=ON; fi
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then cmake --build . -- -property:Configuration=Debug -verbosity:minimal; fi
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then ./Debug/demo.exe demo/pirate.obj; fi
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then cmake --build . -- -property:Configuration=Release -verbosity:minimal; fi
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then ./Release/demo.exe demo/pirate.obj; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make config=iphone; fi
+
+after_script:
+  - if [[ "$TRAVIS_COMPILER" == "gcc" ]]; then
+    find . -type f -name '*.gcno' -exec gcov -p {} +;
+    sed -i -e "s/#####\(.*\)\(\/\/ unreachable.*\)/    -\1\2/" *.gcov;
+    bash <(curl -s https://codecov.io/bash) -f 'src#*.gcov' -X search;
+    fi

+ 40 - 0
3rdparty/meshoptimizer/CMakeLists.txt

@@ -0,0 +1,40 @@
+project(meshoptimizer)
+cmake_minimum_required(VERSION 3.0)
+
+option(BUILD_DEMO "Build demo" OFF)
+option(BUILD_TOOLS "Build tools" OFF)
+
+set(SOURCES
+    src/meshoptimizer.h
+    src/clusterizer.cpp
+    src/indexcodec.cpp
+    src/indexgenerator.cpp
+    src/overdrawanalyzer.cpp
+    src/overdrawoptimizer.cpp
+    src/simplifier.cpp
+    src/stripifier.cpp
+    src/vcacheanalyzer.cpp
+    src/vcacheoptimizer.cpp
+    src/vertexcodec.cpp
+    src/vfetchanalyzer.cpp
+    src/vfetchoptimizer.cpp
+)
+
+add_library(meshoptimizer STATIC ${SOURCES})
+target_include_directories(meshoptimizer INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/src")
+
+if(MSVC)
+	target_compile_options(meshoptimizer PRIVATE /W4 /WX)
+else()
+	target_compile_options(meshoptimizer PRIVATE -Wall -Wextra -Werror)
+endif()
+
+if(BUILD_DEMO)
+    add_executable(demo demo/main.cpp demo/miniz.cpp demo/tests.cpp tools/objparser.cpp)
+    target_link_libraries(demo meshoptimizer)
+endif()
+
+if(BUILD_TOOLS)
+    add_executable(meshencoder tools/meshencoder.cpp tools/objparser.cpp)
+    target_link_libraries(meshencoder meshoptimizer)
+endif()

+ 54 - 0
3rdparty/meshoptimizer/CONTRIBUTING.md

@@ -0,0 +1,54 @@
+Thanks for deciding to contribute to meshoptimizer! These guidelines will try to help make the process painless and efficient.
+
+## Questions
+
+If you have a question regarding the library usage, please [open a GitHub issue](https://github.com/zeux/meshoptimizer/issues/new).
+Some questions just need answers, but it's nice to keep them for future reference in case other people want to know the same thing.
+Some questions help improve the library interface or documentation by inspiring future changes.
+
+## Bugs
+
+If the library doesn't compile on your system, compiles with warnings, doesn't seem to run correctly for your input data or if anything else is amiss, please [open a GitHub issue](https://github.com/zeux/meshoptimizer/issues/new).
+It helps if you note the version of the library this issue happens in, the version of your compiler for compilation issues, and a reproduction case for runtime bugs.
+
+Of course, feel free to [create a pull request](https://help.github.com/articles/about-pull-requests/) to fix the bug yourself.
+
+## Features
+
+New algorithms and improvements to existing algorithms are always welcome; you can open an issue or make the change yourself and submit a pull request.
+
+For major features, consider opening an issue describing an improvement you'd like to see or make before opening a pull request.
+This will give us a chance to discuss the idea before implementing it - some algorithms may not be easy to integrate into existing programs, may not be robust to arbitrary meshes or may be expensive to run or implement/maintain, so a discussion helps make sure these don't block the algorithm development.
+
+## Code style
+
+Contributions to this project are expected to follow the existing code style.
+`.clang-format` file mostly defines syntactic styling rules (you can run `make format` to format the code accordingly).
+
+As for naming conventions, this library uses `snake_case` for variables, `lowerCamelCase` for functions, `UpperCamelCase` for types, `kCamelCase` for global constants and `SCARY_CASE` for macros. All public functions/types must additionally have an extra `meshopt_` prefix to avoid symbol conflicts.
+
+## Dependencies
+
+Please note that this library uses C89 interface for all APIs and a C++98 implementation - C++11 features can not be used.
+This choice is made to maximize compatibility to make sure that any toolchain, including legacy proprietary gaming console toolchains, can compile this code.
+
+Additionally, the library code has zero external dependencies, does not depend on STL and does not use RTTI or exceptions.
+This, again, maximizes compatibility and makes sure the library can be used in environments where STL use is discouraged or prohibited, as well as maximizing runtime performance and minimizing compilation times.
+
+The demo program uses STL since it serves as an example of usage and as a test harness, not as production-ready code.
+
+## Testing
+
+All pull requests will run through a continuous integration pipeline hosted on [Travis CI](https://travis-ci.org/zeux/meshoptimizer) that will run the built-in unit tests and integration tests on Windows, macOS and Linux with gcc, clang and msvc compilers.
+You can run the tests yourself using `make test` or building the demo program with `cmake -DBUILD_DEMO=ON` and running it.
+
+Unit tests can be found in `demo/tests.cpp` and functional tests - in `demo/main.cpp`; when making code changes please try to make sure they are covered by an existing test or add a new test accordingly.
+
+## Documentation
+
+Documentation for this library resides in the `meshoptimizer.h` header, with examples as part of a usage manual available in `README.md`.
+Changes to documentation are always welcome and should use issues/pull requests as outlined above; please note that `README.md` only contains documentation for stable algorithms, as experimental algorithms may change the interface without concern for backwards compatibility.
+
+## Sensitive communication
+
+If you prefer to not disclose the issues or information relevant to the issue such as reproduction case to the public, you can always contact the author via e-mail ([email protected]).

+ 21 - 0
3rdparty/meshoptimizer/LICENSE.md

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016-2019 Arseny Kapoulkine
+
+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.

+ 97 - 0
3rdparty/meshoptimizer/Makefile

@@ -0,0 +1,97 @@
+.SUFFIXES:
+MAKEFLAGS+=-r
+
+config=debug
+files=demo/pirate.obj
+
+BUILD=build/$(config)
+
+LIBRARY_SOURCES=$(wildcard src/*.cpp)
+LIBRARY_OBJECTS=$(LIBRARY_SOURCES:%=$(BUILD)/%.o)
+
+DEMO_SOURCES=$(wildcard demo/*.c demo/*.cpp) tools/objparser.cpp
+DEMO_OBJECTS=$(DEMO_SOURCES:%=$(BUILD)/%.o)
+
+ENCODER_SOURCES=tools/meshencoder.cpp tools/objparser.cpp
+ENCODER_OBJECTS=$(ENCODER_SOURCES:%=$(BUILD)/%.o)
+
+OBJECTS=$(LIBRARY_OBJECTS) $(DEMO_OBJECTS) $(ENCODER_OBJECTS)
+
+LIBRARY=$(BUILD)/libmeshoptimizer.a
+EXECUTABLE=$(BUILD)/meshoptimizer
+
+CFLAGS=-g -Wall -Wextra -Werror -std=c89
+CXXFLAGS=-g -Wall -Wextra -Wshadow -Wno-missing-field-initializers -Werror -std=c++98
+LDFLAGS=
+
+ifeq ($(config),iphone)
+	IPHONESDK=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk
+	CFLAGS+=-arch armv7 -arch arm64 -isysroot $(IPHONESDK)
+	CXXFLAGS+=-arch armv7 -arch arm64 -isysroot $(IPHONESDK) -stdlib=libc++
+	LDFLAGS+=-arch armv7 -arch arm64 -L $(IPHONESDK)/usr/lib -mios-version-min=7.0
+endif
+
+ifeq ($(config),trace)
+	CXXFLAGS+=-DTRACE=2
+endif
+
+ifeq ($(config),release)
+	CXXFLAGS+=-O3 -DNDEBUG
+endif
+
+ifeq ($(config),coverage)
+	CXXFLAGS+=-coverage
+	LDFLAGS+=-coverage
+endif
+
+ifeq ($(config),sanitize)
+	CXXFLAGS+=-fsanitize=address,undefined -fno-sanitize-recover=all
+	LDFLAGS+=-fsanitize=address,undefined
+endif
+
+ifeq ($(config),analyze)
+	CXXFLAGS+=--analyze
+endif
+
+all: $(EXECUTABLE)
+
+test: $(EXECUTABLE)
+	$(EXECUTABLE) $(files)
+
+check: $(EXECUTABLE)
+	$(EXECUTABLE)
+
+dev: $(EXECUTABLE)
+	$(EXECUTABLE) -d $(files)
+
+format:
+	clang-format -i $(LIBRARY_SOURCES) $(DEMO_SOURCES)
+
+meshencoder: $(ENCODER_OBJECTS) $(LIBRARY)
+	$(CXX) $^ $(LDFLAGS) -o $@
+
+js/decoder.js: src/vertexcodec.cpp src/indexcodec.cpp
+	@mkdir -p build
+	emcc $(filter %.cpp,$^) -O3 -DNDEBUG -s EXPORTED_FUNCTIONS='["_meshopt_decodeVertexBuffer", "_meshopt_decodeIndexBuffer"]' -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=32768 -s TOTAL_MEMORY=65536 -o build/decoder.wasm
+	sed -i "s#\(var wasm = \)\".*\";#\\1\"$$(cat build/decoder.wasm | base64 -w 0)\";#" $@
+
+$(EXECUTABLE): $(DEMO_OBJECTS) $(LIBRARY)
+	$(CXX) $^ $(LDFLAGS) -o $@
+
+$(LIBRARY): $(LIBRARY_OBJECTS)
+	ar rcs $@ $^
+
+$(BUILD)/%.cpp.o: %.cpp
+	@mkdir -p $(dir $@)
+	$(CXX) $< $(CXXFLAGS) -c -MMD -MP -o $@
+
+$(BUILD)/%.c.o: %.c
+	@mkdir -p $(dir $@)
+	$(CC) $< $(CFLAGS) -c -MMD -MP -o $@
+
+-include $(OBJECTS:.o=.d)
+
+clean:
+	rm -rf $(BUILD)
+
+.PHONY: all clean format

+ 264 - 0
3rdparty/meshoptimizer/README.md

@@ -0,0 +1,264 @@
+# meshoptimizer [![Build Status](https://travis-ci.org/zeux/meshoptimizer.svg?branch=master)](https://travis-ci.org/zeux/meshoptimizer) [![codecov.io](https://codecov.io/github/zeux/meshoptimizer/coverage.svg?branch=master)](https://codecov.io/github/zeux/meshoptimizer?branch=master) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![GitHub](https://img.shields.io/badge/repo-github-green.svg)](https://github.com/zeux/meshoptimizer)
+
+## Purpose
+
+When a GPU renders triangle meshes, various stages of the GPU pipeline have to process vertex and index data. The efficiency of these stages depends on the data you feed to them; this library provides algorithms to help optimize meshes for these stages, as well as algorithms to reduce the mesh complexity and storage overhead.
+
+The library provides a C and C++ interface for all algorithms; you can use it from C/C++ or from other languages via FFI (such as P/Invoke). If you want to use this library from Rust, you should use [meshopt crate](https://crates.io/crates/meshopt).
+
+## Installing
+
+meshoptimizer is hosted on GitHub; you can download the latest release using git:
+
+```
+git clone -b v0.11 https://github.com/zeux/meshoptimizer.git
+```
+
+Alternatively you can [download the .zip archive from GitHub](https://github.com/zeux/meshoptimizer/archive/v0.11.zip).
+
+## Building
+
+meshoptimizer is distributed as a set of C++ source files. To include it into your project, you can use one of the two options:
+
+* Use CMake to build the library (either as a standalone project or as part of your project)
+* Add source files to your project's build system
+
+The source files are organized in such a way that you don't need to change your build-system settings, and you only need to add the files for the algorithms you use.
+
+## Pipeline
+
+When optimizing a mesh, you should typically feed it through a set of optimizations (the order is important!):
+
+1. Indexing
+2. Vertex cache optimization
+3. Overdraw optimization
+4. Vertex fetch optimization
+5. Vertex quantization
+6. (optional) Vertex/index buffer compression
+
+## Indexing
+
+Most algorithms in this library assume that a mesh has a vertex buffer and an index buffer. For algorithms to work well and also for GPU to render your mesh efficiently, the vertex buffer has to have no redundant vertices; you can generate an index buffer from an unindexed vertex buffer or reindex an existing (potentially redundant) index buffer as follows:
+
+First, generate a remap table from your existing vertex (and, optionally, index) data:
+
+```c++
+size_t index_count = face_count * 3;
+std::vector<unsigned int> remap(index_count); // allocate temporary memory for the remap table
+size_t vertex_count = meshopt_generateVertexRemap(&remap[0], NULL, index_count, &unindexed_vertices[0], index_count, sizeof(Vertex));
+```
+
+Note that in this case we only have an unindexed vertex buffer; the remap table is generated based on binary equivalence of the input vertices, so the resulting mesh will render the same way.
+
+After generating the remap table, you can allocate space for the target vertex buffer (`vertex_count` elements) and index buffer (`index_count` elements) and generate them:
+
+```c++
+meshopt_remapIndexBuffer(indices, NULL, index_count, &remap[0]);
+meshopt_remapVertexBuffer(vertices, &unindexed_vertices[0], index_count, sizeof(Vertex), &remap[0]);
+```
+
+You can then further optimize the resulting buffers by calling the other functions on them in-place.
+
+## Vertex cache optimization
+
+When the GPU renders the mesh, it has to run the vertex shader for each vertex; usually GPUs have a built-in fixed size cache that stores the transformed vertices (the result of running the vertex shader), and uses this cache to reduce the number of vertex shader invocations. This cache is usually small, 16-32 vertices, and can have different replacement policies; to use this cache efficiently, you have to reorder your triangles to maximize the locality of reused vertex references like so:
+
+```c++
+meshopt_optimizeVertexCache(indices, indices, index_count, vertex_count);
+```
+
+## Overdraw optimization
+
+After transforming the vertices, GPU sends the triangles for rasterization which results in generating pixels that are usually first ran through the depth test, and pixels that pass it get the pixel shader executed to generate the final color. As pixel shaders get more expensive, it becomes more and more important to reduce overdraw. While in general improving overdraw requires view-dependent operations, this library provides an algorithm to reorder triangles to minimize the overdraw from all directions, which you should run after vertex cache optimization like this:
+
+```c++
+meshopt_optimizeOverdraw(indices, indices, index_count, &vertices[0].x, vertex_count, sizeof(Vertex), 1.05f);
+```
+
+The overdraw optimizer needs to read vertex positions as a float3 from the vertex; the code snippet above assumes that the vertex stores position as `float x, y, z`.
+
+When performing the overdraw optimization you have to specify a floating-point threshold parameter. The algorithm tries to maintain a balance between vertex cache efficiency and overdraw; the threshold determines how much the algorithm can compromise the vertex cache hit ratio, with 1.05 meaning that the resulting ratio should be at most 5% worse than before the optimization.
+
+## Vertex fetch optimization
+
+After the final triangle order has been established, we still can optimize the vertex buffer for memory efficiency. Before running the vertex shader GPU has to fetch the vertex attributes from the vertex buffer; the fetch is usually backed by a memory cache, and as such optimizing the data for the locality of memory access is important. You can do this by running this code:
+
+To optimize the index/vertex buffers for vertex fetch efficiency, call:
+
+```c++
+meshopt_optimizeVertexFetch(vertices, indices, index_count, vertices, vertex_count, sizeof(Vertex));
+```
+
+This will reorder the vertices in the vertex buffer to try to improve the locality of reference, and rewrite the indices in place to match; if the vertex data is stored using multiple streams, you should use `meshopt_optimizeVertexFetchRemap` instead. This optimization has to be performed on the final index buffer since the optimal vertex order depends on the triangle order.
+
+Note that the algorithm does not try to model cache replacement precisely and instead just orders vertices in the order of use, which generally produces results that are close to optimal.
+
+## Vertex quantization
+
+To optimize memory bandwidth when fetching the vertex data even further, and to reduce the amount of memory required to store the mesh, it is often beneficial to quantize the vertex attributes to smaller types. While this optimization can technically run at any part of the pipeline (and sometimes doing quantization as the first step can improve indexing by merging almost identical vertices), it generally is easier to run this after all other optimizations since some of them require access to float3 positions.
+
+Quantization is usually domain specific; it's common to quantize normals using 3 8-bit integers but you can use higher-precision quantization (for example using 10 bits per component in a 10_10_10_2 format), or a different encoding to use just 2 components. For positions and texture coordinate data the two most common storage formats are half precision floats, and 16-bit normalized integers that encode the position relative to the AABB of the mesh or the UV bounding rectangle.
+
+The number of possible combinations here is very large but this library does provide the building blocks, specifically functions to quantize floating point values to normalized integers, as well as half-precision floats. For example, here's how you can quantize a normal:
+
+```c++
+unsigned int normal =
+	(meshopt_quantizeUnorm(v.nx, 10) << 20) |
+	(meshopt_quantizeUnorm(v.ny, 10) << 10) |
+	 meshopt_quantizeUnorm(v.nz, 10);
+```
+
+and here's how you can quantize a position:
+
+```c++
+unsigned short px = meshopt_quantizeHalf(v.x);
+unsigned short py = meshopt_quantizeHalf(v.y);
+unsigned short pz = meshopt_quantizeHalf(v.z);
+```
+
+## Vertex/index buffer compression
+
+In case storage size or transmission bandwidth is of importance, you might want to additionally compress vertex and index data. While several mesh compression libraries, like Google Draco, are available, they typically are designed to maximize the compression ratio at the cost of disturbing the vertex/index order (which makes the meshes inefficient to render on GPU) or decompression performance. They also frequently don't support custom game-ready quantized vertex formats and thus require to re-quantize the data after loading it, introducing extra quantization errors and making decoding slower.
+
+Alternatively you can use general purpose compression libraries like zstd or Oodle to compress vertex/index data - however these compressors aren't designed to exploit redundancies in vertex/index data and as such compression rates can be unsatisfactory.
+
+To that end, this library provides algorithms to "encode" vertex and index data. The result of the encoding is generally significantly smaller than initial data, and remains compressible with general purpose compressors - so you can either store encoded data directly (for modest compression ratios and maximum decoding performance), or further compress it with zstd/Oodle to maximize compression ratio.
+
+To encode, you need to allocate target buffers (preferably using the worst case bound) and call encoding functions:
+
+```c++
+std::vector<unsigned char> vbuf(meshopt_encodeVertexBufferBound(vertex_count, sizeof(Vertex)));
+vbuf.resize(meshopt_encodeVertexBuffer(&vbuf[0], vbuf.size(), vertices, vertex_count, sizeof(Vertex)));
+
+std::vector<unsigned char> ibuf(meshopt_encodeIndexBufferBound(index_count, vertex_count));
+ibuf.resize(meshopt_encodeIndexBuffer(&ibuf[0], ibuf.size(), indices, index_count));
+```
+
+You can then either serialize `vbuf`/`ibuf` as is, or compress them further. To decode the data at runtime, call decoding functions:
+
+```c++
+int resvb = meshopt_decodeVertexBuffer(vertices, vertex_count, sizeof(Vertex), &vbuf[0], vbuf.size());
+int resib = meshopt_decodeIndexBuffer(indices, index_count, &buffer[0], buffer.size());
+assert(resvb == 0 && resib == 0);
+```
+
+Note that vertex encoding assumes that vertex buffer was optimized for vertex fetch, and that vertices are quantized; index encoding assumes that the vertex/index buffers were optimized for vertex cache and vertex fetch. Feeding unoptimized data into the encoders will produce poor compression ratios. Both codecs are lossless - the only lossy step is quantization that happens before encoding.
+
+Decoding functions are heavily optimized and can directly target write-combined memory; you can expect both decoders to run at 1-3 GB/s on modern desktop CPUs. Compression ratios depend on the data; vertex data compression ratio is typically around 2-4x (compared to already quantized data), index data compression ratio is around 5-6x (compared to raw 16-bit index data). General purpose lossless compressors can further improve on these results.
+
+Due to a very high decoding performance and compatibility with general purpose lossless compressors, the compression is a good fit for the use on the web. To that end, meshoptimizer provides both vertex and index decoders compiled into WebAssembly and wrapped into a module with JavaScript-friendly interface, `js/decoder.js`, that you can use to decode meshes that were encoded offline:
+
+```js
+// ready is a Promise that is resolved when (asynchronous) WebAssembly compilation finishes
+await MeshoptDecoder.ready;
+
+// decode from *Data (Uint8Array) into *Buffer (Uint8Array)
+MeshoptDecoder.decodeVertexBuffer(vertexBuffer, vertexCount, vertexSize, vertexData);
+MeshoptDecoder.decodeIndexBuffer(indexBuffer, indexCount, indexSize, indexData);
+```
+
+A THREE.js mesh loader is provided as an example in `tools/OptMeshLoader.js`; it loads meshes encoded using `tools/meshencoder.cpp`. [Usage example](https://zeuxcg.org/meshoptimizer/demo/) is available, with source in `demo/index.html`.
+
+## Triangle strip conversion
+
+On most hardware, indexed triangle lists are the most efficient way to drive the GPU. However, in some cases triangle strips might prove beneficial:
+
+- On some older GPUs, triangle strips may be a bit more efficient to render
+- On extremely memory constrained systems, index buffers for triangle strips could save a bit of memory
+
+This library provides an algorithm for converting a vertex cache optimized triangle list to a triangle strip:
+
+```c++
+std::vector<unsigned int> strip(meshopt_stripifyBound(index_count));
+size_t strip_size = meshopt_stripify(&strip[0], indices, index_count, vertex_count);
+```
+
+Typically you should expect triangle strips to have ~50-60% of indices compared to triangle lists (~1.5-1.8 indices per triangle) and have ~5% worse ACMR. Note that triangle strips require restart index support for rendering; using degenerate triangles to connect strips is not supported.
+
+## Deinterleaved geometry
+
+All of the examples above assume that geometry is represented as a single vertex buffer and a single index buffer. This requires storing all vertex attributes - position, normal, texture coordinate, skinning weights etc. - in a single contiguous struct. However, in some cases using multiple vertex streams may be preferable. In particular, if some passes require only positional data - such as depth pre-pass or shadow map - then it may be beneficial to split it from the rest of the vertex attributes to make sure the bandwidth use during these passes is optimal. On some mobile GPUs a position-only attribute stream also improves efficiency of tiling algorithms.
+
+Most of the functions in this library either only need the index buffer (such as vertex cache optimization) or only need positional information (such as overdraw optimization). However, several tasks require knowledge about all vertex attributes.
+
+For indexing, `meshopt_generateVertexRemap` assumes that there's just one vertex stream; when multiple vertex streams are used, it's necessary to use `meshopt_generateVertexRemapMulti` as follows:
+
+```c++
+meshopt_Stream streams[] = {
+    {&unindexed_pos[0], sizeof(float) * 3, sizeof(float) * 3},
+    {&unindexed_nrm[0], sizeof(float) * 3, sizeof(float) * 3},
+    {&unindexed_uv[0], sizeof(float) * 2, sizeof(float) * 2},
+};
+
+std::vector<unsigned int> remap(index_count);
+size_t vertex_count = meshopt_generateVertexRemapMulti(&remap[0], NULL, index_count, index_count, streams, sizeof(streams) / sizeof(streams[0]));
+```
+
+After this `meshopt_remapVertexBuffer` needs to be called once for each vertex stream to produce the correctly reindexed stream.
+
+Instead of calling `meshopt_optimizeVertexFetch` for reordering vertices in a single vertex buffer for efficiency, calling `meshopt_optimizeVertexFetchRemap` and then calling `meshopt_remapVertexBuffer` for each stream again is recommended.
+
+Finally, when compressing vertex data, `meshopt_encodeVertexBuffer` should be used on each vertex stream separately - this allows the encoder to best utilize corellation between attribute values for different vertices.
+
+## Simplification
+
+All algorithms presented so far don't affect visual appearance at all, with the exception of quantization that has minimal controlled impact. However, fundamentally the most effective way at reducing the rendering or transmission cost of a mesh is to make the mesh simpler.
+
+This library provides two simplification algorithms that reduce the number of triangles in the mesh. Given a vertex and an index buffer, they generate a second index buffer that uses existing vertices in the vertex buffer. This index buffer can be used directly for rendering with the original vertex buffer (preferably after vertex cache optimization), or a new compact vertex/index buffer can be generated using `meshopt_optimizeVertexFetch` that uses the optimal number and order of vertices.
+
+The first simplification algorithm, `meshopt_simplify`, follows the topology of the original mesh in an attempt to preserve attribute seams, borders and overall appearance. For meshes with inconsistent topology or many seams, such as faceted meshes, it can result in simplifier getting "stuck" and not being able to simplify the mesh fully; it's recommended to preprocess the index buffer with `meshopt_generateShadowIndexBuffer` to discard any vertex attributes that aren't critical and can be rebuilt later such as normals.
+
+```
+float threshold = 0.2f;
+size_t target_index_count = size_t(index_count * threshold);
+float target_error = 1e-2f;
+
+std::vector<unsigned int> lod(index_count);
+lod.resize(meshopt_simplify(&lod[0], indices, index_count, &vertices[0].x, vertex_count, sizeof(Vertex), target_index_count, target_error));
+```
+
+Target error is an approximate measure of the deviation from the original mesh using distance normalized to 0..1 (so 1e-2f means that simplifier will try to maintain the error to be below 1% of the mesh extents). Note that because of topological restrictions and error bounds simplifier isn't guaranteed to reach the target index count and can stop earlier.
+
+The second simplification algorithm, `meshopt_simplifySloppy`, doesn't follow the topology of the original mesh. This means that it doesn't preserve attribute seams or borders, but it can collapse internal details that are too small to matter better because it can merge mesh features that are topologically disjoint but spatially close.
+
+```
+float threshold = 0.2f;
+size_t target_index_count = size_t(index_count * threshold);
+
+std::vector<unsigned int> lod(target_index_count);
+lod.resize(meshopt_simplifySloppy(&lod[0], indices, index_count, &vertices[0].x, vertex_count, sizeof(Vertex), target_index_count));
+```
+
+This algorithm is guaranteed to return a result at or below the target index count. It is 5-6x faster than `meshopt_simplify` when simplification ratio is large, and is able to reach ~20M triangles/sec on a desktop CPU (`meshopt_simplify` works at ~3M triangles/sec).
+
+When a sequence of LOD meshes is generated that all use the original vertex buffer, care must be taken to order vertices optimally to not penalize mobile GPU architectures that are only capable of transforming a sequential vertex buffer range. It's recommended in this case to first optimize each LOD for vertex cache, then assemble all LODs in one large index buffer starting from the coarsest LOD (the one with fewest triangles), and call `meshopt_optimizeVertexFetch` on the final large index buffer. This will make sure that coarser LODs require a smaller vertex range and are efficient wrt vertex fetch and transform.
+
+## Efficiency analyzers
+
+While the only way to get precise performance data is to measure performance on the target GPU, it can be valuable to measure the impact of these optimization in a GPU-independent manner. To this end, the library provides analyzers for all three major optimization routines. For each optimization there is a corresponding analyze function, like `meshopt_analyzeOverdraw`, that returns a struct with statistics.
+
+`meshopt_analyzeVertexCache` returns vertex cache statistics. The common metric to use is ACMR - average cache miss ratio, which is the ratio of the total number of vertex invocations to the triangle count. The worst-case ACMR is 3 (GPU has to process 3 vertices for each triangle); on regular grids the optimal ACMR approaches 0.5. On real meshes it usually is in [0.5..1.5] range depending on the amount of vertex splits. One other useful metric is ATVR - average transformed vertex ratio - which represents the ratio of vertex shader invocations to the total vertices, and has the best case of 1.0 regardless of mesh topology (each vertex is transformed once).
+
+`meshopt_analyzeVertexFetch` returns vertex fetch statistics. The main metric it uses is overfetch - the ratio between the number of bytes read from the vertex buffer to the total number of bytes in the vertex buffer. Assuming non-redundant vertex buffers, the best case is 1.0 - each byte is fetched once.
+
+`meshopt_analyzeOverdraw` returns overdraw statistics. The main metric it uses is overdraw - the ratio between the number of pixel shader invocations to the total number of covered pixels, as measured from several different orthographic cameras. The best case for overdraw is 1.0 - each pixel is shaded once.
+
+Note that all analyzers use approximate models for the relevant GPU units, so the numbers you will get as the result are only a rough approximation of the actual performance.
+
+## Memory management
+
+Many algorithms allocate temporary memory to store intermediate results or accelerate processing. The amount of memory allocated is a function of various input parameters such as vertex count and index count. By default memory is allocated using `operator new` and `operator delete`; if these operators are overloaded by the application, the overloads will be used instead. Alternatively it's possible to specify custom allocation/deallocation functions using `meshopt_setAllocator`, e.g.
+
+```c++
+meshopt_setAllocator(malloc, free);
+```
+
+> Note that currently the library expects the allocation function to either throw in case of out-of-memory (in which case the exception will propagate to the caller) or abort, so technically the use of `malloc` above isn't safe.
+
+Vertex and index decoders (`meshopt_decodeVertexBuffer` and `meshopt_decodeIndexBuffer`) do not allocate memory and work completely within the buffer space provided via arguments.
+
+All functions have bounded stack usage that does not exceed 32 KB for any algorithms.
+
+## License
+
+This library is available to anybody free of charge, under the terms of MIT License (see LICENSE.md).

+ 10 - 0
3rdparty/meshoptimizer/codecov.yml

@@ -0,0 +1,10 @@
+comment: false
+
+coverage:
+  status:
+    project: off
+    patch: off
+
+ignore:
+  - demo
+  - tools

+ 2 - 0
3rdparty/meshoptimizer/demo/ansi.c

@@ -0,0 +1,2 @@
+/* This file makes sure the library can be used by C89 code */
+#include "../src/meshoptimizer.h"

+ 122 - 0
3rdparty/meshoptimizer/demo/index.html

@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>meshoptimizer - demo</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+			}
+			#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
+		</style>
+	</head>
+
+	<body>
+		<div id="info">
+		<a href="https://github.com/zeux/meshoptimizer" target="_blank" rel="noopener">meshoptimizer</a>
+		</div>
+
+		<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
+
+		<script src="../js/decoder.js"></script>
+		<script src="../tools/OptMeshLoader.js"></script>
+
+		<script>
+			var container;
+
+			var camera, scene, renderer;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			var timers = {};
+
+			console.time = function(label) {
+				timers[label] = performance.now();
+			};
+
+			console.timeEnd = function(label) {
+				var time = performance.now() - timers[label];
+				document.getElementById('info').append(label + " took " + time.toFixed(2) + " ms");
+			};
+
+			init();
+			animate();
+
+			function init()
+			{
+				container = document.createElement('div');
+				document.body.appendChild(container);
+
+				camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 100);
+				camera.position.y = 1.0;
+				camera.position.z = 3.0;
+
+				scene = new THREE.Scene();
+
+				var ambientLight = new THREE.AmbientLight(0xcccccc, 0.2);
+				scene.add(ambientLight);
+
+				var pointLight = new THREE.PointLight(0xffffff, 0.8);
+				pointLight.position.set(3, 3, 0);
+				camera.add(pointLight);
+				scene.add(camera);
+
+				var onProgress = function (xhr) {};
+				var onError = function () {};
+
+				new THREE.OptMeshLoader()
+					.setDecoder(MeshoptDecoder)
+					.setMaterials(null) // materials can be fetched using MTLLoader
+					.setPath('./')
+					.load('pirate.optmesh', function (object)
+					{
+						scene.add(object);
+					}, onProgress, onError);
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setPixelRatio(window.devicePixelRatio);
+				renderer.setSize(window.innerWidth, window.innerHeight);
+				container.appendChild(renderer.domElement);
+
+				window.addEventListener('resize', onWindowResize, false);
+			}
+
+			function onWindowResize()
+			{
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize(window.innerWidth, window.innerHeight);
+			}
+
+			function animate()
+			{
+				requestAnimationFrame(animate);
+				render();
+			}
+
+			function render()
+			{
+				renderer.render(scene, camera);
+			}
+		</script>
+	</body>
+</html>

+ 941 - 0
3rdparty/meshoptimizer/demo/main.cpp

@@ -0,0 +1,941 @@
+#include "../src/meshoptimizer.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <vector>
+
+#include "../tools/objparser.h"
+#include "miniz.h"
+
+// This file uses assert() to verify algorithm correctness
+#undef NDEBUG
+#include <assert.h>
+
+#if defined(__linux__)
+double timestamp()
+{
+	timespec ts;
+	clock_gettime(CLOCK_MONOTONIC, &ts);
+	return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec);
+}
+#elif defined(_WIN32)
+struct LARGE_INTEGER
+{
+	__int64 QuadPart;
+};
+extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount);
+extern "C" __declspec(dllimport) int __stdcall QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency);
+
+double timestamp()
+{
+	LARGE_INTEGER freq, counter;
+	QueryPerformanceFrequency(&freq);
+	QueryPerformanceCounter(&counter);
+	return double(counter.QuadPart) / double(freq.QuadPart);
+}
+#else
+double timestamp()
+{
+	return double(clock()) / double(CLOCKS_PER_SEC);
+}
+#endif
+
+const size_t kCacheSize = 16;
+
+struct Vertex
+{
+	float px, py, pz;
+	float nx, ny, nz;
+	float tx, ty;
+};
+
+struct Mesh
+{
+	std::vector<Vertex> vertices;
+	std::vector<unsigned int> indices;
+};
+
+union Triangle {
+	Vertex v[3];
+	char data[sizeof(Vertex) * 3];
+};
+
+Mesh parseObj(const char* path, double& reindex)
+{
+	ObjFile file;
+
+	if (!objParseFile(file, path))
+	{
+		printf("Error loading %s: file not found\n", path);
+		return Mesh();
+	}
+
+	if (!objValidate(file))
+	{
+		printf("Error loading %s: invalid file data\n", path);
+		return Mesh();
+	}
+
+	size_t total_indices = file.f_size / 3;
+
+	std::vector<Vertex> vertices(total_indices);
+
+	for (size_t i = 0; i < total_indices; ++i)
+	{
+		int vi = file.f[i * 3 + 0];
+		int vti = file.f[i * 3 + 1];
+		int vni = file.f[i * 3 + 2];
+
+		Vertex v =
+		    {
+		        file.v[vi * 3 + 0],
+		        file.v[vi * 3 + 1],
+		        file.v[vi * 3 + 2],
+
+		        vni >= 0 ? file.vn[vni * 3 + 0] : 0,
+		        vni >= 0 ? file.vn[vni * 3 + 1] : 0,
+		        vni >= 0 ? file.vn[vni * 3 + 2] : 0,
+
+		        vti >= 0 ? file.vt[vti * 3 + 0] : 0,
+		        vti >= 0 ? file.vt[vti * 3 + 1] : 0,
+		    };
+
+		vertices[i] = v;
+	}
+
+	reindex = timestamp();
+
+	Mesh result;
+
+	std::vector<unsigned int> remap(total_indices);
+
+	size_t total_vertices = meshopt_generateVertexRemap(&remap[0], NULL, total_indices, &vertices[0], total_indices, sizeof(Vertex));
+
+	result.indices.resize(total_indices);
+	meshopt_remapIndexBuffer(&result.indices[0], NULL, total_indices, &remap[0]);
+
+	result.vertices.resize(total_vertices);
+	meshopt_remapVertexBuffer(&result.vertices[0], &vertices[0], total_indices, sizeof(Vertex), &remap[0]);
+
+	return result;
+}
+
+bool isMeshValid(const Mesh& mesh)
+{
+	size_t index_count = mesh.indices.size();
+	size_t vertex_count = mesh.vertices.size();
+
+	if (index_count % 3 != 0)
+		return false;
+
+	const unsigned int* indices = &mesh.indices[0];
+
+	for (size_t i = 0; i < index_count; ++i)
+		if (indices[i] >= vertex_count)
+			return false;
+
+	return true;
+}
+
+bool rotateTriangle(Triangle& t)
+{
+	int c01 = memcmp(&t.v[0], &t.v[1], sizeof(Vertex));
+	int c02 = memcmp(&t.v[0], &t.v[2], sizeof(Vertex));
+	int c12 = memcmp(&t.v[1], &t.v[2], sizeof(Vertex));
+
+	if (c12 < 0 && c01 > 0)
+	{
+		// 1 is minimum, rotate 012 => 120
+		Vertex tv = t.v[0];
+		t.v[0] = t.v[1], t.v[1] = t.v[2], t.v[2] = tv;
+	}
+	else if (c02 > 0 && c12 > 0)
+	{
+		// 2 is minimum, rotate 012 => 201
+		Vertex tv = t.v[2];
+		t.v[2] = t.v[1], t.v[1] = t.v[0], t.v[0] = tv;
+	}
+
+	return c01 != 0 && c02 != 0 && c12 != 0;
+}
+
+unsigned int hashRange(const char* key, size_t len)
+{
+	// MurmurHash2
+	const unsigned int m = 0x5bd1e995;
+	const int r = 24;
+
+	unsigned int h = 0;
+
+	while (len >= 4)
+	{
+		unsigned int k = *reinterpret_cast<const unsigned int*>(key);
+
+		k *= m;
+		k ^= k >> r;
+		k *= m;
+
+		h *= m;
+		h ^= k;
+
+		key += 4;
+		len -= 4;
+	}
+
+	return h;
+}
+
+unsigned int hashMesh(const Mesh& mesh)
+{
+	size_t triangle_count = mesh.indices.size() / 3;
+
+	const Vertex* vertices = &mesh.vertices[0];
+	const unsigned int* indices = &mesh.indices[0];
+
+	unsigned int h1 = 0;
+	unsigned int h2 = 0;
+
+	for (size_t i = 0; i < triangle_count; ++i)
+	{
+		Triangle t;
+		t.v[0] = vertices[indices[i * 3 + 0]];
+		t.v[1] = vertices[indices[i * 3 + 1]];
+		t.v[2] = vertices[indices[i * 3 + 2]];
+
+		// skip degenerate triangles since some algorithms don't preserve them
+		if (rotateTriangle(t))
+		{
+			unsigned int hash = hashRange(t.data, sizeof(t.data));
+
+			h1 ^= hash;
+			h2 += hash;
+		}
+	}
+
+	return h1 * 0x5bd1e995 + h2;
+}
+
+void optNone(Mesh& mesh)
+{
+	(void)mesh;
+}
+
+void optRandomShuffle(Mesh& mesh)
+{
+	size_t triangle_count = mesh.indices.size() / 3;
+
+	unsigned int* indices = &mesh.indices[0];
+
+	unsigned int rng = 0;
+
+	for (size_t i = triangle_count - 1; i > 0; --i)
+	{
+		// Fisher-Yates shuffle
+		size_t j = rng % (i + 1);
+
+		unsigned int t;
+		t = indices[3 * j + 0], indices[3 * j + 0] = indices[3 * i + 0], indices[3 * i + 0] = t;
+		t = indices[3 * j + 1], indices[3 * j + 1] = indices[3 * i + 1], indices[3 * i + 1] = t;
+		t = indices[3 * j + 2], indices[3 * j + 2] = indices[3 * i + 2], indices[3 * i + 2] = t;
+
+		// LCG RNG, constants from Numerical Recipes
+		rng = rng * 1664525 + 1013904223;
+	}
+}
+
+void optCache(Mesh& mesh)
+{
+	meshopt_optimizeVertexCache(&mesh.indices[0], &mesh.indices[0], mesh.indices.size(), mesh.vertices.size());
+}
+
+void optCacheFifo(Mesh& mesh)
+{
+	meshopt_optimizeVertexCacheFifo(&mesh.indices[0], &mesh.indices[0], mesh.indices.size(), mesh.vertices.size(), kCacheSize);
+}
+
+void optOverdraw(Mesh& mesh)
+{
+	// use worst-case ACMR threshold so that overdraw optimizer can sort *all* triangles
+	// warning: this significantly deteriorates the vertex cache efficiency so it is not advised; look at optComplete for the recommended method
+	const float kThreshold = 3.f;
+	meshopt_optimizeOverdraw(&mesh.indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), kThreshold);
+}
+
+void optFetch(Mesh& mesh)
+{
+	meshopt_optimizeVertexFetch(&mesh.vertices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0], mesh.vertices.size(), sizeof(Vertex));
+}
+
+void optFetchRemap(Mesh& mesh)
+{
+	// this produces results equivalent to optFetch, but can be used to remap multiple vertex streams
+	std::vector<unsigned int> remap(mesh.vertices.size());
+	meshopt_optimizeVertexFetchRemap(&remap[0], &mesh.indices[0], mesh.indices.size(), mesh.vertices.size());
+
+	meshopt_remapIndexBuffer(&mesh.indices[0], &mesh.indices[0], mesh.indices.size(), &remap[0]);
+	meshopt_remapVertexBuffer(&mesh.vertices[0], &mesh.vertices[0], mesh.vertices.size(), sizeof(Vertex), &remap[0]);
+}
+
+void optComplete(Mesh& mesh)
+{
+	// vertex cache optimization should go first as it provides starting order for overdraw
+	meshopt_optimizeVertexCache(&mesh.indices[0], &mesh.indices[0], mesh.indices.size(), mesh.vertices.size());
+
+	// reorder indices for overdraw, balancing overdraw and vertex cache efficiency
+	const float kThreshold = 1.01f; // allow up to 1% worse ACMR to get more reordering opportunities for overdraw
+	meshopt_optimizeOverdraw(&mesh.indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), kThreshold);
+
+	// vertex fetch optimization should go last as it depends on the final index order
+	meshopt_optimizeVertexFetch(&mesh.vertices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0], mesh.vertices.size(), sizeof(Vertex));
+}
+
+struct PackedVertex
+{
+	unsigned short px, py, pz;
+	unsigned short pw; // padding to 4b boundary
+	signed char nx, ny, nz, nw;
+	unsigned short tx, ty;
+};
+
+void packMesh(std::vector<PackedVertex>& pv, const std::vector<Vertex>& vertices)
+{
+	for (size_t i = 0; i < vertices.size(); ++i)
+	{
+		const Vertex& vi = vertices[i];
+		PackedVertex& pvi = pv[i];
+
+		pvi.px = meshopt_quantizeHalf(vi.px);
+		pvi.py = meshopt_quantizeHalf(vi.py);
+		pvi.pz = meshopt_quantizeHalf(vi.pz);
+		pvi.pw = 0;
+
+		pvi.nx = char(meshopt_quantizeSnorm(vi.nx, 8));
+		pvi.ny = char(meshopt_quantizeSnorm(vi.ny, 8));
+		pvi.nz = char(meshopt_quantizeSnorm(vi.nz, 8));
+		pvi.nw = 0;
+
+		pvi.tx = meshopt_quantizeHalf(vi.tx);
+		pvi.ty = meshopt_quantizeHalf(vi.ty);
+	}
+}
+
+struct PackedVertexOct
+{
+	unsigned short px, py, pz;
+	signed char nu, nv; // octahedron encoded normal, aliases .pw
+	unsigned short tx, ty;
+};
+
+void packMesh(std::vector<PackedVertexOct>& pv, const std::vector<Vertex>& vertices)
+{
+	for (size_t i = 0; i < vertices.size(); ++i)
+	{
+		const Vertex& vi = vertices[i];
+		PackedVertexOct& pvi = pv[i];
+
+		pvi.px = meshopt_quantizeHalf(vi.px);
+		pvi.py = meshopt_quantizeHalf(vi.py);
+		pvi.pz = meshopt_quantizeHalf(vi.pz);
+
+		float nsum = fabsf(vi.nx) + fabsf(vi.ny) + fabsf(vi.nz);
+		float nx = vi.nx / nsum;
+		float ny = vi.ny / nsum;
+		float nz = vi.nz;
+
+		float nu = nz >= 0 ? nx : (1 - fabsf(ny)) * (nx >= 0 ? 1 : -1);
+		float nv = nz >= 0 ? ny : (1 - fabsf(nx)) * (ny >= 0 ? 1 : -1);
+
+		pvi.nu = char(meshopt_quantizeSnorm(nu, 8));
+		pvi.nv = char(meshopt_quantizeSnorm(nv, 8));
+
+		pvi.tx = meshopt_quantizeHalf(vi.tx);
+		pvi.ty = meshopt_quantizeHalf(vi.ty);
+	}
+}
+
+void simplify(const Mesh& mesh, float threshold = 0.2f)
+{
+	Mesh lod;
+
+	double start = timestamp();
+
+	size_t target_index_count = size_t(mesh.indices.size() * threshold);
+	float target_error = 1e-2f;
+
+	lod.indices.resize(mesh.indices.size()); // note: simplify needs space for index_count elements in the destination array, not target_index_count
+	lod.indices.resize(meshopt_simplify(&lod.indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_index_count, target_error));
+
+	lod.vertices.resize(lod.indices.size() < mesh.vertices.size() ? lod.indices.size() : mesh.vertices.size()); // note: this is just to reduce the cost of resize()
+	lod.vertices.resize(meshopt_optimizeVertexFetch(&lod.vertices[0], &lod.indices[0], lod.indices.size(), &mesh.vertices[0], mesh.vertices.size(), sizeof(Vertex)));
+
+	double end = timestamp();
+
+	printf("%-9s: %d triangles => %d triangles in %.2f msec\n",
+	       "Simplify",
+	       int(mesh.indices.size() / 3), int(lod.indices.size() / 3), (end - start) * 1000);
+}
+
+void simplifySloppy(const Mesh& mesh, float threshold = 0.2f)
+{
+	Mesh lod;
+
+	double start = timestamp();
+
+	size_t target_index_count = size_t(mesh.indices.size() * threshold);
+
+	lod.indices.resize(target_index_count); // note: simplifySloppy, unlike simplify, is guaranteed to output results that don't exceed the requested target_index_count
+	lod.indices.resize(meshopt_simplifySloppy(&lod.indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_index_count));
+
+	lod.vertices.resize(lod.indices.size() < mesh.vertices.size() ? lod.indices.size() : mesh.vertices.size()); // note: this is just to reduce the cost of resize()
+	lod.vertices.resize(meshopt_optimizeVertexFetch(&lod.vertices[0], &lod.indices[0], lod.indices.size(), &mesh.vertices[0], mesh.vertices.size(), sizeof(Vertex)));
+
+	double end = timestamp();
+
+	printf("%-9s: %d triangles => %d triangles in %.2f msec\n",
+	       "SimplifyS",
+	       int(mesh.indices.size() / 3), int(lod.indices.size() / 3), (end - start) * 1000);
+}
+
+void simplifyComplete(const Mesh& mesh)
+{
+	static const size_t lod_count = 5;
+
+	double start = timestamp();
+
+	// generate 4 LOD levels (1-4), with each subsequent LOD using 70% triangles
+	// note that each LOD uses the same (shared) vertex buffer
+	std::vector<unsigned int> lods[lod_count];
+
+	lods[0] = mesh.indices;
+
+	for (size_t i = 1; i < lod_count; ++i)
+	{
+		std::vector<unsigned int>& lod = lods[i];
+
+		float threshold = powf(0.7f, float(i));
+		size_t target_index_count = size_t(mesh.indices.size() * threshold) / 3 * 3;
+		float target_error = 1e-2f;
+
+		// we can simplify all the way from base level or from the last result
+		// simplifying from the base level sometimes produces better results, but simplifying from last level is faster
+		const std::vector<unsigned int>& source = lods[i - 1];
+
+		if (source.size() < target_index_count)
+			target_index_count = source.size();
+
+		lod.resize(source.size());
+		lod.resize(meshopt_simplify(&lod[0], &source[0], source.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_index_count, target_error));
+	}
+
+	double middle = timestamp();
+
+	// optimize each individual LOD for vertex cache & overdraw
+	for (size_t i = 0; i < lod_count; ++i)
+	{
+		std::vector<unsigned int>& lod = lods[i];
+
+		meshopt_optimizeVertexCache(&lod[0], &lod[0], lod.size(), mesh.vertices.size());
+		meshopt_optimizeOverdraw(&lod[0], &lod[0], lod.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), 1.0f);
+	}
+
+	// concatenate all LODs into one IB
+	// note: the order of concatenation is important - since we optimize the entire IB for vertex fetch,
+	// putting coarse LODs first makes sure that the vertex range referenced by them is as small as possible
+	// some GPUs process the entire range referenced by the index buffer region so doing this optimizes the vertex transform
+	// cost for coarse LODs
+	// this order also produces much better vertex fetch cache coherency for coarse LODs (since they're essentially optimized first)
+	// somewhat surprisingly, the vertex fetch cache coherency for fine LODs doesn't seem to suffer that much.
+	size_t lod_index_offsets[lod_count] = {};
+	size_t lod_index_counts[lod_count] = {};
+	size_t total_index_count = 0;
+
+	for (int i = lod_count - 1; i >= 0; --i)
+	{
+		lod_index_offsets[i] = total_index_count;
+		lod_index_counts[i] = lods[i].size();
+
+		total_index_count += lods[i].size();
+	}
+
+	std::vector<unsigned int> indices(total_index_count);
+
+	for (size_t i = 0; i < lod_count; ++i)
+	{
+		memcpy(&indices[lod_index_offsets[i]], &lods[i][0], lods[i].size() * sizeof(lods[i][0]));
+	}
+
+	std::vector<Vertex> vertices = mesh.vertices;
+
+	// vertex fetch optimization should go last as it depends on the final index order
+	// note that the order of LODs above affects vertex fetch results
+	meshopt_optimizeVertexFetch(&vertices[0], &indices[0], indices.size(), &vertices[0], vertices.size(), sizeof(Vertex));
+
+	double end = timestamp();
+
+	printf("%-9s: %d triangles => %d LOD levels down to %d triangles in %.2f msec, optimized in %.2f msec\n",
+	       "SimplifyC",
+	       int(lod_index_counts[0]) / 3, int(lod_count), int(lod_index_counts[lod_count - 1]) / 3,
+	       (middle - start) * 1000, (end - middle) * 1000);
+
+	// for using LOD data at runtime, in addition to vertices and indices you have to save lod_index_offsets/lod_index_counts.
+
+	{
+		meshopt_VertexCacheStatistics vcs0 = meshopt_analyzeVertexCache(&indices[lod_index_offsets[0]], lod_index_counts[0], vertices.size(), kCacheSize, 0, 0);
+		meshopt_VertexFetchStatistics vfs0 = meshopt_analyzeVertexFetch(&indices[lod_index_offsets[0]], lod_index_counts[0], vertices.size(), sizeof(Vertex));
+		meshopt_VertexCacheStatistics vcsN = meshopt_analyzeVertexCache(&indices[lod_index_offsets[lod_count - 1]], lod_index_counts[lod_count - 1], vertices.size(), kCacheSize, 0, 0);
+		meshopt_VertexFetchStatistics vfsN = meshopt_analyzeVertexFetch(&indices[lod_index_offsets[lod_count - 1]], lod_index_counts[lod_count - 1], vertices.size(), sizeof(Vertex));
+
+		typedef PackedVertexOct PV;
+
+		std::vector<PV> pv(vertices.size());
+		packMesh(pv, vertices);
+
+		std::vector<unsigned char> vbuf(meshopt_encodeVertexBufferBound(vertices.size(), sizeof(PV)));
+		vbuf.resize(meshopt_encodeVertexBuffer(&vbuf[0], vbuf.size(), &pv[0], vertices.size(), sizeof(PV)));
+
+		std::vector<unsigned char> ibuf(meshopt_encodeIndexBufferBound(indices.size(), vertices.size()));
+		ibuf.resize(meshopt_encodeIndexBuffer(&ibuf[0], ibuf.size(), &indices[0], indices.size()));
+
+		printf("%-9s  ACMR %f...%f Overfetch %f..%f Codec VB %.1f bits/vertex IB %.1f bits/triangle\n",
+		       "",
+		       vcs0.acmr, vcsN.acmr, vfs0.overfetch, vfsN.overfetch,
+		       double(vbuf.size()) / double(vertices.size()) * 8,
+		       double(ibuf.size()) / double(indices.size() / 3) * 8);
+	}
+}
+
+void optimize(const Mesh& mesh, const char* name, void (*optf)(Mesh& mesh))
+{
+	Mesh copy = mesh;
+
+	double start = timestamp();
+	optf(copy);
+	double end = timestamp();
+
+	assert(isMeshValid(copy));
+	assert(hashMesh(mesh) == hashMesh(copy));
+
+	meshopt_VertexCacheStatistics vcs = meshopt_analyzeVertexCache(&copy.indices[0], copy.indices.size(), copy.vertices.size(), kCacheSize, 0, 0);
+	meshopt_VertexFetchStatistics vfs = meshopt_analyzeVertexFetch(&copy.indices[0], copy.indices.size(), copy.vertices.size(), sizeof(Vertex));
+	meshopt_OverdrawStatistics os = meshopt_analyzeOverdraw(&copy.indices[0], copy.indices.size(), &copy.vertices[0].px, copy.vertices.size(), sizeof(Vertex));
+
+	meshopt_VertexCacheStatistics vcs_nv = meshopt_analyzeVertexCache(&copy.indices[0], copy.indices.size(), copy.vertices.size(), 32, 32, 32);
+	meshopt_VertexCacheStatistics vcs_amd = meshopt_analyzeVertexCache(&copy.indices[0], copy.indices.size(), copy.vertices.size(), 14, 64, 128);
+	meshopt_VertexCacheStatistics vcs_intel = meshopt_analyzeVertexCache(&copy.indices[0], copy.indices.size(), copy.vertices.size(), 128, 0, 0);
+
+	printf("%-9s: ACMR %f ATVR %f (NV %f AMD %f Intel %f) Overfetch %f Overdraw %f in %.2f msec\n", name, vcs.acmr, vcs.atvr, vcs_nv.atvr, vcs_amd.atvr, vcs_intel.atvr, vfs.overfetch, os.overdraw, (end - start) * 1000);
+}
+
+template <typename T>
+size_t compress(const std::vector<T>& data)
+{
+	std::vector<unsigned char> cbuf(tdefl_compress_bound(data.size() * sizeof(T)));
+	unsigned int flags = tdefl_create_comp_flags_from_zip_params(MZ_DEFAULT_LEVEL, 15, MZ_DEFAULT_STRATEGY);
+	return tdefl_compress_mem_to_mem(&cbuf[0], cbuf.size(), &data[0], data.size() * sizeof(T), flags);
+}
+
+void encodeIndex(const Mesh& mesh)
+{
+	// allocate result outside of the timing loop to exclude memset() from decode timing
+	std::vector<unsigned int> result(mesh.indices.size());
+
+	double start = timestamp();
+
+	std::vector<unsigned char> buffer(meshopt_encodeIndexBufferBound(mesh.indices.size(), mesh.vertices.size()));
+	buffer.resize(meshopt_encodeIndexBuffer(&buffer[0], buffer.size(), &mesh.indices[0], mesh.indices.size()));
+
+	double middle = timestamp();
+
+	int res = meshopt_decodeIndexBuffer(&result[0], mesh.indices.size(), &buffer[0], buffer.size());
+	assert(res == 0);
+	(void)res;
+
+	double end = timestamp();
+
+	size_t csize = compress(buffer);
+
+	for (size_t i = 0; i < mesh.indices.size(); i += 3)
+	{
+		assert(
+		    (result[i + 0] == mesh.indices[i + 0] && result[i + 1] == mesh.indices[i + 1] && result[i + 2] == mesh.indices[i + 2]) ||
+		    (result[i + 1] == mesh.indices[i + 0] && result[i + 2] == mesh.indices[i + 1] && result[i + 0] == mesh.indices[i + 2]) ||
+		    (result[i + 2] == mesh.indices[i + 0] && result[i + 0] == mesh.indices[i + 1] && result[i + 1] == mesh.indices[i + 2]));
+	}
+
+	printf("IdxCodec : %.1f bits/triangle (post-deflate %.1f bits/triangle); encode %.2f msec, decode %.2f msec (%.2f GB/s)\n",
+	       double(buffer.size() * 8) / double(mesh.indices.size() / 3),
+	       double(csize * 8) / double(mesh.indices.size() / 3),
+	       (middle - start) * 1000,
+	       (end - middle) * 1000,
+	       (double(result.size() * 4) / (1 << 30)) / (end - middle));
+}
+
+template <typename PV>
+void packVertex(const Mesh& mesh, const char* pvn)
+{
+	std::vector<PV> pv(mesh.vertices.size());
+	packMesh(pv, mesh.vertices);
+
+	size_t csize = compress(pv);
+
+	printf("VtxPack%s  : %.1f bits/vertex (post-deflate %.1f bits/vertex)\n", pvn,
+	       double(pv.size() * sizeof(PV) * 8) / double(mesh.vertices.size()),
+	       double(csize * 8) / double(mesh.vertices.size()));
+}
+
+template <typename PV>
+void encodeVertex(const Mesh& mesh, const char* pvn)
+{
+	std::vector<PV> pv(mesh.vertices.size());
+	packMesh(pv, mesh.vertices);
+
+	// allocate result outside of the timing loop to exclude memset() from decode timing
+	std::vector<PV> result(mesh.vertices.size());
+
+	double start = timestamp();
+
+	std::vector<unsigned char> vbuf(meshopt_encodeVertexBufferBound(mesh.vertices.size(), sizeof(PV)));
+	vbuf.resize(meshopt_encodeVertexBuffer(&vbuf[0], vbuf.size(), &pv[0], mesh.vertices.size(), sizeof(PV)));
+
+	double middle = timestamp();
+
+	int res = meshopt_decodeVertexBuffer(&result[0], mesh.vertices.size(), sizeof(PV), &vbuf[0], vbuf.size());
+	assert(res == 0);
+	(void)res;
+
+	double end = timestamp();
+
+	assert(memcmp(&pv[0], &result[0], pv.size() * sizeof(PV)) == 0);
+
+	size_t csize = compress(vbuf);
+
+	printf("VtxCodec%1s: %.1f bits/vertex (post-deflate %.1f bits/vertex); encode %.2f msec, decode %.2f msec (%.2f GB/s)\n", pvn,
+	       double(vbuf.size() * 8) / double(mesh.vertices.size()),
+	       double(csize * 8) / double(mesh.vertices.size()),
+	       (middle - start) * 1000,
+	       (end - middle) * 1000,
+	       (double(result.size() * sizeof(PV)) / (1 << 30)) / (end - middle));
+}
+
+void stripify(const Mesh& mesh)
+{
+	// note: input mesh is assumed to be optimized for vertex cache and vertex fetch
+	double start = timestamp();
+	std::vector<unsigned int> strip(meshopt_stripifyBound(mesh.indices.size()));
+	strip.resize(meshopt_stripify(&strip[0], &mesh.indices[0], mesh.indices.size(), mesh.vertices.size()));
+	double end = timestamp();
+
+	Mesh copy = mesh;
+	copy.indices.resize(meshopt_unstripify(&copy.indices[0], &strip[0], strip.size()));
+	assert(copy.indices.size() <= meshopt_unstripifyBound(strip.size()));
+
+	assert(isMeshValid(copy));
+	assert(hashMesh(mesh) == hashMesh(copy));
+
+	meshopt_VertexCacheStatistics vcs = meshopt_analyzeVertexCache(&copy.indices[0], mesh.indices.size(), mesh.vertices.size(), kCacheSize, 0, 0);
+	meshopt_VertexCacheStatistics vcs_nv = meshopt_analyzeVertexCache(&copy.indices[0], mesh.indices.size(), mesh.vertices.size(), 32, 32, 32);
+	meshopt_VertexCacheStatistics vcs_amd = meshopt_analyzeVertexCache(&copy.indices[0], mesh.indices.size(), mesh.vertices.size(), 14, 64, 128);
+	meshopt_VertexCacheStatistics vcs_intel = meshopt_analyzeVertexCache(&copy.indices[0], mesh.indices.size(), mesh.vertices.size(), 128, 0, 0);
+
+	printf("Stripify : ACMR %f ATVR %f (NV %f AMD %f Intel %f); %d strip indices (%.1f%%) in %.2f msec\n",
+	       vcs.acmr, vcs.atvr, vcs_nv.atvr, vcs_amd.atvr, vcs_intel.atvr,
+	       int(strip.size()), double(strip.size()) / double(mesh.indices.size()) * 100,
+	       (end - start) * 1000);
+}
+
+void shadow(const Mesh& mesh)
+{
+	// note: input mesh is assumed to be optimized for vertex cache and vertex fetch
+
+	double start = timestamp();
+	// this index buffer can be used for position-only rendering using the same vertex data that the original index buffer uses
+	std::vector<unsigned int> shadow_indices(mesh.indices.size());
+	meshopt_generateShadowIndexBuffer(&shadow_indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0], mesh.vertices.size(), sizeof(float) * 3, sizeof(Vertex));
+	double end = timestamp();
+
+	// while you can't optimize the vertex data after shadow IB was constructed, you can and should optimize the shadow IB for vertex cache
+	// this is valuable even if the original indices array was optimized for vertex cache!
+	meshopt_optimizeVertexCache(&shadow_indices[0], &shadow_indices[0], shadow_indices.size(), mesh.vertices.size());
+
+	meshopt_VertexCacheStatistics vcs = meshopt_analyzeVertexCache(&mesh.indices[0], mesh.indices.size(), mesh.vertices.size(), kCacheSize, 0, 0);
+	meshopt_VertexCacheStatistics vcss = meshopt_analyzeVertexCache(&shadow_indices[0], shadow_indices.size(), mesh.vertices.size(), kCacheSize, 0, 0);
+
+	std::vector<char> shadow_flags(mesh.vertices.size());
+	size_t shadow_vertices = 0;
+
+	for (size_t i = 0; i < shadow_indices.size(); ++i)
+	{
+		unsigned int index = shadow_indices[i];
+		shadow_vertices += 1 - shadow_flags[index];
+		shadow_flags[index] = 1;
+	}
+
+	printf("ShadowIB : ACMR %f (%.2fx improvement); %d shadow vertices (%.2fx improvement) in %.2f msec\n",
+	       vcss.acmr, double(vcs.vertices_transformed) / double(vcss.vertices_transformed),
+	       int(shadow_vertices), double(mesh.vertices.size()) / double(shadow_vertices),
+	       (end - start) * 1000);
+}
+
+void meshlets(const Mesh& mesh)
+{
+	const size_t max_vertices = 64;
+	const size_t max_triangles = 126;
+
+	// note: input mesh is assumed to be optimized for vertex cache and vertex fetch
+	double start = timestamp();
+	std::vector<meshopt_Meshlet> meshlets(meshopt_buildMeshletsBound(mesh.indices.size(), max_vertices, max_triangles));
+	meshlets.resize(meshopt_buildMeshlets(&meshlets[0], &mesh.indices[0], mesh.indices.size(), mesh.vertices.size(), max_vertices, max_triangles));
+	double end = timestamp();
+
+	double avg_vertices = 0;
+	double avg_triangles = 0;
+	size_t not_full = 0;
+
+	for (size_t i = 0; i < meshlets.size(); ++i)
+	{
+		const meshopt_Meshlet& m = meshlets[i];
+
+		avg_vertices += m.vertex_count;
+		avg_triangles += m.triangle_count;
+		not_full += m.vertex_count < max_vertices;
+	}
+
+	avg_vertices /= double(meshlets.size());
+	avg_triangles /= double(meshlets.size());
+
+	printf("Meshlets : %d meshlets (avg vertices %.1f, avg triangles %.1f, not full %d) in %.2f msec\n",
+	       int(meshlets.size()), avg_vertices, avg_triangles, int(not_full), (end - start) * 1000);
+
+	float camera[3] = {100, 100, 100};
+
+	size_t rejected = 0;
+	size_t rejected_s8 = 0;
+	size_t rejected_alt = 0;
+	size_t rejected_alt_s8 = 0;
+	size_t accepted = 0;
+	size_t accepted_s8 = 0;
+
+	double startc = timestamp();
+	for (size_t i = 0; i < meshlets.size(); ++i)
+	{
+		meshopt_Bounds bounds = meshopt_computeMeshletBounds(&meshlets[i], &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex));
+
+		// trivial accept: we can't ever backface cull this meshlet
+		accepted += (bounds.cone_cutoff >= 1);
+		accepted_s8 += (bounds.cone_cutoff_s8 >= 127);
+
+		// perspective projection: dot(normalize(cone_apex - camera_position), cone_axis) > cone_cutoff
+		float mview[3] = {bounds.cone_apex[0] - camera[0], bounds.cone_apex[1] - camera[1], bounds.cone_apex[2] - camera[2]};
+		float mviewlength = sqrtf(mview[0] * mview[0] + mview[1] * mview[1] + mview[2] * mview[2]);
+
+		rejected += mview[0] * bounds.cone_axis[0] + mview[1] * bounds.cone_axis[1] + mview[2] * bounds.cone_axis[2] >= bounds.cone_cutoff * mviewlength;
+		rejected_s8 += mview[0] * (bounds.cone_axis_s8[0] / 127.f) + mview[1] * (bounds.cone_axis_s8[1] / 127.f) + mview[2] * (bounds.cone_axis_s8[2] / 127.f) >= (bounds.cone_cutoff_s8 / 127.f) * mviewlength;
+
+		// alternative formulation for perspective projection that doesn't use apex (and uses cluster bounding sphere instead):
+		// dot(normalize(center - camera_position), cone_axis) > cone_cutoff + radius / length(center - camera_position)
+		float cview[3] = {bounds.center[0] - camera[0], bounds.center[1] - camera[1], bounds.center[2] - camera[2]};
+		float cviewlength = sqrtf(cview[0] * cview[0] + cview[1] * cview[1] + cview[2] * cview[2]);
+
+		rejected_alt += cview[0] * bounds.cone_axis[0] + cview[1] * bounds.cone_axis[1] + cview[2] * bounds.cone_axis[2] >= bounds.cone_cutoff * cviewlength + bounds.radius;
+		rejected_alt_s8 += cview[0] * (bounds.cone_axis_s8[0] / 127.f) + cview[1] * (bounds.cone_axis_s8[1] / 127.f) + cview[2] * (bounds.cone_axis_s8[2] / 127.f) >= (bounds.cone_cutoff_s8 / 127.f) * cviewlength + bounds.radius;
+	}
+	double endc = timestamp();
+
+	printf("ConeCull : rejected apex %d (%.1f%%) / center %d (%.1f%%), trivially accepted %d (%.1f%%) in %.2f msec\n",
+	       int(rejected), double(rejected) / double(meshlets.size()) * 100,
+	       int(rejected_alt), double(rejected_alt) / double(meshlets.size()) * 100,
+	       int(accepted), double(accepted) / double(meshlets.size()) * 100,
+	       (endc - startc) * 1000);
+	printf("ConeCull8: rejected apex %d (%.1f%%) / center %d (%.1f%%), trivially accepted %d (%.1f%%) in %.2f msec\n",
+	       int(rejected_s8), double(rejected_s8) / double(meshlets.size()) * 100,
+	       int(rejected_alt_s8), double(rejected_alt_s8) / double(meshlets.size()) * 100,
+	       int(accepted_s8), double(accepted_s8) / double(meshlets.size()) * 100,
+	       (endc - startc) * 1000);
+}
+
+bool loadMesh(Mesh& mesh, const char* path)
+{
+	double start = timestamp();
+	double middle;
+	mesh = parseObj(path, middle);
+	double end = timestamp();
+
+	if (mesh.vertices.empty())
+	{
+		printf("Mesh %s is empty, skipping\n", path);
+		return false;
+	}
+
+	printf("# %s: %d vertices, %d triangles; read in %.2f msec; indexed in %.2f msec\n", path, int(mesh.vertices.size()), int(mesh.indices.size() / 3), (middle - start) * 1000, (end - middle) * 1000);
+	return true;
+}
+
+void processDeinterleaved(const char* path)
+{
+	// Most algorithms in the library work out of the box with deinterleaved geometry, but some require slightly special treatment;
+	// this code runs a simplified version of complete opt. pipeline using deinterleaved geo. There's no compression performed but you
+	// can trivially run it by quantizing all elements and running meshopt_encodeVertexBuffer once for each vertex stream.
+	ObjFile file;
+	if (!objParseFile(file, path) || !objValidate(file))
+	{
+		printf("Error loading %s: file not found or invalid file data\n", path);
+		return;
+	}
+
+	size_t total_indices = file.f_size / 3;
+
+	std::vector<float> unindexed_pos(total_indices * 3);
+	std::vector<float> unindexed_nrm(total_indices * 3);
+	std::vector<float> unindexed_uv(total_indices * 2);
+
+	for (size_t i = 0; i < total_indices; ++i)
+	{
+		int vi = file.f[i * 3 + 0];
+		int vti = file.f[i * 3 + 1];
+		int vni = file.f[i * 3 + 2];
+
+		unindexed_pos[i * 3 + 0] = file.v[vi * 3 + 0];
+		unindexed_pos[i * 3 + 1] = file.v[vi * 3 + 1];
+		unindexed_pos[i * 3 + 2] = file.v[vi * 3 + 2];
+
+		if (vni >= 0)
+		{
+			unindexed_nrm[i * 3 + 0] = file.vn[vni * 3 + 0];
+			unindexed_nrm[i * 3 + 1] = file.vn[vni * 3 + 1];
+			unindexed_nrm[i * 3 + 2] = file.vn[vni * 3 + 2];
+		}
+
+		if (vti >= 0)
+		{
+			unindexed_uv[i * 2 + 0] = file.vt[vti * 3 + 0];
+			unindexed_uv[i * 2 + 1] = file.vt[vti * 3 + 1];
+		}
+	}
+
+	double start = timestamp();
+
+	meshopt_Stream streams[] = {
+	    {&unindexed_pos[0], sizeof(float) * 3, sizeof(float) * 3},
+	    {&unindexed_nrm[0], sizeof(float) * 3, sizeof(float) * 3},
+	    {&unindexed_uv[0], sizeof(float) * 2, sizeof(float) * 2},
+	};
+
+	std::vector<unsigned int> remap(total_indices);
+
+	size_t total_vertices = meshopt_generateVertexRemapMulti(&remap[0], NULL, total_indices, total_indices, streams, sizeof(streams) / sizeof(streams[0]));
+
+	std::vector<unsigned int> indices(total_indices);
+	meshopt_remapIndexBuffer(&indices[0], NULL, total_indices, &remap[0]);
+
+	std::vector<float> pos(total_vertices * 3);
+	meshopt_remapVertexBuffer(&pos[0], &unindexed_pos[0], total_indices, sizeof(float) * 3, &remap[0]);
+
+	std::vector<float> nrm(total_vertices * 3);
+	meshopt_remapVertexBuffer(&nrm[0], &unindexed_nrm[0], total_indices, sizeof(float) * 3, &remap[0]);
+
+	std::vector<float> uv(total_vertices * 2);
+	meshopt_remapVertexBuffer(&uv[0], &unindexed_uv[0], total_indices, sizeof(float) * 2, &remap[0]);
+
+	double reindex = timestamp();
+
+	meshopt_optimizeVertexCache(&indices[0], &indices[0], total_indices, total_vertices);
+
+	meshopt_optimizeVertexFetchRemap(&remap[0], &indices[0], total_indices, total_vertices);
+	meshopt_remapVertexBuffer(&pos[0], &pos[0], total_vertices, sizeof(float) * 3, &remap[0]);
+	meshopt_remapVertexBuffer(&nrm[0], &nrm[0], total_vertices, sizeof(float) * 3, &remap[0]);
+	meshopt_remapVertexBuffer(&uv[0], &uv[0], total_vertices, sizeof(float) * 2, &remap[0]);
+
+	double optimize = timestamp();
+
+	// note: since shadow index buffer is computed based on regular vertex/index buffer, the stream points at the indexed data - not unindexed_pos
+	meshopt_Stream shadow_stream = {&pos[0], sizeof(float) * 3, sizeof(float) * 3};
+
+	std::vector<unsigned int> shadow_indices(total_indices);
+	meshopt_generateShadowIndexBufferMulti(&shadow_indices[0], &indices[0], total_indices, total_vertices, &shadow_stream, 1);
+
+	meshopt_optimizeVertexCache(&shadow_indices[0], &shadow_indices[0], total_indices, total_vertices);
+
+	double shadow = timestamp();
+
+	printf("Deintrlvd: %d vertices, reindexed in %.2f msec, optimized in %.2f msec, generated & optimized shadow indices in %.2f msec\n",
+	       int(total_vertices), (reindex - start) * 1000, (optimize - reindex) * 1000, (shadow - optimize) * 1000);
+}
+
+void process(const char* path)
+{
+	Mesh mesh;
+	if (!loadMesh(mesh, path))
+		return;
+
+	optimize(mesh, "Original", optNone);
+	optimize(mesh, "Random", optRandomShuffle);
+	optimize(mesh, "Cache", optCache);
+	optimize(mesh, "CacheFifo", optCacheFifo);
+	optimize(mesh, "Overdraw", optOverdraw);
+	optimize(mesh, "Fetch", optFetch);
+	optimize(mesh, "FetchMap", optFetchRemap);
+	optimize(mesh, "Complete", optComplete);
+
+	Mesh copy = mesh;
+	meshopt_optimizeVertexCache(&copy.indices[0], &copy.indices[0], copy.indices.size(), copy.vertices.size());
+	meshopt_optimizeVertexFetch(&copy.vertices[0], &copy.indices[0], copy.indices.size(), &copy.vertices[0], copy.vertices.size(), sizeof(Vertex));
+
+	stripify(copy);
+	meshlets(copy);
+	shadow(copy);
+
+	encodeIndex(copy);
+	packVertex<PackedVertex>(copy, "");
+	encodeVertex<PackedVertex>(copy, "");
+	encodeVertex<PackedVertexOct>(copy, "O");
+
+	simplify(mesh);
+	simplifySloppy(mesh);
+	simplifyComplete(mesh);
+
+	if (path)
+		processDeinterleaved(path);
+}
+
+void processDev(const char* path)
+{
+	Mesh mesh;
+	if (!loadMesh(mesh, path))
+		return;
+
+	simplify(mesh, 0.01f);
+	simplifySloppy(mesh, 0.01f);
+}
+
+int main(int argc, char** argv)
+{
+	void runTests();
+
+	if (argc == 1)
+	{
+		runTests();
+	}
+	else
+	{
+		if (strcmp(argv[1], "-d") == 0)
+		{
+			for (int i = 2; i < argc; ++i)
+			{
+				processDev(argv[i]);
+			}
+		}
+		else
+		{
+			for (int i = 1; i < argc; ++i)
+			{
+				process(argv[i]);
+			}
+
+			runTests();
+		}
+	}
+}

+ 1197 - 0
3rdparty/meshoptimizer/demo/miniz.cpp

@@ -0,0 +1,1197 @@
+/* This is miniz.c with removal of all zlib/zip like functionality - only tdefl/tinfl APIs are left
+   For maximum compatibility unaligned load/store and 64-bit register paths have been removed so this is slower than miniz.c
+
+   miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
+   See "unlicense" statement at the end of this file.
+   Rich Geldreich <[email protected]>, last updated Oct. 13, 2013
+   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
+*/
+
+// clang-format off
+
+#include "miniz.h"
+
+#ifndef MINIZ_HEADER_FILE_ONLY
+
+typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
+typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
+typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
+
+#include <string.h>
+#include <assert.h>
+
+#define MZ_ASSERT(x) assert(x)
+
+#ifdef MINIZ_NO_MALLOC
+  #define MZ_MALLOC(x) NULL
+  #define MZ_FREE(x) (void)x, ((void)0)
+  #define MZ_REALLOC(p, x) NULL
+#else
+  #define MZ_MALLOC(x) malloc(x)
+  #define MZ_FREE(x) free(x)
+  #define MZ_REALLOC(p, x) realloc(p, x)
+#endif
+
+#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
+#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
+#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
+
+#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
+#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
+
+#ifdef _MSC_VER
+  #define MZ_FORCEINLINE __forceinline
+#elif defined(__GNUC__)
+  #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
+#else
+  #define MZ_FORCEINLINE inline
+#endif
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+mz_uint32 mz_adler32(mz_uint32 adler, const unsigned char *ptr, size_t buf_len)
+{
+  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
+  if (!ptr) return MZ_ADLER32_INIT;
+  while (buf_len) {
+    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
+      s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
+      s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
+    }
+    for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
+    s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
+  }
+  return (s2 << 16) + s1;
+}
+
+void mz_free(void *p)
+{
+  MZ_FREE(p);
+}
+
+// ------------------- Low-level Decompression (completely independent from all compression API's)
+
+#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
+#define TINFL_MEMSET(p, c, l) memset(p, c, l)
+
+#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
+#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
+#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
+#define TINFL_CR_FINISH }
+
+// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
+// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
+#define TINFL_GET_BYTE(state_index, c) do { \
+  if (pIn_buf_cur >= pIn_buf_end) { \
+    for ( ; ; ) { \
+      if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
+        TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
+        if (pIn_buf_cur < pIn_buf_end) { \
+          c = *pIn_buf_cur++; \
+          break; \
+        } \
+      } else { \
+        c = 0; \
+        break; \
+      } \
+    } \
+  } else c = *pIn_buf_cur++; } MZ_MACRO_END
+
+#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
+#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
+#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
+
+// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
+// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
+// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
+// bit buffer contains >=15 bits (deflate's max. Huffman code size).
+#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
+  do { \
+    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
+    if (temp >= 0) { \
+      code_len = temp >> 9; \
+      if ((code_len) && (num_bits >= code_len)) \
+      break; \
+    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
+       code_len = TINFL_FAST_LOOKUP_BITS; \
+       do { \
+          temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
+       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
+    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
+  } while (num_bits < 15);
+
+// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
+// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
+// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
+// The slow path is only executed at the very end of the input buffer.
+#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
+  int temp; mz_uint code_len, c; \
+  if (num_bits < 15) { \
+    if ((pIn_buf_end - pIn_buf_cur) < 2) { \
+       TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
+    } else { \
+       bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
+    } \
+  } \
+  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
+    code_len = temp >> 9, temp &= 511; \
+  else { \
+    code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
+  } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
+
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
+{
+  static const int s_length_base[31] = { 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,0,0 };
+  static const int s_length_extra[31]= { 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,0,0 };
+  static const int s_dist_base[32] = { 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,0,0};
+  static const int s_dist_extra[32] = { 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};
+  static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+  static const int s_min_table_sizes[3] = { 257, 1, 4 };
+
+  tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
+  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
+  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
+  size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
+
+  // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
+  if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
+
+  num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
+  TINFL_CR_BEGIN
+
+  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
+  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
+  {
+    TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
+    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
+    if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (mz_uint32)(1U << (8U + (r->m_zhdr0 >> 4)))));
+    if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
+  }
+
+  do
+  {
+    TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
+    if (r->m_type == 0)
+    {
+      TINFL_SKIP_BITS(5, num_bits & 7);
+      for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
+      if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
+      while ((counter) && (num_bits))
+      {
+        TINFL_GET_BITS(51, dist, 8);
+        while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
+        *pOut_buf_cur++ = (mz_uint8)dist;
+        counter--;
+      }
+      while (counter)
+      {
+        size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
+        while (pIn_buf_cur >= pIn_buf_end)
+        {
+          if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
+          {
+            TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
+          }
+          else
+          {
+            TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
+          }
+        }
+        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
+        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
+      }
+    }
+    else if (r->m_type == 3)
+    {
+      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
+    }
+    else
+    {
+      if (r->m_type == 1)
+      {
+        mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
+        r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
+        for ( i = 0; i <= 143; ++i) *p++ = 8;
+        for ( ; i <= 255; ++i) *p++ = 9;
+        for ( ; i <= 279; ++i) *p++ = 7;
+        for ( ; i <= 287; ++i) *p++ = 8;
+      }
+      else
+      {
+        for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
+        MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
+        r->m_table_sizes[2] = 19;
+      }
+      for ( ; (int)r->m_type >= 0; r->m_type--)
+      {
+        int tree_next, tree_cur; tinfl_huff_table *pTable;
+        mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
+        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
+        used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
+        for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
+        if ((65536 != total) && (used_syms > 1))
+        {
+          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
+        }
+        for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
+        {
+          mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
+          cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
+          if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
+          if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
+          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
+          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
+          {
+            tree_cur -= ((rev_code >>= 1) & 1);
+            if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
+          }
+          tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
+        }
+        if (r->m_type == 2)
+        {
+          for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
+          {
+            mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
+            if ((dist == 16) && (!counter))
+            {
+              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
+            }
+            num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
+            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
+          }
+          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
+          {
+            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
+          }
+          TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
+        }
+      }
+      for ( ; ; )
+      {
+        mz_uint8 *pSrc;
+        for ( ; ; )
+        {
+          if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
+          {
+            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
+            if (counter >= 256)
+              break;
+            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
+            *pOut_buf_cur++ = (mz_uint8)counter;
+          }
+          else
+          {
+            int sym2; mz_uint code_len;
+            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
+            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
+              code_len = sym2 >> 9;
+            else
+            {
+              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
+            }
+            counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
+            if (counter & 256)
+              break;
+
+            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
+              code_len = sym2 >> 9;
+            else
+            {
+              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
+            }
+            bit_buf >>= code_len; num_bits -= code_len;
+
+            pOut_buf_cur[0] = (mz_uint8)counter;
+            if (sym2 & 256)
+            {
+              pOut_buf_cur++;
+              counter = sym2;
+              break;
+            }
+            pOut_buf_cur[1] = (mz_uint8)sym2;
+            pOut_buf_cur += 2;
+          }
+        }
+        if ((counter &= 511) == 256) break;
+
+        num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
+        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
+
+        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
+        num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
+        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
+
+        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
+        if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
+        {
+          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
+        }
+
+        pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
+
+        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
+        {
+          while (counter--)
+          {
+            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
+            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
+          }
+          continue;
+        }
+        do
+        {
+          pOut_buf_cur[0] = pSrc[0];
+          pOut_buf_cur[1] = pSrc[1];
+          pOut_buf_cur[2] = pSrc[2];
+          pOut_buf_cur += 3; pSrc += 3;
+        } while ((int)(counter -= 3) > 2);
+        if ((int)counter > 0)
+        {
+          pOut_buf_cur[0] = pSrc[0];
+          if ((int)counter > 1)
+            pOut_buf_cur[1] = pSrc[1];
+          pOut_buf_cur += counter;
+        }
+      }
+    }
+  } while (!(r->m_final & 1));
+  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
+  {
+    TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
+  }
+  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
+  TINFL_CR_FINISH
+
+common_exit:
+  r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
+  *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
+  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
+  {
+    const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
+    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
+    while (buf_len)
+    {
+      for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
+      {
+        s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
+        s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
+      }
+      for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
+      s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
+    }
+    r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
+  }
+  return status;
+}
+
+// Higher level helper functions.
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
+{
+  tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
+  status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
+}
+
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+  int result = 0;
+  tinfl_decompressor decomp;
+  mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
+  if (!pDict)
+    return TINFL_STATUS_FAILED;
+  tinfl_init(&decomp);
+  for ( ; ; )
+  {
+    size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
+    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
+      (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
+    in_buf_ofs += in_buf_size;
+    if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
+      break;
+    if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
+    {
+      result = (status == TINFL_STATUS_DONE);
+      break;
+    }
+    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
+  }
+  MZ_FREE(pDict);
+  *pIn_buf_size = in_buf_ofs;
+  return result;
+}
+
+// ------------------- Low-level Compression (independent from all decompression API's)
+
+// Purposely making these tables static for faster init and thread safety.
+static const mz_uint16 s_tdefl_len_sym[256] = {
+  257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
+  273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
+  277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
+  279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
+  281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
+  282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
+  283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
+  284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };
+
+static const mz_uint8 s_tdefl_len_extra[256] = {
+  0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 };
+
+static const mz_uint8 s_tdefl_small_dist_sym[512] = {
+  0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
+  11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
+  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
+  14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+  14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+  15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };
+
+static const mz_uint8 s_tdefl_small_dist_extra[512] = {
+  0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7 };
+
+static const mz_uint8 s_tdefl_large_dist_sym[128] = {
+  0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
+  26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
+  28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };
+
+static const mz_uint8 s_tdefl_large_dist_extra[128] = {
+  0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
+  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };
+
+// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
+typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
+static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
+{
+  mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
+  for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
+  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
+  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
+  {
+    const mz_uint32* pHist = &hist[pass << 8];
+    mz_uint offsets[256], cur_ofs = 0;
+    for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
+    for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
+    { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
+  }
+  return pCur_syms;
+}
+
+// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
+static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
+{
+  int root, leaf, next, avbl, used, dpth;
+  if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
+  A[0].m_key += A[1].m_key; root = 0; leaf = 2;
+  for (next=1; next < n-1; next++)
+  {
+    if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
+    if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
+  }
+  A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
+  avbl = 1; used = dpth = 0; root = n-2; next = n-1;
+  while (avbl>0)
+  {
+    while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
+    while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
+    avbl = 2*used; dpth++; used = 0;
+  }
+}
+
+// Limits canonical Huffman code table's max code size.
+enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
+static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
+{
+  int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
+  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
+  for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
+  while (total != (1UL << max_code_size))
+  {
+    pNum_codes[max_code_size]--;
+    for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
+    total--;
+  }
+}
+
+static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
+{
+  int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
+  if (static_table)
+  {
+    for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
+  }
+  else
+  {
+    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
+    int num_used_syms = 0;
+    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
+    for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
+
+    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
+
+    for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
+
+    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
+
+    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
+    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
+      for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
+  }
+
+  next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
+
+  for (i = 0; i < table_len; i++)
+  {
+    mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
+    code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
+    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
+  }
+}
+
+#define TDEFL_PUT_BITS(b, l) do { \
+  mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
+  d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
+  while (d->m_bits_in >= 8) { \
+    if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
+      *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
+      d->m_bit_buffer >>= 8; \
+      d->m_bits_in -= 8; \
+  } \
+} MZ_MACRO_END
+
+#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
+  if (rle_repeat_count < 3) { \
+    d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
+    while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
+  } else { \
+    d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
+} rle_repeat_count = 0; } }
+
+#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
+  if (rle_z_count < 3) { \
+    d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
+  } else if (rle_z_count <= 10) { \
+    d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
+  } else { \
+    d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
+} rle_z_count = 0; } }
+
+static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+static void tdefl_start_dynamic_block(tdefl_compressor *d)
+{
+  int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
+  mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
+
+  d->m_huff_count[0][256] = 1;
+
+  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
+  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
+
+  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
+  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
+
+  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
+  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
+  total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
+
+  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
+  for (i = 0; i < total_code_sizes_to_pack; i++)
+  {
+    mz_uint8 code_size = code_sizes_to_pack[i];
+    if (!code_size)
+    {
+      TDEFL_RLE_PREV_CODE_SIZE();
+      if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
+    }
+    else
+    {
+      TDEFL_RLE_ZERO_CODE_SIZE();
+      if (code_size != prev_code_size)
+      {
+        TDEFL_RLE_PREV_CODE_SIZE();
+        d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
+      }
+      else if (++rle_repeat_count == 6)
+      {
+        TDEFL_RLE_PREV_CODE_SIZE();
+      }
+    }
+    prev_code_size = code_size;
+  }
+  if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
+
+  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
+
+  TDEFL_PUT_BITS(2, 2);
+
+  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
+  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
+
+  for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
+  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
+  for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
+
+  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
+  {
+    mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
+    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
+    if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
+  }
+}
+
+static void tdefl_start_static_block(tdefl_compressor *d)
+{
+  mz_uint i;
+  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
+
+  for (i = 0; i <= 143; ++i) *p++ = 8;
+  for ( ; i <= 255; ++i) *p++ = 9;
+  for ( ; i <= 279; ++i) *p++ = 7;
+  for ( ; i <= 287; ++i) *p++ = 8;
+
+  memset(d->m_huff_code_sizes[1], 5, 32);
+
+  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
+  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
+
+  TDEFL_PUT_BITS(1, 2);
+}
+
+static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
+{
+  mz_uint flags;
+  mz_uint8 *pLZ_codes;
+
+  flags = 1;
+  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
+  {
+    if (flags == 1)
+      flags = *pLZ_codes++ | 0x100;
+    if (flags & 1)
+    {
+      mz_uint sym, num_extra_bits;
+      mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
+
+      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+      TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
+
+      if (match_dist < 512)
+      {
+        sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
+      }
+      else
+      {
+        sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
+      }
+      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
+      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
+      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
+    }
+    else
+    {
+      mz_uint lit = *pLZ_codes++;
+      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+    }
+  }
+
+  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
+
+  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
+}
+
+static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
+{
+  if (static_block)
+    tdefl_start_static_block(d);
+  else
+    tdefl_start_dynamic_block(d);
+  return tdefl_compress_lz_codes(d);
+}
+
+static int tdefl_flush_block(tdefl_compressor *d, int flush)
+{
+  mz_uint saved_bit_buf, saved_bits_in;
+  mz_uint8 *pSaved_output_buf;
+  mz_bool comp_block_succeeded = MZ_FALSE;
+  int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
+  mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
+
+  d->m_pOutput_buf = pOutput_buf_start;
+  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
+
+  MZ_ASSERT(!d->m_output_flush_remaining);
+  d->m_output_flush_ofs = 0;
+  d->m_output_flush_remaining = 0;
+
+  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
+  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
+
+  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
+  {
+    TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
+  }
+
+  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
+
+  pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
+
+  if (!use_raw_block)
+    comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
+
+  // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
+  if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
+       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
+  {
+    mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
+    TDEFL_PUT_BITS(0, 2);
+    if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
+    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
+    {
+      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
+    }
+    for (i = 0; i < d->m_total_lz_bytes; ++i)
+    {
+      TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
+    }
+  }
+  // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
+  else if (!comp_block_succeeded)
+  {
+    d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
+    tdefl_compress_block(d, MZ_TRUE);
+  }
+
+  if (flush)
+  {
+    if (flush == TDEFL_FINISH)
+    {
+      if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
+      if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
+    }
+    else
+    {
+      mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
+    }
+  }
+
+  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
+
+  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
+  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
+
+  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
+
+  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
+  {
+    if (d->m_pPut_buf_func)
+    {
+      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
+      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
+        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
+    }
+    else if (pOutput_buf_start == d->m_output_buf)
+    {
+      int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
+      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
+      d->m_out_buf_ofs += bytes_to_copy;
+      if ((n -= bytes_to_copy) != 0)
+      {
+        d->m_output_flush_ofs = bytes_to_copy;
+        d->m_output_flush_remaining = n;
+      }
+    }
+    else
+    {
+      d->m_out_buf_ofs += n;
+    }
+  }
+
+  return d->m_output_flush_remaining;
+}
+
+static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
+{
+  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
+  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
+  const mz_uint8 *s = d->m_dict + pos, *p, *q;
+  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
+  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
+  for ( ; ; )
+  {
+    for ( ; ; )
+    {
+      if (--num_probes_left == 0) return;
+      #define TDEFL_PROBE \
+        next_probe_pos = d->m_next[probe_pos]; \
+        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
+        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
+        if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
+      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
+    }
+    if (!dist) break;
+    p = s; q = d->m_dict + probe_pos;
+    for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
+    if (probe_len > match_len)
+    {
+      *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
+      c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
+    }
+  }
+}
+
+static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
+{
+  d->m_total_lz_bytes++;
+  *d->m_pLZ_code_buf++ = lit;
+  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
+  d->m_huff_count[0][lit]++;
+}
+
+static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
+{
+  mz_uint32 s0, s1;
+
+  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
+
+  d->m_total_lz_bytes += match_len;
+
+  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
+
+  match_dist -= 1;
+  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
+  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
+
+  *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
+
+  s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
+  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
+
+  if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
+}
+
+static mz_bool tdefl_compress_normal(tdefl_compressor *d)
+{
+  const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
+  tdefl_flush flush = d->m_flush;
+
+  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
+  {
+    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
+    // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
+    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
+    {
+      mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
+      mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
+      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
+      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
+      src_buf_left -= num_bytes_to_process;
+      d->m_lookahead_size += num_bytes_to_process;
+      while (pSrc != pSrc_end)
+      {
+        mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
+        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
+        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
+        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
+      }
+    }
+    else
+    {
+      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
+      {
+        mz_uint8 c = *pSrc++;
+        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
+        src_buf_left--;
+        d->m_dict[dst_pos] = c;
+        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
+          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
+        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
+        {
+          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
+          mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
+          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
+        }
+      }
+    }
+    d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
+    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
+      break;
+
+    // Simple lazy/greedy parsing state machine.
+    len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
+    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
+    {
+      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
+      {
+        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
+        cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
+        if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
+      }
+    }
+    else
+    {
+      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
+    }
+    if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
+    {
+      cur_match_dist = cur_match_len = 0;
+    }
+    if (d->m_saved_match_len)
+    {
+      if (cur_match_len > d->m_saved_match_len)
+      {
+        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
+        if (cur_match_len >= 128)
+        {
+          tdefl_record_match(d, cur_match_len, cur_match_dist);
+          d->m_saved_match_len = 0; len_to_move = cur_match_len;
+        }
+        else
+        {
+          d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
+        }
+      }
+      else
+      {
+        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
+        len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
+      }
+    }
+    else if (!cur_match_dist)
+      tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
+    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
+    {
+      tdefl_record_match(d, cur_match_len, cur_match_dist);
+      len_to_move = cur_match_len;
+    }
+    else
+    {
+      d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
+    }
+    // Move the lookahead forward by len_to_move bytes.
+    d->m_lookahead_pos += len_to_move;
+    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
+    d->m_lookahead_size -= len_to_move;
+    d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (int)TDEFL_LZ_DICT_SIZE);
+    // Check if it's time to flush the current LZ codes to the internal output buffer.
+    if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
+         ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
+    {
+      int n;
+      d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
+      if ((n = tdefl_flush_block(d, 0)) != 0)
+        return (n < 0) ? MZ_FALSE : MZ_TRUE;
+    }
+  }
+
+  d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
+  return MZ_TRUE;
+}
+
+static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
+{
+  if (d->m_pIn_buf_size)
+  {
+    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
+  }
+
+  if (d->m_pOut_buf_size)
+  {
+    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
+    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
+    d->m_output_flush_ofs += (mz_uint)n;
+    d->m_output_flush_remaining -= (mz_uint)n;
+    d->m_out_buf_ofs += n;
+
+    *d->m_pOut_buf_size = d->m_out_buf_ofs;
+  }
+
+  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
+}
+
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
+{
+  if (!d)
+  {
+    if (pIn_buf_size) *pIn_buf_size = 0;
+    if (pOut_buf_size) *pOut_buf_size = 0;
+    return TDEFL_STATUS_BAD_PARAM;
+  }
+
+  d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
+  d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
+  d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
+  d->m_out_buf_ofs = 0;
+  d->m_flush = flush;
+
+  if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
+        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
+  {
+    if (pIn_buf_size) *pIn_buf_size = 0;
+    if (pOut_buf_size) *pOut_buf_size = 0;
+    return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
+  }
+  d->m_wants_to_finish |= (flush == TDEFL_FINISH);
+
+  if ((d->m_output_flush_remaining) || (d->m_finished))
+    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
+
+  if (!tdefl_compress_normal(d))
+    return d->m_prev_return_status;
+
+  if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
+    d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
+
+  if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
+  {
+    if (tdefl_flush_block(d, flush) < 0)
+      return d->m_prev_return_status;
+    d->m_finished = (flush == TDEFL_FINISH);
+    if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
+  }
+
+  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
+}
+
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
+{
+  MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
+}
+
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+  d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
+  d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
+  d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
+  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
+  d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
+  d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
+  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
+  d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
+  d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
+  d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
+  d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
+  d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
+  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
+  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
+  return TDEFL_STATUS_OKAY;
+}
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
+{
+  return d->m_prev_return_status;
+}
+
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
+{
+  return d->m_adler32;
+}
+
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+  tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
+  pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
+  succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
+  succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
+  MZ_FREE(pComp); return succeeded;
+}
+
+typedef struct
+{
+  size_t m_size, m_capacity;
+  mz_uint8 *m_pBuf;
+} tdefl_output_buffer;
+
+static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
+{
+  tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
+  size_t new_size = p->m_size + len;
+  if (new_size > p->m_capacity) return MZ_FALSE;
+  memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
+  return MZ_TRUE;
+}
+
+size_t tdefl_compress_bound(size_t source_len)
+{
+  // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
+  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
+}
+
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
+{
+  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
+  if (!pOut_buf) return 0;
+  out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
+  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
+  return out_buf.m_size;
+}
+
+static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
+
+// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
+{
+  mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
+  if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
+
+  if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
+  else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
+  else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
+  else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
+  else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
+
+  return comp_flags;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_FILE_ONLY
+
+/*
+  This is free and unencumbered software released into the public domain.
+
+  Anyone is free to copy, modify, publish, use, compile, sell, or
+  distribute this software, either in source code form or as a compiled
+  binary, for any purpose, commercial or non-commercial, and by any
+  means.
+
+  In jurisdictions that recognize copyright laws, the author or authors
+  of this software dedicate any and all copyright interest in the
+  software to the public domain. We make this dedication for the benefit
+  of the public at large and to the detriment of our heirs and
+  successors. We intend this dedication to be an overt act of
+  relinquishment in perpetuity of all present and future rights to this
+  software under copyright law.
+
+  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 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.
+
+  For more information, please refer to <http://unlicense.org/>
+*/

+ 298 - 0
3rdparty/meshoptimizer/demo/miniz.h

@@ -0,0 +1,298 @@
+/* This is miniz.c with removal of all zlib/zip like functionality - only tdefl/tinfl APIs are left
+   For maximum compatibility unaligned load/store and 64-bit register paths have been removed so this is slower than miniz.c
+
+   miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
+   See "unlicense" statement at the end of this file.
+   Rich Geldreich <[email protected]>, last updated Oct. 13, 2013
+   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
+*/
+
+#ifndef MINIZ_HEADER_INCLUDED
+#define MINIZ_HEADER_INCLUDED
+
+#include <stdlib.h>
+
+// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
+// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
+// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
+// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
+//#define MINIZ_NO_MALLOC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
+void mz_free(void *p);
+
+// Compression strategies.
+enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
+
+// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
+enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
+
+// Window bits
+#define MZ_DEFAULT_WINDOW_BITS 15
+
+// Method
+#define MZ_DEFLATED 8
+
+// ------------------- Types and macros
+
+typedef unsigned char mz_uint8;
+typedef signed short mz_int16;
+typedef unsigned short mz_uint16;
+typedef unsigned int mz_uint32;
+typedef unsigned int mz_uint;
+typedef long long mz_int64;
+typedef unsigned long long mz_uint64;
+typedef int mz_bool;
+
+#define MZ_FALSE (0)
+#define MZ_TRUE (1)
+
+// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
+#ifdef _MSC_VER
+   #define MZ_MACRO_END while (0, 0)
+#else
+   #define MZ_MACRO_END while (0)
+#endif
+
+#define MZ_ADLER32_INIT (1)
+// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
+mz_uint32 mz_adler32(mz_uint32 adler, const unsigned char *ptr, size_t buf_len);
+
+// ------------------- Low-level Decompression API Definitions
+
+// Decompression flags used by tinfl_decompress().
+// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
+// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
+// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
+// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
+enum
+{
+  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
+  TINFL_FLAG_HAS_MORE_INPUT = 2,
+  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
+  TINFL_FLAG_COMPUTE_ADLER32 = 8
+};
+
+// High level decompression functions:
+// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
+// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
+#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
+// Returns 1 on success or 0 on failure.
+typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
+
+// Max size of LZ dictionary.
+#define TINFL_LZ_DICT_SIZE 32768
+
+// Return status.
+typedef enum
+{
+  TINFL_STATUS_BAD_PARAM = -3,
+  TINFL_STATUS_ADLER32_MISMATCH = -2,
+  TINFL_STATUS_FAILED = -1,
+  TINFL_STATUS_DONE = 0,
+  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
+  TINFL_STATUS_HAS_MORE_OUTPUT = 2
+} tinfl_status;
+
+// Initializes the decompressor to its initial state.
+#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
+#define tinfl_get_adler32(r) (r)->m_check_adler32
+
+// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
+// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
+
+// Internal/private bits follow.
+enum
+{
+  TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
+  TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
+};
+
+typedef struct
+{
+  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
+  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
+} tinfl_huff_table;
+
+typedef mz_uint32 tinfl_bit_buf_t;
+#define TINFL_BITBUF_SIZE (32)
+
+struct tinfl_decompressor_tag
+{
+  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
+  tinfl_bit_buf_t m_bit_buf;
+  size_t m_dist_from_out_buf_start;
+  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
+  mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
+};
+
+// ------------------- Low-level Compression API Definitions
+
+// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
+#define TDEFL_LESS_MEMORY 0
+
+// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
+// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
+enum
+{
+  TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
+};
+
+// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
+// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
+// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
+// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
+// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
+// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
+// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
+// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
+// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
+enum
+{
+  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
+  TDEFL_COMPUTE_ADLER32               = 0x02000,
+  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
+  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
+  TDEFL_RLE_MATCHES                   = 0x10000,
+  TDEFL_FILTER_MATCHES                = 0x20000,
+  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
+  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
+};
+
+// High level compression functions:
+
+
+// tdefl_compress_bound() returns a (very) conservative upper bound on the amount of data that could be generated by calling tdefl_compress_*().
+size_t tdefl_compress_bound(size_t source_len);
+
+// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
+// Returns 0 on failure.
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
+typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+
+// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
+
+// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
+#if TDEFL_LESS_MEMORY
+enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#else
+enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#endif
+
+// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
+typedef enum
+{
+  TDEFL_STATUS_BAD_PARAM = -2,
+  TDEFL_STATUS_PUT_BUF_FAILED = -1,
+  TDEFL_STATUS_OKAY = 0,
+  TDEFL_STATUS_DONE = 1,
+} tdefl_status;
+
+// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
+typedef enum
+{
+  TDEFL_NO_FLUSH = 0,
+  TDEFL_SYNC_FLUSH = 2,
+  TDEFL_FULL_FLUSH = 3,
+  TDEFL_FINISH = 4
+} tdefl_flush;
+
+// tdefl's compression state structure.
+typedef struct
+{
+  tdefl_put_buf_func_ptr m_pPut_buf_func;
+  void *m_pPut_buf_user;
+  mz_uint m_flags, m_max_probes[2];
+  int m_greedy_parsing;
+  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
+  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
+  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
+  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
+  tdefl_status m_prev_return_status;
+  const void *m_pIn_buf;
+  void *m_pOut_buf;
+  size_t *m_pIn_buf_size, *m_pOut_buf_size;
+  tdefl_flush m_flush;
+  const mz_uint8 *m_pSrc;
+  size_t m_src_buf_left, m_out_buf_ofs;
+  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
+  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
+  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
+  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
+  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
+} tdefl_compressor;
+
+// Initializes the compressor.
+// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
+// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
+// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
+// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
+
+// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
+// tdefl_compress_buffer() always consumes the entire input buffer.
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
+
+// Create tdefl_compress() flags given zlib-style compression parameters.
+// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
+// window_bits may be -15 (raw deflate) or 15 (zlib)
+// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_INCLUDED
+
+/*
+  This is free and unencumbered software released into the public domain.
+
+  Anyone is free to copy, modify, publish, use, compile, sell, or
+  distribute this software, either in source code form or as a compiled
+  binary, for any purpose, commercial or non-commercial, and by any
+  means.
+
+  In jurisdictions that recognize copyright laws, the author or authors
+  of this software dedicate any and all copyright interest in the
+  software to the public domain. We make this dedication for the benefit
+  of the public at large and to the detriment of our heirs and
+  successors. We intend this dedication to be an overt act of
+  relinquishment in perpetuity of all present and future rights to this
+  software under copyright law.
+
+  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 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.
+
+  For more information, please refer to <http://unlicense.org/>
+*/

+ 11358 - 0
3rdparty/meshoptimizer/demo/pirate.obj

@@ -0,0 +1,11358 @@
+# Blender v2.79 (sub 0) OBJ File: 'pirate.blend'
+# www.blender.org
+# Pirate by Clint Bellanger
+# https://opengameart.org/content/pirate
+# Distributed under CC-BY-SA 3.0
+mtllib pirate.mtl
+o Pirate_Sphere.001
+v -0.086616 1.541207 0.048687
+v 0.000000 1.521174 0.062100
+v 0.086616 1.541207 0.048687
+v -0.086616 1.467515 0.104849
+v -0.000000 1.460505 0.104473
+v 0.086616 1.467515 0.104849
+v -0.075497 1.360887 0.136036
+v 0.000000 1.353877 0.135660
+v 0.075497 1.360887 0.136036
+v -0.062354 1.259913 0.142685
+v 0.000000 1.259005 0.147301
+v 0.062354 1.259913 0.142685
+v 0.000000 1.173866 0.151424
+v 0.058120 1.175055 0.151800
+v -0.058120 1.175056 0.151800
+v 0.236368 0.092607 -0.020215
+v 0.244447 0.050649 0.055733
+v 0.160035 0.050649 0.068862
+v 0.158087 0.096969 -0.009511
+v 0.231907 0.050962 0.096377
+v 0.171927 0.050962 0.109907
+v 0.198856 0.056750 0.063817
+v 0.200434 0.099614 -0.008311
+v 0.203658 0.053735 0.117253
+v 0.228066 0.128577 -0.048921
+v 0.191707 0.128577 -0.030516
+v 0.155310 0.128577 -0.040374
+v 0.243809 0.048939 -0.062636
+v 0.259032 0.034710 0.052294
+v 0.229486 0.128577 -0.086203
+v 0.215595 0.128577 -0.123264
+v 0.215978 0.054773 -0.140594
+v 0.166330 0.128577 -0.141207
+v 0.168375 0.056821 -0.160469
+v 0.138088 0.128577 -0.118289
+v 0.138284 0.053982 -0.136358
+v 0.140126 0.128577 -0.082307
+v 0.145418 0.049313 -0.053791
+v 0.142801 0.033877 0.063946
+v 0.241657 0.038506 0.108880
+v 0.163953 0.037606 0.125343
+v 0.203658 0.036372 0.132175
+v 0.240419 0.028025 -0.064598
+v 0.255085 0.016737 0.039452
+v 0.214742 0.028524 -0.135022
+v 0.170136 0.028524 -0.153646
+v 0.141940 0.028524 -0.131052
+v 0.153248 0.027295 -0.055831
+v 0.145661 0.016737 0.050411
+v 0.238718 0.016737 0.097813
+v 0.164969 0.016737 0.113922
+v 0.202729 0.016737 0.120323
+v 0.242952 0.028025 -0.066538
+v 0.258034 0.016737 0.042949
+v 0.215666 0.028524 -0.141348
+v 0.168821 0.028524 -0.160906
+v 0.139209 0.028524 -0.137178
+v 0.150897 0.027295 -0.057712
+v 0.143524 0.016737 0.054426
+v 0.240914 0.016737 0.103692
+v 0.164210 0.016737 0.120066
+v 0.203423 0.016737 0.126789
+v 0.258034 -0.001088 0.025696
+v 0.242952 0.013555 -0.070778
+v 0.215666 0.014054 -0.141348
+v 0.168821 0.014054 -0.160906
+v 0.139209 0.014054 -0.137178
+v 0.150897 0.012826 -0.061952
+v 0.143524 -0.001088 0.037173
+v 0.240914 -0.000249 0.103692
+v 0.164210 -0.000249 0.120066
+v 0.203423 -0.000249 0.126789
+v 0.242952 -0.000311 -0.070778
+v 0.215666 0.000188 -0.141348
+v 0.168821 0.000188 -0.160906
+v 0.139209 0.000188 -0.137178
+v 0.150897 -0.001041 -0.061952
+v 0.240407 0.067287 0.012779
+v 0.157989 0.070033 0.027636
+v 0.199645 0.074798 0.025643
+v 0.254610 0.041825 -0.006398
+v 0.148123 0.042231 -0.000025
+v 0.250941 0.022381 -0.013800
+v 0.154169 0.022381 -0.007738
+v 0.253682 0.022381 -0.013022
+v 0.151925 0.022381 -0.006671
+v 0.253682 0.005814 -0.021702
+v 0.151925 0.005814 -0.015351
+v 0.218563 0.209613 -0.046429
+v 0.188733 0.208412 -0.021345
+v 0.148752 0.208412 -0.032174
+v 0.230231 0.208412 -0.082515
+v 0.214972 0.208412 -0.125426
+v 0.160857 0.208412 -0.142935
+v 0.129834 0.208412 -0.119961
+v 0.132073 0.208412 -0.078236
+v 0.184486 0.296737 -0.005237
+v 0.225084 0.299002 -0.034678
+v 0.140596 0.296697 -0.019914
+v 0.236935 0.298150 -0.081582
+v 0.217650 0.297630 -0.136721
+v 0.158346 0.295603 -0.157599
+v 0.110046 0.294732 -0.129811
+v 0.112876 0.294808 -0.076172
+v 0.180417 0.388284 0.013613
+v 0.219940 0.392383 -0.019552
+v 0.129895 0.386004 -0.002073
+v 0.236443 0.395326 -0.069991
+v 0.219625 0.400030 -0.135825
+v 0.144725 0.400515 -0.158651
+v 0.091043 0.394958 -0.126268
+v 0.093351 0.389803 -0.062979
+v 0.141647 0.491328 -0.114189
+v 0.205701 0.490563 -0.094984
+v 0.172100 0.480332 0.031533
+v 0.088130 0.486878 -0.030961
+v 0.124555 0.485816 0.028877
+v 0.085756 0.492816 -0.089075
+v 0.138819 0.500966 -0.123683
+v 0.212734 0.500023 -0.101320
+v 0.229349 0.492623 -0.040656
+v 0.212929 0.490855 0.006320
+v 0.174315 0.487937 0.044232
+v 0.078510 0.469649 -0.030733
+v 0.118959 0.469167 0.037975
+v 0.075626 0.476194 -0.096815
+v 0.135258 0.486616 -0.136305
+v 0.219656 0.487755 -0.110271
+v 0.239055 0.480310 -0.041331
+v 0.221618 0.477597 0.013127
+v 0.176187 0.472900 0.055532
+v 0.073827 0.311152 -0.055639
+v 0.116017 0.309592 0.028478
+v 0.066537 0.324125 -0.137977
+v 0.244434 0.339411 -0.148584
+v 0.277813 0.321962 -0.063759
+v 0.262464 0.316457 0.009962
+v 0.191486 0.312070 0.054821
+v 0.178630 0.357606 -0.193864
+v 0.123421 0.350867 -0.185934
+v 0.118294 0.398249 0.026084
+v 0.078910 0.396001 -0.044382
+v 0.074782 0.405104 -0.114011
+v 0.225539 0.420431 -0.125449
+v 0.254013 0.412894 -0.052038
+v 0.236933 0.409543 0.008791
+v 0.180250 0.404852 0.047154
+v 0.153892 0.427512 -0.158986
+v 0.129930 0.424512 -0.155542
+v 0.204864 0.482881 -0.001814
+v 0.129203 0.478420 0.018134
+v 0.219844 0.485703 -0.041760
+v 0.095093 0.485847 -0.085518
+v 0.097055 0.480678 -0.033262
+v 0.058986 1.778749 -0.098358
+v 0.079459 1.777951 -0.069506
+v 0.089357 1.778162 -0.031658
+v 0.086722 1.779085 0.007426
+v 0.072214 1.784068 0.043280
+v 0.056289 1.778569 0.078209
+v 0.030933 1.778055 0.100438
+v 0.000029 1.777957 0.107919
+v -0.030113 1.780207 0.099812
+v -0.055386 1.784491 0.077437
+v -0.075219 1.785706 0.045458
+v -0.088151 1.781940 0.008471
+v -0.090065 1.778396 -0.031092
+v -0.079190 1.777552 -0.068779
+v -0.058930 1.778485 -0.099223
+v -0.031333 1.780597 -0.112832
+v 0.000044 1.782147 -0.114884
+v 0.031409 1.780958 -0.111651
+v 0.058347 1.849556 -0.086516
+v 0.078385 1.847862 -0.063548
+v 0.086845 1.848279 -0.030617
+v 0.083311 1.849049 0.003948
+v 0.071195 1.849480 0.037787
+v 0.053178 1.848875 0.067663
+v 0.029426 1.848109 0.088584
+v 0.000478 1.848497 0.095845
+v -0.027984 1.853117 0.087607
+v -0.052069 1.858957 0.066812
+v -0.071600 1.860267 0.037959
+v -0.084706 1.855989 0.004879
+v -0.087909 1.850094 -0.029810
+v -0.078406 1.847763 -0.063610
+v -0.058167 1.849198 -0.087595
+v -0.030896 1.852027 -0.097518
+v 0.000108 1.853595 -0.099203
+v 0.031101 1.852409 -0.096369
+v 0.065910 1.863193 -0.055048
+v 0.049138 1.864533 -0.074499
+v 0.073086 1.863481 -0.027452
+v 0.070484 1.864051 0.001907
+v 0.060498 1.864257 0.030547
+v 0.045081 1.863910 0.055529
+v 0.024683 1.863350 0.072867
+v 0.000521 1.863915 0.078932
+v -0.023521 1.867598 0.072098
+v -0.044097 1.871953 0.054804
+v -0.060628 1.872897 0.030575
+v -0.071485 1.869625 0.002596
+v -0.073853 1.865274 -0.026848
+v -0.065981 1.863099 -0.055126
+v -0.048960 1.864257 -0.075334
+v -0.026002 1.866220 -0.084925
+v 0.000102 1.867361 -0.086874
+v 0.026196 1.866493 -0.084095
+v 0.000089 1.863019 -0.010396
+v 0.163089 1.835772 -0.135080
+v 0.189568 1.760501 -0.131727
+v -0.008953 1.770214 0.212054
+v -0.203693 1.757624 -0.117194
+v -0.163052 1.839092 -0.132407
+v -0.081971 1.883991 -0.105049
+v 0.000092 1.900686 -0.082792
+v 0.082159 1.884257 -0.104242
+v 0.142218 1.770391 -0.134324
+v 0.074281 1.779322 -0.133913
+v 0.000114 1.782525 -0.124317
+v -0.074089 1.778930 -0.135083
+v -0.141499 1.772850 -0.124412
+v 0.178914 1.767742 -0.065645
+v 0.146196 1.778066 -0.011723
+v 0.101668 1.784760 0.048946
+v 0.072940 1.777907 0.117313
+v 0.029853 1.778522 0.166702
+v -0.042368 1.777305 0.168503
+v -0.071558 1.781615 0.116535
+v -0.105547 1.786529 0.050382
+v -0.147493 1.778899 -0.010879
+v -0.179551 1.768847 -0.059894
+v 0.192030 1.774595 -0.157698
+v -0.196140 1.771098 -0.150907
+v -0.148438 1.795914 -0.157062
+v -0.077901 1.801581 -0.157771
+v 0.000121 1.806535 -0.143703
+v 0.078096 1.802044 -0.156394
+v 0.148773 1.792710 -0.160503
+v 0.055593 1.796899 0.190306
+v 0.091024 1.800365 0.132154
+v 0.120949 1.807803 0.061471
+v 0.167953 1.800547 -0.003569
+v 0.202690 1.790509 -0.058345
+v 0.219763 1.772986 -0.103608
+v 0.025376 1.782599 0.225570
+v 0.041662 1.883651 0.108372
+v 0.065429 1.899024 0.027469
+v 0.122970 1.883781 -0.034211
+v 0.189371 1.834813 -0.085696
+v 0.026824 1.840460 0.191371
+v -0.189957 1.838185 -0.083454
+v -0.028163 1.840382 0.191146
+v -0.040263 1.886331 0.107609
+v -0.065407 1.903963 0.027451
+v -0.123778 1.884084 -0.033638
+v -0.225231 1.766756 -0.101532
+v -0.030773 1.782936 0.225767
+v -0.057529 1.797016 0.189845
+v -0.089435 1.804814 0.131241
+v -0.124267 1.811475 0.061137
+v -0.169496 1.801613 -0.002586
+v -0.203903 1.793766 -0.056224
+v -0.032356 1.740167 0.086580
+v -0.025976 1.740167 0.085311
+v -0.020567 1.740167 0.081697
+v -0.016953 1.740167 0.076288
+v -0.015684 1.740167 0.069908
+v -0.020567 1.751956 0.069908
+v -0.021465 1.751059 0.076288
+v -0.024020 1.748503 0.081697
+v -0.027845 1.744678 0.085311
+v -0.032356 1.746547 0.085311
+v -0.032356 1.751956 0.081697
+v -0.032356 1.755570 0.076288
+v -0.032356 1.756839 0.069908
+v -0.044145 1.751956 0.069908
+v -0.043248 1.751059 0.076288
+v -0.040692 1.748503 0.081697
+v -0.036868 1.744678 0.085311
+v -0.038736 1.740167 0.085311
+v -0.044145 1.740167 0.081697
+v -0.047759 1.740167 0.076288
+v -0.049028 1.740167 0.069908
+v -0.044145 1.728378 0.069908
+v -0.043248 1.729275 0.076288
+v -0.040692 1.731831 0.081697
+v -0.036868 1.735656 0.085311
+v -0.032356 1.733787 0.085311
+v -0.032356 1.728378 0.081697
+v -0.032356 1.724764 0.076288
+v -0.032356 1.723495 0.069908
+v -0.020567 1.728378 0.069908
+v -0.021465 1.729275 0.076288
+v -0.024020 1.731831 0.081697
+v -0.027845 1.735656 0.085311
+v 0.044282 1.751956 0.069841
+v 0.043385 1.751058 0.076221
+v 0.040829 1.748503 0.081630
+v 0.037004 1.744678 0.085244
+v 0.032493 1.746547 0.085244
+v 0.032493 1.751956 0.081630
+v 0.032493 1.755570 0.076221
+v 0.032493 1.756839 0.069841
+v 0.020704 1.751956 0.069841
+v 0.021601 1.751059 0.076221
+v 0.024157 1.748503 0.081630
+v 0.027982 1.744678 0.085244
+v 0.032493 1.740167 0.086513
+v 0.026113 1.740167 0.085244
+v 0.020704 1.740167 0.081630
+v 0.017090 1.740167 0.076221
+v 0.015821 1.740167 0.069841
+v 0.020704 1.728378 0.069841
+v 0.021601 1.729275 0.076221
+v 0.024157 1.731831 0.081630
+v 0.027982 1.735656 0.085244
+v 0.032493 1.733787 0.085244
+v 0.032493 1.728378 0.081630
+v 0.032493 1.724764 0.076221
+v 0.032493 1.723495 0.069841
+v 0.044282 1.728378 0.069841
+v 0.043385 1.729275 0.076221
+v 0.040829 1.731831 0.081630
+v 0.037004 1.735656 0.085244
+v 0.038873 1.740167 0.085244
+v 0.044282 1.740167 0.081630
+v 0.047896 1.740167 0.076221
+v 0.049165 1.740167 0.069841
+v -0.100955 0.562082 -0.055519
+v -0.139085 0.568177 -0.073664
+v -0.177215 0.574273 -0.055519
+v -0.193009 0.576798 -0.011716
+v -0.177215 0.574273 0.032088
+v -0.139085 0.568177 0.053507
+v -0.100955 0.562082 0.032088
+v -0.085161 0.559557 -0.011716
+v -0.081718 0.630116 -0.061458
+v -0.128839 0.636041 -0.079377
+v -0.175961 0.641966 -0.061458
+v -0.195479 0.644420 -0.005828
+v -0.175961 0.641966 0.049802
+v -0.128839 0.636678 0.070935
+v -0.081718 0.630116 0.049802
+v -0.062199 0.627662 -0.005828
+v -0.046760 0.778096 -0.068404
+v -0.107066 0.784189 -0.097090
+v -0.167371 0.790282 -0.068404
+v -0.192350 0.792806 0.000850
+v -0.167371 0.790282 0.070104
+v -0.107066 0.784189 0.100473
+v -0.046760 0.778096 0.070104
+v -0.021781 0.775572 0.000850
+v -0.097675 0.876684 -0.106817
+v -0.165198 0.882608 -0.075282
+v -0.193168 0.885063 0.000850
+v -0.165198 0.882608 0.076982
+v -0.097675 0.876684 0.111042
+v -0.000000 0.868305 0.000850
+v -0.117521 0.480258 -0.093913
+v -0.158176 0.484839 -0.114096
+v -0.198830 0.484932 -0.093318
+v -0.215669 0.480481 -0.043750
+v -0.198830 0.474096 0.005572
+v -0.158176 0.469515 0.025755
+v -0.117522 0.469422 0.004977
+v -0.100682 0.473872 -0.044591
+v -0.145262 0.534017 -0.085305
+v -0.110702 0.528678 -0.066932
+v -0.179822 0.537111 -0.066647
+v -0.194137 0.536148 -0.021887
+v -0.179822 0.531693 0.022755
+v -0.145262 0.526355 0.041128
+v -0.110702 0.523260 0.022470
+v -0.096387 0.524223 -0.022290
+v -0.080202 0.951451 -0.140820
+v -0.152695 0.957376 -0.100630
+v -0.182723 0.959830 -0.003602
+v -0.152695 0.957376 0.093426
+v -0.080202 0.951451 0.133616
+v -0.063169 1.040780 -0.133246
+v -0.130693 1.046705 -0.092997
+v -0.158662 1.049159 0.004173
+v -0.130693 1.046705 0.101343
+v -0.063169 1.040780 0.141593
+v -0.058120 1.123998 -0.103349
+v -0.125903 1.123998 -0.066587
+v -0.153979 1.123998 0.022164
+v -0.125903 1.123998 0.110916
+v -0.058120 1.123998 0.147678
+v 0.000000 0.953011 -0.127545
+v 0.000000 1.039823 -0.129410
+v 0.000000 1.123998 -0.098510
+v -0.065920 0.700805 -0.063973
+v -0.118799 0.706729 -0.091123
+v -0.171678 0.712654 -0.063973
+v -0.193581 0.715108 -0.002489
+v -0.171678 0.712654 0.058995
+v -0.118799 0.706729 0.084462
+v -0.065920 0.700805 0.058995
+v -0.044016 0.698351 -0.002489
+v 0.100955 0.562082 -0.055519
+v 0.139085 0.568177 -0.073664
+v 0.177215 0.574273 -0.055519
+v 0.193009 0.576798 -0.011716
+v 0.177215 0.574273 0.032088
+v 0.139085 0.568177 0.053507
+v 0.100955 0.562082 0.032088
+v 0.085161 0.559557 -0.011716
+v 0.081718 0.630116 -0.061458
+v 0.128839 0.636041 -0.079377
+v 0.175961 0.641966 -0.061458
+v 0.195479 0.644420 -0.005828
+v 0.175961 0.641966 0.049802
+v 0.128839 0.636678 0.070935
+v 0.081718 0.630116 0.049802
+v 0.062199 0.627662 -0.005828
+v 0.046760 0.778096 -0.068404
+v 0.107066 0.784189 -0.097090
+v 0.167371 0.790282 -0.068404
+v 0.192350 0.792806 0.000850
+v 0.167371 0.790282 0.070104
+v 0.107066 0.784189 0.100473
+v 0.046760 0.778096 0.070104
+v 0.021781 0.775572 0.000850
+v -0.000000 0.870759 -0.075282
+v 0.097675 0.876684 -0.106817
+v 0.165198 0.882608 -0.075282
+v 0.193168 0.885063 0.000850
+v 0.165198 0.882608 0.076982
+v 0.097675 0.876684 0.111042
+v -0.000000 0.876858 0.083081
+v 0.117521 0.480258 -0.093913
+v 0.158176 0.484839 -0.114096
+v 0.198830 0.484932 -0.093318
+v 0.215669 0.480481 -0.043750
+v 0.198830 0.474096 0.005572
+v 0.158176 0.469515 0.025755
+v 0.117522 0.469422 0.004977
+v 0.100682 0.473872 -0.044591
+v 0.145262 0.534017 -0.085305
+v 0.110702 0.528678 -0.066932
+v 0.179822 0.537111 -0.066647
+v 0.194137 0.536148 -0.021887
+v 0.179822 0.531693 0.022755
+v 0.145262 0.526355 0.041128
+v 0.110702 0.523260 0.022470
+v 0.096387 0.524223 -0.022290
+v 0.080202 0.951451 -0.140820
+v 0.152695 0.957376 -0.100630
+v 0.182723 0.959830 -0.003602
+v 0.152695 0.957376 0.093426
+v 0.080202 0.951451 0.133616
+v 0.063169 1.040780 -0.133246
+v 0.130693 1.046705 -0.092997
+v 0.158662 1.049159 0.004173
+v 0.130693 1.046705 0.101343
+v 0.063169 1.040780 0.141593
+v 0.058120 1.123998 -0.103349
+v 0.125903 1.123998 -0.066587
+v 0.153979 1.123998 0.022164
+v 0.125903 1.123998 0.110916
+v 0.058120 1.123998 0.147678
+v -0.000000 0.940066 0.136277
+v 0.000000 1.038324 0.144000
+v 0.000000 1.123998 0.147301
+v 0.065920 0.700805 -0.063973
+v 0.118799 0.706729 -0.091123
+v 0.171678 0.712654 -0.063973
+v 0.193581 0.715108 -0.002489
+v 0.171678 0.712654 0.058995
+v 0.118799 0.706729 0.084462
+v 0.065920 0.700805 0.058995
+v 0.044016 0.698351 -0.002489
+v 0.134275 1.530679 -0.176386
+v 0.172047 1.568379 -0.134707
+v 0.183198 1.581694 -0.087722
+v 0.183899 1.582353 -0.037207
+v 0.175968 1.570682 0.009387
+v 0.154211 1.545088 0.050300
+v 0.127586 1.516320 0.085776
+v 0.090502 1.480065 0.118043
+v 0.048199 1.439660 0.139210
+v 0.004523 1.397720 0.152934
+v -0.046749 1.346165 0.168389
+v -0.100793 1.286092 0.157968
+v -0.142447 1.245674 0.120062
+v -0.172509 1.215475 0.065591
+v -0.184084 1.200966 0.010595
+v -0.189708 1.193441 -0.037206
+v -0.183778 1.199644 -0.083800
+v -0.161577 1.220932 -0.127256
+v -0.125529 1.256296 -0.164504
+v -0.082149 1.299133 -0.193113
+v -0.040545 1.343281 -0.203115
+v 0.004932 1.390315 -0.209998
+v 0.049917 1.437272 -0.211098
+v 0.091361 1.483013 -0.199357
+v 0.085005 1.564355 -0.174013
+v 0.115650 1.595672 -0.131694
+v 0.128002 1.611723 -0.087199
+v 0.130140 1.610316 -0.037207
+v 0.123674 1.601299 0.009387
+v 0.103645 1.579924 0.048363
+v 0.078677 1.552097 0.085776
+v 0.047546 1.519726 0.111321
+v 0.006099 1.478006 0.130594
+v -0.039131 1.432221 0.142984
+v -0.086835 1.384427 0.149293
+v -0.134336 1.337502 0.138490
+v -0.172510 1.300595 0.106263
+v -0.197874 1.272699 0.058544
+v -0.209579 1.258838 0.009387
+v -0.212954 1.250003 -0.037206
+v -0.207024 1.256206 -0.083800
+v -0.189637 1.274392 -0.127219
+v -0.162299 1.301960 -0.167083
+v -0.125744 1.339687 -0.198121
+v -0.084020 1.384709 -0.206740
+v -0.038853 1.432207 -0.209998
+v 0.006131 1.479163 -0.211098
+v 0.048350 1.524587 -0.199694
+v 0.080027 1.559096 -0.168589
+v 0.109462 1.589176 -0.127940
+v 0.121327 1.604594 -0.085200
+v 0.123380 1.603243 -0.037181
+v 0.117169 1.594581 0.007574
+v 0.097931 1.574050 0.045012
+v 0.073948 1.547321 0.080948
+v 0.044027 1.516185 0.105412
+v 0.004235 1.476154 0.123997
+v -0.039210 1.432176 0.135898
+v -0.085042 1.386244 0.141913
+v -0.130640 1.341176 0.131492
+v -0.167326 1.305744 0.100627
+v -0.191689 1.278949 0.054791
+v -0.202932 1.265635 0.007574
+v -0.206174 1.257149 -0.037181
+v -0.200478 1.263107 -0.081936
+v -0.183777 1.280576 -0.123641
+v -0.157525 1.307029 -0.161982
+v -0.122402 1.343267 -0.191843
+v -0.082329 1.386534 -0.199939
+v -0.038943 1.432166 -0.203012
+v 0.004265 1.477266 -0.204210
+v 0.044818 1.520897 -0.193256
+v 0.128970 1.525091 -0.170732
+v 0.165253 1.561306 -0.130695
+v 0.175966 1.574095 -0.085562
+v 0.176639 1.574728 -0.037037
+v 0.169020 1.563518 0.007721
+v 0.148120 1.538932 0.047022
+v 0.122544 1.511298 0.081100
+v 0.086903 1.476429 0.112024
+v 0.046286 1.437658 0.132429
+v 0.004330 1.397371 0.145612
+v -0.044931 1.347823 0.160413
+v -0.096818 1.290121 0.150358
+v -0.136849 1.251315 0.114035
+v -0.165727 1.222306 0.061711
+v -0.176846 1.208368 0.008882
+v -0.182248 1.201140 -0.037037
+v -0.176552 1.207098 -0.081795
+v -0.155226 1.227548 -0.123538
+v -0.120598 1.261518 -0.159318
+v -0.078927 1.302668 -0.186801
+v -0.038970 1.345081 -0.196253
+v 0.004724 1.390260 -0.202879
+v 0.047935 1.435364 -0.204077
+v 0.087747 1.479303 -0.192798
+v -0.236368 0.092607 -0.020215
+v -0.244447 0.050649 0.055733
+v -0.160035 0.050649 0.068862
+v -0.158087 0.096969 -0.009511
+v -0.231907 0.050962 0.096377
+v -0.171927 0.050962 0.109907
+v -0.198856 0.056750 0.063817
+v -0.200434 0.099614 -0.008311
+v -0.203658 0.053735 0.117253
+v -0.228066 0.128577 -0.048921
+v -0.191707 0.128577 -0.030516
+v -0.155310 0.128577 -0.040374
+v -0.243809 0.048939 -0.062636
+v -0.259032 0.034710 0.052294
+v -0.229486 0.128577 -0.086203
+v -0.215595 0.128577 -0.123264
+v -0.215978 0.054773 -0.140594
+v -0.166330 0.128577 -0.141207
+v -0.168375 0.056821 -0.160469
+v -0.138088 0.128577 -0.118289
+v -0.138284 0.053982 -0.136358
+v -0.140126 0.128577 -0.082307
+v -0.145418 0.049313 -0.053791
+v -0.142801 0.033877 0.063946
+v -0.241657 0.038506 0.108880
+v -0.163953 0.037606 0.125343
+v -0.203658 0.036372 0.132175
+v -0.240419 0.028025 -0.064598
+v -0.255085 0.016737 0.039452
+v -0.214742 0.028524 -0.135022
+v -0.170136 0.028524 -0.153646
+v -0.141940 0.028524 -0.131052
+v -0.153248 0.027295 -0.055831
+v -0.145661 0.016737 0.050411
+v -0.238718 0.016737 0.097813
+v -0.164969 0.016737 0.113922
+v -0.202729 0.016737 0.120323
+v -0.242952 0.028025 -0.066538
+v -0.258034 0.016737 0.042949
+v -0.215666 0.028524 -0.141348
+v -0.168821 0.028524 -0.160906
+v -0.139209 0.028524 -0.137178
+v -0.150897 0.027295 -0.057712
+v -0.143524 0.016737 0.054426
+v -0.240914 0.016737 0.103692
+v -0.164210 0.016737 0.120066
+v -0.203423 0.016737 0.126789
+v -0.258034 -0.001088 0.025696
+v -0.242952 0.013555 -0.070778
+v -0.215666 0.014054 -0.141348
+v -0.168821 0.014054 -0.160906
+v -0.139209 0.014054 -0.137178
+v -0.150897 0.012826 -0.061952
+v -0.143524 -0.001088 0.037173
+v -0.240914 -0.000249 0.103692
+v -0.164210 -0.000249 0.120066
+v -0.203423 -0.000249 0.126789
+v -0.242952 -0.000311 -0.070778
+v -0.215666 0.000188 -0.141348
+v -0.168821 0.000188 -0.160906
+v -0.139209 0.000188 -0.137178
+v -0.150897 -0.001041 -0.061952
+v -0.240407 0.067287 0.012779
+v -0.157989 0.070033 0.027636
+v -0.199645 0.074798 0.025643
+v -0.254610 0.041825 -0.006398
+v -0.148123 0.042231 -0.000025
+v -0.250941 0.022381 -0.013800
+v -0.154169 0.022381 -0.007738
+v -0.253682 0.022381 -0.013022
+v -0.151925 0.022381 -0.006671
+v -0.253682 0.005814 -0.021702
+v -0.151925 0.005814 -0.015351
+v -0.218563 0.209613 -0.046429
+v -0.188733 0.208412 -0.021345
+v -0.148752 0.208412 -0.032174
+v -0.230231 0.208412 -0.082515
+v -0.214972 0.208412 -0.125426
+v -0.160857 0.208412 -0.142935
+v -0.129834 0.208412 -0.119961
+v -0.132073 0.208412 -0.078236
+v -0.184486 0.296737 -0.005237
+v -0.225084 0.299002 -0.034678
+v -0.140596 0.296697 -0.019914
+v -0.236935 0.298150 -0.081582
+v -0.217650 0.297630 -0.136721
+v -0.158346 0.295603 -0.157599
+v -0.110046 0.294732 -0.129811
+v -0.112876 0.294808 -0.076172
+v -0.180417 0.388284 0.013613
+v -0.219940 0.392383 -0.019552
+v -0.129895 0.386004 -0.002073
+v -0.236443 0.395326 -0.069991
+v -0.219625 0.400030 -0.135825
+v -0.144725 0.400515 -0.158651
+v -0.091043 0.394958 -0.126268
+v -0.093351 0.389803 -0.062979
+v -0.141647 0.491328 -0.114189
+v -0.205701 0.490563 -0.094984
+v -0.172100 0.480332 0.031533
+v -0.088130 0.486878 -0.030961
+v -0.124555 0.485816 0.028877
+v -0.085756 0.492816 -0.089075
+v -0.138819 0.500966 -0.123683
+v -0.212734 0.500023 -0.101320
+v -0.229349 0.492623 -0.040656
+v -0.212929 0.490855 0.006320
+v -0.174315 0.487937 0.044232
+v -0.078510 0.469649 -0.030733
+v -0.118959 0.469167 0.037975
+v -0.075626 0.476194 -0.096815
+v -0.135258 0.486616 -0.136305
+v -0.219656 0.487755 -0.110271
+v -0.239055 0.480310 -0.041331
+v -0.221618 0.477597 0.013127
+v -0.176187 0.472900 0.055532
+v -0.073827 0.311152 -0.055639
+v -0.116017 0.309592 0.028478
+v -0.066537 0.324125 -0.137977
+v -0.244434 0.339411 -0.148584
+v -0.277813 0.321962 -0.063759
+v -0.262464 0.316457 0.009962
+v -0.191486 0.312070 0.054821
+v -0.178630 0.357606 -0.193864
+v -0.123421 0.350867 -0.185934
+v -0.118294 0.398249 0.026084
+v -0.078910 0.396001 -0.044382
+v -0.074782 0.405104 -0.114011
+v -0.225539 0.420431 -0.125449
+v -0.254013 0.412894 -0.052038
+v -0.236933 0.409543 0.008791
+v -0.180250 0.404852 0.047154
+v -0.153892 0.427512 -0.158986
+v -0.129930 0.424512 -0.155542
+v -0.204864 0.482881 -0.001814
+v -0.129203 0.478420 0.018134
+v -0.219844 0.485703 -0.041760
+v -0.095093 0.485847 -0.085518
+v -0.097055 0.480678 -0.033262
+v -0.055529 1.493171 0.092907
+v -0.055632 1.451355 0.129636
+v -0.040152 1.385805 0.146414
+v -0.031399 1.323361 0.152706
+v -0.026148 1.252309 0.159674
+v -0.023899 1.183441 0.163047
+v -0.023899 1.119257 0.159816
+v -0.035756 1.024998 0.164243
+v -0.057075 0.882970 0.166144
+v -0.087342 0.767263 0.175068
+v -0.130256 0.600958 0.203083
+v -0.263084 0.602740 0.125120
+v -0.303530 0.629328 -0.012713
+v -0.279738 0.659615 -0.142583
+v -0.180476 0.680835 -0.218781
+v -0.052293 0.696431 -0.229468
+v -0.000000 0.903639 -0.186417
+v -0.000000 1.019671 -0.164335
+v 0.000000 1.119257 -0.127489
+v -0.021313 0.802760 -0.209410
+v 0.000000 1.183441 -0.137360
+v 0.000000 1.376735 -0.198452
+v 0.000000 1.451759 -0.198452
+v 0.000000 1.524567 -0.186393
+v -0.200106 0.766720 0.128702
+v -0.256106 0.773491 0.005349
+v -0.222970 0.788889 -0.105964
+v -0.139229 0.802427 -0.183604
+v -0.166305 0.883253 0.130780
+v -0.216473 0.887417 0.005856
+v -0.194182 0.897068 -0.096436
+v -0.113426 0.903290 -0.164762
+v -0.136724 1.018924 0.134398
+v -0.186892 1.015852 0.017915
+v -0.164600 1.017062 -0.083171
+v -0.086115 1.020203 -0.143668
+v -0.121152 1.119257 0.137785
+v -0.172670 1.119257 0.018168
+v -0.149779 1.119257 -0.074245
+v -0.077684 1.119257 -0.119280
+v -0.120262 1.183441 0.143953
+v -0.173867 1.183441 0.019491
+v -0.162576 1.183441 -0.083776
+v -0.083964 1.183441 -0.137626
+v -0.120061 1.252504 0.134398
+v -0.185320 1.251011 0.010953
+v -0.181651 1.243637 -0.097475
+v -0.101614 1.250648 -0.152374
+v -0.130367 1.318038 0.132279
+v -0.212258 1.300892 0.010329
+v -0.206866 1.296449 -0.103040
+v -0.124560 1.308405 -0.178665
+v -0.309009 1.485512 -0.042012
+v -0.299405 1.454274 0.011206
+v -0.262364 1.400470 0.013574
+v -0.246013 1.343623 -0.013905
+v -0.232733 1.329661 -0.096472
+v -0.249925 1.351043 -0.156010
+v -0.280159 1.425431 -0.159697
+v -0.300754 1.477066 -0.123508
+v -0.358489 1.441829 -0.053517
+v -0.341332 1.415725 -0.016209
+v -0.312568 1.371026 0.007202
+v -0.295059 1.326406 -0.025422
+v -0.284217 1.313647 -0.093763
+v -0.293527 1.334403 -0.159059
+v -0.329213 1.395204 -0.158847
+v -0.350392 1.432640 -0.118576
+v -0.153061 1.396596 0.117845
+v -0.234974 1.401947 0.041187
+v -0.232898 1.345370 -0.160297
+v -0.135208 1.361853 -0.200577
+v -0.418271 1.393451 -0.067665
+v -0.404607 1.371110 -0.028798
+v -0.378331 1.331015 -0.009391
+v -0.358364 1.296543 -0.036435
+v -0.352312 1.285127 -0.093088
+v -0.362546 1.300656 -0.147216
+v -0.392129 1.351058 -0.147040
+v -0.412726 1.386348 -0.113657
+v -0.238603 1.451604 0.050911
+v -0.247663 1.426305 -0.187326
+v -0.137532 1.441997 -0.201822
+v -0.161963 1.461164 0.112142
+v -0.249717 1.546276 -0.020199
+v -0.242352 1.535791 -0.122329
+v -0.164602 1.516542 0.061273
+v -0.126600 1.523267 -0.170931
+v -0.096686 1.597695 -0.035012
+v -0.091318 1.612576 -0.091144
+v -0.079937 1.584289 0.006058
+v -0.052429 1.559129 0.039906
+v -0.059511 1.620940 -0.125205
+v -0.127213 1.655769 -0.030739
+v -0.121658 1.675305 -0.095090
+v -0.109973 1.639888 0.018116
+v -0.080687 1.612360 0.057116
+v -0.088142 1.685365 -0.137990
+v 0.000000 1.693757 -0.156027
+v -0.165594 1.623511 -0.109647
+v -0.170923 1.602495 -0.021107
+v -0.104190 1.560981 0.096990
+v -0.146253 1.584960 0.045949
+v -0.097500 1.639982 -0.170080
+v 0.000000 1.645165 -0.191679
+v -0.168111 1.573843 -0.106737
+v -0.178915 1.570728 -0.027279
+v -0.128327 1.552606 0.035805
+v -0.057487 1.531572 0.066407
+v -0.100267 1.576621 -0.151559
+v -0.470204 1.368917 -0.069429
+v -0.454158 1.346519 -0.036405
+v -0.426572 1.304602 -0.020104
+v -0.408229 1.267183 -0.043107
+v -0.405618 1.253222 -0.091268
+v -0.419175 1.267909 -0.137238
+v -0.448776 1.321324 -0.137073
+v -0.467372 1.359826 -0.108665
+v -0.509538 1.307247 -0.023719
+v -0.521968 1.326629 -0.055033
+v -0.487954 1.270359 -0.008292
+v -0.472451 1.236567 -0.030094
+v -0.469302 1.223250 -0.075754
+v -0.479316 1.235488 -0.119334
+v -0.503579 1.283145 -0.119189
+v -0.519343 1.317980 -0.092259
+v -0.576228 1.275383 -0.040033
+v -0.563878 1.261239 -0.011934
+v -0.544363 1.233828 0.001865
+v -0.532909 1.208638 -0.017657
+v -0.533244 1.198450 -0.058594
+v -0.544480 1.207245 -0.097677
+v -0.564582 1.242551 -0.097592
+v -0.575978 1.268567 -0.073467
+v -0.621947 1.243404 -0.024871
+v -0.606588 1.231470 0.001990
+v -0.584973 1.207811 0.013254
+v -0.574175 1.185285 -0.008347
+v -0.577637 1.175574 -0.050069
+v -0.592578 1.182565 -0.088309
+v -0.614130 1.213647 -0.085271
+v -0.624485 1.236964 -0.058985
+v -0.548048 1.283423 -0.000028
+v -0.569435 1.303588 -0.033291
+v -0.519235 1.245224 0.013920
+v -0.506848 1.210827 -0.012829
+v -0.513994 1.197634 -0.064495
+v -0.535664 1.210644 -0.111848
+v -0.562988 1.259448 -0.108086
+v -0.574545 1.294888 -0.075536
+v -0.518948 1.363826 -0.037351
+v -0.490553 1.334002 0.007940
+v -0.453133 1.278392 0.026932
+v -0.438403 1.229340 -0.009490
+v -0.449396 1.211424 -0.079838
+v -0.478726 1.231261 -0.144314
+v -0.513263 1.301594 -0.139192
+v -0.526753 1.352042 -0.094871
+v 0.055529 1.493171 0.092907
+v 0.055632 1.451355 0.129636
+v 0.040152 1.385805 0.146414
+v 0.031399 1.323361 0.152706
+v 0.026148 1.252309 0.159674
+v 0.023899 1.183441 0.163047
+v 0.023899 1.119257 0.159816
+v 0.035756 1.024998 0.164243
+v 0.057075 0.882970 0.166144
+v 0.087342 0.767263 0.175068
+v 0.130256 0.600958 0.203083
+v 0.263084 0.602740 0.125120
+v 0.303530 0.629328 -0.012713
+v 0.279738 0.659615 -0.142583
+v 0.180476 0.680835 -0.218781
+v 0.052293 0.696431 -0.229468
+v 0.021313 0.802760 -0.209410
+v 0.000000 1.254463 -0.158657
+v -0.000000 1.315609 -0.183981
+v 0.200106 0.766720 0.128702
+v 0.256106 0.773491 0.005349
+v 0.222970 0.788889 -0.105964
+v 0.139229 0.802427 -0.183604
+v 0.166305 0.883253 0.130780
+v 0.216473 0.887417 0.005856
+v 0.194182 0.897068 -0.096436
+v 0.113426 0.903290 -0.164762
+v 0.136724 1.018924 0.134398
+v 0.186892 1.015852 0.017915
+v 0.164600 1.017062 -0.083171
+v 0.086115 1.020203 -0.143668
+v 0.121152 1.119257 0.137785
+v 0.172670 1.119257 0.018168
+v 0.149779 1.119257 -0.074245
+v 0.077684 1.119257 -0.119280
+v 0.120262 1.183441 0.143953
+v 0.173867 1.183441 0.019491
+v 0.162576 1.183441 -0.083776
+v 0.083964 1.183441 -0.137626
+v 0.120061 1.252504 0.134398
+v 0.185320 1.251011 0.010953
+v 0.181651 1.243637 -0.097475
+v 0.101614 1.250648 -0.152374
+v 0.130367 1.318038 0.132279
+v 0.212258 1.300892 0.010329
+v 0.206866 1.296449 -0.103040
+v 0.124560 1.308405 -0.178665
+v 0.309009 1.485512 -0.042012
+v 0.299405 1.454274 0.011206
+v 0.262364 1.400470 0.013574
+v 0.246013 1.343623 -0.013905
+v 0.232733 1.329661 -0.096472
+v 0.249925 1.351043 -0.156010
+v 0.280159 1.425431 -0.159697
+v 0.300754 1.477066 -0.123508
+v 0.358489 1.441829 -0.053517
+v 0.341332 1.415725 -0.016209
+v 0.312568 1.371026 0.007202
+v 0.295059 1.326406 -0.025422
+v 0.284217 1.313647 -0.093763
+v 0.293527 1.334403 -0.159059
+v 0.329213 1.395204 -0.158847
+v 0.350392 1.432640 -0.118576
+v 0.153061 1.396596 0.117845
+v 0.234974 1.401947 0.041187
+v 0.232898 1.345370 -0.160297
+v 0.135208 1.361853 -0.200577
+v 0.418271 1.393451 -0.067665
+v 0.404607 1.371110 -0.028798
+v 0.378331 1.331015 -0.009391
+v 0.358364 1.296543 -0.036435
+v 0.352312 1.285127 -0.093088
+v 0.362546 1.300656 -0.147216
+v 0.392129 1.351058 -0.147040
+v 0.412726 1.386348 -0.113657
+v 0.238603 1.451604 0.050911
+v 0.247663 1.426305 -0.187326
+v 0.137532 1.441997 -0.201822
+v 0.161963 1.461164 0.112142
+v 0.249717 1.546276 -0.020199
+v 0.242352 1.535791 -0.122329
+v 0.164602 1.516542 0.061273
+v 0.126600 1.523267 -0.170931
+v 0.096686 1.597695 -0.035012
+v 0.091318 1.612576 -0.091144
+v 0.079937 1.584289 0.006058
+v 0.052429 1.559129 0.039906
+v 0.059511 1.620940 -0.125205
+v 0.000000 1.628451 -0.141560
+v 0.127213 1.655769 -0.030739
+v 0.121658 1.675305 -0.095090
+v 0.109973 1.639888 0.018116
+v 0.080687 1.612360 0.057116
+v 0.088142 1.685365 -0.137990
+v 0.165594 1.623511 -0.109647
+v 0.170923 1.602495 -0.021107
+v 0.104190 1.560981 0.096990
+v 0.146253 1.584960 0.045949
+v 0.097500 1.639982 -0.170080
+v 0.168111 1.573843 -0.106737
+v 0.178915 1.570728 -0.027279
+v 0.128327 1.552606 0.035805
+v 0.057487 1.531572 0.066407
+v 0.000000 1.584163 -0.163783
+v 0.100267 1.576621 -0.151559
+v 0.470204 1.368917 -0.069429
+v 0.454158 1.346519 -0.036405
+v 0.426572 1.304602 -0.020104
+v 0.408229 1.267183 -0.043107
+v 0.405618 1.253222 -0.091268
+v 0.419175 1.267909 -0.137238
+v 0.448776 1.321324 -0.137073
+v 0.467372 1.359826 -0.108665
+v 0.509538 1.307247 -0.023719
+v 0.521968 1.326629 -0.055033
+v 0.487954 1.270359 -0.008292
+v 0.472451 1.236567 -0.030094
+v 0.469302 1.223250 -0.075754
+v 0.479316 1.235488 -0.119334
+v 0.503579 1.283145 -0.119189
+v 0.519343 1.317980 -0.092259
+v 0.576228 1.275383 -0.040033
+v 0.563878 1.261239 -0.011934
+v 0.544363 1.233828 0.001865
+v 0.532909 1.208638 -0.017657
+v 0.533244 1.198450 -0.058594
+v 0.544480 1.207245 -0.097677
+v 0.564582 1.242551 -0.097592
+v 0.575978 1.268567 -0.073467
+v 0.621947 1.243404 -0.024871
+v 0.606588 1.231470 0.001990
+v 0.584973 1.207811 0.013254
+v 0.574175 1.185285 -0.008347
+v 0.577637 1.175574 -0.050069
+v 0.592578 1.182565 -0.088309
+v 0.614130 1.213647 -0.085271
+v 0.624485 1.236964 -0.058985
+v 0.548048 1.283423 -0.000028
+v 0.569435 1.303588 -0.033291
+v 0.519235 1.245224 0.013920
+v 0.506848 1.210827 -0.012829
+v 0.513994 1.197634 -0.064495
+v 0.535664 1.210644 -0.111848
+v 0.562988 1.259448 -0.108086
+v 0.574545 1.294888 -0.075536
+v 0.518948 1.363826 -0.037351
+v 0.490553 1.334002 0.007940
+v 0.453133 1.278392 0.026932
+v 0.438403 1.229340 -0.009490
+v 0.449396 1.211424 -0.079838
+v 0.478726 1.231261 -0.144314
+v 0.513263 1.301594 -0.139192
+v 0.526753 1.352042 -0.094871
+v 0.088152 1.183441 -0.144985
+v 0.170685 1.183441 -0.088437
+v 0.182540 1.183441 0.020003
+v 0.126261 1.183441 0.150700
+v 0.081559 1.119257 -0.128551
+v 0.157250 1.119257 -0.078428
+v 0.181283 1.119257 0.018614
+v 0.127195 1.119257 0.144223
+v 0.025091 1.119257 0.167358
+v 0.025091 1.183441 0.170750
+v -0.088152 1.183441 -0.144985
+v -0.170685 1.183441 -0.088437
+v -0.182540 1.183441 0.020003
+v -0.126261 1.183441 0.150700
+v -0.081559 1.119257 -0.128551
+v -0.157250 1.119257 -0.078428
+v -0.181283 1.119257 0.018614
+v -0.127195 1.119257 0.144223
+v -0.000000 1.183441 -0.144198
+v -0.000000 1.119257 -0.134141
+v -0.025091 1.119257 0.167358
+v -0.025091 1.183441 0.170750
+v 0.032665 1.515867 0.061271
+v 0.000046 1.506738 0.057291
+v 0.009008 1.509201 0.059572
+v 0.014802 1.510792 0.060556
+v 0.022246 1.512831 0.061265
+v 0.004174 1.507801 0.058344
+v 0.047380 1.520089 0.058843
+v 0.086181 1.529302 0.036547
+v 0.104020 1.533417 0.016887
+v 0.127030 1.565279 -0.112151
+v 0.140316 1.569182 -0.078594
+v 0.140484 1.563938 -0.046658
+v 0.132480 1.553798 -0.020614
+v 0.119583 1.541506 -0.002499
+v 0.103516 1.555723 -0.139450
+v 0.674888 1.110830 -0.003673
+v 0.612610 1.157199 0.002101
+v 0.674545 1.117330 0.019286
+v 0.706858 1.099530 0.023730
+v 0.710139 1.097504 0.045483
+v 0.669417 1.155014 0.039740
+v 0.647492 1.157972 0.056044
+v 0.661499 1.177832 0.004751
+v 0.635999 1.142938 0.053810
+v 0.729386 1.080314 0.059558
+v 0.719635 1.088437 0.052730
+v 0.744902 1.067028 -0.001493
+v 0.726869 1.071270 -0.000494
+v 0.736876 1.060203 0.001079
+v 0.743075 1.053009 0.001969
+v 0.645372 1.134767 0.068654
+v 0.662357 1.126353 0.097420
+v 0.657118 1.139621 0.080730
+v 0.732353 1.052126 -0.034486
+v 0.713486 1.062962 -0.030949
+v 0.718813 1.054992 -0.030781
+v 0.724174 1.048125 -0.032724
+v 0.754945 1.052232 0.000265
+v 0.753210 1.051807 0.042524
+v 0.743049 1.070876 0.068770
+v 0.748944 1.075721 0.067038
+v 0.631187 1.182153 -0.060137
+v 0.608335 1.195320 -0.067070
+v 0.559506 1.202946 -0.041688
+v 0.562544 1.220983 -0.017718
+v 0.669640 1.104069 -0.024403
+v 0.627276 1.139434 0.009177
+v 0.714807 1.090642 0.027332
+v 0.695859 1.107043 0.027280
+v 0.727431 1.078475 0.031722
+v 0.696927 1.098358 0.001796
+v 0.703119 1.103989 0.038953
+v 0.633594 1.210668 -0.010901
+v 0.647811 1.194846 -0.002174
+v 0.652695 1.145887 0.071041
+v 0.712533 1.113137 0.036251
+v 0.719345 1.105960 0.042952
+v 0.728522 1.096502 0.050164
+v 0.737676 1.087669 0.056634
+v 0.705954 1.119005 0.023964
+v 0.716645 1.109843 0.021743
+v 0.725072 1.099576 0.024312
+v 0.747342 1.073881 0.033310
+v 0.736533 1.086177 0.029001
+v 0.696296 1.140563 0.016160
+v 0.708298 1.111171 -0.002280
+v 0.696457 1.132692 -0.009182
+v 0.708394 1.090153 -0.032321
+v 0.703739 1.097623 -0.031627
+v 0.715028 1.083526 -0.002103
+v 0.706621 1.091983 -0.003424
+v 0.724658 1.092521 -0.005640
+v 0.716293 1.102370 -0.006407
+v 0.735778 1.079242 -0.003190
+v 0.698534 1.082554 -0.028880
+v 0.690590 1.094611 -0.022870
+v 0.694321 1.089775 -0.029227
+v 0.705918 1.072451 -0.029914
+v 0.715476 1.079874 -0.032419
+v 0.650145 1.128751 0.079602
+v 0.661139 1.136280 0.088389
+v 0.664916 1.135274 0.096804
+v 0.655866 1.126043 0.089251
+v 0.727975 1.061423 -0.033305
+v 0.722408 1.069734 -0.032870
+v 0.750177 1.058739 -0.000720
+v 0.748876 1.047540 0.001710
+v 0.760269 1.057284 0.040446
+v 0.754922 1.065134 0.037294
+v 0.746595 1.058580 0.040406
+v 0.738799 1.066683 0.037092
+v 0.736467 1.074060 0.064212
+v 0.744538 1.081398 0.061437
+v 0.615434 1.228177 -0.023378
+v 0.590023 1.247385 -0.040312
+v 0.661068 1.157391 -0.045104
+v 0.664961 1.169456 -0.023274
+v 0.587070 1.181785 -0.037609
+v 0.559761 1.211244 -0.028605
+v 0.585196 1.196178 -0.011534
+v 0.633854 1.137880 -0.012377
+v 0.601909 1.175540 -0.005262
+v 0.578364 1.210416 -0.074700
+v 0.608685 1.163981 -0.034361
+v 0.621257 1.146775 -0.032980
+v 0.633379 1.131144 -0.031188
+v 0.703711 1.088645 -0.016576
+v 0.712716 1.079507 -0.014927
+v 0.725322 1.067865 -0.012271
+v 0.735923 1.057540 -0.009999
+v 0.742203 1.050307 -0.008593
+v 0.748456 1.045616 -0.006070
+v 0.755212 1.050032 -0.008025
+v 0.750431 1.057000 -0.010678
+v 0.744125 1.064766 -0.012315
+v 0.733938 1.075834 -0.014611
+v 0.722202 1.088450 -0.018332
+v 0.712501 1.098042 -0.021141
+v 0.700170 1.105421 -0.026439
+v 0.690631 1.125018 -0.031907
+v 0.646118 1.169501 -0.050893
+v 0.562504 1.198289 -0.055965
+v 0.591163 1.179253 -0.050869
+v 0.612975 1.162797 -0.047605
+v 0.625289 1.146584 -0.048665
+v 0.636769 1.132086 -0.048725
+v 0.668763 1.105041 -0.043369
+v 0.681188 1.094929 -0.040700
+v 0.687931 1.088314 -0.040485
+v 0.693752 1.080715 -0.040848
+v 0.701580 1.070576 -0.041451
+v 0.709330 1.060843 -0.041866
+v 0.715570 1.053672 -0.041779
+v 0.721939 1.047881 -0.041068
+v 0.729140 1.052229 -0.043852
+v 0.724430 1.060406 -0.044051
+v 0.718454 1.068123 -0.043548
+v 0.711056 1.077947 -0.043821
+v 0.703314 1.088221 -0.043762
+v 0.697523 1.096518 -0.043640
+v 0.691512 1.105148 -0.044287
+v 0.680400 1.116818 -0.047024
+v 0.649712 1.143939 -0.055466
+v 0.635474 1.155394 -0.056575
+v 0.619869 1.167972 -0.057263
+v 0.597704 1.182203 -0.061944
+v 0.568559 1.198926 -0.068300
+v 0.585402 1.188237 -0.024350
+v 0.604116 1.167808 -0.019721
+v 0.618151 1.151636 -0.015785
+v 0.707523 1.094909 0.010309
+v 0.715423 1.085616 0.013751
+v 0.727984 1.074069 0.020076
+v 0.739291 1.062430 0.025747
+v 0.746843 1.054016 0.029661
+v 0.753531 1.048433 0.033598
+v 0.760509 1.053722 0.031717
+v 0.755461 1.060904 0.027049
+v 0.748087 1.069597 0.022795
+v 0.737262 1.081977 0.017412
+v 0.726102 1.095113 0.011160
+v 0.717710 1.104636 0.006157
+v 0.651211 1.185025 -0.031012
+v 0.635891 1.199200 -0.039893
+v 0.615718 1.214473 -0.051091
+v 0.587649 1.231131 -0.065039
+v 0.580376 1.244796 -0.016765
+v 0.601626 1.222414 -0.000946
+v 0.617504 1.203980 0.011000
+v 0.630214 1.188406 0.019663
+v 0.645689 1.174979 0.034668
+v 0.687072 1.141182 0.038127
+v 0.701374 1.129937 0.043063
+v 0.709271 1.120481 0.048463
+v 0.716513 1.111768 0.053868
+v 0.726257 1.101887 0.060552
+v 0.735765 1.092832 0.066725
+v 0.742516 1.086052 0.071015
+v 0.747885 1.079823 0.074469
+v 0.741875 1.074101 0.076535
+v 0.734655 1.079178 0.074287
+v 0.727307 1.085463 0.069924
+v 0.717230 1.094135 0.063806
+v 0.707014 1.103360 0.056808
+v 0.698643 1.110361 0.051242
+v 0.688986 1.116561 0.045938
+v 0.674013 1.125840 0.039401
+v 0.623163 1.149869 0.034216
+v 0.613844 1.170335 0.018360
+v 0.604447 1.187261 0.007201
+v 0.588880 1.207248 -0.000362
+v 0.568976 1.232436 -0.011231
+v 0.679594 1.158810 0.010768
+v 0.680715 1.150920 -0.015581
+v 0.676328 1.141581 -0.037838
+v 0.665879 1.130452 -0.051364
+v 0.652273 1.117288 -0.046885
+v 0.650507 1.117073 -0.028105
+v 0.655369 1.126643 -0.009846
+v 0.653305 1.130948 0.012378
+v 0.652383 1.133142 0.035792
+v 0.651913 1.134051 0.048879
+v 0.656959 1.129360 0.062812
+v 0.662192 1.124307 0.073167
+v 0.667196 1.122067 0.083716
+v 0.670769 1.123390 0.093898
+v 0.674276 1.132866 0.093584
+v 0.670998 1.133584 0.083875
+v 0.667633 1.136297 0.075134
+v 0.663312 1.140577 0.065521
+v 0.661870 1.147834 0.051705
+v 0.066200 1.524831 0.051173
+v -0.000140 1.518403 -0.153647
+v 0.013576 1.521601 -0.156987
+v 0.030145 1.528860 -0.161555
+v 0.051938 1.537383 -0.163007
+v 0.077462 1.546570 -0.156404
+v -0.032671 1.515867 0.061272
+v -0.009013 1.509201 0.059572
+v -0.014807 1.510792 0.060556
+v -0.022251 1.512831 0.061265
+v -0.004179 1.507801 0.058344
+v -0.047385 1.520089 0.058843
+v -0.086187 1.529302 0.036547
+v -0.104025 1.533417 0.016887
+v -0.127035 1.565279 -0.112151
+v -0.140321 1.569182 -0.078594
+v -0.140489 1.563938 -0.046658
+v -0.132486 1.553798 -0.020614
+v -0.119588 1.541506 -0.002499
+v -0.103521 1.555723 -0.139450
+v -0.674908 1.110830 -0.003673
+v -0.612625 1.157199 0.002101
+v -0.674578 1.117330 0.019286
+v -0.706865 1.099530 0.023730
+v -0.710172 1.097507 0.045484
+v -0.669610 1.155001 0.039719
+v -0.647512 1.157971 0.056042
+v -0.661505 1.177832 0.004751
+v -0.636011 1.142938 0.053810
+v -0.729412 1.080313 0.059557
+v -0.719668 1.088437 0.052730
+v -0.744914 1.067028 -0.001493
+v -0.726889 1.071270 -0.000494
+v -0.736885 1.060203 0.001079
+v -0.743082 1.053009 0.001969
+v -0.645423 1.134767 0.068654
+v -0.662370 1.126353 0.097420
+v -0.657138 1.139620 0.080730
+v -0.732395 1.052120 -0.034486
+v -0.713543 1.062960 -0.030947
+v -0.718822 1.054992 -0.030781
+v -0.724193 1.048124 -0.032724
+v -0.755011 1.052230 0.000263
+v -0.753218 1.051807 0.042524
+v -0.743069 1.070876 0.068770
+v -0.748987 1.075720 0.067041
+v -0.631193 1.182153 -0.060137
+v -0.608340 1.195320 -0.067070
+v -0.559511 1.202946 -0.041688
+v -0.562549 1.220983 -0.017718
+v -0.669655 1.104069 -0.024403
+v -0.627285 1.139434 0.009177
+v -0.714824 1.090642 0.027332
+v -0.695874 1.107042 0.027280
+v -0.727443 1.078475 0.031723
+v -0.696946 1.098358 0.001796
+v -0.703138 1.103988 0.038953
+v -0.633599 1.210668 -0.010901
+v -0.647816 1.194846 -0.002174
+v -0.652935 1.145912 0.071046
+v -0.712544 1.113137 0.036251
+v -0.719353 1.105960 0.042952
+v -0.728530 1.096502 0.050164
+v -0.737684 1.087669 0.056634
+v -0.706039 1.119006 0.023963
+v -0.716664 1.109843 0.021743
+v -0.725084 1.099576 0.024312
+v -0.747346 1.073881 0.033310
+v -0.736545 1.086177 0.029001
+v -0.696304 1.140563 0.016160
+v -0.708312 1.111171 -0.002280
+v -0.696464 1.132692 -0.009182
+v -0.708408 1.090153 -0.032321
+v -0.703756 1.097623 -0.031627
+v -0.715046 1.083527 -0.002103
+v -0.706627 1.091983 -0.003424
+v -0.724670 1.092521 -0.005639
+v -0.716310 1.102371 -0.006407
+v -0.735788 1.079242 -0.003190
+v -0.698594 1.082554 -0.028880
+v -0.690607 1.094611 -0.022870
+v -0.694353 1.089775 -0.029227
+v -0.705983 1.072452 -0.029916
+v -0.715489 1.079874 -0.032419
+v -0.650156 1.128751 0.079602
+v -0.661221 1.136286 0.088391
+v -0.665107 1.135262 0.096802
+v -0.655875 1.126043 0.089251
+v -0.727985 1.061423 -0.033305
+v -0.722420 1.069735 -0.032870
+v -0.750205 1.058737 -0.000720
+v -0.748885 1.047540 0.001710
+v -0.760363 1.057276 0.040441
+v -0.754941 1.065133 0.037294
+v -0.746603 1.058580 0.040406
+v -0.738816 1.066683 0.037093
+v -0.736501 1.074059 0.064212
+v -0.744545 1.081398 0.061437
+v -0.615439 1.228176 -0.023378
+v -0.590028 1.247385 -0.040312
+v -0.661077 1.157391 -0.045104
+v -0.664968 1.169456 -0.023274
+v -0.587108 1.181786 -0.037609
+v -0.559767 1.211244 -0.028605
+v -0.585218 1.196178 -0.011534
+v -0.633879 1.137881 -0.012377
+v -0.601942 1.175540 -0.005261
+v -0.578369 1.210416 -0.074700
+v -0.608698 1.163982 -0.034361
+v -0.621275 1.146775 -0.032980
+v -0.633387 1.131144 -0.031187
+v -0.703722 1.088645 -0.016576
+v -0.712738 1.079508 -0.014927
+v -0.725348 1.067866 -0.012270
+v -0.735938 1.057540 -0.009999
+v -0.742232 1.050307 -0.008593
+v -0.748464 1.045616 -0.006070
+v -0.755247 1.050032 -0.008025
+v -0.750448 1.057000 -0.010678
+v -0.744135 1.064765 -0.012314
+v -0.733948 1.075834 -0.014611
+v -0.722212 1.088450 -0.018333
+v -0.712516 1.098042 -0.021142
+v -0.700181 1.105421 -0.026440
+v -0.690639 1.125018 -0.031907
+v -0.646125 1.169501 -0.050893
+v -0.562509 1.198289 -0.055965
+v -0.591175 1.179253 -0.050869
+v -0.612984 1.162797 -0.047605
+v -0.625322 1.146585 -0.048662
+v -0.636816 1.132088 -0.048720
+v -0.668772 1.105041 -0.043369
+v -0.681213 1.094929 -0.040701
+v -0.687948 1.088314 -0.040485
+v -0.693788 1.080716 -0.040849
+v -0.701636 1.070577 -0.041453
+v -0.709365 1.060843 -0.041866
+v -0.715577 1.053672 -0.041779
+v -0.721946 1.047881 -0.041068
+v -0.729147 1.052229 -0.043852
+v -0.724438 1.060406 -0.044051
+v -0.718462 1.068123 -0.043548
+v -0.711063 1.077947 -0.043821
+v -0.703320 1.088221 -0.043762
+v -0.697532 1.096518 -0.043640
+v -0.691530 1.105148 -0.044287
+v -0.680408 1.116818 -0.047024
+v -0.649726 1.143939 -0.055466
+v -0.635483 1.155394 -0.056575
+v -0.619877 1.167972 -0.057263
+v -0.597710 1.182203 -0.061944
+v -0.568564 1.198926 -0.068300
+v -0.585425 1.188238 -0.024350
+v -0.604139 1.167808 -0.019720
+v -0.618167 1.151636 -0.015785
+v -0.707533 1.094909 0.010309
+v -0.715452 1.085618 0.013752
+v -0.728003 1.074068 0.020076
+v -0.739337 1.062427 0.025747
+v -0.746857 1.054017 0.029662
+v -0.753558 1.048432 0.033598
+v -0.760582 1.053724 0.031725
+v -0.755472 1.060903 0.027049
+v -0.748096 1.069598 0.022795
+v -0.737275 1.081977 0.017413
+v -0.726112 1.095113 0.011160
+v -0.717731 1.104637 0.006156
+v -0.651217 1.185025 -0.031012
+v -0.635896 1.199200 -0.039893
+v -0.615722 1.214473 -0.051091
+v -0.587654 1.231131 -0.065039
+v -0.580381 1.244796 -0.016766
+v -0.601631 1.222414 -0.000946
+v -0.617509 1.203980 0.011000
+v -0.630220 1.188406 0.019663
+v -0.645694 1.174979 0.034668
+v -0.687078 1.141182 0.038127
+v -0.701396 1.129938 0.043064
+v -0.709294 1.120480 0.048462
+v -0.716520 1.111768 0.053868
+v -0.726269 1.101887 0.060552
+v -0.735777 1.092833 0.066725
+v -0.742548 1.086050 0.071014
+v -0.747970 1.079823 0.074468
+v -0.741887 1.074101 0.076535
+v -0.734661 1.079178 0.074287
+v -0.727315 1.085463 0.069923
+v -0.717241 1.094135 0.063806
+v -0.707020 1.103360 0.056808
+v -0.698654 1.110362 0.051242
+v -0.689008 1.116561 0.045938
+v -0.674040 1.125840 0.039400
+v -0.623180 1.149869 0.034216
+v -0.613861 1.170335 0.018360
+v -0.604456 1.187261 0.007201
+v -0.588886 1.207248 -0.000362
+v -0.568981 1.232436 -0.011231
+v -0.679600 1.158810 0.010768
+v -0.680724 1.150920 -0.015581
+v -0.676335 1.141581 -0.037838
+v -0.665889 1.130452 -0.051364
+v -0.652305 1.117288 -0.046884
+v -0.650516 1.117073 -0.028105
+v -0.655411 1.126643 -0.009845
+v -0.653438 1.130962 0.012381
+v -0.652550 1.133137 0.035798
+v -0.652047 1.134045 0.048879
+v -0.657034 1.129361 0.062811
+v -0.662200 1.124307 0.073166
+v -0.667215 1.122067 0.083716
+v -0.670780 1.123390 0.093898
+v -0.674303 1.132869 0.093584
+v -0.671023 1.133583 0.083875
+v -0.667644 1.136297 0.075134
+v -0.663358 1.140578 0.065521
+v -0.661928 1.147833 0.051706
+v -0.066206 1.524831 0.051173
+v -0.013581 1.521601 -0.156987
+v -0.030150 1.528860 -0.161555
+v -0.051943 1.537383 -0.163007
+v -0.077467 1.546570 -0.156404
+v 0.016440 1.733953 0.092814
+v 0.015479 1.744801 0.094338
+v 0.022064 1.748498 0.095013
+v 0.031923 1.750293 0.093778
+v 0.041516 1.749222 0.088251
+v 0.048488 1.744817 0.081332
+v 0.048449 1.732886 0.080714
+v 0.042298 1.728872 0.085420
+v 0.032368 1.727176 0.089015
+v 0.022517 1.729830 0.091192
+v 0.011617 1.730172 0.100463
+v 0.010992 1.750319 0.102809
+v 0.021362 1.754496 0.104559
+v 0.034352 1.757105 0.100859
+v 0.046749 1.755080 0.090966
+v 0.054885 1.748453 0.078446
+v 0.055073 1.728446 0.075963
+v 0.047762 1.722077 0.084227
+v 0.033745 1.717348 0.091640
+v 0.019883 1.723545 0.095647
+v 0.005542 1.731350 0.109217
+v 0.003955 1.751374 0.104446
+v -0.000033 1.731820 0.112244
+v -0.000105 1.751439 0.104896
+v 0.011277 1.712724 0.113847
+v 0.005793 1.713540 0.119628
+v -0.000010 1.714100 0.122622
+v 0.010974 1.720073 0.108118
+v 0.005564 1.722013 0.114535
+v -0.000038 1.723076 0.117868
+v 0.016942 1.715278 0.101556
+v 0.024824 1.707887 0.096007
+v 0.031870 1.698761 0.092161
+v 0.040197 1.681297 0.083590
+v 0.030561 1.678311 0.091347
+v 0.023189 1.694570 0.096951
+v 0.018821 1.701539 0.101010
+v 0.016750 1.709550 0.107386
+v 0.010757 1.766776 0.105238
+v 0.021538 1.769955 0.103235
+v 0.036005 1.771319 0.097074
+v 0.050902 1.766775 0.085155
+v 0.060005 1.755731 0.069133
+v 0.004166 1.765125 0.105608
+v -0.000087 1.764755 0.106067
+v 0.042235 1.671245 0.079756
+v 0.033290 1.645675 0.087024
+v 0.023829 1.641648 0.097000
+v 0.012188 1.648334 0.102717
+v 0.000008 1.650845 0.105491
+v 0.000043 1.654477 0.104249
+v 0.012162 1.653005 0.100362
+v 0.021983 1.650285 0.094783
+v 0.029301 1.652337 0.090062
+v 0.035372 1.669856 0.086431
+v 0.000017 1.635961 0.107843
+v 0.016596 1.619360 0.058151
+v -0.000035 1.615885 0.064632
+v 0.025469 1.624636 0.049003
+v 0.035695 1.638153 0.079040
+v 0.026228 1.631845 0.092068
+v 0.000031 1.626929 0.104330
+v 0.050788 1.739956 0.078037
+v 0.056690 1.740914 0.071917
+v 0.013528 1.740929 0.093875
+v 0.008377 1.742533 0.099944
+v 0.003869 1.743630 0.103772
+v -0.000034 1.743795 0.104751
+v 0.026682 1.667361 0.091784
+v 0.019117 1.667678 0.097280
+v 0.011413 1.669253 0.102415
+v 0.000059 1.669251 0.104884
+v 0.026193 1.658541 0.092529
+v 0.000054 1.658008 0.106506
+v 0.012084 1.657874 0.102816
+v 0.020448 1.657203 0.096986
+v 0.027022 1.672997 0.093577
+v 0.020145 1.676308 0.100352
+v 0.018876 1.669444 0.098634
+v 0.011636 1.679527 0.108647
+v 0.000025 1.680331 0.109883
+v 0.000030 1.670997 0.106078
+v 0.010806 1.670935 0.104084
+v 0.030894 1.668774 0.090028
+v 0.026374 1.666418 0.091716
+v 0.029954 1.661002 0.089655
+v 0.033811 1.656891 0.086084
+v 0.039465 1.652656 0.079524
+v 0.010589 1.683931 0.107093
+v -0.000056 1.684216 0.108220
+v 0.023845 1.666535 0.093650
+v 0.024028 1.668292 0.094088
+v -0.000036 1.706416 0.126284
+v 0.006607 1.706497 0.123249
+v 0.011152 1.706459 0.116966
+v 0.014360 1.704753 0.110387
+v 0.014849 1.700772 0.105939
+v 0.011544 1.697742 0.105502
+v 0.013785 1.695702 0.103717
+v 0.007485 1.696371 0.107887
+v 0.007592 1.693601 0.107562
+v 0.004247 1.695858 0.110665
+v -0.000073 1.692964 0.110126
+v 0.020020 1.681538 0.099803
+v 0.015806 1.691922 0.101714
+v 0.008225 1.690942 0.106929
+v 0.000007 1.690820 0.108241
+v 0.013676 1.637056 0.105332
+v 0.014754 1.628197 0.101139
+v 0.008131 1.616610 0.063153
+v 0.000053 1.664440 0.108414
+v 0.012267 1.664506 0.104780
+v 0.019951 1.664088 0.098265
+v 0.024738 1.663814 0.093677
+v 0.027689 1.664449 0.091295
+v 0.028215 1.667919 0.091592
+v 0.025251 1.669996 0.094481
+v 0.019731 1.672104 0.100195
+v 0.011260 1.674506 0.106957
+v 0.000034 1.674524 0.109320
+v 0.035604 1.632976 0.035981
+v 0.048029 1.646799 0.019060
+v 0.061889 1.665129 0.002744
+v 0.065894 1.680989 -0.008410
+v 0.070251 1.685087 0.002219
+v 0.045012 1.649855 0.063508
+v 0.049767 1.674830 0.068819
+v 0.049602 1.685919 0.074742
+v 0.043287 1.705239 0.087040
+v 0.054608 1.713185 0.077067
+v 0.063460 1.723354 0.060011
+v 0.062580 1.744276 0.060069
+v 0.058550 1.682395 0.053832
+v 0.058485 1.693517 0.061171
+v 0.066773 1.693695 0.034745
+v 0.066196 1.703305 0.042174
+v 0.009686 1.643924 0.106047
+v 0.000003 1.644385 0.107544
+v 0.003994 1.697403 0.117907
+v -0.000093 1.696027 0.119655
+v 0.005509 1.700325 0.121720
+v -0.000081 1.699480 0.124631
+v 0.008564 1.701084 0.115837
+v 0.011250 1.701146 0.110996
+v 0.011209 1.700174 0.107676
+v 0.009250 1.699946 0.105040
+v 0.005696 1.699643 0.114717
+v 0.004806 1.698991 0.109536
+v 0.006359 1.698992 0.106701
+v 0.006177 1.701333 0.111647
+v 0.005263 1.701355 0.108796
+v 0.006007 1.701244 0.106868
+v 0.007585 1.702590 0.106285
+v 0.009251 1.702575 0.107954
+v 0.008477 1.702143 0.110056
+v 0.007672 1.701306 0.112274
+v 0.006667 1.702509 0.109000
+v 0.005152 1.700781 0.110806
+v 0.004549 1.698954 0.112277
+v 0.003329 1.696164 0.114065
+v -0.000090 1.694631 0.114814
+v 0.021837 1.737594 0.086253
+v 0.020275 1.739011 0.085949
+v 0.021592 1.740106 0.086528
+v 0.025422 1.742281 0.087338
+v 0.031555 1.743967 0.087440
+v 0.037824 1.743250 0.086457
+v 0.041881 1.741717 0.084111
+v 0.043163 1.740476 0.082369
+v 0.041668 1.738321 0.083256
+v 0.037765 1.736606 0.085061
+v 0.031964 1.735716 0.086364
+v 0.025909 1.736576 0.086677
+v 0.032153 1.732865 0.087641
+v 0.024682 1.733953 0.088036
+v 0.019644 1.735680 0.087783
+v 0.017496 1.739742 0.087959
+v 0.018864 1.742605 0.087640
+v 0.023800 1.745699 0.088220
+v 0.031516 1.746377 0.089036
+v 0.039002 1.745482 0.086631
+v 0.044082 1.742891 0.082938
+v 0.045832 1.740236 0.080902
+v 0.044092 1.736379 0.082290
+v 0.039462 1.733871 0.085429
+v 0.022404 1.737726 0.084972
+v 0.021954 1.740060 0.085420
+v 0.025368 1.742523 0.086120
+v 0.031372 1.744508 0.086249
+v 0.037616 1.743875 0.085027
+v 0.041484 1.742346 0.083176
+v 0.042448 1.740651 0.081731
+v 0.040869 1.737930 0.082242
+v 0.037351 1.736270 0.083567
+v 0.031849 1.735163 0.084875
+v 0.025985 1.736292 0.085109
+v 0.022726 1.737138 0.084041
+v 0.022044 1.739008 0.084359
+v 0.022144 1.740324 0.084669
+v 0.025069 1.742093 0.084169
+v 0.031153 1.743902 0.083249
+v 0.037458 1.743570 0.082281
+v 0.040698 1.742257 0.081774
+v 0.041019 1.740608 0.080540
+v 0.040371 1.737388 0.080969
+v 0.037359 1.735746 0.081271
+v 0.031690 1.733979 0.082093
+v 0.025410 1.735014 0.083248
+v 0.031258 1.740910 0.080416
+v 0.037411 1.740976 0.079929
+v 0.024765 1.739979 0.082100
+v 0.013064 1.786527 0.099713
+v 0.024720 1.787806 0.094843
+v 0.039612 1.786279 0.085965
+v 0.053593 1.778310 0.072103
+v 0.063618 1.763804 0.055698
+v 0.005313 1.785273 0.101430
+v -0.000040 1.784905 0.101766
+v 0.069849 1.728509 0.035613
+v 0.067525 1.749283 0.044865
+v 0.069880 1.704149 0.015914
+v 0.069980 1.712265 0.021754
+v 0.063120 1.652046 -0.043685
+v 0.063008 1.674361 -0.046297
+v 0.058976 1.634891 -0.002158
+v 0.029928 1.541102 0.033169
+v 0.048332 1.537609 0.028333
+v 0.065688 1.620044 -0.039398
+v 0.046793 1.528980 0.043839
+v 0.025353 1.524534 0.046158
+v -0.000048 1.613263 0.052220
+v 0.000002 1.535384 0.030170
+v 0.045401 1.638162 0.011128
+v 0.031140 1.628047 0.028755
+v 0.006394 1.614430 0.051175
+v 0.013189 1.617340 0.047018
+v 0.020781 1.621769 0.039483
+v 0.021818 1.541617 0.034247
+v 0.017871 1.523124 0.045326
+v 0.015043 1.540731 0.032244
+v 0.008479 1.540329 0.028899
+v 0.034863 1.526842 0.046472
+v 0.038922 1.539646 0.031007
+v 0.064868 1.628958 -0.017339
+v 0.068341 1.654261 -0.026186
+v 0.069373 1.675792 -0.030955
+v -0.000122 1.597369 0.036863
+v 0.004866 1.597711 0.035834
+v 0.010364 1.598515 0.032876
+v 0.016194 1.599834 0.027885
+v 0.023492 1.601210 0.021346
+v 0.034423 1.600878 0.016177
+v 0.047989 1.598148 0.012879
+v 0.058352 1.591414 0.003279
+v 0.063578 1.580765 -0.009546
+v -0.000004 1.566682 0.024621
+v 0.003601 1.566476 0.024446
+v 0.007553 1.564867 0.024184
+v 0.012312 1.562691 0.024284
+v 0.018551 1.562169 0.024909
+v 0.026544 1.562406 0.026839
+v 0.036683 1.561321 0.026377
+v 0.046650 1.557509 0.022140
+v 0.054687 1.551300 0.016522
+v 0.073030 1.758262 0.018127
+v 0.068029 1.771070 0.041876
+v 0.065141 1.712848 -0.004466
+v 0.073107 1.717853 0.005914
+v 0.059566 1.789673 0.058214
+v 0.068132 1.697142 -0.017676
+v 0.045207 1.801670 0.071881
+v 0.030267 1.807253 0.081848
+v -0.000032 1.810426 0.092106
+v 0.017393 1.809724 0.088634
+v 0.007525 1.810372 0.091503
+v 0.075382 1.763160 -0.000406
+v 0.074420 1.781548 0.004536
+v 0.070293 1.807330 0.013168
+v 0.058346 1.828248 0.021167
+v 0.041753 1.841151 0.027304
+v 0.025715 1.848985 0.031977
+v 0.011688 1.853004 0.034738
+v -0.000045 1.854177 0.035574
+v 0.069759 1.702470 -0.021451
+v 0.076863 1.748759 -0.022851
+v 0.076214 1.734640 -0.035953
+v 0.074620 1.725802 -0.035785
+v 0.073190 1.716841 -0.031757
+v 0.076942 1.742609 -0.031703
+v 0.076281 1.720511 -0.006288
+v 0.072562 1.732126 0.018956
+v 0.071177 1.754128 0.030026
+v 0.071046 1.776379 0.028348
+v 0.064527 1.798235 0.043434
+v 0.049998 1.813690 0.055664
+v 0.034880 1.822871 0.065535
+v 0.020838 1.827950 0.072250
+v 0.009365 1.830476 0.075801
+v -0.000033 1.831153 0.076778
+v 0.070919 1.710329 0.003169
+v 0.065640 1.691155 -0.015431
+v 0.070634 1.690918 0.008014
+v 0.066767 1.678397 0.022452
+v 0.056647 1.662779 0.040915
+v 0.072247 1.720858 -0.007201
+v 0.074912 1.732527 0.002836
+v 0.075896 1.740303 0.004206
+v 0.076434 1.750853 -0.003857
+v 0.067814 1.682050 -0.004032
+v 0.064286 1.667920 0.008371
+v 0.052101 1.650279 0.026220
+v 0.039832 1.636121 0.044662
+v 0.029329 1.627494 0.059672
+v 0.019541 1.622101 0.070804
+v 0.010024 1.619549 0.077228
+v 0.000015 1.618811 0.079257
+v 0.071620 1.709066 -0.026083
+v 0.060788 1.530576 0.036368
+v 0.075430 1.534566 0.022602
+v 0.057237 1.536253 0.026327
+v 0.100306 1.554460 -0.010734
+v 0.064605 1.543825 0.015811
+v 0.078590 1.567150 -0.015633
+v 0.068113 1.698900 -0.033429
+v 0.067511 1.707214 -0.034044
+v 0.072331 1.743066 -0.033188
+v 0.073759 1.751898 -0.028361
+v 0.068296 1.715531 -0.034993
+v 0.069271 1.724566 -0.035956
+v 0.070643 1.734196 -0.035757
+v 0.074989 1.759156 -0.020124
+v 0.069015 1.689374 -0.032719
+v 0.075628 1.762365 -0.010271
+v 0.075342 1.781265 -0.007950
+v 0.072496 1.808179 -0.003886
+v 0.061768 1.830952 0.000108
+v 0.045307 1.845691 0.003215
+v 0.028351 1.854537 0.005435
+v 0.012963 1.859086 0.006719
+v -0.000061 1.860283 0.007078
+v -0.000230 1.688992 -0.093111
+v -0.000290 1.788235 -0.108869
+v 0.060154 1.763633 -0.080008
+v 0.065012 1.818998 -0.044311
+v 0.074245 1.770705 -0.031645
+v 0.075491 1.777991 -0.020273
+v 0.072928 1.796076 -0.038015
+v 0.073628 1.804859 -0.021311
+v 0.063929 1.828358 -0.022211
+v 0.068877 1.735349 -0.048209
+v 0.072646 1.760114 -0.040338
+v 0.071072 1.747939 -0.045843
+v 0.064210 1.802779 -0.061622
+v 0.070342 1.782480 -0.050941
+v 0.065477 1.750265 -0.064323
+v 0.067762 1.766621 -0.059519
+v 0.062446 1.783468 -0.073207
+v -0.000070 1.852281 -0.057453
+v 0.033397 1.845215 -0.053288
+v 0.050801 1.835601 -0.049425
+v 0.048165 1.844258 -0.022996
+v 0.030846 1.853708 -0.023926
+v 0.016113 1.850606 -0.056290
+v 0.014451 1.859137 -0.024854
+v -0.000069 1.860602 -0.025234
+v 0.034035 1.782497 -0.102196
+v 0.035259 1.828087 -0.077296
+v 0.052199 1.818518 -0.070858
+v 0.049278 1.774579 -0.093016
+v 0.051606 1.796924 -0.085165
+v 0.035500 1.805825 -0.093529
+v -0.000114 1.834591 -0.083489
+v 0.017288 1.833013 -0.081681
+v 0.016834 1.786892 -0.107275
+v 0.017430 1.810189 -0.098312
+v -0.000225 1.811400 -0.099945
+v 0.041588 1.677303 -0.075621
+v 0.051134 1.727628 -0.080832
+v 0.064123 1.712345 -0.047994
+v 0.066245 1.723488 -0.048520
+v 0.058460 1.720116 -0.065133
+v 0.062011 1.734618 -0.065733
+v 0.055962 1.744715 -0.082023
+v 0.063127 1.701350 -0.047602
+v 0.063175 1.689497 -0.047362
+v 0.046828 1.711698 -0.078268
+v 0.055125 1.706358 -0.063619
+v 0.054023 1.675254 -0.063166
+v 0.053212 1.692068 -0.062668
+v 0.042852 1.695734 -0.075625
+v -0.000301 1.746679 -0.109680
+v 0.027626 1.740944 -0.101918
+v 0.040563 1.734637 -0.093729
+v 0.044964 1.753551 -0.094829
+v 0.031096 1.760520 -0.104153
+v 0.013885 1.745159 -0.107758
+v 0.015607 1.764973 -0.110046
+v -0.000355 1.766522 -0.111703
+v 0.019183 1.684644 -0.089803
+v 0.024547 1.722875 -0.098107
+v 0.036450 1.717302 -0.089902
+v 0.030659 1.680693 -0.085473
+v 0.032466 1.700086 -0.086016
+v 0.021594 1.704793 -0.093737
+v -0.000239 1.728580 -0.105104
+v 0.012187 1.727068 -0.103302
+v 0.009029 1.687848 -0.092277
+v 0.010591 1.708549 -0.098352
+v -0.000257 1.709927 -0.099816
+v 0.000020 1.520793 0.043117
+v 0.011564 1.522348 0.044505
+v 0.005722 1.521526 0.043516
+v 0.088852 1.575770 -0.132210
+v 0.052399 1.610813 -0.118401
+v 0.054458 1.628022 -0.092308
+v 0.066325 1.628566 -0.066877
+v 0.117309 1.585153 -0.077249
+v 0.110944 1.567968 -0.026859
+v 0.071153 1.595545 -0.124303
+v 0.090386 1.605099 -0.072884
+v 0.086150 1.583089 -0.028796
+v 0.056826 1.653671 -0.063934
+v 0.044108 1.655068 -0.079535
+v 0.082673 1.604229 -0.100343
+v 0.107148 1.583321 -0.107287
+v 0.008800 1.661542 -0.092443
+v -0.000168 1.662050 -0.092204
+v 0.032176 1.658535 -0.091053
+v 0.019401 1.660454 -0.093737
+v 0.009332 1.634341 -0.100294
+v -0.000038 1.633839 -0.098851
+v 0.034686 1.635475 -0.101899
+v 0.020422 1.635603 -0.102955
+v 0.009940 1.609310 -0.111180
+v -0.000007 1.608010 -0.109334
+v 0.035436 1.615047 -0.117918
+v 0.021072 1.612992 -0.115948
+v -0.000167 1.538961 -0.145279
+v 0.012223 1.541756 -0.147605
+v 0.026971 1.548670 -0.151627
+v 0.011210 1.564107 -0.134853
+v -0.000133 1.562011 -0.133070
+v 0.024171 1.569839 -0.139188
+v 0.039722 1.577489 -0.141734
+v 0.045780 1.557310 -0.152380
+v 0.056400 1.585571 -0.137865
+v 0.067302 1.566757 -0.146987
+v 0.047841 1.598169 -0.130298
+v 0.035728 1.596246 -0.130847
+v 0.021966 1.591440 -0.127763
+v 0.010810 1.587211 -0.122010
+v -0.000120 1.585393 -0.119345
+v -0.000037 1.844370 0.058206
+v 0.010542 1.843437 0.057247
+v 0.023309 1.840075 0.053884
+v 0.038387 1.833530 0.047842
+v 0.054304 1.822209 0.039422
+v 0.067169 1.803566 0.028582
+v 0.072953 1.779848 0.016483
+v 0.074419 1.761748 0.008789
+v 0.076858 1.747115 0.001483
+v 0.070263 1.697215 0.012293
+v 0.066949 1.685391 0.028486
+v 0.057849 1.672101 0.047424
+v 0.048762 1.663781 0.064639
+v 0.042141 1.661730 0.077786
+v 0.035892 1.662841 0.084875
+v 0.031603 1.664481 0.088914
+v 0.028961 1.665901 0.090707
+v 0.027337 1.666702 0.091190
+v 0.076444 1.750926 -0.011798
+v -0.000060 1.582050 0.030366
+v 0.004349 1.582245 0.029321
+v 0.008983 1.582512 0.026869
+v 0.014108 1.582812 0.023709
+v 0.021065 1.582801 0.020904
+v 0.030804 1.582183 0.020995
+v 0.042676 1.580210 0.019778
+v 0.053207 1.574617 0.012935
+v 0.060546 1.565681 0.004096
+v 0.072045 1.554122 0.000164
+v 0.088515 1.542491 0.005471
+v 0.005047 1.550807 0.024670
+v 0.000005 1.546272 0.025246
+v 0.000011 1.554737 0.023735
+v 0.002948 1.556099 0.023814
+v 0.000038 1.620693 0.093186
+v 0.012678 1.621893 0.090585
+v 0.023411 1.625304 0.082758
+v 0.033717 1.631166 0.069837
+v 0.043489 1.640605 0.053099
+v 0.055302 1.654711 0.033052
+v 0.065942 1.672331 0.015393
+v 0.075455 1.724851 -0.016817
+v 0.077993 1.733473 -0.008316
+v 0.079963 1.744299 -0.010268
+v 0.084202 1.747008 -0.020146
+v 0.085646 1.751063 -0.016501
+v 0.083964 1.745605 -0.005179
+v 0.081348 1.737237 -0.002213
+v 0.078995 1.737107 -0.006182
+v 0.084682 1.745129 -0.027761
+v 0.084040 1.741523 -0.031278
+v 0.083199 1.735492 -0.033578
+v 0.083904 1.736295 -0.037335
+v 0.085018 1.743047 -0.034405
+v 0.085676 1.749057 -0.028961
+v 0.078676 1.730526 -0.002604
+v 0.075795 1.721044 -0.010951
+v 0.079993 1.754382 -0.014894
+v 0.079132 1.735682 -0.036989
+v 0.080014 1.743198 -0.034047
+v 0.080149 1.751023 -0.027795
+v 0.079769 1.752202 -0.006075
+v 0.081446 1.728202 -0.034219
+v 0.080140 1.719759 -0.031680
+v 0.078578 1.711046 -0.027873
+v 0.076120 1.703245 -0.022557
+v 0.077901 1.701380 -0.027078
+v 0.079617 1.709586 -0.032314
+v 0.080856 1.718512 -0.036285
+v 0.082016 1.727798 -0.038393
+v 0.073498 1.701292 -0.026845
+v 0.075137 1.709569 -0.030627
+v 0.076303 1.718309 -0.034170
+v 0.077470 1.727204 -0.036750
+v 0.076110 1.696404 -0.015891
+v 0.075880 1.688338 -0.007354
+v 0.073928 1.685553 -0.014040
+v 0.076520 1.693935 -0.021143
+v 0.072249 1.694338 -0.021957
+v 0.070352 1.688843 -0.014849
+v 0.070346 1.703779 0.001170
+v 0.066794 1.705050 -0.005241
+v 0.072327 1.697160 -0.002218
+v 0.071613 1.702806 -0.009547
+v 0.065883 1.680467 -0.012559
+v 0.061759 1.661888 -0.003208
+v 0.066269 1.658645 -0.012145
+v 0.068068 1.679207 -0.019108
+v 0.067028 1.690578 -0.021785
+v 0.066656 1.697872 -0.022940
+v 0.067306 1.704369 -0.024368
+v 0.068792 1.711066 -0.026890
+v 0.070821 1.718288 -0.031645
+v 0.072122 1.727282 -0.034617
+v 0.073296 1.735921 -0.033303
+v 0.074178 1.743700 -0.027957
+v 0.074239 1.750685 -0.020016
+v 0.074834 1.753667 -0.010693
+v 0.075364 1.753619 -0.002392
+v 0.075229 1.751125 0.004691
+v 0.074194 1.744087 0.011074
+v 0.073994 1.733394 0.008456
+v 0.072240 1.741722 0.023885
+v 0.068946 1.738042 0.039760
+v 0.063459 1.734822 0.057789
+v 0.056725 1.734630 0.071748
+v 0.050466 1.736369 0.078056
+v 0.045657 1.738340 0.080686
+v 0.043110 1.739510 0.082231
+v 0.042455 1.739267 0.081454
+v 0.040939 1.738749 0.080182
+v 0.037268 1.737952 0.079761
+v 0.031389 1.737208 0.080290
+v 0.025047 1.737210 0.081703
+v 0.022245 1.738082 0.083969
+v 0.020310 1.738237 0.085922
+v 0.017843 1.737850 0.088142
+v 0.013913 1.737745 0.093533
+v 0.008596 1.737475 0.099514
+v 0.004697 1.738221 0.105789
+v -0.000022 1.738311 0.107677
+v 0.020758 1.738982 0.084846
+v 0.021009 1.738169 0.084825
+v 0.083884 1.728019 -0.027851
+v 0.082049 1.720263 -0.025463
+v 0.077695 1.713336 -0.021535
+v 0.074529 1.707918 -0.016279
+v 0.066732 1.712506 -0.009922
+v 0.072644 1.714223 -0.014272
+v 0.075886 1.719035 -0.018948
+v 0.080961 1.727326 -0.020681
+v 0.079311 1.722572 -0.021539
+v 0.079757 1.739110 -0.015888
+v 0.085101 1.742390 -0.024457
+v 0.085178 1.734921 -0.027381
+v 0.082519 1.732832 -0.018880
+v 0.075867 1.729004 -0.012865
+v 0.077068 1.726102 -0.005939
+v 0.074239 1.726985 -0.002165
+v 0.073959 1.726861 0.002416
+v 0.072695 1.724917 0.012615
+v 0.069925 1.720304 0.029019
+v 0.065473 1.712886 0.050301
+v 0.057624 1.703466 0.068903
+v 0.048045 1.695440 0.081280
+v 0.036614 1.690315 0.087982
+v 0.027304 1.687463 0.094477
+v 0.018346 1.687018 0.100441
+v 0.009477 1.687585 0.106700
+v -0.000053 1.687639 0.107997
+v 0.090927 1.597029 -0.047136
+v 0.117632 1.578977 -0.049122
+v -0.000134 1.607983 0.045941
+v 0.006127 1.608663 0.044819
+v 0.012520 1.610448 0.041153
+v 0.019181 1.612788 0.034426
+v 0.027034 1.616058 0.024984
+v 0.038442 1.617996 0.013932
+v 0.053218 1.615282 0.006285
+v 0.061660 1.608403 -0.006838
+v 0.065602 1.597407 -0.023120
+v 0.026164 1.666994 0.090746
+v 0.023149 1.667386 0.092814
+v 0.025362 1.667083 0.091259
+v 0.023135 1.667651 0.093041
+v 0.025489 1.667201 0.091265
+v 0.000041 1.670299 0.103229
+v 0.010442 1.669980 0.101243
+v 0.018221 1.668650 0.096556
+v 0.018678 1.668534 0.095726
+v 0.010660 1.669179 0.099465
+v 0.000064 1.668598 0.101684
+v -0.016542 1.733953 0.092813
+v -0.015484 1.744801 0.094338
+v -0.022069 1.748498 0.095013
+v -0.031927 1.750293 0.093778
+v -0.041523 1.749222 0.088251
+v -0.048497 1.744817 0.081332
+v -0.048467 1.732886 0.080713
+v -0.042318 1.728872 0.085420
+v -0.032400 1.727176 0.089015
+v -0.022610 1.729828 0.091188
+v -0.011625 1.730172 0.100463
+v -0.011005 1.750319 0.102809
+v -0.021379 1.754496 0.104559
+v -0.034375 1.757106 0.100859
+v -0.046776 1.755080 0.090966
+v -0.054908 1.748453 0.078446
+v -0.055157 1.728446 0.075963
+v -0.047877 1.722077 0.084230
+v -0.033859 1.717347 0.091638
+v -0.019945 1.723545 0.095648
+v -0.005558 1.731350 0.109217
+v -0.004015 1.751374 0.104444
+v -0.011457 1.712728 0.113853
+v -0.005815 1.713540 0.119628
+v -0.010982 1.720073 0.108118
+v -0.005593 1.722012 0.114534
+v -0.016982 1.715278 0.101556
+v -0.024901 1.707887 0.096006
+v -0.031904 1.698761 0.092161
+v -0.040209 1.681297 0.083590
+v -0.030639 1.678311 0.091348
+v -0.023311 1.694571 0.096956
+v -0.018928 1.701537 0.101013
+v -0.016962 1.709539 0.107375
+v -0.010763 1.766776 0.105238
+v -0.021546 1.769955 0.103235
+v -0.036087 1.771319 0.097074
+v -0.050916 1.766775 0.085155
+v -0.060022 1.755731 0.069133
+v -0.004196 1.765125 0.105607
+v -0.042283 1.671245 0.079756
+v -0.033294 1.645675 0.087024
+v -0.023843 1.641648 0.097000
+v -0.012206 1.648334 0.102717
+v -0.012180 1.653005 0.100362
+v -0.021988 1.650285 0.094783
+v -0.029306 1.652337 0.090062
+v -0.035388 1.669856 0.086431
+v -0.016602 1.619360 0.058151
+v -0.025474 1.624636 0.049003
+v -0.035703 1.638153 0.079040
+v -0.026234 1.631845 0.092068
+v -0.050793 1.739956 0.078037
+v -0.056709 1.740914 0.071917
+v -0.013574 1.740929 0.093875
+v -0.008409 1.742533 0.099944
+v -0.003882 1.743630 0.103772
+v -0.026687 1.667361 0.091784
+v -0.019123 1.667678 0.097280
+v -0.011419 1.669253 0.102415
+v -0.026213 1.658541 0.092529
+v -0.012117 1.657874 0.102816
+v -0.020521 1.657203 0.096986
+v -0.027027 1.672997 0.093577
+v -0.020150 1.676308 0.100352
+v -0.018881 1.669444 0.098634
+v -0.011641 1.679527 0.108647
+v -0.010811 1.670935 0.104084
+v -0.030902 1.668774 0.090028
+v -0.026379 1.666418 0.091716
+v -0.029959 1.661002 0.089655
+v -0.033816 1.656891 0.086084
+v -0.039478 1.652656 0.079524
+v -0.010594 1.683931 0.107093
+v -0.023851 1.666535 0.093650
+v -0.024032 1.668292 0.094088
+v -0.006619 1.706497 0.123248
+v -0.011264 1.706459 0.116965
+v -0.014554 1.704753 0.110388
+v -0.014923 1.700773 0.105940
+v -0.011562 1.697742 0.105502
+v -0.013797 1.695702 0.103717
+v -0.007490 1.696371 0.107887
+v -0.007597 1.693601 0.107562
+v -0.004252 1.695858 0.110665
+v -0.020025 1.681538 0.099803
+v -0.015811 1.691922 0.101714
+v -0.008231 1.690942 0.106929
+v -0.013687 1.637056 0.105332
+v -0.014759 1.628197 0.101139
+v -0.008136 1.616610 0.063153
+v -0.012272 1.664506 0.104780
+v -0.019982 1.664088 0.098265
+v -0.024751 1.663814 0.093677
+v -0.027694 1.664449 0.091295
+v -0.028220 1.667919 0.091592
+v -0.025256 1.669996 0.094481
+v -0.019736 1.672104 0.100195
+v -0.011265 1.674506 0.106957
+v -0.035610 1.632976 0.035981
+v -0.048034 1.646799 0.019060
+v -0.061928 1.665128 0.002743
+v -0.065957 1.680984 -0.008410
+v -0.070460 1.685080 0.002219
+v -0.045017 1.649855 0.063508
+v -0.049780 1.674830 0.068819
+v -0.049637 1.685919 0.074742
+v -0.043342 1.705239 0.087040
+v -0.054704 1.713185 0.077066
+v -0.063626 1.723354 0.060011
+v -0.062615 1.744277 0.060070
+v -0.058563 1.682395 0.053832
+v -0.058500 1.693517 0.061171
+v -0.066917 1.693695 0.034745
+v -0.066305 1.703305 0.042174
+v -0.009701 1.643924 0.106047
+v -0.003999 1.697403 0.117907
+v -0.005514 1.700325 0.121720
+v -0.008569 1.701084 0.115837
+v -0.011268 1.701146 0.110996
+v -0.011231 1.700174 0.107676
+v -0.009263 1.699946 0.105040
+v -0.005701 1.699643 0.114717
+v -0.004811 1.698991 0.109536
+v -0.006364 1.698992 0.106701
+v -0.006182 1.701333 0.111647
+v -0.005268 1.701355 0.108796
+v -0.006012 1.701244 0.106868
+v -0.007591 1.702590 0.106285
+v -0.009266 1.702575 0.107954
+v -0.008487 1.702143 0.110057
+v -0.007678 1.701306 0.112274
+v -0.006673 1.702509 0.109000
+v -0.005157 1.700781 0.110806
+v -0.004555 1.698954 0.112277
+v -0.003334 1.696164 0.114065
+v -0.021851 1.737594 0.086253
+v -0.020283 1.739011 0.085949
+v -0.021599 1.740106 0.086528
+v -0.025427 1.742281 0.087338
+v -0.031560 1.743967 0.087440
+v -0.037829 1.743250 0.086457
+v -0.041888 1.741717 0.084111
+v -0.043171 1.740476 0.082369
+v -0.041684 1.738321 0.083256
+v -0.037792 1.736606 0.085061
+v -0.031990 1.735716 0.086364
+v -0.025928 1.736576 0.086677
+v -0.032185 1.732865 0.087641
+v -0.024712 1.733953 0.088036
+v -0.019678 1.735680 0.087784
+v -0.017509 1.739742 0.087959
+v -0.018869 1.742605 0.087640
+v -0.023805 1.745699 0.088220
+v -0.031521 1.746377 0.089036
+v -0.039007 1.745482 0.086631
+v -0.044087 1.742891 0.082938
+v -0.045838 1.740236 0.080902
+v -0.044112 1.736378 0.082289
+v -0.039494 1.733870 0.085429
+v -0.022416 1.737726 0.084972
+v -0.021962 1.740060 0.085420
+v -0.025373 1.742523 0.086120
+v -0.031377 1.744508 0.086249
+v -0.037621 1.743875 0.085027
+v -0.041489 1.742346 0.083176
+v -0.042455 1.740651 0.081731
+v -0.040885 1.737930 0.082242
+v -0.037377 1.736271 0.083567
+v -0.031874 1.735163 0.084875
+v -0.026000 1.736292 0.085110
+v -0.022737 1.737138 0.084041
+v -0.022052 1.739008 0.084359
+v -0.022150 1.740324 0.084669
+v -0.025074 1.742093 0.084169
+v -0.031158 1.743902 0.083249
+v -0.037463 1.743570 0.082281
+v -0.040703 1.742257 0.081774
+v -0.041026 1.740608 0.080540
+v -0.040387 1.737388 0.080969
+v -0.037370 1.735746 0.081271
+v -0.031695 1.733979 0.082093
+v -0.025418 1.735014 0.083247
+v -0.031263 1.740910 0.080416
+v -0.037416 1.740976 0.079929
+v -0.024770 1.739979 0.082100
+v -0.013069 1.786527 0.099713
+v -0.024759 1.787806 0.094843
+v -0.039835 1.786281 0.085968
+v -0.053661 1.778309 0.072102
+v -0.063634 1.763804 0.055698
+v -0.005318 1.785273 0.101430
+v -0.070145 1.728509 0.035612
+v -0.067574 1.749283 0.044865
+v -0.069933 1.704149 0.015914
+v -0.070041 1.712265 0.021753
+v -0.063126 1.652046 -0.043685
+v -0.063014 1.674361 -0.046297
+v -0.058981 1.634891 -0.002158
+v -0.029933 1.541102 0.033169
+v -0.048337 1.537609 0.028333
+v -0.065693 1.620044 -0.039398
+v -0.046798 1.528980 0.043839
+v -0.025358 1.524534 0.046158
+v -0.045406 1.638162 0.011128
+v -0.031166 1.628047 0.028755
+v -0.006441 1.614429 0.051175
+v -0.013224 1.617340 0.047018
+v -0.020806 1.621769 0.039483
+v -0.021823 1.541617 0.034247
+v -0.017876 1.523124 0.045326
+v -0.015049 1.540731 0.032244
+v -0.008485 1.540329 0.028899
+v -0.034868 1.526842 0.046472
+v -0.038927 1.539646 0.031007
+v -0.064873 1.628958 -0.017339
+v -0.068348 1.654261 -0.026186
+v -0.069381 1.675792 -0.030955
+v -0.005057 1.597715 0.035828
+v -0.010495 1.598517 0.032872
+v -0.016260 1.599836 0.027883
+v -0.023527 1.601210 0.021346
+v -0.034439 1.600878 0.016177
+v -0.047995 1.598148 0.012879
+v -0.058357 1.591414 0.003279
+v -0.063583 1.580765 -0.009546
+v -0.003614 1.566476 0.024446
+v -0.007563 1.564867 0.024184
+v -0.012320 1.562691 0.024284
+v -0.018559 1.562169 0.024909
+v -0.026556 1.562406 0.026839
+v -0.036690 1.561321 0.026377
+v -0.046656 1.557509 0.022140
+v -0.054692 1.551300 0.016522
+v -0.073035 1.758262 0.018127
+v -0.068084 1.771070 0.041875
+v -0.065477 1.712833 -0.004526
+v -0.073198 1.717853 0.005915
+v -0.059684 1.789672 0.058213
+v -0.068208 1.697144 -0.017675
+v -0.045375 1.801670 0.071882
+v -0.030359 1.807252 0.081847
+v -0.017400 1.809724 0.088634
+v -0.007537 1.810372 0.091503
+v -0.075387 1.763160 -0.000406
+v -0.074425 1.781548 0.004536
+v -0.070298 1.807330 0.013168
+v -0.058351 1.828248 0.021167
+v -0.041758 1.841151 0.027304
+v -0.025720 1.848985 0.031977
+v -0.011693 1.853004 0.034738
+v -0.069789 1.702471 -0.021450
+v -0.076874 1.748758 -0.022851
+v -0.076228 1.734640 -0.035953
+v -0.074637 1.725803 -0.035785
+v -0.073208 1.716842 -0.031757
+v -0.076955 1.742609 -0.031703
+v -0.076349 1.720509 -0.006286
+v -0.072818 1.732124 0.018954
+v -0.071191 1.754128 0.030026
+v -0.071070 1.776379 0.028348
+v -0.064633 1.798235 0.043433
+v -0.050047 1.813689 0.055665
+v -0.034947 1.822871 0.065535
+v -0.020846 1.827950 0.072250
+v -0.009370 1.830476 0.075801
+v -0.070968 1.710329 0.003169
+v -0.065724 1.691149 -0.015432
+v -0.070868 1.690916 0.008013
+v -0.066931 1.678397 0.022452
+v -0.056658 1.662779 0.040915
+v -0.072473 1.720847 -0.007229
+v -0.075044 1.732521 0.002831
+v -0.075944 1.740302 0.004206
+v -0.076442 1.750853 -0.003857
+v -0.067962 1.682032 -0.004031
+v -0.064396 1.667919 0.008371
+v -0.052123 1.650279 0.026220
+v -0.039838 1.636121 0.044662
+v -0.029334 1.627494 0.059672
+v -0.019546 1.622101 0.070804
+v -0.010029 1.619549 0.077228
+v -0.071660 1.709066 -0.026082
+v -0.060794 1.530576 0.036368
+v -0.075436 1.534566 0.022602
+v -0.057243 1.536253 0.026327
+v -0.100311 1.554460 -0.010734
+v -0.064610 1.543825 0.015811
+v -0.078595 1.567150 -0.015633
+v -0.068128 1.698900 -0.033429
+v -0.067528 1.707215 -0.034044
+v -0.072343 1.743066 -0.033188
+v -0.073771 1.751898 -0.028361
+v -0.068313 1.715531 -0.034993
+v -0.069285 1.724566 -0.035955
+v -0.070656 1.734196 -0.035756
+v -0.074998 1.759156 -0.020123
+v -0.069027 1.689374 -0.032719
+v -0.075634 1.762365 -0.010271
+v -0.075347 1.781265 -0.007950
+v -0.072501 1.808179 -0.003886
+v -0.061773 1.830952 0.000108
+v -0.045312 1.845691 0.003215
+v -0.028356 1.854537 0.005435
+v -0.012969 1.859086 0.006719
+v -0.060159 1.763633 -0.080008
+v -0.065017 1.818998 -0.044311
+v -0.074253 1.770705 -0.031645
+v -0.075498 1.777990 -0.020273
+v -0.072933 1.796076 -0.038015
+v -0.073633 1.804859 -0.021311
+v -0.063934 1.828358 -0.022211
+v -0.068889 1.735349 -0.048209
+v -0.072655 1.760113 -0.040338
+v -0.071083 1.747939 -0.045842
+v -0.064215 1.802779 -0.061622
+v -0.070347 1.782480 -0.050941
+v -0.065484 1.750265 -0.064323
+v -0.067768 1.766621 -0.059519
+v -0.062451 1.783468 -0.073207
+v -0.033402 1.845215 -0.053288
+v -0.050806 1.835601 -0.049425
+v -0.048170 1.844258 -0.022996
+v -0.030851 1.853708 -0.023926
+v -0.016118 1.850606 -0.056290
+v -0.014456 1.859137 -0.024854
+v -0.034040 1.782497 -0.102196
+v -0.035264 1.828087 -0.077296
+v -0.052204 1.818518 -0.070858
+v -0.049283 1.774579 -0.093016
+v -0.051611 1.796924 -0.085165
+v -0.035505 1.805825 -0.093529
+v -0.017293 1.833013 -0.081681
+v -0.016839 1.786892 -0.107275
+v -0.017435 1.810189 -0.098312
+v -0.041593 1.677303 -0.075621
+v -0.051139 1.727628 -0.080832
+v -0.064135 1.712345 -0.047994
+v -0.066256 1.723488 -0.048520
+v -0.058466 1.720116 -0.065133
+v -0.062018 1.734618 -0.065733
+v -0.055967 1.744715 -0.082023
+v -0.063136 1.701350 -0.047602
+v -0.063182 1.689497 -0.047362
+v -0.046833 1.711698 -0.078268
+v -0.055131 1.706358 -0.063619
+v -0.054028 1.675254 -0.063166
+v -0.053219 1.692068 -0.062668
+v -0.042857 1.695734 -0.075625
+v -0.027631 1.740944 -0.101918
+v -0.040568 1.734637 -0.093729
+v -0.044969 1.753551 -0.094829
+v -0.031101 1.760520 -0.104154
+v -0.013891 1.745159 -0.107758
+v -0.015613 1.764973 -0.110046
+v -0.019188 1.684644 -0.089803
+v -0.024552 1.722875 -0.098107
+v -0.036455 1.717302 -0.089902
+v -0.030664 1.680693 -0.085473
+v -0.032471 1.700086 -0.086016
+v -0.021599 1.704793 -0.093737
+v -0.012196 1.727068 -0.103302
+v -0.009080 1.687851 -0.092276
+v -0.010639 1.708551 -0.098348
+v -0.011570 1.522348 0.044505
+v -0.005727 1.521526 0.043516
+v -0.088857 1.575770 -0.132210
+v -0.052404 1.610813 -0.118401
+v -0.054463 1.628022 -0.092308
+v -0.066330 1.628566 -0.066877
+v -0.117314 1.585153 -0.077249
+v -0.110949 1.567968 -0.026859
+v -0.071158 1.595545 -0.124303
+v -0.090391 1.605099 -0.072884
+v -0.086155 1.583089 -0.028796
+v -0.056832 1.653671 -0.063934
+v -0.044114 1.655068 -0.079535
+v -0.082679 1.604229 -0.100343
+v -0.107153 1.583321 -0.107287
+v -0.008852 1.661546 -0.092446
+v -0.032181 1.658535 -0.091053
+v -0.019406 1.660454 -0.093737
+v -0.009337 1.634341 -0.100294
+v -0.034691 1.635475 -0.101899
+v -0.020427 1.635603 -0.102955
+v -0.009945 1.609310 -0.111180
+v -0.035441 1.615047 -0.117918
+v -0.021077 1.612992 -0.115948
+v -0.012228 1.541756 -0.147605
+v -0.026976 1.548670 -0.151627
+v -0.011215 1.564107 -0.134853
+v -0.024177 1.569839 -0.139188
+v -0.039728 1.577489 -0.141734
+v -0.045785 1.557310 -0.152380
+v -0.056405 1.585571 -0.137865
+v -0.067307 1.566757 -0.146987
+v -0.047846 1.598169 -0.130298
+v -0.035734 1.596246 -0.130847
+v -0.021972 1.591440 -0.127763
+v -0.010815 1.587211 -0.122010
+v -0.010547 1.843437 0.057247
+v -0.023314 1.840075 0.053884
+v -0.038393 1.833530 0.047842
+v -0.054313 1.822208 0.039422
+v -0.067212 1.803566 0.028582
+v -0.072967 1.779848 0.016483
+v -0.074424 1.761748 0.008789
+v -0.076870 1.747116 0.001483
+v -0.070455 1.697214 0.012293
+v -0.067097 1.685391 0.028486
+v -0.057857 1.672101 0.047424
+v -0.048770 1.663781 0.064639
+v -0.042186 1.661730 0.077786
+v -0.035897 1.662841 0.084875
+v -0.031608 1.664481 0.088914
+v -0.028966 1.665901 0.090707
+v -0.027342 1.666702 0.091190
+v -0.076454 1.750925 -0.011798
+v -0.004418 1.582246 0.029320
+v -0.009036 1.582513 0.026868
+v -0.014137 1.582812 0.023708
+v -0.021082 1.582801 0.020904
+v -0.030821 1.582183 0.020995
+v -0.042688 1.580210 0.019778
+v -0.053214 1.574617 0.012935
+v -0.060551 1.565681 0.004096
+v -0.072050 1.554122 0.000164
+v -0.088520 1.542491 0.005471
+v -0.005053 1.550807 0.024670
+v -0.002954 1.556098 0.023814
+v -0.012683 1.621893 0.090585
+v -0.023416 1.625304 0.082758
+v -0.033722 1.631166 0.069837
+v -0.043494 1.640605 0.053099
+v -0.055321 1.654711 0.033052
+v -0.066106 1.672330 0.015393
+v -0.075517 1.724859 -0.016819
+v -0.078670 1.733459 -0.008283
+v -0.080172 1.744300 -0.010265
+v -0.084499 1.746982 -0.020146
+v -0.085683 1.751063 -0.016501
+v -0.084054 1.745605 -0.005176
+v -0.081515 1.737245 -0.002214
+v -0.079660 1.737020 -0.006208
+v -0.084852 1.745111 -0.027748
+v -0.084122 1.741521 -0.031275
+v -0.083280 1.735492 -0.033575
+v -0.083984 1.736294 -0.037333
+v -0.085079 1.743047 -0.034405
+v -0.085706 1.749057 -0.028962
+v -0.078916 1.730537 -0.002625
+v -0.076132 1.721060 -0.010974
+v -0.080004 1.754382 -0.014894
+v -0.079147 1.735682 -0.036988
+v -0.080027 1.743198 -0.034047
+v -0.080160 1.751023 -0.027795
+v -0.079774 1.752202 -0.006074
+v -0.081502 1.728201 -0.034217
+v -0.080237 1.719759 -0.031680
+v -0.078697 1.711049 -0.027874
+v -0.076225 1.703248 -0.022558
+v -0.077965 1.701381 -0.027078
+v -0.079663 1.709587 -0.032315
+v -0.080938 1.718514 -0.036284
+v -0.082085 1.727799 -0.038394
+v -0.073533 1.701293 -0.026844
+v -0.075165 1.709569 -0.030627
+v -0.076325 1.718310 -0.034170
+v -0.077493 1.727205 -0.036750
+v -0.076222 1.696404 -0.015892
+v -0.076092 1.688368 -0.007369
+v -0.074101 1.685568 -0.014038
+v -0.076624 1.693936 -0.021143
+v -0.072325 1.694338 -0.021955
+v -0.070498 1.688837 -0.014849
+v -0.070426 1.703779 0.001171
+v -0.066925 1.705056 -0.005257
+v -0.072508 1.697161 -0.002220
+v -0.071798 1.702803 -0.009550
+v -0.065924 1.680465 -0.012559
+v -0.061767 1.661888 -0.003208
+v -0.066277 1.658645 -0.012145
+v -0.068091 1.679207 -0.019108
+v -0.067062 1.690576 -0.021785
+v -0.066676 1.697872 -0.022940
+v -0.067325 1.704370 -0.024367
+v -0.068812 1.711066 -0.026890
+v -0.070837 1.718289 -0.031645
+v -0.072137 1.727283 -0.034617
+v -0.073310 1.735921 -0.033303
+v -0.074192 1.743699 -0.027957
+v -0.074250 1.750684 -0.020016
+v -0.074842 1.753666 -0.010693
+v -0.075370 1.753619 -0.002392
+v -0.075238 1.751125 0.004691
+v -0.074252 1.744084 0.011073
+v -0.074165 1.733387 0.008455
+v -0.072430 1.741721 0.023884
+v -0.069200 1.738042 0.039761
+v -0.063621 1.734822 0.057789
+v -0.056749 1.734630 0.071748
+v -0.050472 1.736369 0.078056
+v -0.045665 1.738340 0.080686
+v -0.043123 1.739510 0.082231
+v -0.042468 1.739267 0.081454
+v -0.040950 1.738749 0.080182
+v -0.037273 1.737952 0.079761
+v -0.031394 1.737208 0.080290
+v -0.025052 1.737210 0.081703
+v -0.022254 1.738082 0.083969
+v -0.020320 1.738237 0.085922
+v -0.017866 1.737850 0.088142
+v -0.013983 1.737746 0.093533
+v -0.008616 1.737475 0.099515
+v -0.004702 1.738221 0.105789
+v -0.020766 1.738982 0.084846
+v -0.021019 1.738169 0.084825
+v -0.084278 1.728020 -0.027854
+v -0.082458 1.720284 -0.025477
+v -0.078181 1.713315 -0.021514
+v -0.074896 1.707891 -0.016325
+v -0.066973 1.712496 -0.009964
+v -0.072887 1.714231 -0.014278
+v -0.076042 1.719061 -0.018970
+v -0.081428 1.727332 -0.020669
+v -0.079601 1.722572 -0.021521
+v -0.080443 1.739083 -0.015822
+v -0.085414 1.742389 -0.024470
+v -0.085530 1.734919 -0.027400
+v -0.083075 1.732831 -0.018878
+v -0.076001 1.729014 -0.012865
+v -0.077444 1.726111 -0.005953
+v -0.074448 1.726965 -0.002171
+v -0.074107 1.726852 0.002416
+v -0.072884 1.724916 0.012616
+v -0.070101 1.720304 0.029020
+v -0.065569 1.712886 0.050301
+v -0.057647 1.703466 0.068903
+v -0.048119 1.695440 0.081280
+v -0.036626 1.690315 0.087982
+v -0.027440 1.687463 0.094481
+v -0.018351 1.687018 0.100441
+v -0.009482 1.687585 0.106700
+v -0.090933 1.597029 -0.047136
+v -0.117637 1.578977 -0.049122
+v -0.006319 1.608667 0.044813
+v -0.012645 1.610453 0.041146
+v -0.019239 1.612790 0.034423
+v -0.027059 1.616058 0.024984
+v -0.038452 1.617996 0.013932
+v -0.053223 1.615282 0.006285
+v -0.061665 1.608403 -0.006838
+v -0.065607 1.597407 -0.023120
+v -0.026169 1.666994 0.090746
+v -0.023154 1.667386 0.092814
+v -0.025367 1.667083 0.091259
+v -0.023140 1.667651 0.093041
+v -0.025494 1.667201 0.091265
+v -0.010447 1.669980 0.101243
+v -0.018226 1.668650 0.096556
+v -0.018683 1.668534 0.095726
+v -0.010665 1.669179 0.099465
+v 0.240419 0.028025 -0.064598
+v 0.214742 0.028524 -0.135022
+v 0.170136 0.028524 -0.153646
+v 0.141940 0.028524 -0.131052
+v 0.153248 0.027295 -0.055831
+v 0.255085 0.016737 0.039452
+v 0.238718 0.016737 0.097813
+v 0.145661 0.016737 0.050411
+v 0.164969 0.016737 0.113922
+v 0.202729 0.016737 0.120323
+v 0.242952 0.028025 -0.066538
+v 0.215666 0.028524 -0.141348
+v 0.168821 0.028524 -0.160906
+v 0.139209 0.028524 -0.137178
+v 0.150897 0.027295 -0.057712
+v 0.258034 0.016737 0.042949
+v 0.240914 0.016737 0.103692
+v 0.143524 0.016737 0.054426
+v 0.164210 0.016737 0.120066
+v 0.203423 0.016737 0.126789
+v 0.242952 0.013555 -0.070778
+v 0.242952 0.013555 -0.070778
+v 0.242952 0.013555 -0.070778
+v 0.215666 0.014054 -0.141348
+v 0.168821 0.014054 -0.160906
+v 0.139209 0.014054 -0.137178
+v 0.150897 0.012826 -0.061952
+v 0.150897 0.012826 -0.061952
+v 0.150897 0.012826 -0.061952
+v 0.258034 -0.001088 0.025696
+v 0.240914 -0.000249 0.103692
+v 0.143524 -0.001088 0.037173
+v 0.164210 -0.000249 0.120066
+v 0.203423 -0.000249 0.126789
+v 0.242952 -0.000311 -0.070778
+v 0.242952 -0.000311 -0.070778
+v 0.215666 0.000188 -0.141348
+v 0.168821 0.000188 -0.160906
+v 0.139209 0.000188 -0.137178
+v 0.150897 -0.001041 -0.061952
+v 0.150897 -0.001041 -0.061952
+v 0.250941 0.022381 -0.013800
+v 0.154169 0.022381 -0.007738
+v 0.253682 0.022381 -0.013022
+v 0.151925 0.022381 -0.006671
+v 0.253682 0.005814 -0.021702
+v 0.151925 0.005814 -0.015351
+v 0.141647 0.491328 -0.114189
+v 0.205701 0.490563 -0.094984
+v 0.204864 0.482881 -0.001814
+v 0.219844 0.485703 -0.041760
+v 0.095093 0.485847 -0.085518
+v 0.097055 0.480678 -0.033262
+v 0.129203 0.478420 0.018134
+v 0.172100 0.480332 0.031533
+v 0.134275 1.530679 -0.176386
+v 0.172047 1.568379 -0.134707
+v 0.183198 1.581694 -0.087722
+v 0.183899 1.582353 -0.037207
+v 0.175968 1.570682 0.009387
+v 0.154211 1.545088 0.050300
+v 0.127586 1.516320 0.085776
+v 0.090502 1.480065 0.118043
+v 0.048199 1.439660 0.139210
+v 0.004523 1.397720 0.152934
+v -0.046749 1.346165 0.168389
+v -0.100793 1.286092 0.157968
+v -0.142447 1.245674 0.120062
+v -0.172509 1.215475 0.065591
+v -0.184084 1.200966 0.010595
+v -0.189708 1.193441 -0.037206
+v -0.183778 1.199644 -0.083800
+v -0.161577 1.220932 -0.127256
+v -0.125529 1.256296 -0.164504
+v -0.082149 1.299133 -0.193113
+v -0.040545 1.343281 -0.203115
+v 0.004932 1.390315 -0.209998
+v 0.049917 1.437272 -0.211098
+v 0.091361 1.483013 -0.199357
+v 0.085005 1.564355 -0.174013
+v 0.115650 1.595672 -0.131694
+v 0.128002 1.611723 -0.087199
+v 0.130140 1.610316 -0.037207
+v 0.123674 1.601299 0.009387
+v 0.103645 1.579924 0.048363
+v 0.078677 1.552097 0.085776
+v 0.047546 1.519726 0.111321
+v 0.006099 1.478006 0.130594
+v -0.039131 1.432221 0.142984
+v -0.086835 1.384427 0.149293
+v -0.134336 1.337502 0.138490
+v -0.172510 1.300595 0.106263
+v -0.197874 1.272699 0.058544
+v -0.209579 1.258838 0.009387
+v -0.212954 1.250003 -0.037206
+v -0.207024 1.256206 -0.083800
+v -0.189637 1.274392 -0.127219
+v -0.162299 1.301960 -0.167083
+v -0.125744 1.339687 -0.198121
+v -0.084020 1.384709 -0.206740
+v -0.038853 1.432207 -0.209998
+v 0.006131 1.479163 -0.211098
+v 0.048350 1.524587 -0.199694
+v -0.240419 0.028025 -0.064598
+v -0.214742 0.028524 -0.135022
+v -0.170136 0.028524 -0.153646
+v -0.141940 0.028524 -0.131052
+v -0.153248 0.027295 -0.055831
+v -0.255085 0.016737 0.039452
+v -0.238718 0.016737 0.097813
+v -0.145661 0.016737 0.050411
+v -0.164969 0.016737 0.113922
+v -0.202729 0.016737 0.120323
+v -0.242952 0.028025 -0.066538
+v -0.215666 0.028524 -0.141348
+v -0.168821 0.028524 -0.160906
+v -0.139209 0.028524 -0.137178
+v -0.150897 0.027295 -0.057712
+v -0.258034 0.016737 0.042949
+v -0.240914 0.016737 0.103692
+v -0.143524 0.016737 0.054426
+v -0.164210 0.016737 0.120066
+v -0.203423 0.016737 0.126789
+v -0.242952 0.013555 -0.070778
+v -0.242952 0.013555 -0.070778
+v -0.242952 0.013555 -0.070778
+v -0.215666 0.014054 -0.141348
+v -0.168821 0.014054 -0.160906
+v -0.139209 0.014054 -0.137178
+v -0.150897 0.012826 -0.061952
+v -0.150897 0.012826 -0.061952
+v -0.150897 0.012826 -0.061952
+v -0.258034 -0.001088 0.025696
+v -0.240914 -0.000249 0.103692
+v -0.143524 -0.001088 0.037173
+v -0.164210 -0.000249 0.120066
+v -0.203423 -0.000249 0.126789
+v -0.242952 -0.000311 -0.070778
+v -0.242952 -0.000311 -0.070778
+v -0.215666 0.000188 -0.141348
+v -0.168821 0.000188 -0.160906
+v -0.139209 0.000188 -0.137178
+v -0.150897 -0.001041 -0.061952
+v -0.150897 -0.001041 -0.061952
+v -0.250941 0.022381 -0.013800
+v -0.154169 0.022381 -0.007738
+v -0.253682 0.022381 -0.013022
+v -0.151925 0.022381 -0.006671
+v -0.253682 0.005814 -0.021702
+v -0.151925 0.005814 -0.015351
+v -0.141647 0.491328 -0.114189
+v -0.205701 0.490563 -0.094984
+v -0.204864 0.482881 -0.001814
+v -0.219844 0.485703 -0.041760
+v -0.095093 0.485847 -0.085518
+v -0.097055 0.480678 -0.033262
+v -0.129203 0.478420 0.018134
+v -0.172100 0.480332 0.031533
+v -0.121152 1.119257 0.137785
+v -0.172670 1.119257 0.018168
+v -0.149779 1.119257 -0.074245
+v -0.077684 1.119257 -0.119280
+v 0.000000 1.119257 -0.127489
+v -0.023899 1.119257 0.159816
+v -0.120262 1.183441 0.143953
+v -0.173867 1.183441 0.019491
+v -0.162576 1.183441 -0.083776
+v -0.083964 1.183441 -0.137626
+v -0.023899 1.183441 0.163047
+v 0.000000 1.183441 -0.137360
+v -0.096686 1.597695 -0.035012
+v -0.091318 1.612576 -0.091144
+v -0.079937 1.584289 0.006058
+v -0.052429 1.559129 0.039906
+v -0.059511 1.620940 -0.125205
+v -0.621947 1.243404 -0.024871
+v -0.606588 1.231470 0.001990
+v -0.584973 1.207811 0.013254
+v -0.574175 1.185285 -0.008347
+v -0.577637 1.175574 -0.050069
+v -0.592578 1.182565 -0.088309
+v -0.614130 1.213647 -0.085271
+v -0.624485 1.236964 -0.058985
+v 0.121152 1.119257 0.137785
+v 0.172670 1.119257 0.018168
+v 0.149779 1.119257 -0.074245
+v 0.077684 1.119257 -0.119280
+v 0.023899 1.119257 0.159816
+v 0.120262 1.183441 0.143953
+v 0.173867 1.183441 0.019491
+v 0.162576 1.183441 -0.083776
+v 0.083964 1.183441 -0.137626
+v 0.023899 1.183441 0.163047
+v 0.096686 1.597695 -0.035012
+v 0.091318 1.612576 -0.091144
+v 0.079937 1.584289 0.006058
+v 0.052429 1.559129 0.039906
+v 0.059511 1.620940 -0.125205
+v 0.000000 1.628451 -0.141560
+v 0.621947 1.243404 -0.024871
+v 0.606588 1.231470 0.001990
+v 0.584973 1.207811 0.013254
+v 0.574175 1.185285 -0.008347
+v 0.577637 1.175574 -0.050069
+v 0.592578 1.182565 -0.088309
+v 0.614130 1.213647 -0.085271
+v 0.624485 1.236964 -0.058985
+v 0.081559 1.119257 -0.128551
+v -0.000000 1.119257 -0.134141
+v 0.088152 1.183441 -0.144985
+v -0.000000 1.183441 -0.144198
+v 0.126261 1.183441 0.150700
+v 0.025091 1.183441 0.170750
+v 0.170685 1.183441 -0.088437
+v 0.182540 1.183441 0.020003
+v 0.127195 1.119257 0.144223
+v 0.025091 1.119257 0.167358
+v 0.157250 1.119257 -0.078428
+v 0.181283 1.119257 0.018614
+v -0.088152 1.183441 -0.144985
+v -0.126261 1.183441 0.150700
+v -0.025091 1.183441 0.170750
+v -0.170685 1.183441 -0.088437
+v -0.182540 1.183441 0.020003
+v -0.127195 1.119257 0.144223
+v -0.025091 1.119257 0.167358
+v -0.081559 1.119257 -0.128551
+v -0.157250 1.119257 -0.078428
+v -0.181283 1.119257 0.018614
+vt 0.449580 0.858975
+vt 0.446811 0.893259
+vt 0.433140 0.885831
+vt 0.433670 0.864937
+vt 0.423531 0.880869
+vt 0.423529 0.868245
+vt 0.415835 0.877335
+vt 0.415702 0.871436
+vt 0.414515 0.889573
+vt 0.411628 0.881619
+vt 0.417651 0.899717
+vt 0.421685 0.914018
+vt 0.390458 0.911080
+vt 0.397272 0.898573
+vt 0.402067 0.889322
+vt 0.405591 0.881662
+vt 0.393393 0.880542
+vt 0.401227 0.877410
+vt 0.383359 0.883769
+vt 0.370935 0.888385
+vt 0.370935 0.858506
+vt 0.384257 0.863504
+vt 0.393621 0.868148
+vt 0.401411 0.871385
+vt 0.402268 0.859233
+vt 0.405556 0.867002
+vt 0.398851 0.849239
+vt 0.392501 0.835844
+vt 0.424993 0.835030
+vt 0.419584 0.849580
+vt 0.414715 0.859212
+vt 0.411644 0.867121
+vt 0.417597 0.956332
+vt 0.417576 0.950144
+vt 0.425355 0.946640
+vt 0.425700 0.959173
+vt 0.435322 0.942917
+vt 0.435382 0.963543
+vt 0.449377 0.937962
+vt 0.448665 0.969820
+vt 0.421195 0.978216
+vt 0.426245 0.991732
+vt 0.416986 0.968612
+vt 0.413252 0.960694
+vt 0.407161 0.960617
+vt 0.404125 0.968616
+vt 0.400574 0.978915
+vt 0.395539 0.991932
+vt 0.385867 0.964205
+vt 0.370935 0.970769
+vt 0.395308 0.959573
+vt 0.403059 0.956313
+vt 0.402858 0.950352
+vt 0.395254 0.947339
+vt 0.385027 0.943389
+vt 0.370935 0.936984
+vt 0.399532 0.928313
+vt 0.394459 0.914018
+vt 0.403739 0.938160
+vt 0.407142 0.946172
+vt 0.413099 0.945981
+vt 0.416326 0.938377
+vt 0.420413 0.928266
+vt 0.426931 0.914702
+vt 0.408574 0.874372
+vt 0.410219 0.953325
+vt 0.226562 0.171042
+vt 0.229618 0.153547
+vt 0.213794 0.153209
+vt 0.216627 0.161433
+vt 0.226410 0.138889
+vt 0.215327 0.145725
+vt 0.269719 0.159499
+vt 0.266410 0.180819
+vt 0.294307 0.186604
+vt 0.294055 0.158409
+vt 0.270713 0.134889
+vt 0.298036 0.132710
+vt 0.258461 0.210978
+vt 0.301739 0.207512
+vt 0.274770 0.242260
+vt 0.305605 0.227598
+vt 0.281959 0.262495
+vt 0.310855 0.250656
+vt 0.315800 0.072344
+vt 0.289002 0.056629
+vt 0.282673 0.071246
+vt 0.311929 0.088777
+vt 0.264747 0.101276
+vt 0.307225 0.106799
+vt 0.211147 0.163031
+vt 0.222831 0.178025
+vt 0.224252 0.130297
+vt 0.210242 0.143682
+vt 0.208454 0.152443
+vt 0.251082 0.216519
+vt 0.263951 0.244894
+vt 0.269636 0.264314
+vt 0.277026 0.053942
+vt 0.272423 0.068261
+vt 0.256811 0.095031
+vt 0.205182 0.168917
+vt 0.220732 0.186309
+vt 0.223728 0.122074
+vt 0.205147 0.138166
+vt 0.199559 0.152688
+vt 0.185011 0.084085
+vt 0.144484 0.073736
+vt 0.144751 0.075541
+vt 0.185416 0.086719
+vt 0.205403 0.102002
+vt 0.204551 0.106150
+vt 0.183202 0.143308
+vt 0.201722 0.135143
+vt 0.201745 0.130825
+vt 0.184485 0.141155
+vt 0.141493 0.143342
+vt 0.142525 0.142035
+vt 0.080099 0.067409
+vt 0.041460 0.079404
+vt 0.041565 0.082754
+vt 0.078547 0.069709
+vt 0.036207 0.141284
+vt 0.078817 0.152441
+vt 0.076744 0.150829
+vt 0.036267 0.138918
+vt 0.020677 0.121887
+vt 0.023290 0.118459
+vt 0.019815 0.100613
+vt 0.021521 0.105052
+vt 0.185416 0.086719
+vt 0.144751 0.075541
+vt 0.144483 0.084078
+vt 0.181939 0.092531
+vt 0.204551 0.106150
+vt 0.198910 0.111854
+vt 0.184485 0.141155
+vt 0.201745 0.130825
+vt 0.197755 0.123798
+vt 0.182580 0.134913
+vt 0.142525 0.142035
+vt 0.143589 0.133666
+vt 0.078547 0.069709
+vt 0.041565 0.082754
+vt 0.047086 0.090558
+vt 0.089323 0.078817
+vt 0.036267 0.138918
+vt 0.076744 0.150829
+vt 0.086438 0.141007
+vt 0.041116 0.132335
+vt 0.023290 0.118459
+vt 0.032271 0.112484
+vt 0.021521 0.105052
+vt 0.181939 0.092531
+vt 0.144483 0.084078
+vt 0.147047 0.088006
+vt 0.179083 0.097193
+vt 0.198910 0.111854
+vt 0.193071 0.117160
+vt 0.182580 0.134913
+vt 0.197755 0.123798
+vt 0.181037 0.130160
+vt 0.143589 0.133666
+vt 0.147328 0.129616
+vt 0.147047 0.088006
+vt 0.147328 0.129616
+vt 0.181037 0.130160
+vt 0.179083 0.097193
+vt 0.193071 0.117160
+vt 0.144483 0.084078
+vt 0.143589 0.133666
+vt 0.147328 0.129616
+vt 0.147047 0.088006
+vt 0.089323 0.078817
+vt 0.047086 0.090558
+vt 0.041116 0.132335
+vt 0.086438 0.141007
+vt 0.032271 0.112484
+vt 0.245305 0.176883
+vt 0.247368 0.156147
+vt 0.245837 0.135881
+vt 0.241382 0.192418
+vt 0.247015 0.117246
+vt 0.237166 0.200209
+vt 0.243328 0.108719
+vt 0.114084 0.067095
+vt 0.113248 0.068587
+vt 0.114585 0.148101
+vt 0.113698 0.146940
+vt 0.113248 0.068587
+vt 0.116087 0.079310
+vt 0.113698 0.146940
+vt 0.116115 0.135892
+vt 0.116115 0.135892
+vt 0.116087 0.079310
+vt 0.143589 0.133666
+vt 0.144483 0.084078
+vt 0.343837 0.181822
+vt 0.345261 0.160962
+vt 0.347096 0.138981
+vt 0.343165 0.201512
+vt 0.343765 0.223779
+vt 0.344299 0.249475
+vt 0.350237 0.094115
+vt 0.349758 0.076974
+vt 0.348735 0.114152
+vt 0.387991 0.183482
+vt 0.389992 0.161674
+vt 0.391106 0.141087
+vt 0.385108 0.203688
+vt 0.383523 0.228087
+vt 0.381637 0.254339
+vt 0.389239 0.091371
+vt 0.385619 0.069439
+vt 0.389769 0.113982
+vt 0.427126 0.183782
+vt 0.429698 0.163320
+vt 0.429738 0.142056
+vt 0.424347 0.204292
+vt 0.422566 0.229611
+vt 0.424840 0.259782
+vt 0.427811 0.091080
+vt 0.427593 0.066817
+vt 0.429128 0.114476
+vt 0.081919 0.177576
+vt 0.080241 0.180500
+vt 0.099685 0.188250
+vt 0.099913 0.184162
+vt 0.067501 0.169108
+vt 0.064900 0.171780
+vt 0.059214 0.153117
+vt 0.054794 0.154109
+vt 0.171154 0.153117
+vt 0.159295 0.172265
+vt 0.162213 0.175238
+vt 0.175881 0.153828
+vt 0.143601 0.181366
+vt 0.144924 0.184881
+vt 0.129579 0.184219
+vt 0.129740 0.188639
+vt 0.113974 0.191097
+vt 0.114198 0.186685
+vt 0.077311 0.185604
+vt 0.098367 0.193721
+vt 0.060508 0.176299
+vt 0.048772 0.156819
+vt 0.165918 0.178906
+vt 0.182692 0.155388
+vt 0.146747 0.189406
+vt 0.130229 0.193924
+vt 0.113448 0.196200
+vt 0.064600 0.205653
+vt 0.090460 0.213946
+vt 0.049088 0.231773
+vt 0.082019 0.244697
+vt 0.044529 0.192489
+vt 0.023834 0.214521
+vt 0.157185 0.209804
+vt 0.180567 0.195484
+vt 0.170991 0.240628
+vt 0.199169 0.220714
+vt 0.136177 0.215367
+vt 0.144044 0.248982
+vt 0.112772 0.216603
+vt 0.112056 0.250004
+vt 0.199159 0.173643
+vt 0.218280 0.197160
+vt 0.030243 0.171420
+vt 0.008089 0.190338
+vt 0.464533 0.182687
+vt 0.467609 0.163910
+vt 0.467580 0.145645
+vt 0.461994 0.199903
+vt 0.460739 0.222485
+vt 0.465593 0.250101
+vt 0.465044 0.099687
+vt 0.467609 0.076893
+vt 0.466213 0.121048
+vt 0.161560 0.402243
+vt 0.155588 0.395509
+vt 0.134626 0.410605
+vt 0.146864 0.425262
+vt 0.127497 0.391275
+vt 0.152830 0.385975
+vt 0.127264 0.371100
+vt 0.153383 0.375493
+vt 0.134716 0.352237
+vt 0.156932 0.365158
+vt 0.145395 0.334369
+vt 0.162411 0.356153
+vt 0.160447 0.323865
+vt 0.169799 0.350020
+vt 0.177475 0.320161
+vt 0.178468 0.347729
+vt 0.194608 0.323042
+vt 0.186891 0.350662
+vt 0.210291 0.333563
+vt 0.193747 0.356991
+vt 0.223414 0.349480
+vt 0.199287 0.365151
+vt 0.230882 0.369006
+vt 0.203745 0.374332
+vt 0.231524 0.389807
+vt 0.205469 0.384522
+vt 0.224638 0.409261
+vt 0.203005 0.394667
+vt 0.212389 0.424654
+vt 0.197149 0.402034
+vt 0.197372 0.433287
+vt 0.188865 0.405252
+vt 0.179699 0.435910
+vt 0.179384 0.405997
+vt 0.162040 0.433331
+vt 0.169888 0.405254
+vt 0.165387 0.397638
+vt 0.160572 0.392283
+vt 0.158418 0.384595
+vt 0.158964 0.376281
+vt 0.161637 0.368049
+vt 0.165965 0.360925
+vt 0.171743 0.356015
+vt 0.178593 0.354261
+vt 0.185319 0.356439
+vt 0.190856 0.361326
+vt 0.195230 0.367767
+vt 0.198608 0.375152
+vt 0.199761 0.383347
+vt 0.197879 0.391455
+vt 0.193207 0.397352
+vt 0.186697 0.400151
+vt 0.179298 0.400776
+vt 0.171898 0.400197
+vt 0.178814 0.379350
+vt 0.179769 0.441150
+vt 0.221479 0.443653
+vt 0.256818 0.438950
+vt 0.289823 0.435602
+vt 0.137780 0.444611
+vt 0.102166 0.444863
+vt 0.077709 0.444123
+vt 0.083017 0.411236
+vt 0.097247 0.382934
+vt 0.118968 0.348422
+vt 0.138683 0.313766
+vt 0.160629 0.287922
+vt 0.180188 0.263330
+vt 0.198518 0.285300
+vt 0.216421 0.311488
+vt 0.239706 0.345595
+vt 0.261990 0.379891
+vt 0.277767 0.406096
+vt 0.258659 0.459445
+vt 0.284835 0.453304
+vt 0.264043 0.483454
+vt 0.221478 0.504250
+vt 0.223490 0.459014
+vt 0.181117 0.514996
+vt 0.180077 0.458023
+vt 0.140539 0.505936
+vt 0.136318 0.460481
+vt 0.097191 0.485804
+vt 0.100655 0.461818
+vt 0.077873 0.458646
+vt 0.144974 0.275250
+vt 0.161388 0.256884
+vt 0.128621 0.256115
+vt 0.126787 0.303834
+vt 0.086241 0.279508
+vt 0.104546 0.338805
+vt 0.055299 0.310343
+vt 0.082787 0.376723
+vt 0.042576 0.351978
+vt 0.068614 0.405298
+vt 0.044158 0.400261
+vt 0.061831 0.429301
+vt 0.208879 0.272663
+vt 0.192460 0.255496
+vt 0.225038 0.253308
+vt 0.268938 0.274082
+vt 0.229092 0.300701
+vt 0.302213 0.302785
+vt 0.254202 0.335934
+vt 0.315656 0.344933
+vt 0.276573 0.372608
+vt 0.317865 0.392224
+vt 0.293549 0.400188
+vt 0.301058 0.427072
+vt 0.198759 0.014828
+vt 0.222350 0.014086
+vt 0.225351 0.035722
+vt 0.202970 0.036062
+vt 0.181802 0.015068
+vt 0.184866 0.037201
+vt 0.165781 0.039107
+vt 0.163527 0.016516
+vt 0.147732 0.040863
+vt 0.146627 0.019020
+vt 0.127089 0.021494
+vt 0.129597 0.044996
+vt 0.109381 0.048515
+vt 0.107302 0.025406
+vt 0.089500 0.053020
+vt 0.084308 0.031079
+vt 0.066071 0.058633
+vt 0.061110 0.037042
+vt 0.042124 0.064867
+vt 0.037762 0.043424
+vt 0.010834 0.050893
+vt 0.017458 0.072394
+vt 0.511165 0.043447
+vt 0.536993 0.053487
+vt 0.527229 0.073598
+vt 0.505665 0.063756
+vt 0.489710 0.035104
+vt 0.484654 0.056823
+vt 0.463246 0.050665
+vt 0.466794 0.027952
+vt 0.443529 0.046206
+vt 0.446550 0.021943
+vt 0.425383 0.041270
+vt 0.428544 0.018957
+vt 0.412223 0.017650
+vt 0.407054 0.038941
+vt 0.387963 0.037877
+vt 0.393758 0.016432
+vt 0.370467 0.015023
+vt 0.366871 0.036829
+vt 0.345593 0.014298
+vt 0.344160 0.035900
+vt 0.321358 0.013160
+vt 0.320863 0.036705
+vt 0.296412 0.036649
+vt 0.296765 0.012973
+vt 0.272244 0.012915
+vt 0.271910 0.035815
+vt 0.247906 0.013068
+vt 0.247801 0.035841
+vt 0.202970 0.036062
+vt 0.225351 0.035722
+vt 0.226515 0.038974
+vt 0.203971 0.039652
+vt 0.184866 0.037201
+vt 0.185261 0.041150
+vt 0.165781 0.039107
+vt 0.165701 0.043024
+vt 0.147732 0.040863
+vt 0.147361 0.044516
+vt 0.129597 0.044996
+vt 0.129124 0.048490
+vt 0.109381 0.048515
+vt 0.109030 0.051791
+vt 0.089500 0.053020
+vt 0.089310 0.056207
+vt 0.066071 0.058633
+vt 0.066429 0.061755
+vt 0.042124 0.064867
+vt 0.043392 0.067828
+vt 0.017458 0.072394
+vt 0.019813 0.075036
+vt 0.505665 0.063756
+vt 0.527229 0.073598
+vt 0.526478 0.076523
+vt 0.505443 0.066939
+vt 0.484654 0.056823
+vt 0.484326 0.060219
+vt 0.463246 0.050665
+vt 0.462739 0.054336
+vt 0.443529 0.046206
+vt 0.442909 0.050073
+vt 0.425383 0.041270
+vt 0.424602 0.045251
+vt 0.407054 0.038941
+vt 0.406065 0.042638
+vt 0.387963 0.037877
+vt 0.386843 0.041329
+vt 0.366871 0.036829
+vt 0.365783 0.040029
+vt 0.344160 0.035900
+vt 0.343103 0.038850
+vt 0.320863 0.036705
+vt 0.320106 0.039720
+vt 0.296412 0.036649
+vt 0.296500 0.039755
+vt 0.271910 0.035815
+vt 0.272773 0.038876
+vt 0.247801 0.035841
+vt 0.248977 0.038910
+vt 0.222350 0.014086
+vt 0.198759 0.014828
+vt 0.199687 0.011221
+vt 0.223818 0.010772
+vt 0.181802 0.015068
+vt 0.181553 0.010779
+vt 0.163527 0.016516
+vt 0.162421 0.012640
+vt 0.146627 0.019020
+vt 0.144887 0.015688
+vt 0.127089 0.021494
+vt 0.125141 0.018434
+vt 0.107302 0.025406
+vt 0.105487 0.022568
+vt 0.084308 0.031079
+vt 0.082771 0.028292
+vt 0.061110 0.037042
+vt 0.060037 0.034148
+vt 0.037762 0.043424
+vt 0.037449 0.040101
+vt 0.010834 0.050893
+vt 0.011806 0.047081
+vt 0.536993 0.053487
+vt 0.511165 0.043447
+vt 0.513311 0.040731
+vt 0.538834 0.050433
+vt 0.489710 0.035104
+vt 0.491532 0.031973
+vt 0.466794 0.027952
+vt 0.468347 0.024422
+vt 0.446550 0.021943
+vt 0.447882 0.017991
+vt 0.428544 0.018957
+vt 0.429133 0.014719
+vt 0.412223 0.017650
+vt 0.411628 0.013830
+vt 0.393758 0.016432
+vt 0.392516 0.012983
+vt 0.370467 0.015023
+vt 0.369188 0.011747
+vt 0.345593 0.014298
+vt 0.344564 0.011199
+vt 0.321358 0.013160
+vt 0.320786 0.010038
+vt 0.296765 0.012973
+vt 0.297047 0.009849
+vt 0.272244 0.012915
+vt 0.273167 0.009848
+vt 0.247906 0.013068
+vt 0.249194 0.009894
+vt 0.226562 0.171042
+vt 0.216627 0.161433
+vt 0.213794 0.153209
+vt 0.229618 0.153547
+vt 0.215327 0.145725
+vt 0.226410 0.138889
+vt 0.294307 0.186604
+vt 0.266410 0.180819
+vt 0.269719 0.159499
+vt 0.294055 0.158409
+vt 0.270713 0.134889
+vt 0.298036 0.132710
+vt 0.301739 0.207512
+vt 0.258461 0.210978
+vt 0.305605 0.227598
+vt 0.274770 0.242260
+vt 0.310855 0.250656
+vt 0.281959 0.262495
+vt 0.315800 0.072344
+vt 0.311929 0.088777
+vt 0.282673 0.071246
+vt 0.289002 0.056629
+vt 0.307225 0.106799
+vt 0.264747 0.101276
+vt 0.222831 0.178025
+vt 0.211147 0.163031
+vt 0.210242 0.143682
+vt 0.224252 0.130297
+vt 0.208454 0.152443
+vt 0.263951 0.244894
+vt 0.251082 0.216519
+vt 0.269636 0.264314
+vt 0.272423 0.068261
+vt 0.277026 0.053942
+vt 0.256811 0.095031
+vt 0.220732 0.186309
+vt 0.205182 0.168917
+vt 0.205147 0.138166
+vt 0.223728 0.122074
+vt 0.199559 0.152688
+vt 0.185011 0.084085
+vt 0.185416 0.086719
+vt 0.144751 0.075541
+vt 0.144484 0.073736
+vt 0.205403 0.102002
+vt 0.204551 0.106150
+vt 0.183202 0.143308
+vt 0.184485 0.141155
+vt 0.201745 0.130825
+vt 0.201722 0.135143
+vt 0.141493 0.143342
+vt 0.142525 0.142035
+vt 0.080099 0.067409
+vt 0.078547 0.069709
+vt 0.041565 0.082754
+vt 0.041460 0.079404
+vt 0.036207 0.141284
+vt 0.036267 0.138918
+vt 0.076744 0.150829
+vt 0.078817 0.152441
+vt 0.020677 0.121887
+vt 0.023290 0.118459
+vt 0.021521 0.105052
+vt 0.019815 0.100613
+vt 0.185416 0.086719
+vt 0.181939 0.092531
+vt 0.144483 0.084078
+vt 0.144751 0.075541
+vt 0.204551 0.106150
+vt 0.198910 0.111854
+vt 0.184485 0.141155
+vt 0.182580 0.134913
+vt 0.197755 0.123798
+vt 0.201745 0.130825
+vt 0.142525 0.142035
+vt 0.143589 0.133666
+vt 0.078547 0.069709
+vt 0.089323 0.078817
+vt 0.047086 0.090558
+vt 0.041565 0.082754
+vt 0.036267 0.138918
+vt 0.041116 0.132335
+vt 0.086438 0.141007
+vt 0.076744 0.150829
+vt 0.023290 0.118459
+vt 0.032271 0.112484
+vt 0.021521 0.105052
+vt 0.181939 0.092531
+vt 0.179083 0.097193
+vt 0.147047 0.088006
+vt 0.144483 0.084078
+vt 0.198910 0.111854
+vt 0.193071 0.117160
+vt 0.182580 0.134913
+vt 0.181037 0.130160
+vt 0.197755 0.123798
+vt 0.143589 0.133666
+vt 0.147328 0.129616
+vt 0.147047 0.088006
+vt 0.179083 0.097193
+vt 0.181037 0.130160
+vt 0.147328 0.129616
+vt 0.193071 0.117160
+vt 0.144483 0.084078
+vt 0.147047 0.088006
+vt 0.147328 0.129616
+vt 0.143589 0.133666
+vt 0.089323 0.078817
+vt 0.086438 0.141007
+vt 0.041116 0.132335
+vt 0.047086 0.090558
+vt 0.032271 0.112484
+vt 0.245305 0.176883
+vt 0.247368 0.156147
+vt 0.245837 0.135881
+vt 0.241382 0.192418
+vt 0.247015 0.117246
+vt 0.237166 0.200209
+vt 0.243328 0.108719
+vt 0.113248 0.068587
+vt 0.114084 0.067095
+vt 0.113698 0.146940
+vt 0.114585 0.148101
+vt 0.116087 0.079310
+vt 0.113248 0.068587
+vt 0.116115 0.135892
+vt 0.113698 0.146940
+vt 0.116087 0.079310
+vt 0.116115 0.135892
+vt 0.144483 0.084078
+vt 0.143589 0.133666
+vt 0.345261 0.160962
+vt 0.343837 0.181822
+vt 0.347096 0.138981
+vt 0.343165 0.201512
+vt 0.343765 0.223779
+vt 0.344299 0.249475
+vt 0.349758 0.076974
+vt 0.350237 0.094115
+vt 0.348735 0.114152
+vt 0.389992 0.161674
+vt 0.387991 0.183482
+vt 0.391106 0.141087
+vt 0.385108 0.203688
+vt 0.383523 0.228087
+vt 0.381637 0.254339
+vt 0.385619 0.069439
+vt 0.389239 0.091371
+vt 0.389769 0.113982
+vt 0.429698 0.163320
+vt 0.427126 0.183782
+vt 0.429738 0.142056
+vt 0.424347 0.204292
+vt 0.422566 0.229611
+vt 0.424840 0.259782
+vt 0.427593 0.066817
+vt 0.427811 0.091080
+vt 0.429128 0.114476
+vt 0.081919 0.177576
+vt 0.099913 0.184162
+vt 0.099685 0.188250
+vt 0.080241 0.180500
+vt 0.064900 0.171780
+vt 0.067501 0.169108
+vt 0.054794 0.154109
+vt 0.059214 0.153117
+vt 0.171154 0.153117
+vt 0.175881 0.153828
+vt 0.162213 0.175238
+vt 0.159295 0.172265
+vt 0.144924 0.184881
+vt 0.143601 0.181366
+vt 0.129740 0.188639
+vt 0.129579 0.184219
+vt 0.114198 0.186685
+vt 0.113974 0.191097
+vt 0.098367 0.193721
+vt 0.077311 0.185604
+vt 0.060508 0.176299
+vt 0.048772 0.156819
+vt 0.182692 0.155388
+vt 0.165918 0.178906
+vt 0.146747 0.189406
+vt 0.130229 0.193924
+vt 0.113448 0.196200
+vt 0.090460 0.213946
+vt 0.064600 0.205653
+vt 0.082019 0.244697
+vt 0.049088 0.231773
+vt 0.044529 0.192489
+vt 0.023834 0.214521
+vt 0.180567 0.195484
+vt 0.157185 0.209804
+vt 0.199169 0.220714
+vt 0.170991 0.240628
+vt 0.136177 0.215367
+vt 0.144044 0.248982
+vt 0.112772 0.216603
+vt 0.112056 0.250004
+vt 0.199159 0.173643
+vt 0.218280 0.197160
+vt 0.030243 0.171420
+vt 0.008089 0.190338
+vt 0.467609 0.163910
+vt 0.464533 0.182687
+vt 0.467580 0.145645
+vt 0.461994 0.199903
+vt 0.460739 0.222485
+vt 0.465593 0.250101
+vt 0.467609 0.076893
+vt 0.465044 0.099687
+vt 0.466213 0.121048
+vt 0.824979 0.045863
+vt 0.793239 0.045819
+vt 0.793312 0.041673
+vt 0.825514 0.041655
+vt 0.793893 0.008820
+vt 0.827890 0.012944
+vt 0.828581 0.017380
+vt 0.793815 0.013267
+vt 0.939153 0.031665
+vt 0.979840 0.032855
+vt 0.979755 0.038216
+vt 0.938105 0.037188
+vt 0.862021 0.016414
+vt 0.861433 0.021442
+vt 0.898925 0.022267
+vt 0.897466 0.027142
+vt 0.971485 0.076154
+vt 0.930825 0.061364
+vt 0.931849 0.055717
+vt 0.973626 0.070853
+vt 0.857410 0.048076
+vt 0.858591 0.043648
+vt 0.892122 0.054446
+vt 0.892962 0.049427
+vt 0.759776 0.011742
+vt 0.758929 0.016149
+vt 0.608761 0.027123
+vt 0.648032 0.026496
+vt 0.648918 0.031986
+vt 0.609242 0.031905
+vt 0.725555 0.014001
+vt 0.725965 0.019044
+vt 0.688488 0.018531
+vt 0.689772 0.023449
+vt 0.655359 0.056552
+vt 0.615849 0.068576
+vt 0.614741 0.063712
+vt 0.654567 0.050945
+vt 0.761519 0.044736
+vt 0.761134 0.040513
+vt 0.729040 0.045799
+vt 0.728016 0.041333
+vt 0.694151 0.050945
+vt 0.693483 0.045909
+vt 0.654567 0.050945
+vt 0.648918 0.031986
+vt 0.689772 0.023449
+vt 0.693483 0.045909
+vt 0.725965 0.019044
+vt 0.728016 0.041333
+vt 0.758929 0.016149
+vt 0.761134 0.040513
+vt 0.609242 0.031905
+vt 0.614741 0.063712
+vt 0.793312 0.041673
+vt 0.793815 0.013267
+vt 0.931849 0.055717
+vt 0.892962 0.049427
+vt 0.897466 0.027142
+vt 0.938105 0.037188
+vt 0.858591 0.043648
+vt 0.861433 0.021442
+vt 0.825514 0.041655
+vt 0.828581 0.017380
+vt 0.979755 0.038216
+vt 0.973626 0.070853
+vt 0.579840 0.033462
+vt 0.580275 0.028828
+vt 0.586823 0.076152
+vt 0.584904 0.071762
+vt 0.584904 0.071762
+vt 0.579840 0.033462
+vt 0.104500 0.536214
+vt 0.105732 0.526505
+vt 0.114426 0.528654
+vt 0.112823 0.537425
+vt 0.123022 0.531811
+vt 0.122042 0.539539
+vt 0.117940 0.538790
+vt 0.119592 0.530467
+vt 0.078999 0.531783
+vt 0.079412 0.521731
+vt 0.085663 0.522844
+vt 0.084893 0.532679
+vt 0.073567 0.511819
+vt 0.073483 0.505967
+vt 0.079489 0.506681
+vt 0.079286 0.513366
+vt 0.097178 0.510132
+vt 0.095841 0.516649
+vt 0.086454 0.514927
+vt 0.087336 0.508697
+vt 0.094721 0.524391
+vt 0.116274 0.521220
+vt 0.117835 0.515207
+vt 0.123610 0.517489
+vt 0.121664 0.523054
+vt 0.127950 0.519596
+vt 0.125248 0.524531
+vt 0.066875 0.504854
+vt 0.067932 0.510440
+vt 0.062507 0.509670
+vt 0.060099 0.504182
+vt 0.068905 0.519309
+vt 0.064061 0.518154
+vt 0.073994 0.520429
+vt 0.068891 0.529347
+vt 0.063634 0.527723
+vt 0.107153 0.519113
+vt 0.108756 0.513016
+vt 0.057551 0.509684
+vt 0.054170 0.504868
+vt 0.059161 0.517300
+vt 0.073903 0.530789
+vt 0.094035 0.534646
+vt 0.059014 0.525280
+vt 0.259060 0.536214
+vt 0.250751 0.537425
+vt 0.249134 0.528654
+vt 0.257842 0.526505
+vt 0.240545 0.531811
+vt 0.243975 0.530467
+vt 0.245620 0.538790
+vt 0.241518 0.539539
+vt 0.284575 0.531783
+vt 0.278681 0.532679
+vt 0.277911 0.522844
+vt 0.284162 0.521731
+vt 0.289993 0.511819
+vt 0.284288 0.513366
+vt 0.284071 0.506681
+vt 0.290077 0.505967
+vt 0.266389 0.510132
+vt 0.276224 0.508697
+vt 0.277113 0.514927
+vt 0.267719 0.516649
+vt 0.268846 0.524391
+vt 0.247300 0.521220
+vt 0.241903 0.523054
+vt 0.239964 0.517489
+vt 0.245732 0.515207
+vt 0.238326 0.524531
+vt 0.235624 0.519596
+vt 0.296692 0.504854
+vt 0.303461 0.504182
+vt 0.301060 0.509670
+vt 0.295628 0.510440
+vt 0.299499 0.518154
+vt 0.294662 0.519309
+vt 0.289573 0.520429
+vt 0.299926 0.527723
+vt 0.294662 0.529347
+vt 0.256400 0.519113
+vt 0.254811 0.513016
+vt 0.309390 0.504868
+vt 0.306016 0.509684
+vt 0.304399 0.517300
+vt 0.289671 0.530789
+vt 0.269539 0.534646
+vt 0.304560 0.525280
+vt 0.390760 0.520514
+vt 0.336134 0.535945
+vt 0.335878 0.477450
+vt 0.390759 0.473676
+vt 0.445641 0.477449
+vt 0.445386 0.535945
+vt 0.343131 0.407459
+vt 0.390759 0.403233
+vt 0.438387 0.407458
+vt 0.351461 0.343819
+vt 0.390758 0.342970
+vt 0.430055 0.343818
+vt 0.354191 0.290140
+vt 0.390758 0.289390
+vt 0.427326 0.290140
+vt 0.061135 0.632763
+vt 0.063655 0.610363
+vt 0.074736 0.604595
+vt 0.074295 0.625763
+vt 0.057369 0.540426
+vt 0.054492 0.558794
+vt 0.042242 0.552452
+vt 0.048822 0.539355
+vt 0.054597 0.585583
+vt 0.042970 0.582979
+vt 0.047058 0.631419
+vt 0.050852 0.610538
+vt 0.131163 0.634639
+vt 0.131289 0.642297
+vt 0.127040 0.641562
+vt 0.130316 0.626757
+vt 0.050124 0.642451
+vt 0.057110 0.643109
+vt 0.048927 0.650662
+vt 0.056221 0.651355
+vt 0.132479 0.652342
+vt 0.127229 0.651796
+vt 0.133949 0.669849
+vt 0.128335 0.670255
+vt 0.036621 0.626190
+vt 0.039169 0.607948
+vt 0.053351 0.669968
+vt 0.046939 0.669324
+vt 0.116911 0.654701
+vt 0.121209 0.653091
+vt 0.122651 0.671501
+vt 0.117541 0.671431
+vt 0.116400 0.645923
+vt 0.119935 0.643452
+vt 0.115805 0.640568
+vt 0.115833 0.633351
+vt 0.041486 0.640001
+vt 0.039323 0.647533
+vt 0.033065 0.643837
+vt 0.034997 0.635591
+vt 0.035396 0.661631
+vt 0.029509 0.658880
+vt 0.133074 0.651670
+vt 0.131856 0.642248
+vt 0.135118 0.639469
+vt 0.137316 0.649507
+vt 0.140382 0.665733
+vt 0.135139 0.670927
+vt 0.143609 0.603412
+vt 0.139311 0.594319
+vt 0.146451 0.595663
+vt 0.144869 0.605106
+vt 0.137239 0.609873
+vt 0.142727 0.607563
+vt 0.127712 0.610888
+vt 0.127341 0.591435
+vt 0.149804 0.580648
+vt 0.140410 0.565570
+vt 0.156902 0.571541
+vt 0.151134 0.553271
+vt 0.157896 0.596188
+vt 0.154214 0.606100
+vt 0.162481 0.589545
+vt 0.127362 0.566830
+vt 0.127726 0.552592
+vt 0.137974 0.552347
+vt 0.032470 0.570638
+vt 0.035130 0.586003
+vt 0.026485 0.596818
+vt 0.023293 0.584953
+vt 0.151071 0.614773
+vt 0.157665 0.612183
+vt 0.154424 0.622046
+vt 0.160913 0.617671
+vt 0.158785 0.626792
+vt 0.165001 0.620695
+vt 0.165932 0.626386
+vt 0.139010 0.625182
+vt 0.140998 0.635612
+vt 0.143273 0.679698
+vt 0.138800 0.685942
+vt 0.145870 0.662072
+vt 0.148292 0.676597
+vt 0.141516 0.692179
+vt 0.144757 0.686026
+vt 0.032274 0.675015
+vt 0.030748 0.681700
+vt 0.025036 0.679628
+vt 0.026443 0.672845
+vt 0.104276 0.587774
+vt 0.104024 0.606135
+vt 0.095127 0.600451
+vt 0.095092 0.583609
+vt 0.092334 0.630229
+vt 0.097136 0.634639
+vt 0.095806 0.645678
+vt 0.090850 0.642066
+vt 0.099901 0.636536
+vt 0.099208 0.647064
+vt 0.094539 0.614724
+vt 0.085950 0.614808
+vt 0.086069 0.599660
+vt 0.093440 0.623019
+vt 0.085733 0.622543
+vt 0.085404 0.629431
+vt 0.085103 0.640974
+vt 0.101056 0.645741
+vt 0.105347 0.647771
+vt 0.105067 0.665502
+vt 0.099845 0.665614
+vt 0.105354 0.637397
+vt 0.101259 0.635451
+vt 0.105179 0.681651
+vt 0.100272 0.684353
+vt 0.110835 0.649801
+vt 0.110604 0.666377
+vt 0.115602 0.654288
+vt 0.115693 0.667847
+vt 0.064194 0.650067
+vt 0.071187 0.647365
+vt 0.070571 0.666342
+vt 0.063858 0.668309
+vt 0.115546 0.645545
+vt 0.111787 0.641156
+vt 0.110107 0.682428
+vt 0.109568 0.689204
+vt 0.105186 0.688441
+vt 0.114055 0.686180
+vt 0.112312 0.693663
+vt 0.069682 0.683618
+vt 0.063508 0.685242
+vt 0.101448 0.628682
+vt 0.102645 0.619771
+vt 0.063284 0.691626
+vt 0.069717 0.690331
+vt 0.063340 0.696659
+vt 0.069220 0.696008
+vt 0.110429 0.698472
+vt 0.108532 0.694573
+vt 0.098662 0.628374
+vt 0.100391 0.632343
+vt 0.077802 0.634716
+vt 0.079020 0.645678
+vt 0.164371 0.608921
+vt 0.161452 0.602992
+vt 0.165939 0.596447
+vt 0.168557 0.604168
+vt 0.167094 0.615970
+vt 0.169978 0.615697
+vt 0.018890 0.590553
+vt 0.022565 0.603237
+vt 0.009825 0.603846
+vt 0.014683 0.596510
+vt 0.018211 0.608592
+vt 0.011855 0.613422
+vt 0.093426 0.661645
+vt 0.091774 0.666300
+vt 0.089205 0.664536
+vt 0.089506 0.658698
+vt 0.092670 0.671522
+vt 0.086748 0.665649
+vt 0.096345 0.668043
+vt 0.080371 0.662765
+vt 0.079923 0.656969
+vt 0.085145 0.652370
+vt 0.085397 0.659265
+vt 0.098641 0.660777
+vt 0.094483 0.655982
+vt 0.081253 0.668995
+vt 0.105781 0.693901
+vt 0.103562 0.697737
+vt 0.129420 0.701776
+vt 0.129350 0.694769
+vt 0.133788 0.697695
+vt 0.131142 0.705381
+vt 0.134488 0.689029
+vt 0.129147 0.687265
+vt 0.124520 0.706935
+vt 0.126228 0.701958
+vt 0.042746 0.700852
+vt 0.043446 0.693642
+vt 0.049739 0.694069
+vt 0.048633 0.701293
+vt 0.121188 0.701209
+vt 0.124800 0.695938
+vt 0.119102 0.693250
+vt 0.123967 0.688602
+vt 0.145499 0.696547
+vt 0.146577 0.691080
+vt 0.028998 0.688861
+vt 0.024077 0.687447
+vt 0.149328 0.690240
+vt 0.151652 0.693257
+vt 0.149202 0.683527
+vt 0.094567 0.553677
+vt 0.094679 0.565171
+vt 0.086615 0.563519
+vt 0.086636 0.551990
+vt 0.066105 0.562595
+vt 0.066924 0.545564
+vt 0.076465 0.548805
+vt 0.076794 0.562609
+vt 0.076094 0.583224
+vt 0.065965 0.585912
+vt 0.115385 0.611665
+vt 0.113712 0.551605
+vt 0.114468 0.566676
+vt 0.103422 0.566830
+vt 0.102302 0.553894
+vt 0.115196 0.590889
+vt 0.086433 0.581922
+vt 0.076976 0.629452
+vt 0.089891 0.652531
+vt 0.050859 0.686894
+vt 0.044328 0.686348
+vt 0.142888 0.645587
+vt 0.064404 0.641961
+vt 0.071285 0.639014
+vt 0.145870 0.623131
+vt 0.147487 0.633050
+vt 0.148999 0.642234
+vt 0.145009 0.543016
+vt 0.151743 0.659720
+vt 0.153647 0.676317
+vt 0.101553 0.692361
+vt 0.153563 0.684745
+vt 0.302124 0.632763
+vt 0.288957 0.625763
+vt 0.288516 0.604595
+vt 0.299597 0.610363
+vt 0.305883 0.540426
+vt 0.314430 0.539355
+vt 0.321010 0.552452
+vt 0.308760 0.558794
+vt 0.320282 0.582979
+vt 0.308655 0.585583
+vt 0.316194 0.631419
+vt 0.312400 0.610538
+vt 0.232089 0.634639
+vt 0.232936 0.626757
+vt 0.236212 0.641562
+vt 0.231963 0.642297
+vt 0.313128 0.642451
+vt 0.306142 0.643109
+vt 0.314325 0.650662
+vt 0.307031 0.651355
+vt 0.236023 0.651796
+vt 0.230773 0.652342
+vt 0.234917 0.670255
+vt 0.229303 0.669849
+vt 0.324083 0.607948
+vt 0.326631 0.626190
+vt 0.316313 0.669324
+vt 0.309901 0.669968
+vt 0.246341 0.654701
+vt 0.245704 0.671431
+vt 0.240601 0.671501
+vt 0.242043 0.653091
+vt 0.243317 0.643452
+vt 0.246852 0.645923
+vt 0.247419 0.633351
+vt 0.247447 0.640568
+vt 0.321766 0.640001
+vt 0.328248 0.635591
+vt 0.330187 0.643837
+vt 0.323929 0.647533
+vt 0.333743 0.658880
+vt 0.327856 0.661631
+vt 0.230178 0.651670
+vt 0.225936 0.649507
+vt 0.228127 0.639469
+vt 0.231396 0.642248
+vt 0.228113 0.670927
+vt 0.222870 0.665733
+vt 0.219643 0.603412
+vt 0.218383 0.605106
+vt 0.216801 0.595663
+vt 0.223941 0.594319
+vt 0.226013 0.609873
+vt 0.220518 0.607563
+vt 0.235911 0.591435
+vt 0.235540 0.610888
+vt 0.213448 0.580648
+vt 0.222842 0.565570
+vt 0.206350 0.571541
+vt 0.212118 0.553271
+vt 0.209038 0.606100
+vt 0.205356 0.596188
+vt 0.200771 0.589545
+vt 0.235890 0.566830
+vt 0.225271 0.552347
+vt 0.235526 0.552592
+vt 0.330782 0.570638
+vt 0.339959 0.584953
+vt 0.336767 0.596818
+vt 0.328122 0.586003
+vt 0.212181 0.614773
+vt 0.208828 0.622046
+vt 0.205587 0.612183
+vt 0.204467 0.626792
+vt 0.202339 0.617671
+vt 0.197320 0.626386
+vt 0.198251 0.620695
+vt 0.222254 0.635612
+vt 0.224235 0.625182
+vt 0.224452 0.685942
+vt 0.219979 0.679698
+vt 0.214953 0.676597
+vt 0.217382 0.662072
+vt 0.221736 0.692179
+vt 0.218495 0.686026
+vt 0.330978 0.675015
+vt 0.336809 0.672845
+vt 0.338216 0.679628
+vt 0.332504 0.681700
+vt 0.258976 0.587774
+vt 0.268160 0.583609
+vt 0.268125 0.600451
+vt 0.259228 0.606135
+vt 0.270918 0.630229
+vt 0.272402 0.642066
+vt 0.267446 0.645678
+vt 0.266116 0.634639
+vt 0.264044 0.647064
+vt 0.263351 0.636536
+vt 0.277197 0.599660
+vt 0.277302 0.614808
+vt 0.268713 0.614724
+vt 0.277519 0.622543
+vt 0.269812 0.623019
+vt 0.277834 0.629431
+vt 0.278149 0.640974
+vt 0.262196 0.645741
+vt 0.263407 0.665614
+vt 0.258185 0.665502
+vt 0.257905 0.647771
+vt 0.257898 0.637397
+vt 0.261993 0.635451
+vt 0.262980 0.684353
+vt 0.258073 0.681651
+vt 0.252648 0.666377
+vt 0.252417 0.649801
+vt 0.247566 0.667847
+vt 0.247650 0.654288
+vt 0.299058 0.650067
+vt 0.299394 0.668309
+vt 0.292681 0.666342
+vt 0.292065 0.647365
+vt 0.251465 0.641156
+vt 0.247706 0.645545
+vt 0.253145 0.682428
+vt 0.258066 0.688441
+vt 0.253684 0.689204
+vt 0.250940 0.693663
+vt 0.249197 0.686180
+vt 0.299744 0.685242
+vt 0.293570 0.683618
+vt 0.260607 0.619771
+vt 0.261804 0.628682
+vt 0.299968 0.691626
+vt 0.293535 0.690331
+vt 0.299912 0.696659
+vt 0.294032 0.696008
+vt 0.254720 0.694573
+vt 0.252823 0.698472
+vt 0.262861 0.632343
+vt 0.264590 0.628374
+vt 0.285450 0.634716
+vt 0.284232 0.645678
+vt 0.198881 0.608921
+vt 0.194695 0.604168
+vt 0.197313 0.596447
+vt 0.201800 0.602992
+vt 0.196158 0.615970
+vt 0.193274 0.615697
+vt 0.344362 0.590553
+vt 0.340687 0.603237
+vt 0.353427 0.603846
+vt 0.351397 0.613422
+vt 0.345041 0.608592
+vt 0.348569 0.596510
+vt 0.269826 0.661645
+vt 0.273746 0.658698
+vt 0.274047 0.664536
+vt 0.271478 0.666300
+vt 0.276504 0.665649
+vt 0.270596 0.671522
+vt 0.266907 0.668043
+vt 0.282881 0.662765
+vt 0.277855 0.659265
+vt 0.278100 0.652370
+vt 0.283329 0.656969
+vt 0.264611 0.660777
+vt 0.268769 0.655982
+vt 0.281999 0.668995
+vt 0.257464 0.693901
+vt 0.259690 0.697737
+vt 0.233832 0.701776
+vt 0.232110 0.705381
+vt 0.229464 0.697695
+vt 0.233902 0.694769
+vt 0.228764 0.689029
+vt 0.234105 0.687265
+vt 0.238732 0.706935
+vt 0.237031 0.701958
+vt 0.320506 0.700852
+vt 0.314619 0.701293
+vt 0.313513 0.694069
+vt 0.319806 0.693642
+vt 0.238452 0.695938
+vt 0.242064 0.701209
+vt 0.239285 0.688602
+vt 0.244150 0.693250
+vt 0.217753 0.696547
+vt 0.216675 0.691080
+vt 0.339175 0.687447
+vt 0.334254 0.688861
+vt 0.211600 0.693257
+vt 0.213917 0.690240
+vt 0.214050 0.683527
+vt 0.268685 0.553677
+vt 0.276616 0.551990
+vt 0.276637 0.563519
+vt 0.268573 0.565171
+vt 0.297147 0.562595
+vt 0.286458 0.562609
+vt 0.286787 0.548805
+vt 0.296328 0.545564
+vt 0.297294 0.585912
+vt 0.287158 0.583224
+vt 0.247853 0.611665
+vt 0.249540 0.551605
+vt 0.260950 0.553894
+vt 0.259830 0.566830
+vt 0.248784 0.566676
+vt 0.248056 0.590889
+vt 0.276819 0.581922
+vt 0.286276 0.629452
+vt 0.273347 0.652531
+vt 0.318924 0.686348
+vt 0.312393 0.686894
+vt 0.220364 0.645587
+vt 0.298848 0.641961
+vt 0.291967 0.639014
+vt 0.217382 0.623131
+vt 0.215765 0.633050
+vt 0.214253 0.642234
+vt 0.218243 0.543016
+vt 0.211509 0.659720
+vt 0.209605 0.676317
+vt 0.261699 0.692361
+vt 0.209689 0.684745
+vt 0.195600 0.890617
+vt 0.192100 0.890778
+vt 0.193563 0.885521
+vt 0.196517 0.887992
+vt 0.198547 0.897778
+vt 0.196720 0.903329
+vt 0.192289 0.899066
+vt 0.195943 0.894593
+vt 0.203405 0.900592
+vt 0.202915 0.905597
+vt 0.209404 0.899759
+vt 0.210279 0.903959
+vt 0.214199 0.895839
+vt 0.217510 0.897960
+vt 0.214997 0.891709
+vt 0.218896 0.892017
+vt 0.210440 0.883442
+vt 0.212687 0.878878
+vt 0.216950 0.883526
+vt 0.213758 0.887138
+vt 0.204196 0.881804
+vt 0.204007 0.876106
+vt 0.198883 0.884933
+vt 0.197224 0.880824
+vt 0.189545 0.890813
+vt 0.189622 0.885451
+vt 0.187879 0.891261
+vt 0.187879 0.886228
+vt 0.189573 0.877310
+vt 0.192205 0.876309
+vt 0.187879 0.878157
+vt 0.189447 0.870485
+vt 0.191456 0.870709
+vt 0.187879 0.870926
+vt 0.201550 0.851074
+vt 0.203335 0.844508
+vt 0.208480 0.847497
+vt 0.206219 0.853811
+vt 0.195152 0.873740
+vt 0.199338 0.867804
+vt 0.194053 0.869407
+vt 0.196818 0.863513
+vt 0.199555 0.856919
+vt 0.203580 0.859747
+vt 0.196860 0.913262
+vt 0.192100 0.911414
+vt 0.204357 0.913360
+vt 0.213576 0.909874
+vt 0.224034 0.901404
+vt 0.189622 0.910119
+vt 0.189671 0.900179
+vt 0.187879 0.909132
+vt 0.187879 0.899920
+vt 0.202222 0.825860
+vt 0.198666 0.824257
+vt 0.197210 0.818545
+vt 0.203909 0.821534
+vt 0.193654 0.826651
+vt 0.187879 0.827281
+vt 0.187879 0.824761
+vt 0.192863 0.823284
+vt 0.205757 0.833259
+vt 0.204847 0.829927
+vt 0.208368 0.827687
+vt 0.210146 0.833007
+vt 0.210286 0.839349
+vt 0.205694 0.837354
+vt 0.191561 0.819308
+vt 0.192555 0.814975
+vt 0.192758 0.811363
+vt 0.197126 0.813820
+vt 0.204959 0.818027
+vt 0.198463 0.799582
+vt 0.206464 0.801899
+vt 0.206422 0.805840
+vt 0.198498 0.802074
+vt 0.193367 0.800191
+vt 0.192933 0.798259
+vt 0.218455 0.887460
+vt 0.214563 0.889357
+vt 0.191764 0.894047
+vt 0.195481 0.892346
+vt 0.189531 0.894677
+vt 0.187879 0.894558
+vt 0.187879 0.833924
+vt 0.192800 0.833392
+vt 0.192674 0.836409
+vt 0.187879 0.836626
+vt 0.201592 0.834393
+vt 0.201347 0.834127
+vt 0.202040 0.833238
+vt 0.202348 0.833987
+vt 0.197910 0.829843
+vt 0.201039 0.830452
+vt 0.193584 0.829738
+vt 0.187879 0.829220
+vt 0.197266 0.832580
+vt 0.197084 0.834862
+vt 0.201403 0.834785
+vt 0.202117 0.835002
+vt 0.200885 0.836871
+vt 0.200528 0.835618
+vt 0.192821 0.841414
+vt 0.192772 0.843612
+vt 0.187879 0.842800
+vt 0.187879 0.840847
+vt 0.197574 0.837984
+vt 0.197707 0.839776
+vt 0.203398 0.833525
+vt 0.202957 0.831978
+vt 0.201284 0.838761
+vt 0.203055 0.835597
+vt 0.200612 0.832461
+vt 0.200269 0.833903
+vt 0.197007 0.851207
+vt 0.192128 0.851704
+vt 0.192555 0.849240
+vt 0.198057 0.846797
+vt 0.187879 0.845138
+vt 0.192814 0.846076
+vt 0.187879 0.848190
+vt 0.189440 0.865403
+vt 0.187879 0.865263
+vt 0.192961 0.865697
+vt 0.194319 0.862365
+vt 0.191064 0.866019
+vt 0.192982 0.858704
+vt 0.194074 0.857528
+vt 0.191351 0.857633
+vt 0.191015 0.856100
+vt 0.189825 0.857290
+vt 0.187879 0.855085
+vt 0.187879 0.850605
+vt 0.197994 0.841771
+vt 0.195558 0.855015
+vt 0.191449 0.854441
+vt 0.187879 0.853853
+vt 0.187879 0.819175
+vt 0.187879 0.813113
+vt 0.187879 0.809732
+vt 0.187879 0.798966
+vt 0.187879 0.797405
+vt 0.250809 0.840952
+vt 0.259678 0.854406
+vt 0.256857 0.857745
+vt 0.247309 0.846769
+vt 0.216642 0.805203
+vt 0.216460 0.811062
+vt 0.233078 0.812294
+vt 0.232644 0.819805
+vt 0.255541 0.831250
+vt 0.253868 0.835779
+vt 0.214815 0.824628
+vt 0.210489 0.865872
+vt 0.217510 0.833931
+vt 0.217517 0.842842
+vt 0.215480 0.852446
+vt 0.213226 0.859299
+vt 0.227401 0.892871
+vt 0.217825 0.872137
+vt 0.226771 0.879571
+vt 0.227989 0.886557
+vt 0.221213 0.865718
+vt 0.224356 0.858648
+vt 0.231552 0.871948
+vt 0.235598 0.865109
+vt 0.228213 0.848834
+vt 0.241212 0.856457
+vt 0.187879 0.858151
+vt 0.189461 0.859593
+vt 0.189811 0.861693
+vt 0.187879 0.861350
+vt 0.190525 0.860230
+vt 0.191113 0.861798
+vt 0.192142 0.862442
+vt 0.192737 0.861056
+vt 0.192254 0.859684
+vt 0.191274 0.860314
+vt 0.191694 0.860167
+vt 0.191799 0.860923
+vt 0.191393 0.860860
+vt 0.190931 0.858844
+vt 0.190518 0.859236
+vt 0.189237 0.858116
+vt 0.191575 0.859096
+vt 0.191456 0.859740
+vt 0.191197 0.859866
+vt 0.191862 0.859985
+vt 0.191680 0.859698
+vt 0.192002 0.860412
+vt 0.187879 0.857178
+vt 0.198687 0.889742
+vt 0.198036 0.890897
+vt 0.198358 0.892444
+vt 0.200269 0.894901
+vt 0.203951 0.896966
+vt 0.208494 0.896399
+vt 0.211000 0.894229
+vt 0.211791 0.892234
+vt 0.211336 0.890162
+vt 0.208907 0.887117
+vt 0.204532 0.885962
+vt 0.200591 0.888090
+vt 0.211707 0.891261
+vt 0.198022 0.891548
+vt 0.204763 0.888944
+vt 0.201088 0.889777
+vt 0.199198 0.890617
+vt 0.198771 0.891107
+vt 0.198750 0.891506
+vt 0.199072 0.892052
+vt 0.200864 0.893900
+vt 0.204049 0.895433
+vt 0.207766 0.894691
+vt 0.209656 0.893340
+vt 0.210181 0.892619
+vt 0.210097 0.892255
+vt 0.209796 0.891709
+vt 0.207990 0.889840
+vt 0.199562 0.891898
+vt 0.201102 0.893578
+vt 0.204147 0.894936
+vt 0.207640 0.894215
+vt 0.209264 0.893088
+vt 0.209551 0.892605
+vt 0.209229 0.891961
+vt 0.207528 0.890512
+vt 0.204672 0.889763
+vt 0.201403 0.890428
+vt 0.199744 0.891044
+vt 0.209509 0.892346
+vt 0.199982 0.891954
+vt 0.201361 0.893074
+vt 0.204154 0.893984
+vt 0.207262 0.893459
+vt 0.208557 0.892829
+vt 0.208557 0.892465
+vt 0.208396 0.891940
+vt 0.207052 0.891163
+vt 0.204777 0.890568
+vt 0.201830 0.891037
+vt 0.200472 0.891184
+vt 0.208494 0.892255
+vt 0.199926 0.891534
+vt 0.201305 0.891877
+vt 0.207150 0.891786
+vt 0.204560 0.892220
+vt 0.207304 0.892367
+vt 0.204700 0.891366
+vt 0.201508 0.891387
+vt 0.200150 0.891324
+vt 0.199758 0.924448
+vt 0.193605 0.924189
+vt 0.208844 0.922243
+vt 0.220380 0.916566
+vt 0.231755 0.905604
+vt 0.190280 0.924147
+vt 0.187879 0.923797
+vt 0.243368 0.881874
+vt 0.240470 0.888118
+vt 0.237481 0.895433
+vt 0.246623 0.877429
+vt 0.250564 0.871990
+vt 0.254995 0.865123
+vt 0.269471 0.845439
+vt 0.257851 0.825986
+vt 0.262072 0.821415
+vt 0.273293 0.842597
+vt 0.233575 0.798483
+vt 0.256248 0.788781
+vt 0.243914 0.794892
+vt 0.236522 0.784063
+vt 0.248289 0.777539
+vt 0.199758 0.712404
+vt 0.204882 0.712404
+vt 0.209698 0.721952
+vt 0.203846 0.722239
+vt 0.215683 0.732816
+vt 0.209271 0.734202
+vt 0.226498 0.787696
+vt 0.200941 0.767473
+vt 0.206688 0.766598
+vt 0.211665 0.779940
+vt 0.204231 0.780696
+vt 0.216131 0.795984
+vt 0.214108 0.788123
+vt 0.206303 0.795011
+vt 0.205428 0.788144
+vt 0.192534 0.793835
+vt 0.187879 0.793891
+vt 0.192548 0.787878
+vt 0.187879 0.787962
+vt 0.198666 0.794157
+vt 0.198463 0.787794
+vt 0.220709 0.778680
+vt 0.214101 0.765030
+vt 0.222039 0.761642
+vt 0.230145 0.774578
+vt 0.203524 0.735070
+vt 0.199107 0.722498
+vt 0.196167 0.712411
+vt 0.196027 0.768012
+vt 0.198036 0.780752
+vt 0.215011 0.712390
+vt 0.218203 0.721686
+vt 0.222165 0.730723
+vt 0.273391 0.782376
+vt 0.260042 0.770357
+vt 0.282554 0.810957
+vt 0.270647 0.815521
+vt 0.280902 0.838929
+vt 0.291472 0.835912
+vt 0.191743 0.768600
+vt 0.192513 0.781172
+vt 0.187879 0.782026
+vt 0.187879 0.769132
+vt 0.240890 0.767718
+vt 0.231881 0.755811
+vt 0.238132 0.749560
+vt 0.248037 0.760011
+vt 0.191456 0.743680
+vt 0.187879 0.740054
+vt 0.187879 0.735623
+vt 0.193325 0.736358
+vt 0.198113 0.735819
+vt 0.202418 0.752276
+vt 0.198155 0.753102
+vt 0.208725 0.750771
+vt 0.215774 0.747810
+vt 0.223642 0.743659
+vt 0.229382 0.739459
+vt 0.252951 0.884443
+vt 0.250088 0.891002
+vt 0.246392 0.898597
+vt 0.240078 0.909083
+vt 0.259965 0.875567
+vt 0.259776 0.869211
+vt 0.262681 0.871178
+vt 0.263584 0.877268
+vt 0.255968 0.880607
+vt 0.229095 0.922523
+vt 0.192121 0.945273
+vt 0.187879 0.948787
+vt 0.216502 0.932008
+vt 0.205855 0.937937
+vt 0.197574 0.942067
+vt 0.248394 0.911631
+vt 0.238069 0.926485
+vt 0.225882 0.937958
+vt 0.214087 0.946855
+vt 0.203685 0.953659
+vt 0.195432 0.959168
+vt 0.187879 0.964404
+vt 0.260630 0.898947
+vt 0.261645 0.897764
+vt 0.266153 0.900564
+vt 0.265572 0.901642
+vt 0.260189 0.881944
+vt 0.265467 0.878199
+vt 0.262079 0.882735
+vt 0.257690 0.885395
+vt 0.259804 0.885983
+vt 0.259216 0.892864
+vt 0.256654 0.893585
+vt 0.271725 0.900774
+vt 0.271515 0.901810
+vt 0.255170 0.913073
+vt 0.258684 0.903938
+vt 0.264417 0.905751
+vt 0.262093 0.913997
+vt 0.246035 0.928662
+vt 0.255317 0.930055
+vt 0.235227 0.941661
+vt 0.247043 0.944251
+vt 0.223817 0.952441
+vt 0.237726 0.956627
+vt 0.212764 0.961051
+vt 0.227898 0.967386
+vt 0.203055 0.968086
+vt 0.218483 0.977102
+vt 0.193724 0.973504
+vt 0.209047 0.986671
+vt 0.253119 0.901523
+vt 0.255639 0.861000
+vt 0.244635 0.851375
+vt 0.230439 0.841162
+vt 0.231342 0.834309
+vt 0.232063 0.826791
+vt 0.215746 0.817642
+vt 0.205456 0.811811
+vt 0.197364 0.807870
+vt 0.192835 0.805476
+vt 0.187879 0.804307
+vt 0.266727 0.849408
+vt 0.263850 0.851907
+vt 0.227716 0.721672
+vt 0.226701 0.712390
+vt 0.241037 0.712383
+vt 0.239840 0.722960
+vt 0.228213 0.728343
+vt 0.236074 0.732620
+vt 0.251089 0.724955
+vt 0.255674 0.712383
+vt 0.267658 0.712362
+vt 0.262030 0.726418
+vt 0.245804 0.738402
+vt 0.256395 0.743904
+vt 0.278270 0.860552
+vt 0.275505 0.856716
+vt 0.279180 0.855925
+vt 0.281336 0.860349
+vt 0.281497 0.893067
+vt 0.284038 0.885878
+vt 0.284983 0.886270
+vt 0.281966 0.893970
+vt 0.280839 0.864997
+vt 0.283240 0.865158
+vt 0.284423 0.878752
+vt 0.283114 0.870947
+vt 0.284801 0.871150
+vt 0.285683 0.879137
+vt 0.276947 0.898387
+vt 0.276800 0.899549
+vt 0.272761 0.852264
+vt 0.276821 0.850619
+vt 0.270871 0.905821
+vt 0.269667 0.914011
+vt 0.266181 0.930216
+vt 0.261624 0.944951
+vt 0.256591 0.958167
+vt 0.251047 0.970011
+vt 0.245097 0.980952
+vt 0.238251 0.990689
+vt 0.352071 0.852467
+vt 0.359512 0.855491
+vt 0.359512 0.870135
+vt 0.351553 0.868490
+vt 0.347059 0.925799
+vt 0.359512 0.929593
+vt 0.355494 0.950166
+vt 0.342103 0.942970
+vt 0.305486 0.895384
+vt 0.315496 0.905401
+vt 0.310533 0.917462
+vt 0.301706 0.905821
+vt 0.287265 0.923097
+vt 0.291899 0.938217
+vt 0.276065 0.943327
+vt 0.276541 0.928151
+vt 0.276583 0.903770
+vt 0.282575 0.898821
+vt 0.284108 0.908467
+vt 0.276807 0.912387
+vt 0.288847 0.884135
+vt 0.289169 0.875644
+vt 0.296001 0.884457
+vt 0.294188 0.893578
+vt 0.286880 0.891611
+vt 0.290303 0.901887
+vt 0.302959 0.928837
+vt 0.295595 0.915236
+vt 0.325205 0.984802
+vt 0.283954 0.990528
+vt 0.280762 0.980028
+vt 0.313403 0.972958
+vt 0.276681 0.956382
+vt 0.297170 0.950656
+vt 0.304219 0.961702
+vt 0.278270 0.968205
+vt 0.325282 0.913437
+vt 0.335768 0.920304
+vt 0.330056 0.935340
+vt 0.319724 0.926989
+vt 0.320312 0.950019
+vt 0.310820 0.939911
+vt 0.346373 0.970900
+vt 0.332114 0.960113
+vt 0.306137 0.835485
+vt 0.321369 0.837823
+vt 0.321614 0.853951
+vt 0.307817 0.849478
+vt 0.308426 0.873327
+vt 0.320151 0.880502
+vt 0.318625 0.892997
+vt 0.307488 0.884380
+vt 0.288700 0.868497
+vt 0.287643 0.862134
+vt 0.296484 0.866243
+vt 0.296701 0.875315
+vt 0.284311 0.848778
+vt 0.294209 0.847497
+vt 0.286264 0.855862
+vt 0.295707 0.857178
+vt 0.321005 0.867748
+vt 0.308524 0.861917
+vt 0.359512 0.897932
+vt 0.359512 0.913703
+vt 0.349152 0.910553
+vt 0.350384 0.896266
+vt 0.328775 0.899997
+vt 0.330770 0.886795
+vt 0.340759 0.892234
+vt 0.338911 0.905926
+vt 0.333528 0.841911
+vt 0.343769 0.847742
+vt 0.342957 0.864192
+vt 0.332821 0.858690
+vt 0.341998 0.878689
+vt 0.331869 0.873250
+vt 0.359512 0.885024
+vt 0.350839 0.883043
+vt 0.195187 0.722603
+vt 0.193122 0.712411
+vt 0.191169 0.722477
+vt 0.190077 0.712411
+vt 0.187879 0.721728
+vt 0.187879 0.712411
+vt 0.270178 0.752094
+vt 0.281189 0.756238
+vt 0.322174 0.726446
+vt 0.308972 0.729911
+vt 0.307103 0.712341
+vt 0.319577 0.712348
+vt 0.278816 0.712348
+vt 0.275078 0.729183
+vt 0.292669 0.712341
+vt 0.292886 0.731458
+vt 0.283835 0.730520
+vt 0.285739 0.712348
+vt 0.325422 0.748846
+vt 0.311856 0.757169
+vt 0.293376 0.759269
+vt 0.317855 0.789894
+vt 0.330420 0.766906
+vt 0.296155 0.788809
+vt 0.301153 0.811685
+vt 0.319479 0.815381
+vt 0.353219 0.829759
+vt 0.359512 0.832223
+vt 0.334039 0.820603
+vt 0.344399 0.825475
+vt 0.353716 0.806386
+vt 0.359512 0.809487
+vt 0.334928 0.797265
+vt 0.345330 0.802214
+vt 0.354437 0.785470
+vt 0.359512 0.788795
+vt 0.338687 0.776034
+vt 0.346835 0.781305
+vt 0.355564 0.723436
+vt 0.355445 0.712390
+vt 0.359512 0.712390
+vt 0.359512 0.722169
+vt 0.348781 0.723254
+vt 0.348151 0.712383
+vt 0.341151 0.724353
+vt 0.340724 0.712362
+vt 0.354878 0.766906
+vt 0.359512 0.771351
+vt 0.348242 0.762895
+vt 0.355543 0.746431
+vt 0.348893 0.743848
+vt 0.359512 0.748097
+vt 0.341228 0.759325
+vt 0.341599 0.742525
+vt 0.335628 0.756238
+vt 0.333892 0.742875
+vt 0.332331 0.724269
+vt 0.331505 0.712348
+vt 0.187879 0.839776
+vt 0.192891 0.839923
+vt 0.197490 0.837193
+vt 0.200395 0.835303
+vt 0.192779 0.837354
+vt 0.187879 0.837445
+vt 0.197161 0.835611
+vt 0.200815 0.834358
+vt 0.201004 0.834561
+vt 0.187879 0.755790
+vt 0.190826 0.755482
+vt 0.194375 0.754516
+vt 0.190154 0.748377
+vt 0.187879 0.745871
+vt 0.264186 0.883603
+vt 0.267413 0.879711
+vt 0.269618 0.882077
+vt 0.267056 0.884786
+vt 0.264123 0.898072
+vt 0.267189 0.895251
+vt 0.271641 0.897302
+vt 0.270871 0.900928
+vt 0.261799 0.892325
+vt 0.264662 0.891044
+vt 0.262156 0.886389
+vt 0.265369 0.886893
+vt 0.275624 0.896217
+vt 0.276443 0.898681
+vt 0.278046 0.892465
+vt 0.280006 0.894047
+vt 0.279726 0.887642
+vt 0.281672 0.888825
+vt 0.267525 0.900207
+vt 0.282260 0.888111
+vt 0.280314 0.893837
+vt 0.276583 0.898478
+vt 0.271641 0.900795
+vt 0.279607 0.881692
+vt 0.281777 0.881622
+vt 0.278221 0.875749
+vt 0.280440 0.875294
+vt 0.275785 0.870527
+vt 0.278347 0.869512
+vt 0.273349 0.866684
+vt 0.275806 0.864885
+vt 0.277206 0.864045
+vt 0.279544 0.868532
+vt 0.281455 0.874223
+vt 0.282631 0.880782
+vt 0.270325 0.863191
+vt 0.273265 0.861098
+vt 0.269387 0.857486
+vt 0.265425 0.859656
+vt 0.274217 0.859663
+vt 0.270745 0.855596
+vt 0.260413 0.865242
+vt 0.263157 0.867839
+vt 0.262219 0.862449
+vt 0.266545 0.866754
+vt 0.199464 0.891485
+vt 0.199534 0.891268
+vt 0.266104 0.871948
+vt 0.268988 0.874664
+vt 0.270045 0.869344
+vt 0.272719 0.872886
+vt 0.275932 0.877289
+vt 0.276758 0.882959
+vt 0.271459 0.878164
+vt 0.273762 0.880278
+vt 0.273188 0.884254
+vt 0.269758 0.891751
+vt 0.271760 0.887817
+vt 0.274063 0.892542
+vt 0.275750 0.887915
+vt 0.200213 0.834351
+vt 0.200906 0.834876
+vt 0.201025 0.834652
+vt 0.180158 0.890617
+vt 0.179248 0.887992
+vt 0.182209 0.885521
+vt 0.183672 0.890778
+vt 0.177218 0.897778
+vt 0.179822 0.894593
+vt 0.183476 0.899066
+vt 0.179031 0.903329
+vt 0.172346 0.900592
+vt 0.172836 0.905597
+vt 0.166354 0.899759
+vt 0.165493 0.903959
+vt 0.161573 0.895839
+vt 0.158262 0.897960
+vt 0.160768 0.891709
+vt 0.156869 0.892017
+vt 0.165332 0.883442
+vt 0.162007 0.887138
+vt 0.158815 0.883526
+vt 0.163064 0.878878
+vt 0.171569 0.881804
+vt 0.171758 0.876106
+vt 0.176875 0.884933
+vt 0.178541 0.880824
+vt 0.186150 0.885451
+vt 0.186213 0.890813
+vt 0.183560 0.876309
+vt 0.186192 0.877310
+vt 0.184302 0.870709
+vt 0.186318 0.870485
+vt 0.174215 0.851074
+vt 0.169539 0.853811
+vt 0.167285 0.847497
+vt 0.172430 0.844508
+vt 0.180606 0.873740
+vt 0.176427 0.867804
+vt 0.181712 0.869407
+vt 0.178947 0.863513
+vt 0.172178 0.859747
+vt 0.176217 0.856919
+vt 0.183672 0.911414
+vt 0.178898 0.913262
+vt 0.171408 0.913360
+vt 0.162189 0.909874
+vt 0.151731 0.901404
+vt 0.186087 0.900179
+vt 0.186150 0.910119
+vt 0.173536 0.825860
+vt 0.171856 0.821534
+vt 0.178541 0.818545
+vt 0.177099 0.824257
+vt 0.182097 0.826651
+vt 0.182902 0.823284
+vt 0.170008 0.833259
+vt 0.165605 0.833007
+vt 0.167390 0.827687
+vt 0.170918 0.829927
+vt 0.165479 0.839349
+vt 0.170071 0.837354
+vt 0.183203 0.814975
+vt 0.184204 0.819308
+vt 0.178639 0.813820
+vt 0.183000 0.811363
+vt 0.170813 0.818027
+vt 0.177302 0.799582
+vt 0.177274 0.802074
+vt 0.169343 0.805840
+vt 0.169301 0.801899
+vt 0.182398 0.800191
+vt 0.182839 0.798259
+vt 0.161209 0.889357
+vt 0.157310 0.887460
+vt 0.180270 0.892346
+vt 0.183987 0.894047
+vt 0.186234 0.894677
+vt 0.183091 0.836409
+vt 0.182965 0.833392
+vt 0.174173 0.834393
+vt 0.173417 0.833987
+vt 0.173718 0.833238
+vt 0.174418 0.834127
+vt 0.177862 0.829843
+vt 0.174733 0.830452
+vt 0.182174 0.829738
+vt 0.178681 0.834862
+vt 0.178478 0.832580
+vt 0.174369 0.834785
+vt 0.175244 0.835618
+vt 0.174866 0.836871
+vt 0.173641 0.835002
+vt 0.182930 0.841414
+vt 0.183000 0.843612
+vt 0.178177 0.837984
+vt 0.178051 0.839776
+vt 0.172367 0.833525
+vt 0.172794 0.831978
+vt 0.172703 0.835597
+vt 0.174474 0.838761
+vt 0.175496 0.833903
+vt 0.175160 0.832461
+vt 0.178744 0.851207
+vt 0.177708 0.846797
+vt 0.183224 0.849240
+vt 0.183637 0.851704
+vt 0.182951 0.846076
+vt 0.186332 0.865403
+vt 0.181446 0.862365
+vt 0.182797 0.865697
+vt 0.184708 0.866019
+vt 0.181691 0.857528
+vt 0.182769 0.858704
+vt 0.184750 0.856100
+vt 0.184407 0.857633
+vt 0.185947 0.857290
+vt 0.177764 0.841771
+vt 0.180207 0.855015
+vt 0.184309 0.854441
+vt 0.124956 0.840952
+vt 0.128456 0.846769
+vt 0.118908 0.857745
+vt 0.116080 0.854406
+vt 0.159298 0.811062
+vt 0.159116 0.805203
+vt 0.143121 0.819805
+vt 0.142673 0.812294
+vt 0.121890 0.835779
+vt 0.120210 0.831250
+vt 0.160943 0.824628
+vt 0.165276 0.865872
+vt 0.158262 0.833931
+vt 0.160292 0.852446
+vt 0.158248 0.842842
+vt 0.162532 0.859299
+vt 0.148371 0.892871
+vt 0.157940 0.872137
+vt 0.149001 0.879571
+vt 0.147783 0.886557
+vt 0.154552 0.865718
+vt 0.151416 0.858648
+vt 0.144206 0.871948
+vt 0.140167 0.865109
+vt 0.147559 0.848834
+vt 0.134546 0.856457
+vt 0.185954 0.861693
+vt 0.186311 0.859593
+vt 0.184652 0.861798
+vt 0.185240 0.860230
+vt 0.183616 0.862442
+vt 0.183021 0.861056
+vt 0.183511 0.859684
+vt 0.184484 0.860314
+vt 0.184365 0.860860
+vt 0.183959 0.860923
+vt 0.184078 0.860167
+vt 0.186535 0.858116
+vt 0.185254 0.859236
+vt 0.184820 0.858844
+vt 0.184190 0.859096
+vt 0.184554 0.859866
+vt 0.184302 0.859740
+vt 0.184085 0.859698
+vt 0.183903 0.859985
+vt 0.183756 0.860412
+vt 0.177722 0.890897
+vt 0.177071 0.889742
+vt 0.175510 0.894901
+vt 0.177400 0.892444
+vt 0.171814 0.896966
+vt 0.167271 0.896399
+vt 0.164751 0.894229
+vt 0.163953 0.892234
+vt 0.166858 0.887117
+vt 0.164436 0.890162
+vt 0.171240 0.885962
+vt 0.175181 0.888090
+vt 0.164058 0.891261
+vt 0.177729 0.891548
+vt 0.174677 0.889777
+vt 0.171002 0.888944
+vt 0.176567 0.890617
+vt 0.176994 0.891107
+vt 0.176693 0.892052
+vt 0.177008 0.891506
+vt 0.174901 0.893900
+vt 0.171709 0.895433
+vt 0.167999 0.894691
+vt 0.166102 0.893340
+vt 0.165584 0.892619
+vt 0.165969 0.891709
+vt 0.165675 0.892255
+vt 0.167775 0.889840
+vt 0.174656 0.893578
+vt 0.176196 0.891898
+vt 0.171618 0.894936
+vt 0.168132 0.894215
+vt 0.166508 0.893088
+vt 0.166228 0.892605
+vt 0.168237 0.890512
+vt 0.166536 0.891961
+vt 0.171086 0.889763
+vt 0.174355 0.890428
+vt 0.176021 0.891044
+vt 0.166256 0.892346
+vt 0.174411 0.893074
+vt 0.175790 0.891954
+vt 0.171611 0.893984
+vt 0.168503 0.893459
+vt 0.167208 0.892829
+vt 0.167208 0.892465
+vt 0.168706 0.891163
+vt 0.167369 0.891940
+vt 0.170988 0.890568
+vt 0.173942 0.891037
+vt 0.175293 0.891184
+vt 0.167271 0.892255
+vt 0.174453 0.891877
+vt 0.175839 0.891534
+vt 0.168622 0.891786
+vt 0.168461 0.892367
+vt 0.171205 0.892220
+vt 0.174257 0.891387
+vt 0.171065 0.891366
+vt 0.175615 0.891324
+vt 0.182153 0.924189
+vt 0.176014 0.924448
+vt 0.166921 0.922243
+vt 0.155378 0.916566
+vt 0.144010 0.905604
+vt 0.185485 0.924147
+vt 0.135295 0.888118
+vt 0.132397 0.881874
+vt 0.138284 0.895433
+vt 0.129142 0.877429
+vt 0.125201 0.871990
+vt 0.120770 0.865123
+vt 0.106294 0.845439
+vt 0.102458 0.842597
+vt 0.113700 0.821415
+vt 0.117914 0.825986
+vt 0.142183 0.798483
+vt 0.119517 0.788781
+vt 0.127476 0.777539
+vt 0.139250 0.784063
+vt 0.131858 0.794892
+vt 0.166053 0.721952
+vt 0.170883 0.712404
+vt 0.176014 0.712404
+vt 0.171912 0.722239
+vt 0.160075 0.732816
+vt 0.166494 0.734202
+vt 0.149267 0.787696
+vt 0.174824 0.767473
+vt 0.171527 0.780696
+vt 0.164093 0.779940
+vt 0.169077 0.766598
+vt 0.159627 0.795984
+vt 0.161657 0.788123
+vt 0.169455 0.795011
+vt 0.170337 0.788144
+vt 0.183224 0.793835
+vt 0.183224 0.787878
+vt 0.177092 0.794157
+vt 0.177295 0.787794
+vt 0.155056 0.778680
+vt 0.145620 0.774578
+vt 0.153733 0.761642
+vt 0.161657 0.765030
+vt 0.176665 0.722498
+vt 0.172241 0.735070
+vt 0.179598 0.712411
+vt 0.179738 0.768012
+vt 0.177722 0.780752
+vt 0.157555 0.721686
+vt 0.160747 0.712390
+vt 0.153593 0.730723
+vt 0.102374 0.782376
+vt 0.115716 0.770357
+vt 0.105118 0.815521
+vt 0.093211 0.810957
+vt 0.094870 0.838929
+vt 0.084279 0.835912
+vt 0.184022 0.768600
+vt 0.183252 0.781172
+vt 0.134875 0.767718
+vt 0.143884 0.755811
+vt 0.137633 0.749560
+vt 0.127714 0.760011
+vt 0.184302 0.743680
+vt 0.182440 0.736358
+vt 0.177610 0.753102
+vt 0.173354 0.752276
+vt 0.177645 0.735819
+vt 0.167040 0.750771
+vt 0.159991 0.747810
+vt 0.152130 0.743659
+vt 0.146383 0.739459
+vt 0.125684 0.891002
+vt 0.122807 0.884443
+vt 0.135680 0.909083
+vt 0.129380 0.898597
+vt 0.115800 0.875567
+vt 0.112160 0.877268
+vt 0.113091 0.871178
+vt 0.115996 0.869211
+vt 0.119797 0.880607
+vt 0.146663 0.922523
+vt 0.183651 0.945273
+vt 0.159256 0.932008
+vt 0.169903 0.937937
+vt 0.178177 0.942067
+vt 0.137696 0.926485
+vt 0.127357 0.911631
+vt 0.149883 0.937958
+vt 0.161664 0.946855
+vt 0.172073 0.953659
+vt 0.180340 0.959168
+vt 0.115142 0.898947
+vt 0.110193 0.901642
+vt 0.109619 0.900564
+vt 0.114127 0.897764
+vt 0.115569 0.881944
+vt 0.113679 0.882735
+vt 0.110291 0.878199
+vt 0.118075 0.885395
+vt 0.119111 0.893585
+vt 0.116549 0.892864
+vt 0.115961 0.885983
+vt 0.104257 0.901810
+vt 0.104033 0.900774
+vt 0.120595 0.913073
+vt 0.113679 0.913997
+vt 0.111334 0.905751
+vt 0.117074 0.903938
+vt 0.129716 0.928662
+vt 0.120448 0.930055
+vt 0.140538 0.941661
+vt 0.128729 0.944251
+vt 0.151948 0.952441
+vt 0.138039 0.956627
+vt 0.162994 0.961051
+vt 0.147867 0.967386
+vt 0.172710 0.968086
+vt 0.157289 0.977102
+vt 0.182048 0.973504
+vt 0.166711 0.986671
+vt 0.122646 0.901523
+vt 0.120119 0.861000
+vt 0.131116 0.851375
+vt 0.144430 0.834309
+vt 0.145312 0.841162
+vt 0.143702 0.826791
+vt 0.160019 0.817642
+vt 0.170309 0.811811
+vt 0.178394 0.807870
+vt 0.182930 0.805476
+vt 0.111915 0.851907
+vt 0.109038 0.849408
+vt 0.148035 0.721672
+vt 0.135925 0.722960
+vt 0.134728 0.712383
+vt 0.149050 0.712390
+vt 0.139684 0.732620
+vt 0.147559 0.728343
+vt 0.124676 0.724955
+vt 0.113742 0.726418
+vt 0.108114 0.712362
+vt 0.120098 0.712383
+vt 0.119370 0.743904
+vt 0.129968 0.738402
+vt 0.097495 0.860552
+vt 0.094429 0.860349
+vt 0.096578 0.855925
+vt 0.100253 0.856716
+vt 0.094268 0.893067
+vt 0.093785 0.893970
+vt 0.090789 0.886270
+vt 0.091727 0.885878
+vt 0.094933 0.864997
+vt 0.092525 0.865158
+vt 0.091342 0.878752
+vt 0.090082 0.879137
+vt 0.090978 0.871150
+vt 0.092658 0.870947
+vt 0.098818 0.898387
+vt 0.098965 0.899549
+vt 0.098944 0.850619
+vt 0.102997 0.852264
+vt 0.106105 0.914011
+vt 0.104894 0.905821
+vt 0.109584 0.930216
+vt 0.114148 0.944951
+vt 0.119167 0.958167
+vt 0.124718 0.970011
+vt 0.130668 0.980952
+vt 0.137507 0.990689
+vt 0.023687 0.852467
+vt 0.024198 0.868490
+vt 0.016253 0.870135
+vt 0.016253 0.855491
+vt 0.028706 0.925799
+vt 0.033655 0.942970
+vt 0.020271 0.950166
+vt 0.016253 0.929593
+vt 0.070265 0.895384
+vt 0.074059 0.905821
+vt 0.065225 0.917462
+vt 0.060269 0.905401
+vt 0.088500 0.923097
+vt 0.099224 0.928151
+vt 0.099693 0.943327
+vt 0.083852 0.938217
+vt 0.099168 0.903770
+vt 0.098944 0.912387
+vt 0.091650 0.908467
+vt 0.093176 0.898821
+vt 0.086911 0.884135
+vt 0.081577 0.893578
+vt 0.079764 0.884457
+vt 0.086596 0.875644
+vt 0.085455 0.901887
+vt 0.088871 0.891611
+vt 0.072813 0.928837
+vt 0.080156 0.915236
+vt 0.050560 0.984802
+vt 0.062362 0.972958
+vt 0.094996 0.980028
+vt 0.091811 0.990528
+vt 0.099084 0.956382
+vt 0.097481 0.968205
+vt 0.071553 0.961702
+vt 0.078602 0.950656
+vt 0.050483 0.913437
+vt 0.056041 0.926989
+vt 0.045709 0.935340
+vt 0.039997 0.920304
+vt 0.055453 0.950019
+vt 0.064952 0.939911
+vt 0.029392 0.970900
+vt 0.043637 0.960113
+vt 0.069628 0.835485
+vt 0.067948 0.849478
+vt 0.054151 0.853951
+vt 0.054396 0.837823
+vt 0.067339 0.873327
+vt 0.068284 0.884380
+vt 0.057140 0.892997
+vt 0.055614 0.880502
+vt 0.087058 0.868497
+vt 0.079057 0.875315
+vt 0.079274 0.866243
+vt 0.088129 0.862134
+vt 0.091461 0.848778
+vt 0.081549 0.847497
+vt 0.080051 0.857178
+vt 0.089508 0.855862
+vt 0.054760 0.867748
+vt 0.067248 0.861917
+vt 0.016253 0.897932
+vt 0.025388 0.896266
+vt 0.026613 0.910553
+vt 0.016253 0.913703
+vt 0.046997 0.899997
+vt 0.036854 0.905926
+vt 0.035006 0.892234
+vt 0.044988 0.886795
+vt 0.042244 0.841911
+vt 0.042944 0.858690
+vt 0.032808 0.864192
+vt 0.031996 0.847742
+vt 0.033767 0.878689
+vt 0.043896 0.873250
+vt 0.016253 0.885024
+vt 0.024919 0.883043
+vt 0.182636 0.712411
+vt 0.180571 0.722603
+vt 0.184596 0.722477
+vt 0.185681 0.712411
+vt 0.094569 0.756238
+vt 0.105580 0.752094
+vt 0.053584 0.726446
+vt 0.056181 0.712348
+vt 0.068655 0.712341
+vt 0.066800 0.729911
+vt 0.096949 0.712348
+vt 0.100680 0.729183
+vt 0.083096 0.712341
+vt 0.090019 0.712348
+vt 0.091930 0.730520
+vt 0.082893 0.731458
+vt 0.050329 0.748846
+vt 0.063916 0.757169
+vt 0.082389 0.759269
+vt 0.057896 0.789894
+vt 0.045352 0.766906
+vt 0.079617 0.788809
+vt 0.074612 0.811685
+vt 0.056286 0.815381
+vt 0.016253 0.832223
+vt 0.022532 0.829759
+vt 0.031366 0.825475
+vt 0.041726 0.820603
+vt 0.016253 0.809487
+vt 0.022042 0.806386
+vt 0.030428 0.802214
+vt 0.040830 0.797265
+vt 0.016253 0.788795
+vt 0.021314 0.785470
+vt 0.028923 0.781305
+vt 0.037085 0.776034
+vt 0.020194 0.723436
+vt 0.016253 0.722169
+vt 0.016253 0.712390
+vt 0.020313 0.712390
+vt 0.026991 0.723254
+vt 0.027621 0.712383
+vt 0.034614 0.724353
+vt 0.035041 0.712362
+vt 0.020887 0.766906
+vt 0.016253 0.771351
+vt 0.027509 0.762895
+vt 0.026872 0.743848
+vt 0.020215 0.746431
+vt 0.016253 0.748097
+vt 0.034537 0.759325
+vt 0.034152 0.742525
+vt 0.040123 0.756238
+vt 0.043434 0.724269
+vt 0.041880 0.742875
+vt 0.044246 0.712348
+vt 0.182881 0.839923
+vt 0.178268 0.837193
+vt 0.175370 0.835303
+vt 0.182986 0.837354
+vt 0.178604 0.835611
+vt 0.174957 0.834358
+vt 0.174761 0.834561
+vt 0.184932 0.755482
+vt 0.181397 0.754516
+vt 0.185611 0.748377
+vt 0.111586 0.883603
+vt 0.108709 0.884786
+vt 0.106147 0.882077
+vt 0.108359 0.879711
+vt 0.111649 0.898072
+vt 0.104887 0.900928
+vt 0.104117 0.897302
+vt 0.108569 0.895251
+vt 0.113966 0.892325
+vt 0.111103 0.891044
+vt 0.113609 0.886389
+vt 0.110396 0.886893
+vt 0.099308 0.898681
+vt 0.100134 0.896217
+vt 0.095766 0.894047
+vt 0.097705 0.892465
+vt 0.094100 0.888825
+vt 0.096039 0.887642
+vt 0.108240 0.900207
+vt 0.095451 0.893837
+vt 0.093512 0.888111
+vt 0.099182 0.898478
+vt 0.104124 0.900795
+vt 0.093988 0.881622
+vt 0.096158 0.881692
+vt 0.095318 0.875294
+vt 0.097551 0.875749
+vt 0.097411 0.869512
+vt 0.099980 0.870527
+vt 0.099959 0.864885
+vt 0.102416 0.866684
+vt 0.096214 0.868532
+vt 0.098559 0.864045
+vt 0.094310 0.874223
+vt 0.093134 0.880782
+vt 0.102493 0.861098
+vt 0.105440 0.863191
+vt 0.106371 0.857486
+vt 0.110333 0.859656
+vt 0.101555 0.859663
+vt 0.105027 0.855596
+vt 0.115352 0.865242
+vt 0.112608 0.867839
+vt 0.109220 0.866754
+vt 0.113539 0.862449
+vt 0.176301 0.891485
+vt 0.176238 0.891268
+vt 0.106763 0.874664
+vt 0.109647 0.871948
+vt 0.105720 0.869344
+vt 0.103039 0.872886
+vt 0.099833 0.877289
+vt 0.099014 0.882959
+vt 0.104306 0.878164
+vt 0.102577 0.884254
+vt 0.102003 0.880278
+vt 0.106007 0.891751
+vt 0.104012 0.887817
+vt 0.101702 0.892542
+vt 0.100015 0.887915
+vt 0.175552 0.834351
+vt 0.174859 0.834876
+vt 0.174740 0.834652
+vt 0.544030 0.162262
+vt 0.549261 0.132031
+vt 0.569552 0.133746
+vt 0.565128 0.165297
+vt 0.590469 0.136962
+vt 0.586584 0.168012
+vt 0.611995 0.141081
+vt 0.611089 0.170459
+vt 0.632136 0.143478
+vt 0.634614 0.171874
+vt 0.650241 0.143111
+vt 0.654723 0.170813
+vt 0.667083 0.138634
+vt 0.673887 0.165795
+vt 0.683617 0.131504
+vt 0.694459 0.156871
+vt 0.520951 0.157129
+vt 0.530036 0.130503
+vt 0.554788 0.226461
+vt 0.550990 0.263839
+vt 0.511265 0.260442
+vt 0.527872 0.222247
+vt 0.581740 0.228715
+vt 0.580187 0.264878
+vt 0.610895 0.229989
+vt 0.610391 0.264821
+vt 0.639498 0.230168
+vt 0.640565 0.265681
+vt 0.665604 0.228549
+vt 0.670115 0.264962
+vt 0.691528 0.222947
+vt 0.709501 0.262002
+vt 0.718014 0.211348
+vt 0.734826 0.243567
+vt 0.485372 0.246806
+vt 0.499683 0.212835
+vt 0.553745 0.116510
+vt 0.571592 0.115986
+vt 0.557692 0.094239
+vt 0.574239 0.091166
+vt 0.589810 0.118299
+vt 0.591387 0.092237
+vt 0.611278 0.122282
+vt 0.609938 0.096224
+vt 0.631865 0.125001
+vt 0.628498 0.100191
+vt 0.648231 0.125525
+vt 0.645169 0.102324
+vt 0.663709 0.122857
+vt 0.662400 0.100846
+vt 0.680989 0.117072
+vt 0.681835 0.096041
+vt 0.534742 0.117212
+vt 0.538892 0.097462
+vt 0.572984 0.292452
+vt 0.545412 0.294571
+vt 0.608602 0.292211
+vt 0.645576 0.294116
+vt 0.676301 0.295490
+vt 0.572429 0.325163
+vt 0.543957 0.325757
+vt 0.610055 0.326859
+vt 0.649327 0.328919
+vt 0.679923 0.329711
+vt 0.579387 0.354689
+vt 0.549942 0.357964
+vt 0.614842 0.355946
+vt 0.650225 0.359149
+vt 0.679677 0.361865
+vt 0.704166 0.330605
+vt 0.701904 0.363393
+vt 0.706795 0.293105
+vt 0.515855 0.297093
+vt 0.521022 0.330080
+vt 0.528421 0.363393
+vt 0.560342 0.195144
+vt 0.536553 0.190862
+vt 0.584337 0.197363
+vt 0.610719 0.199143
+vt 0.636650 0.199747
+vt 0.659661 0.198110
+vt 0.681989 0.192639
+vt 0.705440 0.182902
+vt 0.511601 0.183989
+vt 0.909788 0.132516
+vt 0.929971 0.130807
+vt 0.935178 0.160878
+vt 0.914192 0.163899
+vt 0.888982 0.135717
+vt 0.892850 0.166601
+vt 0.867572 0.139817
+vt 0.868476 0.169038
+vt 0.847539 0.142203
+vt 0.845077 0.170447
+vt 0.829532 0.141840
+vt 0.825076 0.169393
+vt 0.812781 0.137389
+vt 0.806016 0.164404
+vt 0.796336 0.130300
+vt 0.785555 0.155530
+vt 0.949094 0.129286
+vt 0.958134 0.155769
+vt 0.924482 0.224736
+vt 0.951254 0.220543
+vt 0.967777 0.258534
+vt 0.928263 0.261916
+vt 0.897674 0.226981
+vt 0.899220 0.262952
+vt 0.868673 0.228249
+vt 0.869176 0.262896
+vt 0.840222 0.228429
+vt 0.839163 0.263753
+vt 0.814256 0.226820
+vt 0.809770 0.263038
+vt 0.788471 0.221248
+vt 0.770595 0.260093
+vt 0.762128 0.209711
+vt 0.745406 0.241756
+vt 0.979293 0.211178
+vt 0.993532 0.244968
+vt 0.925508 0.115370
+vt 0.907756 0.114851
+vt 0.905120 0.090163
+vt 0.921579 0.093217
+vt 0.889636 0.117154
+vt 0.888063 0.091231
+vt 0.868282 0.121119
+vt 0.869611 0.095200
+vt 0.847806 0.123826
+vt 0.851151 0.099149
+vt 0.831528 0.124349
+vt 0.834570 0.101274
+vt 0.816135 0.121698
+vt 0.817433 0.099807
+vt 0.798948 0.115947
+vt 0.798104 0.095031
+vt 0.944411 0.116066
+vt 0.940280 0.096421
+vt 0.933813 0.292486
+vt 0.906387 0.290379
+vt 0.870957 0.290141
+vt 0.834178 0.292036
+vt 0.803617 0.293403
+vt 0.935262 0.323507
+vt 0.906940 0.322918
+vt 0.869512 0.324606
+vt 0.830447 0.326655
+vt 0.800013 0.327442
+vt 0.929311 0.355546
+vt 0.900019 0.352289
+vt 0.864751 0.353540
+vt 0.829554 0.356726
+vt 0.800257 0.359426
+vt 0.778148 0.360946
+vt 0.775899 0.328332
+vt 0.773285 0.291031
+vt 0.963215 0.294992
+vt 0.958077 0.327807
+vt 0.950719 0.360946
+vt 0.942617 0.189325
+vt 0.918955 0.193586
+vt 0.895088 0.195796
+vt 0.868846 0.197568
+vt 0.843054 0.198171
+vt 0.820167 0.196544
+vt 0.797958 0.191103
+vt 0.774634 0.181419
+vt 0.967437 0.182487
+vt 0.887064 0.375332
+vt 0.940035 0.391815
+vt 0.917995 0.455716
+vt 0.870247 0.432190
+vt 0.836073 0.367751
+vt 0.824546 0.423475
+vt 0.788655 0.371611
+vt 0.778784 0.421763
+vt 0.955353 0.484000
+vt 0.986675 0.426237
+vt 0.732314 0.422220
+vt 0.741108 0.381004
+vt 0.900859 0.500210
+vt 0.852406 0.476768
+vt 0.811575 0.466545
+vt 0.770041 0.462344
+vt 0.937386 0.525591
+vt 0.725651 0.461548
+vt 0.880775 0.551075
+vt 0.836701 0.527336
+vt 0.797792 0.514127
+vt 0.759377 0.508439
+vt 0.913857 0.575039
+vt 0.725651 0.506149
+vt 0.865684 0.587482
+vt 0.821281 0.564934
+vt 0.787202 0.552815
+vt 0.755325 0.547510
+vt 0.725651 0.546264
+vt 0.898001 0.607830
+vt 0.569988 0.700590
+vt 0.585328 0.719905
+vt 0.546321 0.754766
+vt 0.535520 0.732184
+vt 0.509563 0.768667
+vt 0.504323 0.747817
+vt 0.675711 0.994379
+vt 0.668356 0.975055
+vt 0.698759 0.964984
+vt 0.705521 0.987438
+vt 0.610127 0.696548
+vt 0.595169 0.678228
+vt 0.732795 0.987196
+vt 0.732794 0.962797
+vt 0.599583 0.738801
+vt 0.555640 0.774850
+vt 0.515662 0.787440
+vt 0.657888 0.959183
+vt 0.691394 0.943641
+vt 0.624971 0.715188
+vt 0.732794 0.941074
+vt 0.603384 0.833329
+vt 0.617210 0.851804
+vt 0.597434 0.867055
+vt 0.585874 0.851314
+vt 0.584980 0.813744
+vt 0.569211 0.833435
+vt 0.556947 0.800928
+vt 0.546762 0.823712
+vt 0.521444 0.800093
+vt 0.521927 0.816784
+vt 0.645904 0.929888
+vt 0.644990 0.953827
+vt 0.628911 0.953150
+vt 0.627877 0.930700
+vt 0.639473 0.899216
+vt 0.620190 0.907346
+vt 0.631625 0.876874
+vt 0.611086 0.888231
+vt 0.637719 0.731981
+vt 0.614475 0.763949
+vt 0.593459 0.800158
+vt 0.652546 0.931978
+vt 0.688612 0.924506
+vt 0.732795 0.920494
+vt 0.575018 0.888069
+vt 0.562870 0.873723
+vt 0.548625 0.858496
+vt 0.532725 0.848360
+vt 0.514132 0.839286
+vt 0.606113 0.955636
+vt 0.602662 0.937567
+vt 0.595448 0.919093
+vt 0.585940 0.902616
+vt 0.611576 0.807529
+vt 0.653300 0.901743
+vt 0.688758 0.898706
+vt 0.732795 0.895839
+vt 0.649974 0.751148
+vt 0.629721 0.779176
+vt 0.640006 0.834554
+vt 0.653952 0.861751
+vt 0.662656 0.764809
+vt 0.644615 0.797575
+vt 0.692152 0.870965
+vt 0.732796 0.872146
+vt 0.463719 0.617262
+vt 0.444181 0.640306
+vt 0.411954 0.624176
+vt 0.435328 0.598532
+vt 0.507715 0.593502
+vt 0.483111 0.602546
+vt 0.457466 0.583360
+vt 0.482990 0.572211
+vt 0.435205 0.663171
+vt 0.430337 0.695020
+vt 0.397018 0.695020
+vt 0.400633 0.650102
+vt 0.387055 0.598617
+vt 0.420846 0.565611
+vt 0.454881 0.547866
+vt 0.489614 0.537081
+vt 0.366470 0.695021
+vt 0.372441 0.644080
+vt 0.661317 0.826152
+vt 0.675408 0.846937
+vt 0.686811 0.815629
+vt 0.698153 0.830461
+vt 0.672320 0.776433
+vt 0.662649 0.800206
+vt 0.681635 0.784822
+vt 0.683389 0.801078
+vt 0.700561 0.852932
+vt 0.732797 0.851748
+vt 0.712587 0.835739
+vt 0.732798 0.835786
+vt 0.559205 0.902622
+vt 0.549001 0.890834
+vt 0.534429 0.876148
+vt 0.519219 0.865725
+vt 0.503900 0.856835
+vt 0.587167 0.960003
+vt 0.582948 0.944963
+vt 0.575561 0.927326
+vt 0.567531 0.913018
+vt 0.540077 0.915350
+vt 0.529826 0.906995
+vt 0.517398 0.897218
+vt 0.505832 0.887784
+vt 0.493477 0.877807
+vt 0.566086 0.967743
+vt 0.562902 0.953735
+vt 0.556264 0.938127
+vt 0.548642 0.924913
+vt 0.519152 0.931261
+vt 0.510448 0.923146
+vt 0.501167 0.914442
+vt 0.492575 0.906612
+vt 0.482102 0.897502
+vt 0.545274 0.975605
+vt 0.540655 0.962839
+vt 0.534209 0.950746
+vt 0.527138 0.940113
+vt 0.503485 0.942839
+vt 0.496518 0.934822
+vt 0.489492 0.926408
+vt 0.482232 0.918688
+vt 0.471761 0.909890
+vt 0.530689 0.981736
+vt 0.524518 0.970370
+vt 0.517646 0.960553
+vt 0.510690 0.951233
+vt 0.796059 0.669944
+vt 0.797327 0.684804
+vt 0.761766 0.691146
+vt 0.759393 0.670512
+vt 0.800064 0.699862
+vt 0.768023 0.713991
+vt 0.807137 0.712911
+vt 0.779774 0.732015
+vt 0.819904 0.727583
+vt 0.797581 0.749343
+vt 0.819904 0.608781
+vt 0.808127 0.623008
+vt 0.782016 0.605592
+vt 0.798364 0.586888
+vt 0.801463 0.638516
+vt 0.769822 0.628971
+vt 0.797261 0.654344
+vt 0.761848 0.650543
+vt 0.727152 0.698963
+vt 0.723401 0.671819
+vt 0.736196 0.728778
+vt 0.753272 0.751032
+vt 0.777947 0.772442
+vt 0.756732 0.586802
+vt 0.779379 0.563621
+vt 0.738826 0.617150
+vt 0.727058 0.645545
+vt 0.564234 0.375332
+vt 0.581052 0.432191
+vt 0.533304 0.455717
+vt 0.511263 0.391816
+vt 0.615225 0.367750
+vt 0.626753 0.423474
+vt 0.662644 0.371609
+vt 0.672517 0.421762
+vt 0.495946 0.484003
+vt 0.464623 0.426240
+vt 0.710193 0.381002
+vt 0.718988 0.422219
+vt 0.598894 0.476769
+vt 0.550441 0.500212
+vt 0.639725 0.466546
+vt 0.681259 0.462344
+vt 0.513914 0.525594
+vt 0.614600 0.527338
+vt 0.570526 0.551077
+vt 0.653509 0.514128
+vt 0.691924 0.508440
+vt 0.537444 0.575042
+vt 0.630020 0.564936
+vt 0.585617 0.587484
+vt 0.664100 0.552816
+vt 0.695977 0.547510
+vt 0.553300 0.607833
+vt 0.895598 0.700619
+vt 0.930060 0.732210
+vt 0.919260 0.754787
+vt 0.880260 0.719930
+vt 0.961252 0.747841
+vt 0.956012 0.768688
+vt 0.789877 0.994378
+vt 0.760068 0.987438
+vt 0.766829 0.964984
+vt 0.797232 0.975055
+vt 0.855465 0.696575
+vt 0.870421 0.678258
+vt 0.909942 0.774869
+vt 0.866006 0.738823
+vt 0.949914 0.787459
+vt 0.774194 0.943641
+vt 0.807700 0.959183
+vt 0.840622 0.715212
+vt 0.862202 0.833339
+vt 0.879709 0.851322
+vt 0.868150 0.867062
+vt 0.848377 0.851812
+vt 0.880604 0.813757
+vt 0.896371 0.833446
+vt 0.908634 0.800943
+vt 0.918817 0.823724
+vt 0.944132 0.800109
+vt 0.943648 0.816798
+vt 0.819683 0.929889
+vt 0.837709 0.930701
+vt 0.836675 0.953150
+vt 0.820596 0.953827
+vt 0.826114 0.899219
+vt 0.845396 0.907349
+vt 0.833962 0.876879
+vt 0.854498 0.888236
+vt 0.827875 0.732002
+vt 0.851115 0.763967
+vt 0.872127 0.800172
+vt 0.813041 0.931979
+vt 0.776976 0.924507
+vt 0.902711 0.873730
+vt 0.890564 0.888074
+vt 0.916954 0.858504
+vt 0.932852 0.848369
+vt 0.951442 0.839296
+vt 0.862922 0.937568
+vt 0.859470 0.955636
+vt 0.870136 0.919095
+vt 0.879642 0.902620
+vt 0.854012 0.807541
+vt 0.812287 0.901746
+vt 0.776831 0.898707
+vt 0.815620 0.751167
+vt 0.835870 0.779192
+vt 0.811637 0.861756
+vt 0.825584 0.834563
+vt 0.802940 0.764824
+vt 0.820977 0.797588
+vt 0.773439 0.870968
+vt 0.463721 0.772779
+vt 0.435329 0.791508
+vt 0.411956 0.765864
+vt 0.444183 0.749734
+vt 0.507716 0.796541
+vt 0.482990 0.817830
+vt 0.457466 0.806681
+vt 0.483112 0.787496
+vt 0.435207 0.726868
+vt 0.400635 0.739939
+vt 0.420846 0.824427
+vt 0.387057 0.791421
+vt 0.489612 0.852961
+vt 0.454880 0.842174
+vt 0.372443 0.745961
+vt 0.790184 0.846942
+vt 0.804275 0.826160
+vt 0.767441 0.830465
+vt 0.778785 0.815636
+vt 0.793277 0.776446
+vt 0.802945 0.800217
+vt 0.782207 0.801087
+vt 0.783963 0.784834
+vt 0.765031 0.852934
+vt 0.753008 0.835742
+vt 0.916579 0.890839
+vt 0.906375 0.902626
+vt 0.931149 0.876153
+vt 0.946357 0.865731
+vt 0.961674 0.856842
+vt 0.882635 0.944965
+vt 0.878415 0.960004
+vt 0.890021 0.927329
+vt 0.898051 0.913022
+vt 0.935753 0.906998
+vt 0.925503 0.915352
+vt 0.948179 0.897221
+vt 0.959743 0.887787
+vt 0.972096 0.877811
+vt 0.902679 0.953737
+vt 0.899496 0.967744
+vt 0.909318 0.938128
+vt 0.916938 0.924915
+vt 0.955130 0.923146
+vt 0.946427 0.931262
+vt 0.964409 0.914442
+vt 0.973000 0.906613
+vt 0.983471 0.897503
+vt 0.924927 0.962840
+vt 0.920307 0.975606
+vt 0.931372 0.950747
+vt 0.938443 0.940114
+vt 0.969060 0.934820
+vt 0.962095 0.942838
+vt 0.976085 0.926406
+vt 0.983343 0.918686
+vt 0.993812 0.909888
+vt 0.941063 0.970371
+vt 0.934893 0.981737
+vt 0.947936 0.960553
+vt 0.954891 0.951233
+vt 0.703019 0.666118
+vt 0.666353 0.665551
+vt 0.668726 0.644916
+vt 0.704287 0.651259
+vt 0.674984 0.622071
+vt 0.707024 0.636201
+vt 0.686735 0.604048
+vt 0.714097 0.623153
+vt 0.704543 0.586720
+vt 0.726865 0.608481
+vt 0.726866 0.727280
+vt 0.705327 0.749173
+vt 0.688977 0.730470
+vt 0.715088 0.713053
+vt 0.676782 0.707091
+vt 0.708424 0.697545
+vt 0.668807 0.685520
+vt 0.704220 0.681718
+vt 0.630360 0.664243
+vt 0.634112 0.637099
+vt 0.643157 0.607284
+vt 0.660233 0.585031
+vt 0.684909 0.563621
+vt 0.686342 0.772442
+vt 0.663693 0.749262
+vt 0.645786 0.718913
+vt 0.634017 0.690518
+vn 0.9808 0.0000 0.1951
+vn 0.6935 0.6935 0.1951
+vn 0.6578 0.6578 0.3668
+vn 0.9303 0.0000 0.3668
+vn 0.5159 0.5159 0.6838
+vn 0.7296 0.0000 0.6838
+vn 0.2988 0.2988 0.9063
+vn 0.4226 0.0000 0.9063
+vn 0.0000 0.7296 0.6838
+vn 0.0000 0.4226 0.9063
+vn 0.0000 0.9303 0.3668
+vn 0.0000 0.9808 0.1951
+vn -0.6935 0.6935 0.1951
+vn -0.6578 0.6578 0.3668
+vn -0.5159 0.5159 0.6838
+vn -0.2988 0.2988 0.9063
+vn -0.7296 0.0000 0.6838
+vn -0.4226 0.0000 0.9063
+vn -0.9303 0.0000 0.3668
+vn -0.9808 0.0000 0.1951
+vn -0.6935 -0.6935 0.1951
+vn -0.6578 -0.6578 0.3668
+vn -0.5159 -0.5159 0.6838
+vn -0.2988 -0.2988 0.9063
+vn 0.0000 -0.7296 0.6839
+vn 0.0000 -0.4226 0.9063
+vn 0.0000 -0.9303 0.3668
+vn 0.0000 -0.9808 0.1951
+vn 0.6935 -0.6935 0.1951
+vn 0.6578 -0.6578 0.3668
+vn 0.5159 -0.5159 0.6839
+vn 0.2988 -0.2988 0.9063
+vn 0.0000 0.7296 0.6839
+vn 0.0000 0.0000 1.0000
+vn 0.5643 0.8040 0.1874
+vn 0.0349 0.9721 0.2318
+vn 0.0947 0.8904 0.4452
+vn 0.4281 0.8664 0.2569
+vn -0.5387 0.8154 0.2117
+vn -0.3772 0.8679 0.3231
+vn 0.1450 0.7340 0.6634
+vn 0.7758 0.5399 0.3265
+vn 0.8703 0.2401 0.4299
+vn 0.1390 0.3490 0.9267
+vn -0.6682 0.5266 0.5255
+vn -0.7534 0.1115 0.6481
+vn 0.9774 0.0400 -0.2074
+vn 0.9857 0.0764 -0.1498
+vn 0.6959 -0.0005 -0.7181
+vn 0.7255 0.0813 -0.6833
+vn -0.1401 0.0042 -0.9901
+vn -0.1604 0.1024 -0.9817
+vn -0.8955 -0.0806 -0.4376
+vn -0.9261 -0.0122 -0.3771
+vn -0.9898 -0.0967 0.1042
+vn -0.9834 -0.0490 0.1744
+vn 0.7592 0.1627 0.6302
+vn 0.9763 0.1522 0.1538
+vn -0.9769 0.1285 0.1706
+vn -0.5997 0.1582 0.7844
+vn 0.1708 0.1190 0.9781
+vn 0.9530 -0.1198 -0.2783
+vn 0.7327 -0.1711 -0.6586
+vn -0.1230 -0.2498 -0.9604
+vn -0.9050 -0.2604 -0.3363
+vn -0.9612 -0.2711 0.0510
+vn 0.7664 -0.4016 0.5014
+vn 0.9768 -0.2119 0.0309
+vn -0.9783 -0.2069 0.0067
+vn -0.6627 -0.4289 0.6138
+vn 0.1814 -0.5018 0.8457
+vn 0.0058 1.0000 0.0024
+vn 0.0173 0.9977 0.0647
+vn 0.0140 0.9991 0.0408
+vn 0.0019 1.0000 0.0008
+vn 0.0000 1.0000 0.0000
+vn -0.0224 0.9996 0.0142
+vn -0.0042 1.0000 0.0027
+vn -0.0213 0.9966 0.0796
+vn -0.0286 0.9987 0.0418
+vn -0.0590 0.9951 0.0785
+vn -0.0184 0.9995 0.0245
+vn 0.1013 0.9910 0.0873
+vn 0.0174 0.9997 0.0150
+vn 0.7189 0.0279 -0.6945
+vn 0.9626 0.0684 -0.2620
+vn 0.9571 0.0645 -0.2824
+vn 0.7201 0.0280 -0.6933
+vn -0.1395 0.0000 -0.9902
+vn -0.9302 -0.0125 -0.3669
+vn -0.9322 -0.0126 -0.3615
+vn -0.9971 -0.0141 0.0751
+vn -0.9955 -0.0159 0.0926
+vn 0.9860 -0.0695 0.1517
+vn 0.8051 -0.0640 0.5896
+vn 0.8059 -0.0642 0.5885
+vn 0.9999 0.0103 0.0087
+vn -0.6658 -0.0783 0.7420
+vn -0.9853 -0.0678 0.1570
+vn -0.9989 0.0388 -0.0261
+vn -0.6672 -0.0785 0.7407
+vn 0.1900 0.0000 0.9817
+vn 0.7158 0.0000 -0.6983
+vn 0.9327 0.0000 -0.3606
+vn 0.7170 0.0000 -0.6970
+vn -0.9310 0.0000 -0.3649
+vn -0.9332 0.0000 -0.3594
+vn -0.9881 0.0000 0.1535
+vn 0.0033 -0.9999 -0.0127
+vn 0.0023 -0.9999 -0.0089
+vn 0.0027 -0.9999 -0.0103
+vn 0.0000 -1.0000 0.0000
+vn 0.0954 0.0000 0.9954
+vn -0.0056 -0.9974 -0.0721
+vn 0.0013 -0.9999 0.0089
+vn 0.0012 -0.9999 0.0084
+vn -0.0046 -0.9981 -0.0606
+vn 0.6696 0.6973 0.2557
+vn 0.1028 0.8632 0.4942
+vn -0.6143 0.7079 0.3484
+vn 0.9873 0.1398 -0.0755
+vn -0.9995 0.0267 0.0124
+vn 0.9779 -0.1336 -0.1604
+vn -0.9660 -0.2525 -0.0552
+vn -0.0163 0.9943 0.1053
+vn -0.0438 0.9933 0.1068
+vn 0.0311 0.9941 0.1034
+vn 0.0784 0.9911 0.1075
+vn 0.9903 0.0667 -0.1216
+vn 0.9864 0.0718 -0.1479
+vn -0.9952 0.0603 -0.0766
+vn -0.9986 0.0348 -0.0406
+vn -0.0098 -0.9895 -0.1438
+vn -0.0098 -0.9895 -0.1439
+vn -0.0081 -0.9884 -0.1514
+vn 0.8285 -0.0534 0.5575
+vn 0.1751 -0.1238 0.9767
+vn -0.6633 -0.1615 0.7307
+vn 0.9980 -0.0279 -0.0564
+vn 0.7054 -0.0600 -0.7062
+vn -0.1476 -0.1158 -0.9822
+vn -0.8880 -0.1676 -0.4282
+vn -0.9642 -0.1540 0.2156
+vn 0.8321 -0.0872 0.5477
+vn 0.1824 -0.1765 0.9672
+vn -0.6357 -0.2123 0.7422
+vn 0.9988 -0.0410 -0.0260
+vn 0.7005 -0.0492 -0.7119
+vn -0.0960 -0.1009 -0.9902
+vn -0.8561 -0.1889 -0.4810
+vn -0.9500 -0.2058 0.2347
+vn 0.8354 -0.0230 0.5491
+vn 0.2129 -0.1662 0.9628
+vn -0.6209 -0.2031 0.7571
+vn 0.9959 0.0898 0.0090
+vn 0.6932 0.2000 -0.6924
+vn -0.1296 0.2023 -0.9707
+vn -0.8672 0.0488 -0.4956
+vn -0.9589 -0.1257 0.2542
+vn 0.5578 0.8200 -0.1283
+vn -0.3067 0.9382 0.1602
+vn -0.2646 0.9275 0.2640
+vn 0.3538 0.8414 -0.4085
+vn 0.4636 0.8056 0.3688
+vn -0.3696 0.9282 -0.0433
+vn 0.0360 0.7070 0.7062
+vn -0.0649 0.9775 -0.2006
+vn -0.4514 0.7279 0.5161
+vn 0.2260 0.9671 -0.1168
+vn -0.6267 0.7781 0.0426
+vn 0.2509 0.9651 0.0752
+vn -0.5250 0.8071 -0.2700
+vn 0.1836 0.9705 0.1564
+vn 0.0480 0.9255 0.3755
+vn -0.1718 0.8630 -0.4750
+vn -0.9321 0.2105 0.2948
+vn -0.6008 0.1924 0.7758
+vn -0.8687 0.3474 -0.3530
+vn -0.1809 0.5031 -0.8451
+vn 0.6545 0.4714 -0.5910
+vn 0.9164 0.3983 0.0378
+vn 0.7583 0.3540 0.5473
+vn 0.1593 0.2625 0.9517
+vn -0.9604 -0.0017 0.2784
+vn -0.6481 -0.0459 0.7602
+vn -0.9610 0.0396 0.2738
+vn -0.6532 0.0267 0.7566
+vn -0.9165 0.1694 -0.3624
+vn -0.9272 0.1982 -0.3177
+vn 0.9709 0.2383 -0.0220
+vn 0.7237 0.3410 -0.6000
+vn 0.9615 0.2732 -0.0290
+vn 0.7596 0.3717 -0.5336
+vn 0.8061 0.1566 0.5707
+vn 0.8005 0.2079 0.5620
+vn 0.1455 0.0126 0.9893
+vn 0.1321 0.1030 0.9858
+vn 0.4210 0.3782 -0.8244
+vn 0.5070 0.4330 -0.7453
+vn -0.6329 0.2678 -0.7264
+vn -0.6678 0.3027 -0.6799
+vn 0.8194 0.0042 0.5731
+vn 0.2042 -0.1556 0.9665
+vn -0.5818 -0.1815 0.7927
+vn 0.9828 0.1584 0.0945
+vn 0.7138 0.3758 -0.5909
+vn -0.1448 0.4327 -0.8898
+vn -0.9073 0.2036 -0.3680
+vn -0.9447 -0.0626 0.3218
+vn 0.5684 0.4212 -0.7067
+vn 0.8292 0.3811 -0.4088
+vn 0.6229 0.7278 -0.2867
+vn 0.4379 0.7944 -0.4209
+vn 0.6725 0.7303 -0.1198
+vn 0.9261 0.3677 -0.0848
+vn 0.6326 0.7729 0.0491
+vn 0.9099 0.3658 0.1957
+vn 0.6224 0.7252 0.2945
+vn 0.8397 0.3773 0.3904
+vn 0.4227 0.8023 0.4215
+vn 0.7024 0.4112 0.5809
+vn 0.2416 0.8125 0.5304
+vn 0.4131 0.4433 0.7955
+vn -0.0042 0.8036 0.5950
+vn 0.0177 0.4490 0.8933
+vn -0.1995 0.7997 0.5662
+vn -0.3616 0.4600 0.8110
+vn -0.4445 0.7648 0.4664
+vn -0.6326 0.4611 0.6222
+vn -0.5921 0.7521 0.2894
+vn -0.8083 0.4348 0.3969
+vn -0.6529 0.7562 0.0428
+vn -0.9061 0.3968 0.1467
+vn -0.6632 0.7307 -0.1617
+vn -0.9214 0.3656 -0.1315
+vn -0.6329 0.7220 -0.2795
+vn -0.8258 0.3753 -0.4209
+vn -0.4337 0.8022 -0.4103
+vn -0.5758 0.4194 -0.7018
+vn -0.1841 0.8154 -0.5488
+vn -0.2334 0.4557 -0.8590
+vn 0.0078 0.7958 -0.6054
+vn 0.0132 0.4587 -0.8885
+vn 0.1951 0.8080 -0.5560
+vn 0.2450 0.4549 -0.8561
+vn 0.2894 0.9051 -0.3114
+vn 0.3992 0.8986 -0.1818
+vn 0.4342 0.8998 -0.0419
+vn 0.4264 0.9007 0.0834
+vn 0.3884 0.9030 0.1838
+vn 0.3197 0.9057 0.2783
+vn 0.2018 0.9081 0.3669
+vn 0.0685 0.9092 0.4106
+vn -0.0517 0.9243 0.3781
+vn -0.1844 0.9428 0.2777
+vn -0.3140 0.9413 0.1234
+vn -0.3878 0.9213 -0.0288
+vn -0.4024 0.9057 -0.1333
+vn -0.3835 0.8993 -0.2100
+vn -0.2905 0.9044 -0.3124
+vn -0.1374 0.9128 -0.3845
+vn 0.0021 0.9184 -0.3956
+vn 0.1396 0.9140 -0.3809
+vn 0.0322 0.9994 -0.0120
+vn 0.0033 0.5454 -0.8382
+vn 0.0412 0.1898 -0.9809
+vn -0.0090 0.3287 -0.9444
+vn -0.4245 -0.9052 0.0175
+vn -0.0551 0.3208 -0.9455
+vn -0.0438 0.2972 -0.9538
+vn 0.2574 -0.6565 -0.7090
+vn 0.8623 0.0269 0.5057
+vn 0.7951 0.3225 0.5136
+vn 0.7586 0.5118 0.4032
+vn 0.8786 0.1567 0.4510
+vn 0.8159 0.2487 0.5219
+vn -0.2534 -0.8652 0.4326
+vn -0.8412 0.2313 0.4887
+vn -0.8099 0.3698 0.4553
+vn -0.7885 0.4400 0.4297
+vn -0.7905 0.3883 0.4736
+vn -0.8086 0.2466 0.5341
+vn -0.0430 -0.1536 -0.9872
+vn 0.1329 -0.6703 -0.7301
+vn -0.1098 0.4881 -0.8658
+vn 0.0657 0.5343 -0.8427
+vn 0.0789 -0.1132 -0.9904
+vn 0.0039 0.5423 -0.8402
+vn 0.0079 -0.0543 -0.9985
+vn -0.0684 0.5347 -0.8422
+vn -0.1110 -0.0825 -0.9904
+vn 0.0688 0.5040 -0.8610
+vn -0.0165 -0.1200 -0.9926
+vn -0.0827 -0.5025 -0.8606
+vn 0.8057 -0.2191 0.5503
+vn 0.6322 -0.6802 0.3709
+vn 0.7025 0.4908 0.5154
+vn 0.8809 -0.1507 0.4487
+vn 0.7418 0.5519 0.3808
+vn 0.8707 -0.0538 0.4888
+vn 0.7161 0.5662 0.4081
+vn 0.8087 -0.0862 0.5819
+vn 0.7042 0.5523 0.4462
+vn 0.8716 -0.1670 0.4609
+vn 0.7978 0.4907 0.3503
+vn 0.6875 -0.6447 0.3342
+vn -0.8472 -0.1510 0.5094
+vn -0.7342 -0.5202 0.4363
+vn -0.7088 0.5038 0.4936
+vn -0.7257 0.5610 0.3982
+vn -0.8927 -0.0851 0.4425
+vn -0.7082 0.5753 0.4092
+vn -0.8581 -0.0227 0.5130
+vn -0.7039 0.5624 0.4337
+vn -0.8097 -0.0734 0.5822
+vn -0.7851 0.5027 0.3617
+vn -0.8606 -0.0916 0.5010
+vn -0.6582 -0.5762 0.4845
+vn 0.3752 0.7432 -0.5540
+vn 0.2752 0.4698 -0.8388
+vn 0.2696 0.4489 -0.8520
+vn 0.3661 0.7237 -0.5849
+vn 0.4506 0.8723 -0.1897
+vn 0.4492 0.8709 -0.1991
+vn 0.4726 0.8720 0.1269
+vn 0.4727 0.8721 0.1265
+vn 0.4491 0.7697 0.4536
+vn 0.4515 0.7777 0.4374
+vn 0.4055 0.6255 0.6665
+vn 0.4045 0.6214 0.6710
+vn 0.3404 0.4999 0.7964
+vn 0.3471 0.5092 0.7875
+vn 0.2132 0.3815 0.8994
+vn 0.2123 0.3808 0.8999
+vn 0.0750 0.2979 0.9516
+vn 0.0760 0.2984 0.9514
+vn -0.0333 0.2791 0.9597
+vn -0.0280 0.2780 0.9601
+vn -0.2097 0.2106 0.9548
+vn -0.2110 0.2097 0.9547
+vn -0.4812 0.0034 0.8766
+vn -0.4667 0.0164 0.8842
+vn -0.6958 -0.1962 0.6909
+vn -0.6890 -0.1898 0.6994
+vn -0.8328 -0.3222 0.4501
+vn -0.8396 -0.3279 0.4331
+vn -0.8966 -0.3772 0.2318
+vn -0.8987 -0.3785 0.2212
+vn -0.9227 -0.3854 -0.0028
+vn -0.9228 -0.3852 -0.0077
+vn -0.8657 -0.3755 -0.3309
+vn -0.8532 -0.3742 -0.3632
+vn -0.6545 -0.3737 -0.6572
+vn -0.6833 -0.3721 -0.6281
+vn -0.4339 -0.3700 -0.8215
+vn -0.4162 -0.3687 -0.8311
+vn -0.1782 -0.2616 -0.9486
+vn -0.1764 -0.2602 -0.9493
+vn -0.0415 -0.1176 -0.9922
+vn -0.0414 -0.1171 -0.9922
+vn -0.0217 -0.0444 -0.9988
+vn -0.0217 -0.0443 -0.9988
+vn 0.0586 0.0589 -0.9965
+vn 0.0595 0.0598 -0.9964
+vn 0.1792 0.2177 -0.9594
+vn 0.1808 0.2205 -0.9585
+vn -0.7294 0.6838 -0.0192
+vn -0.7253 0.6884 0.0018
+vn -0.7275 0.6861 -0.0025
+vn -0.7275 0.6860 -0.0121
+vn -0.7291 0.6843 0.0056
+vn -0.7293 0.6842 0.0047
+vn -0.7222 0.6903 0.0425
+vn -0.7223 0.6904 0.0413
+vn -0.7214 0.6920 0.0241
+vn -0.7210 0.6926 0.0205
+vn -0.7217 0.6919 0.0177
+vn -0.7227 0.6908 0.0214
+vn -0.7215 0.6920 0.0214
+vn -0.7200 0.6937 0.0179
+vn -0.7136 0.7005 0.0067
+vn -0.7122 0.7019 0.0050
+vn -0.7099 0.7043 0.0022
+vn -0.7100 0.7041 0.0024
+vn -0.7091 0.7050 0.0031
+vn -0.7094 0.7048 0.0031
+vn -0.7049 0.7092 0.0029
+vn -0.7058 0.7084 0.0028
+vn -0.7004 0.7137 0.0064
+vn -0.7013 0.7128 0.0054
+vn -0.7098 0.7043 -0.0104
+vn -0.7074 0.7067 -0.0063
+vn -0.7180 0.6955 -0.0250
+vn -0.7210 0.6909 -0.0529
+vn -0.7207 0.6914 -0.0502
+vn -0.7248 0.6878 -0.0391
+vn -0.7248 0.6878 -0.0393
+vn -0.7253 0.6884 -0.0013
+vn -0.7253 0.6884 -0.0014
+vn -0.7234 0.6904 -0.0075
+vn -0.7227 0.6911 -0.0096
+vn -0.7214 0.6924 -0.0132
+vn -0.7217 0.6921 -0.0124
+vn -0.7266 0.6870 -0.0059
+vn -0.7289 0.6846 -0.0034
+vn -0.7299 0.6836 -0.0013
+vn -0.7284 0.6850 -0.0023
+vn -0.7234 0.6903 -0.0050
+vn -0.7235 0.6902 -0.0050
+vn -0.7275 0.6860 -0.0081
+vn -0.7259 0.6877 -0.0072
+vn -0.7315 0.6817 -0.0106
+vn -0.7314 0.6818 -0.0104
+vn 0.7236 -0.6902 -0.0032
+vn 0.7229 -0.6909 0.0057
+vn 0.7211 -0.6928 -0.0006
+vn 0.7295 -0.6839 0.0085
+vn 0.7258 -0.6878 0.0105
+vn 0.7257 -0.6879 0.0103
+vn 0.7237 -0.6897 -0.0227
+vn 0.7236 -0.6897 -0.0275
+vn 0.7226 -0.6895 -0.0487
+vn 0.7226 -0.6895 -0.0482
+vn 0.7207 -0.6921 -0.0394
+vn 0.7194 -0.6937 -0.0340
+vn 0.7120 -0.7020 -0.0128
+vn 0.7087 -0.7054 -0.0054
+vn 0.6996 -0.7144 0.0119
+vn 0.6983 -0.7156 0.0134
+vn 0.6951 -0.7187 0.0167
+vn 0.6951 -0.7187 0.0166
+vn 0.7041 -0.7099 0.0157
+vn 0.7024 -0.7115 0.0157
+vn 0.7296 -0.6834 0.0246
+vn 0.7233 -0.6902 0.0214
+vn 0.7175 -0.6965 0.0045
+vn 0.7247 -0.6889 0.0124
+vn 0.7061 -0.7080 -0.0058
+vn 0.7053 -0.7089 -0.0071
+vn 0.7143 -0.6996 0.0170
+vn 0.7137 -0.7003 0.0146
+vn 0.7179 -0.6955 0.0284
+vn 0.7180 -0.6954 0.0288
+vn 0.7180 -0.6959 0.0117
+vn 0.7180 -0.6959 0.0121
+vn 0.7168 -0.6972 0.0089
+vn 0.7163 -0.6977 0.0121
+vn 0.7144 -0.6993 0.0240
+vn 0.7141 -0.6995 0.0248
+vn 0.7131 -0.7005 0.0273
+vn 0.7127 -0.7009 0.0281
+vn 0.7186 -0.6951 0.0226
+vn 0.7224 -0.6912 0.0186
+vn 0.7251 -0.6885 0.0136
+vn 0.7239 -0.6897 0.0142
+vn 0.7211 -0.6926 0.0160
+vn 0.7210 -0.6927 0.0160
+vn 0.7315 -0.6815 0.0212
+vn 0.7286 -0.6846 0.0195
+vn 0.7373 -0.6751 0.0244
+vn 0.7374 -0.6749 0.0246
+vn -0.5643 0.8040 0.1874
+vn -0.4281 0.8664 0.2569
+vn -0.0947 0.8904 0.4452
+vn -0.0349 0.9721 0.2318
+vn 0.3772 0.8679 0.3231
+vn 0.5387 0.8154 0.2117
+vn -0.8703 0.2401 0.4299
+vn -0.7758 0.5399 0.3265
+vn -0.1450 0.7340 0.6634
+vn -0.1390 0.3490 0.9267
+vn 0.6682 0.5266 0.5255
+vn 0.7534 0.1115 0.6481
+vn -0.9857 0.0764 -0.1498
+vn -0.9774 0.0400 -0.2074
+vn -0.7255 0.0813 -0.6833
+vn -0.6959 -0.0005 -0.7181
+vn 0.1604 0.1024 -0.9817
+vn 0.1401 0.0042 -0.9901
+vn 0.9261 -0.0122 -0.3771
+vn 0.8955 -0.0806 -0.4376
+vn 0.9834 -0.0490 0.1744
+vn 0.9898 -0.0967 0.1042
+vn -0.9763 0.1522 0.1538
+vn -0.7592 0.1627 0.6302
+vn 0.5997 0.1582 0.7844
+vn 0.9769 0.1285 0.1706
+vn -0.1708 0.1190 0.9781
+vn -0.7327 -0.1711 -0.6586
+vn -0.9530 -0.1198 -0.2783
+vn 0.1230 -0.2498 -0.9604
+vn 0.9050 -0.2604 -0.3363
+vn 0.9612 -0.2711 0.0510
+vn -0.9768 -0.2119 0.0309
+vn -0.7664 -0.4016 0.5014
+vn 0.6627 -0.4289 0.6138
+vn 0.9783 -0.2069 0.0067
+vn -0.1814 -0.5018 0.8457
+vn -0.0058 1.0000 0.0024
+vn -0.0019 1.0000 0.0008
+vn -0.0140 0.9991 0.0408
+vn -0.0173 0.9977 0.0647
+vn 0.0224 0.9996 0.0142
+vn 0.0042 1.0000 0.0027
+vn 0.0213 0.9966 0.0796
+vn 0.0286 0.9987 0.0418
+vn 0.0590 0.9951 0.0785
+vn 0.0184 0.9995 0.0245
+vn -0.0174 0.9997 0.0150
+vn -0.1013 0.9910 0.0873
+vn -0.7189 0.0279 -0.6945
+vn -0.7201 0.0280 -0.6933
+vn -0.9571 0.0645 -0.2824
+vn -0.9626 0.0684 -0.2620
+vn 0.1395 0.0000 -0.9902
+vn 0.9302 -0.0125 -0.3669
+vn 0.9322 -0.0126 -0.3615
+vn 0.9971 -0.0141 0.0751
+vn 0.9955 -0.0159 0.0926
+vn -0.9860 -0.0695 0.1517
+vn -0.9999 0.0103 0.0087
+vn -0.8059 -0.0642 0.5885
+vn -0.8051 -0.0640 0.5896
+vn 0.6658 -0.0783 0.7420
+vn 0.6672 -0.0785 0.7407
+vn 0.9989 0.0388 -0.0261
+vn 0.9853 -0.0678 0.1570
+vn -0.1900 0.0000 0.9817
+vn -0.7158 0.0000 -0.6983
+vn -0.7170 0.0000 -0.6970
+vn -0.9327 0.0000 -0.3606
+vn 0.9310 0.0000 -0.3649
+vn 0.9332 0.0000 -0.3594
+vn 0.9881 0.0000 0.1535
+vn -0.0033 -0.9999 -0.0127
+vn -0.0027 -0.9999 -0.0103
+vn -0.0023 -0.9999 -0.0089
+vn -0.0954 0.0000 0.9954
+vn 0.0056 -0.9974 -0.0721
+vn 0.0046 -0.9981 -0.0606
+vn -0.0012 -0.9999 0.0084
+vn -0.0013 -0.9999 0.0089
+vn -0.6696 0.6973 0.2557
+vn -0.1028 0.8632 0.4942
+vn 0.6143 0.7079 0.3484
+vn -0.9873 0.1398 -0.0755
+vn 0.9995 0.0267 0.0124
+vn -0.9779 -0.1336 -0.1604
+vn 0.9660 -0.2525 -0.0552
+vn 0.0438 0.9933 0.1068
+vn 0.0163 0.9943 0.1053
+vn -0.0784 0.9911 0.1075
+vn -0.0311 0.9941 0.1034
+vn -0.9864 0.0718 -0.1479
+vn -0.9903 0.0667 -0.1216
+vn 0.9986 0.0348 -0.0406
+vn 0.9952 0.0603 -0.0766
+vn 0.0098 -0.9895 -0.1439
+vn 0.0098 -0.9895 -0.1438
+vn 0.0081 -0.9884 -0.1514
+vn -0.1751 -0.1238 0.9767
+vn -0.8285 -0.0534 0.5575
+vn 0.6633 -0.1615 0.7307
+vn -0.9980 -0.0279 -0.0564
+vn -0.7054 -0.0600 -0.7062
+vn 0.1476 -0.1158 -0.9822
+vn 0.8880 -0.1676 -0.4282
+vn 0.9642 -0.1540 0.2156
+vn -0.1824 -0.1765 0.9672
+vn -0.8321 -0.0872 0.5477
+vn 0.6357 -0.2123 0.7422
+vn -0.9988 -0.0410 -0.0260
+vn -0.7005 -0.0492 -0.7119
+vn 0.0960 -0.1009 -0.9902
+vn 0.8561 -0.1889 -0.4810
+vn 0.9500 -0.2058 0.2347
+vn -0.2129 -0.1662 0.9628
+vn -0.8354 -0.0230 0.5491
+vn 0.6209 -0.2031 0.7571
+vn -0.9959 0.0898 0.0090
+vn -0.6932 0.2000 -0.6924
+vn 0.1296 0.2023 -0.9707
+vn 0.8672 0.0488 -0.4956
+vn 0.9589 -0.1257 0.2542
+vn -0.5578 0.8200 -0.1283
+vn -0.3538 0.8414 -0.4085
+vn 0.2646 0.9275 0.2640
+vn 0.3067 0.9382 0.1602
+vn 0.3696 0.9282 -0.0433
+vn -0.4636 0.8056 0.3688
+vn 0.0649 0.9775 -0.2006
+vn -0.0360 0.7070 0.7062
+vn -0.2260 0.9671 -0.1168
+vn 0.4514 0.7279 0.5161
+vn -0.2509 0.9651 0.0752
+vn 0.6267 0.7781 0.0426
+vn -0.1836 0.9705 0.1564
+vn 0.5250 0.8071 -0.2700
+vn 0.1718 0.8630 -0.4750
+vn -0.0480 0.9255 0.3755
+vn 0.6008 0.1924 0.7758
+vn 0.9321 0.2105 0.2948
+vn 0.8687 0.3474 -0.3530
+vn 0.1809 0.5031 -0.8451
+vn -0.6545 0.4714 -0.5910
+vn -0.9164 0.3983 0.0378
+vn -0.7583 0.3540 0.5473
+vn -0.1593 0.2625 0.9517
+vn 0.6481 -0.0459 0.7602
+vn 0.9604 -0.0017 0.2784
+vn 0.6532 0.0267 0.7566
+vn 0.9610 0.0396 0.2738
+vn 0.9165 0.1694 -0.3624
+vn 0.9272 0.1982 -0.3177
+vn -0.7237 0.3410 -0.6000
+vn -0.9709 0.2383 -0.0220
+vn -0.7596 0.3717 -0.5336
+vn -0.9615 0.2732 -0.0290
+vn -0.8061 0.1566 0.5707
+vn -0.8005 0.2079 0.5620
+vn -0.1455 0.0126 0.9893
+vn -0.1321 0.1030 0.9858
+vn -0.4210 0.3782 -0.8244
+vn -0.5070 0.4330 -0.7453
+vn 0.6329 0.2678 -0.7264
+vn 0.6678 0.3027 -0.6799
+vn -0.2042 -0.1556 0.9665
+vn -0.8194 0.0042 0.5731
+vn 0.5818 -0.1815 0.7927
+vn -0.9828 0.1584 0.0945
+vn -0.7138 0.3758 -0.5909
+vn 0.1448 0.4327 -0.8898
+vn 0.9073 0.2036 -0.3680
+vn 0.9447 -0.0626 0.3218
+vn -0.6501 -0.0552 0.7578
+vn -0.6162 -0.0574 0.7855
+vn -0.9896 -0.0777 0.1207
+vn -0.9904 -0.0789 0.1137
+vn -0.8206 -0.2037 -0.5339
+vn -0.8253 -0.2023 -0.5272
+vn -0.2995 -0.2358 -0.9244
+vn -0.2933 -0.2353 -0.9266
+vn -0.1039 -0.0634 0.9926
+vn -0.1046 -0.0635 0.9925
+vn 0.0000 -0.2035 -0.9791
+vn 0.6501 -0.0552 0.7578
+vn 0.9904 -0.0789 0.1137
+vn 0.9896 -0.0777 0.1207
+vn 0.6162 -0.0574 0.7855
+vn 0.8253 -0.2023 -0.5272
+vn 0.8206 -0.2037 -0.5339
+vn 0.2933 -0.2353 -0.9266
+vn 0.2995 -0.2358 -0.9244
+vn 0.1039 -0.0634 0.9926
+vn 0.1046 -0.0635 0.9925
+vn 0.5867 0.4925 -0.6428
+vn 0.6344 0.5441 -0.5489
+vn 0.3189 0.0218 -0.9475
+vn 0.2481 -0.0747 -0.9658
+vn -0.5290 -0.8139 -0.2402
+vn -0.5352 -0.8351 -0.1272
+vn -0.2644 -0.6963 -0.6672
+vn -0.2163 -0.6168 -0.7568
+vn -0.4068 0.0869 0.9093
+vn -0.5131 -0.0359 0.8575
+vn 0.1113 0.6099 0.7845
+vn 0.2069 0.6956 0.6880
+vn -0.8217 -0.4729 0.3181
+vn -0.8436 -0.5214 0.1282
+vn -0.7674 -0.0267 0.6405
+vn -0.6554 -0.0763 0.7514
+vn 0.6539 0.7285 0.2041
+vn 0.6378 0.7485 0.1815
+vn 0.0350 0.5455 0.8374
+vn 0.0019 0.6154 0.7882
+vn 0.6195 0.7823 0.0655
+vn 0.4573 0.1525 -0.8761
+vn 0.5605 0.2968 -0.7731
+vn -0.0270 -0.1694 -0.9852
+vn -0.1560 -0.4219 -0.8931
+vn -0.6250 -0.5332 -0.5701
+vn -0.6080 -0.6690 -0.4275
+vn -0.7595 -0.6503 0.0143
+vn -0.7697 -0.6314 0.0938
+vn -0.7246 -0.6873 -0.0500
+vn -0.7741 -0.6307 -0.0551
+vn -0.6974 -0.6462 0.3099
+vn -0.6403 -0.7607 0.1061
+vn -0.7103 -0.4686 0.5253
+vn -0.6522 -0.6209 0.4348
+vn -0.6191 -0.7507 0.2304
+vn 0.7121 0.5679 -0.4128
+vn 0.7577 0.5658 -0.3251
+vn -0.6536 -0.4130 0.6343
+vn 0.6214 0.7812 -0.0602
+vn -0.5867 0.4925 -0.6428
+vn -0.2481 -0.0747 -0.9658
+vn -0.3189 0.0218 -0.9475
+vn -0.6344 0.5441 -0.5489
+vn 0.5291 -0.8140 -0.2398
+vn 0.2163 -0.6169 -0.7567
+vn 0.2644 -0.6964 -0.6671
+vn 0.5351 -0.8352 -0.1268
+vn 0.4069 0.0867 0.9093
+vn -0.2069 0.6956 0.6880
+vn -0.1113 0.6099 0.7846
+vn 0.5132 -0.0362 0.8574
+vn 0.8217 -0.4729 0.3179
+vn 0.6556 -0.0766 0.7512
+vn 0.7675 -0.0268 0.6404
+vn 0.8437 -0.5213 0.1281
+vn -0.6539 0.7285 0.2041
+vn -0.0018 0.6154 0.7882
+vn -0.0350 0.5455 0.8374
+vn -0.6378 0.7485 0.1815
+vn -0.6195 0.7823 0.0655
+vn -0.4573 0.1525 -0.8761
+vn 0.1560 -0.4221 -0.8930
+vn 0.0272 -0.1697 -0.9851
+vn -0.5604 0.2969 -0.7731
+vn 0.6079 -0.6692 -0.4272
+vn 0.6247 -0.5335 -0.5702
+vn 0.7595 -0.6503 0.0144
+vn 0.7739 -0.6308 -0.0553
+vn 0.7247 -0.6873 -0.0499
+vn 0.7699 -0.6312 0.0938
+vn 0.6403 -0.7607 0.1062
+vn 0.6973 -0.6463 0.3099
+vn 0.7102 -0.4689 0.5251
+vn 0.6188 -0.7509 0.2306
+vn 0.6519 -0.6212 0.4348
+vn -0.7121 0.5679 -0.4128
+vn -0.7577 0.5658 -0.3251
+vn 0.6534 -0.4133 0.6342
+vn -0.6214 0.7812 -0.0602
+vn 0.0000 0.5914 0.8064
+vn 0.0316 0.5911 0.8060
+vn 0.0308 0.4554 0.8897
+vn 0.0000 0.4364 0.8997
+vn -0.0308 0.4554 0.8897
+vn -0.0316 0.5911 0.8060
+vn 0.0053 0.2001 0.9797
+vn 0.0000 0.1821 0.9832
+vn -0.0053 0.2001 0.9797
+vn -0.0293 0.0845 0.9960
+vn 0.0000 0.0840 0.9965
+vn 0.0293 0.0845 0.9960
+vn -0.0337 0.0768 0.9965
+vn 0.0000 0.0768 0.9970
+vn 0.0337 0.0768 0.9965
+vn -0.2639 -0.9229 0.2804
+vn -0.5502 -0.7853 0.2838
+vn -0.5543 -0.8025 0.2206
+vn -0.2597 -0.9390 0.2256
+vn -0.6224 -0.7773 0.0913
+vn -0.8156 -0.2854 0.5033
+vn -0.4764 -0.8671 0.1454
+vn -0.2137 -0.9079 0.3605
+vn -0.2650 -0.9136 0.3082
+vn -0.5307 -0.8193 0.2169
+vn -0.3614 -0.4355 0.8245
+vn 0.6115 0.6158 0.4967
+vn 0.9253 0.3726 0.0707
+vn -0.3077 -0.8602 -0.4066
+vn -0.5429 -0.2364 0.8058
+vn -0.4774 -0.7141 -0.5120
+vn 0.5385 0.6378 0.5506
+vn -0.5263 -0.2101 0.8239
+vn 0.5362 0.6596 0.5267
+vn -0.5197 -0.3168 0.7934
+vn -0.3943 -0.4563 0.7976
+vn -0.4687 -0.7263 -0.5027
+vn 0.6151 0.1681 -0.7703
+vn 0.6056 0.1588 -0.7797
+vn 0.6847 0.2040 -0.6996
+vn 0.9241 0.3363 -0.1812
+vn -0.2064 -0.9190 -0.3359
+vn -0.3505 -0.8126 -0.4655
+vn -0.6384 -0.1511 0.7546
+vn -0.6010 -0.2153 0.7696
+vn -0.3800 -0.8005 -0.4635
+vn -0.6182 -0.1377 0.7738
+vn 0.8422 0.0462 -0.5371
+vn 0.7189 0.0910 -0.6891
+vn 0.6671 0.1120 -0.7365
+vn 0.6074 0.4649 0.6440
+vn 0.9569 0.1108 0.2682
+vn 0.1561 -0.9810 -0.1152
+vn 0.4081 0.5417 0.7348
+vn 0.7953 0.6057 0.0260
+vn 0.7091 0.6996 0.0873
+vn -0.1219 0.7312 0.6711
+vn 0.0861 0.7418 0.6650
+vn -0.8705 -0.2709 0.4108
+vn -0.1397 0.7839 0.6049
+vn 0.9502 0.2931 -0.1055
+vn -0.8876 -0.3498 0.2996
+vn 0.6767 0.7203 0.1526
+vn 0.2139 -0.8716 -0.4410
+vn 0.8944 0.3965 -0.2070
+vn 0.2764 -0.8589 -0.4311
+vn 0.8778 0.4236 -0.2235
+vn 0.3988 -0.8937 -0.2055
+vn 0.8715 0.3520 0.3414
+vn 0.5563 -0.7154 0.4228
+vn 0.4584 0.6602 0.5950
+vn 0.4427 0.7237 0.5294
+vn 0.6466 0.1100 -0.7548
+vn -0.3852 -0.8051 -0.4510
+vn 0.4280 0.7653 0.4806
+vn 0.4386 0.7680 0.4667
+vn -0.3182 -0.8583 -0.4025
+vn 0.7022 0.0591 -0.7095
+vn -0.5268 -0.1932 0.8277
+vn -0.5936 -0.1400 0.7924
+vn 0.6956 0.4361 -0.5709
+vn 0.7708 0.4104 -0.4872
+vn 0.3933 0.0489 -0.9181
+vn 0.3017 0.0102 -0.9533
+vn 0.3482 0.2615 -0.9002
+vn 0.7546 0.4969 0.4285
+vn 0.7400 0.4853 0.4657
+vn 0.3758 0.2801 -0.8833
+vn -0.3462 -0.2911 0.8918
+vn -0.3428 -0.3327 0.8785
+vn 0.4376 0.1417 -0.8879
+vn -0.4476 -0.7287 -0.5182
+vn -0.3621 -0.7150 -0.5980
+vn 0.3710 0.2472 -0.8951
+vn -0.6496 -0.6094 -0.4545
+vn -0.7330 -0.5146 -0.4448
+vn -0.6915 -0.5415 -0.4781
+vn -0.5542 -0.6909 -0.4642
+vn 0.4561 0.2024 -0.8666
+vn 0.4927 0.2234 -0.8410
+vn -0.5438 -0.6721 -0.5025
+vn 0.4856 0.2306 -0.8432
+vn -0.3897 -0.8233 -0.4127
+vn 0.5302 0.2436 -0.8121
+vn -0.5614 -0.6305 -0.5359
+vn 0.6357 0.6197 0.4602
+vn 0.6257 0.5990 0.4997
+vn -0.3981 -0.2807 0.8733
+vn -0.4138 -0.2854 0.8644
+vn -0.2250 -0.4896 0.8424
+vn 0.7202 0.5854 0.3723
+vn 0.6359 0.5551 0.5361
+vn 0.6458 0.5111 0.5672
+vn 0.5900 0.1849 -0.7859
+vn -0.4275 -0.2898 0.8563
+vn -0.4019 -0.3358 0.8519
+vn 0.8694 0.2119 -0.4463
+vn -0.5067 -0.6875 -0.5202
+vn 0.0260 -0.6685 0.7432
+vn -0.0347 -0.9581 -0.2843
+vn 0.8344 -0.0024 0.5511
+vn 0.9019 0.3363 0.2710
+vn -0.2236 -0.5208 0.8238
+vn -0.2998 0.8627 0.4071
+vn -0.2232 0.8304 0.5104
+vn -0.8625 -0.4081 0.2992
+vn -0.7765 -0.4543 0.4365
+vn -0.0961 0.6693 0.7367
+vn -0.3810 -0.3719 0.8465
+vn 0.7649 0.4133 0.4940
+vn 0.9079 -0.2552 0.3326
+vn 0.6127 -0.2835 -0.7377
+vn 0.4411 0.2565 -0.8600
+vn 0.0121 -0.7999 0.6000
+vn -0.2419 -0.8693 -0.4310
+vn -0.3346 -0.3858 0.8597
+vn -0.3572 -0.3238 0.8761
+vn -0.6850 -0.5326 -0.4971
+vn -0.6569 -0.5612 -0.5034
+vn 0.7223 0.4910 0.4869
+vn 0.8177 -0.2963 -0.4935
+vn 0.7985 0.0944 0.5945
+vn 0.5864 0.6405 0.4959
+vn -0.5138 -0.1709 0.8407
+vn -0.0509 -0.5529 0.8317
+vn -0.5367 -0.1576 0.8289
+vn 0.5527 0.6792 0.4830
+vn -0.0105 -0.9829 -0.1836
+vn 0.8447 -0.3419 -0.4117
+vn -0.4639 -0.7522 -0.4679
+vn 0.6364 0.0752 -0.7677
+vn -0.4995 -0.7101 -0.4963
+vn 0.5879 0.1422 -0.7963
+vn 0.1442 -0.9864 -0.0787
+vn 0.9043 -0.3073 -0.2962
+vn -0.0049 -0.5033 0.8641
+vn 0.7508 0.2203 0.6226
+vn 0.4887 0.7214 0.4907
+vn 0.1530 -0.0386 -0.9875
+vn -0.5243 -0.5828 -0.6207
+vn -0.6027 -0.7866 0.1343
+vn -0.6928 -0.7179 0.0685
+vn -0.6119 -0.7715 0.1744
+vn -0.5510 -0.7897 0.2697
+vn 0.8391 0.4838 -0.2485
+vn 0.7673 0.5777 -0.2782
+vn 0.6330 0.3985 -0.6636
+vn 0.7683 0.5821 -0.2662
+vn -0.4094 -0.6659 -0.6236
+vn 0.4010 0.2994 -0.8657
+vn 0.4268 0.7456 0.5117
+vn 0.2639 -0.9228 0.2804
+vn 0.2598 -0.9389 0.2255
+vn 0.5544 -0.8024 0.2207
+vn 0.5506 -0.7848 0.2842
+vn 0.8152 -0.2862 0.5034
+vn 0.6218 -0.7778 0.0916
+vn 0.2129 -0.9077 0.3616
+vn 0.4767 -0.8668 0.1462
+vn 0.2655 -0.9135 0.3081
+vn 0.5317 -0.8186 0.2171
+vn -0.9253 0.3724 0.0711
+vn -0.6123 0.6149 0.4969
+vn 0.3612 -0.4361 0.8242
+vn 0.3077 -0.8603 -0.4064
+vn 0.5428 -0.2366 0.8058
+vn 0.4769 -0.7141 -0.5123
+vn -0.5385 0.6377 0.5507
+vn -0.5362 0.6595 0.5267
+vn 0.5264 -0.2105 0.8237
+vn 0.3954 -0.4557 0.7974
+vn 0.5199 -0.3167 0.7933
+vn 0.4686 -0.7263 -0.5028
+vn -0.6057 0.1588 -0.7797
+vn -0.6152 0.1679 -0.7703
+vn -0.6851 0.2033 -0.6995
+vn -0.9241 0.3362 -0.1818
+vn 0.2062 -0.9192 -0.3355
+vn 0.6011 -0.2154 0.7696
+vn 0.6386 -0.1517 0.7544
+vn 0.3498 -0.8126 -0.4661
+vn 0.6185 -0.1382 0.7735
+vn 0.3794 -0.8003 -0.4642
+vn -0.7190 0.0909 -0.6890
+vn -0.8430 0.0452 -0.5359
+vn -0.6671 0.1121 -0.7365
+vn -0.1583 -0.9808 -0.1137
+vn -0.9562 0.1124 0.2702
+vn -0.6069 0.4659 0.6439
+vn -0.4079 0.5414 0.7351
+vn -0.7093 0.6995 0.0865
+vn -0.7952 0.6059 0.0254
+vn 0.1229 0.7307 0.6715
+vn -0.0854 0.7421 0.6648
+vn 0.8695 -0.2719 0.4122
+vn -0.9511 0.2907 -0.1040
+vn 0.1302 0.7873 0.6027
+vn 0.8883 -0.3482 0.2993
+vn -0.6765 0.7206 0.1521
+vn -0.2160 -0.8713 -0.4405
+vn -0.2756 -0.8593 -0.4307
+vn -0.8955 0.3946 -0.2054
+vn -0.3988 -0.8936 -0.2057
+vn -0.8779 0.4227 -0.2249
+vn -0.5557 -0.7164 0.4218
+vn -0.8726 0.3504 0.3404
+vn -0.4432 0.7231 0.5298
+vn -0.4579 0.6601 0.5954
+vn 0.3848 -0.8050 -0.4515
+vn -0.6464 0.1101 -0.7550
+vn -0.4385 0.7681 0.4666
+vn -0.4281 0.7654 0.4805
+vn 0.3176 -0.8581 -0.4034
+vn -0.7007 0.0593 -0.7109
+vn 0.5939 -0.1405 0.7922
+vn 0.5270 -0.1937 0.8274
+vn -0.6956 0.4361 -0.5708
+vn -0.3016 0.0102 -0.9533
+vn -0.3933 0.0490 -0.9181
+vn -0.7708 0.4105 -0.4872
+vn -0.3479 0.2611 -0.9004
+vn -0.3755 0.2799 -0.8835
+vn -0.7402 0.4855 0.4652
+vn -0.7548 0.4970 0.4281
+vn 0.3421 -0.3322 0.8789
+vn 0.3449 -0.2912 0.8923
+vn 0.3622 -0.7150 -0.5979
+vn 0.4474 -0.7287 -0.5184
+vn -0.4377 0.1419 -0.8878
+vn 0.6492 -0.6101 -0.4541
+vn -0.3709 0.2469 -0.8952
+vn 0.7325 -0.5158 -0.4442
+vn 0.6916 -0.5416 -0.4778
+vn 0.5539 -0.6911 -0.4642
+vn 0.5438 -0.6719 -0.5027
+vn -0.4926 0.2233 -0.8411
+vn -0.4561 0.2022 -0.8666
+vn -0.4856 0.2307 -0.8432
+vn 0.3897 -0.8233 -0.4126
+vn 0.5614 -0.6305 -0.5360
+vn -0.5299 0.2437 -0.8123
+vn -0.6257 0.5990 0.4997
+vn -0.6358 0.6196 0.4602
+vn 0.4139 -0.2854 0.8644
+vn 0.3979 -0.2809 0.8733
+vn -0.7202 0.5854 0.3722
+vn 0.2251 -0.4899 0.8422
+vn -0.6357 0.5553 0.5361
+vn -0.5889 0.1855 -0.7866
+vn -0.6452 0.5120 0.5670
+vn 0.4025 -0.3360 0.8515
+vn 0.4278 -0.2901 0.8560
+vn -0.8694 0.2122 -0.4462
+vn 0.5063 -0.6872 -0.5209
+vn -0.0243 -0.6686 0.7432
+vn 0.0365 -0.9579 -0.2848
+vn -0.8351 -0.0030 0.5500
+vn 0.2230 -0.5209 0.8239
+vn -0.9019 0.3365 0.2708
+vn 0.2965 0.8639 0.4070
+vn 0.7761 -0.4523 0.4394
+vn 0.8639 -0.4058 0.2982
+vn 0.2248 0.8299 0.5106
+vn 0.0866 0.6696 0.7376
+vn 0.3829 -0.3690 0.8468
+vn -0.7647 0.4137 0.4939
+vn -0.4406 0.2567 -0.8602
+vn -0.6118 -0.2834 -0.7385
+vn -0.9082 -0.2551 0.3317
+vn 0.2425 -0.8691 -0.4310
+vn -0.0120 -0.7999 0.6000
+vn 0.3356 -0.3854 0.8596
+vn 0.6579 -0.5605 -0.5029
+vn 0.6861 -0.5315 -0.4967
+vn 0.3569 -0.3221 0.8768
+vn -0.7226 0.4910 0.4865
+vn -0.8172 -0.2966 -0.4942
+vn -0.7996 0.0939 0.5932
+vn 0.0532 -0.5525 0.8318
+vn 0.5142 -0.1712 0.8404
+vn -0.5850 0.6419 0.4957
+vn 0.5370 -0.1578 0.8287
+vn -0.5525 0.6792 0.4831
+vn 0.0115 -0.9828 -0.1844
+vn -0.8449 -0.3413 -0.4118
+vn 0.4641 -0.7520 -0.4680
+vn -0.6347 0.0760 -0.7690
+vn -0.5879 0.1423 -0.7963
+vn 0.4989 -0.7098 -0.4972
+vn -0.1428 -0.9865 -0.0794
+vn -0.9038 -0.3078 -0.2973
+vn 0.0068 -0.5033 0.8640
+vn -0.7525 0.2197 0.6209
+vn -0.4883 0.7223 0.4897
+vn 0.5241 -0.5827 -0.6211
+vn -0.1529 -0.0387 -0.9875
+vn 0.6023 -0.7867 0.1349
+vn 0.6928 -0.7179 0.0681
+vn 0.5510 -0.7895 0.2705
+vn 0.6120 -0.7714 0.1743
+vn -0.8389 0.4840 -0.2489
+vn -0.6330 0.3985 -0.6636
+vn -0.7673 0.5777 -0.2782
+vn -0.7683 0.5821 -0.2662
+vn 0.4094 -0.6656 -0.6239
+vn -0.4008 0.2993 -0.8659
+vn -0.4268 0.7455 0.5118
+vn 0.7582 0.2197 0.6139
+vn 0.7683 0.2270 0.5985
+vn 0.7289 0.3504 0.5882
+vn 0.6271 0.4322 0.6480
+vn 0.2808 -0.7982 0.5330
+vn 0.2296 -0.3707 0.8999
+vn 0.3005 -0.3598 0.8833
+vn 0.5432 -0.6083 0.5787
+vn 0.2564 -0.7570 0.6009
+vn 0.4443 -0.2793 0.8512
+vn 0.3707 -0.6150 0.6959
+vn 0.6432 -0.2588 0.7206
+vn 0.4973 -0.4428 0.7460
+vn 0.7764 -0.2221 0.5898
+vn 0.6035 -0.1940 0.7734
+vn 0.8323 -0.1104 0.5431
+vn 0.4249 0.2239 0.8771
+vn 0.6032 0.1015 0.7911
+vn 0.7829 0.1171 0.6110
+vn 0.5765 0.2389 0.7814
+vn 0.3123 0.2911 0.9043
+vn 0.4449 0.1368 0.8850
+vn 0.4106 0.4375 0.8000
+vn 0.5586 0.3086 0.7699
+vn 0.5984 0.3789 0.7059
+vn 0.6377 0.4165 0.6480
+vn -0.0012 0.4888 0.8724
+vn -0.0018 0.5252 0.8509
+vn 0.6285 0.4140 0.6585
+vn 0.7646 0.3588 0.5354
+vn -0.0019 0.5069 0.8620
+vn 0.5952 0.4053 0.6939
+vn 0.7822 0.3161 0.5369
+vn -0.0000 0.4783 0.8782
+vn 0.5764 -0.0305 0.8166
+vn 0.6335 -0.0656 0.7709
+vn 0.6856 -0.1623 0.7096
+vn 0.5863 -0.1444 0.7971
+vn 0.7228 0.2496 0.6443
+vn 0.5743 0.0604 0.8164
+vn 0.8457 0.1133 0.5214
+vn 0.6987 -0.1054 0.7076
+vn 0.5543 -0.0240 0.8320
+vn 0.5129 -0.0626 0.8561
+vn 0.2505 0.2151 0.9439
+vn 0.1112 0.0934 0.9894
+vn 0.5249 0.2817 0.8032
+vn 0.7906 0.2004 0.5786
+vn 0.9182 0.0382 0.3941
+vn 0.1079 0.0482 0.9930
+vn 0.1982 -0.1280 0.9717
+vn -0.0016 0.0508 0.9987
+vn -0.0029 -0.0709 0.9975
+vn 0.6447 0.0479 0.7629
+vn 0.5792 0.0915 0.8100
+vn 0.6718 0.0253 0.7403
+vn 0.7821 -0.0792 0.6181
+vn 0.4368 -0.0073 0.8995
+vn 0.0018 -0.0942 0.9955
+vn -0.0003 0.3992 0.9168
+vn 0.4355 0.3392 0.8338
+vn 0.6934 -0.1085 0.7123
+vn 0.6929 -0.0406 0.7198
+vn 0.8389 -0.1663 0.5182
+vn 0.8260 -0.1741 0.5361
+vn 0.7719 -0.1557 0.6163
+vn 0.6703 -0.1058 0.7344
+vn 0.3185 0.2238 0.9211
+vn 0.4400 -0.0919 0.8932
+vn 0.4340 -0.5919 0.6791
+vn 0.7140 -0.4843 0.5055
+vn 0.8408 -0.4059 0.3582
+vn 0.4530 -0.8890 0.0665
+vn 0.5708 -0.8210 0.0130
+vn 0.5992 -0.8000 0.0306
+vn 0.4465 -0.8902 0.0908
+vn 0.2340 -0.9614 0.1449
+vn 0.2551 -0.9553 0.1496
+vn 0.8333 0.0587 0.5496
+vn 0.6356 0.1060 0.7647
+vn 0.6740 -0.1415 0.7250
+vn 0.7595 -0.1903 0.6220
+vn 0.4297 0.0634 0.9008
+vn -0.0018 0.1940 0.9810
+vn 0.0011 0.1267 0.9919
+vn 0.4440 0.1291 0.8867
+vn 0.2810 0.8336 0.4756
+vn 0.0007 0.8745 0.4850
+vn 0.2239 -0.1651 0.9605
+vn 0.4341 0.5425 0.7192
+vn 0.5389 0.0443 0.8412
+vn 0.4574 -0.1100 0.8824
+vn 0.5737 -0.1514 0.8049
+vn 0.6222 -0.0359 0.7820
+vn 0.4025 -0.3061 0.8627
+vn 0.0014 -0.3820 0.9242
+vn 0.6379 0.1158 0.7613
+vn 0.5120 0.6898 0.5118
+vn 0.1267 -0.7389 0.6618
+vn 0.4449 -0.2964 0.8451
+vn 0.5599 -0.3430 0.7542
+vn 0.2820 -0.7669 0.5764
+vn 0.1836 -0.8027 0.5674
+vn 0.3493 -0.4081 0.8435
+vn 0.0005 -0.4352 0.9003
+vn 0.0002 -0.8286 0.5598
+vn 0.2763 -0.7842 0.5555
+vn 0.5560 -0.3713 0.7436
+vn 0.5989 -0.1033 0.7941
+vn 0.6156 -0.0436 0.7869
+vn 0.6388 -0.0931 0.7637
+vn 0.6008 -0.1194 0.7904
+vn 0.6345 0.1051 0.7657
+vn 0.5628 0.5589 0.6089
+vn 0.5777 0.0794 0.8123
+vn 0.3768 0.0939 0.9215
+vn 0.4074 0.2368 0.8820
+vn 0.6372 0.0876 0.7656
+vn 0.0008 0.0973 0.9952
+vn 0.4223 0.0628 0.9042
+vn -0.0011 0.2424 0.9702
+vn 0.6432 0.0412 0.7646
+vn -0.0016 0.0902 0.9959
+vn 0.8080 -0.2907 0.5124
+vn 0.6423 -0.4734 0.6028
+vn 0.8296 -0.0756 0.5532
+vn 0.4301 -0.2327 0.8723
+vn 0.5863 -0.1966 0.7859
+vn 0.5485 0.0652 0.8336
+vn 0.4421 -0.2856 0.8502
+vn 0.7363 -0.3884 0.5541
+vn -0.0065 -0.6837 0.7297
+vn -0.0013 0.0307 0.9995
+vn 0.6607 -0.0385 0.7496
+vn 0.5651 -0.0099 0.8250
+vn 0.3843 -0.1113 0.9164
+vn 0.0025 -0.2507 0.9680
+vn 0.0001 0.2142 0.9768
+vn 0.0003 -0.1929 0.9812
+vn 0.0005 -0.6541 0.7564
+vn 0.0002 -0.9863 0.1646
+vn -0.0004 -0.9821 0.1881
+vn 0.9288 -0.3647 0.0655
+vn 0.9420 -0.3108 0.1264
+vn 0.9825 -0.0652 0.1742
+vn 0.9540 -0.2391 0.1807
+vn 0.6856 -0.7273 0.0310
+vn 0.6975 -0.7165 -0.0093
+vn 0.7934 -0.6047 0.0697
+vn 0.7778 -0.6280 -0.0254
+vn 0.8989 -0.4382 -0.0031
+vn 0.8698 -0.4851 -0.0900
+vn 0.8912 -0.3417 0.2982
+vn 0.5824 -0.0899 0.8079
+vn 0.8924 -0.2492 0.3761
+vn 0.8615 -0.2203 0.4574
+vn 0.8052 -0.2293 0.5468
+vn 0.7174 -0.2016 0.6669
+vn 0.9355 -0.0226 0.3527
+vn 0.8004 -0.0605 0.5963
+vn 0.9296 -0.0194 0.3680
+vn 0.9355 0.0184 0.3527
+vn 0.8829 -0.1617 0.4407
+vn 0.9070 -0.2055 0.3676
+vn 0.9589 -0.1118 0.2609
+vn 0.9661 -0.1306 0.2226
+vn 0.9134 -0.2235 0.3400
+vn 0.9673 -0.1345 0.2147
+vn -0.0077 -0.9073 0.4205
+vn 0.5738 -0.7885 0.2210
+vn 0.6131 -0.5511 0.5659
+vn -0.0053 -0.5700 0.8216
+vn 0.6828 -0.7227 -0.1070
+vn 0.6583 -0.7222 0.2121
+vn 0.3005 -0.9102 0.2849
+vn -0.0864 -0.8240 0.5599
+vn 0.0508 -0.1701 0.9841
+vn 0.4794 -0.8242 -0.3014
+vn 0.3572 -0.9297 -0.0893
+vn -0.1660 -0.9697 -0.1791
+vn 0.1188 -0.9566 -0.2658
+vn 0.9348 0.0031 0.3550
+vn 0.9108 -0.4120 -0.0250
+vn 0.6838 -0.7113 0.1628
+vn 0.6259 0.2243 0.7469
+vn 0.8694 -0.4674 0.1600
+vn 0.8431 -0.5220 -0.1293
+vn 0.1321 -0.7737 0.6196
+vn 0.7475 -0.3038 0.5907
+vn -0.4339 -0.8863 0.1620
+vn -0.0095 -0.9611 0.2760
+vn 0.4239 0.5181 0.7428
+vn 0.6842 0.2856 0.6710
+vn 0.4343 -0.5007 0.7488
+vn 0.1718 -0.6532 0.7374
+vn 0.1506 -0.6232 0.7674
+vn 0.3354 -0.4684 0.8173
+vn 0.4507 -0.3902 0.8028
+vn 0.4709 -0.2305 0.8515
+vn 0.4901 0.2327 0.8400
+vn 0.3445 0.2478 0.9055
+vn 0.2073 0.3290 0.9213
+vn 0.2049 0.4727 0.8570
+vn 0.5107 0.0732 0.8566
+vn 0.6915 -0.1222 0.7119
+vn 0.0887 0.8676 0.4893
+vn 0.1953 0.8434 0.5004
+vn 0.2855 0.7825 0.5534
+vn 0.6216 0.4313 0.6539
+vn 0.6761 -0.2232 0.7021
+vn 0.4150 -0.6373 0.6492
+vn 0.2639 -0.7886 0.5554
+vn 0.1015 -0.8883 0.4479
+vn 0.0315 -0.8718 0.4888
+vn -0.0269 -0.7701 0.6373
+vn -0.0586 -0.4636 0.8841
+vn -0.0179 0.1928 0.9810
+vn -0.0081 0.7203 0.6935
+vn -0.0016 0.8168 0.5769
+vn 0.5870 -0.7756 0.2319
+vn 0.4189 -0.9076 -0.0290
+vn 0.0971 -0.9887 -0.1137
+vn -0.2621 -0.9584 -0.1130
+vn -0.5486 -0.8301 0.0992
+vn -0.7003 -0.4384 0.5633
+vn -0.5495 0.8342 0.0453
+vn -0.3517 0.9142 -0.2010
+vn -0.0664 0.9420 -0.3288
+vn 0.2329 0.9147 -0.3301
+vn 0.4197 0.9076 0.0074
+vn -0.7428 0.3618 0.5633
+vn 0.6023 -0.6748 0.4264
+vn 0.4478 -0.8006 0.3981
+vn 0.1610 -0.8795 0.4477
+vn -0.1231 -0.8754 0.4674
+vn -0.3728 -0.7714 0.5156
+vn -0.4050 -0.3814 0.8310
+vn -0.4878 0.7882 0.3751
+vn -0.2984 0.8819 0.3650
+vn -0.0045 0.9598 0.2805
+vn 0.3976 0.9027 0.1640
+vn 0.6170 0.7787 0.1132
+vn -0.4851 0.2970 0.8224
+vn 0.5795 -0.3055 0.7555
+vn 0.4514 -0.3508 0.8205
+vn -0.0685 0.2510 0.9655
+vn 0.1788 -0.3938 0.9016
+vn -0.0384 -0.3904 0.9198
+vn 0.1355 0.2574 0.9567
+vn 0.4353 0.2475 0.8656
+vn 0.6648 0.3251 0.6726
+vn 0.4090 0.3750 0.8319
+vn 0.2337 0.3243 0.9166
+vn 0.6208 0.3724 0.6898
+vn 0.8311 0.2465 0.4984
+vn 0.9360 0.0803 0.3425
+vn 0.1045 0.2871 0.9522
+vn -0.0005 0.2781 0.9605
+vn 0.9784 -0.0448 0.2019
+vn 0.9702 -0.0006 0.2425
+vn 0.9619 0.0069 0.2731
+vn 0.9825 -0.0949 0.1599
+vn 0.9854 -0.1102 0.1298
+vn 0.9915 -0.0888 0.0943
+vn 0.9880 -0.1543 -0.0030
+vn 0.9150 -0.1765 0.3627
+vn 0.9299 -0.0402 0.3656
+vn 0.9738 0.0487 0.2221
+vn 0.8012 -0.2927 0.5219
+vn 0.9819 -0.0320 0.1866
+vn 0.8314 -0.0290 0.5549
+vn 0.6979 0.0679 0.7129
+vn 0.9319 0.0355 0.3608
+vn -0.2330 0.7887 0.5688
+vn -0.1733 0.8108 0.5591
+vn -0.0406 0.7854 0.6177
+vn -0.1187 0.7190 0.6848
+vn 0.2815 0.5347 0.7967
+vn 0.1209 0.4666 0.8761
+vn 0.6155 -0.0837 0.7837
+vn 0.4122 -0.1155 0.9037
+vn 0.2281 0.0598 0.9718
+vn 0.5482 -0.1726 0.8183
+vn 0.6457 -0.3360 0.6856
+vn 0.7675 -0.5440 0.3392
+vn 0.7195 -0.3168 0.6179
+vn 0.6938 -0.6651 0.2762
+vn 0.7239 -0.4323 0.5376
+vn 0.3470 -0.8618 0.3699
+vn -0.0003 -0.9059 0.4235
+vn 0.3786 -0.6455 0.6633
+vn -0.0023 -0.7054 0.7088
+vn 0.5796 -0.7589 0.2967
+vn 0.6210 -0.5266 0.5805
+vn 0.3775 0.0646 0.9237
+vn 0.1235 0.2131 0.9692
+vn 0.3949 0.2199 0.8920
+vn 0.5367 0.1600 0.8285
+vn -0.1141 0.4584 0.8814
+vn -0.1984 0.6807 0.7052
+vn -0.2395 0.7730 0.5874
+vn 0.4125 -0.2410 0.8785
+vn 0.5680 -0.4289 0.7024
+vn -0.0469 0.8608 0.5068
+vn 0.0623 0.8558 0.5135
+vn 0.3302 0.6493 0.6851
+vn 0.9360 0.3086 0.1692
+vn 0.8394 0.2729 0.4700
+vn 0.9763 0.0412 -0.2122
+vn 0.9982 -0.0604 -0.0012
+vn 0.9929 -0.0176 -0.1176
+vn 0.9183 -0.0115 -0.3956
+vn 0.2800 -0.3257 0.9030
+vn 0.3546 -0.4979 0.7914
+vn -0.0019 -0.5312 0.8472
+vn -0.0009 -0.3603 0.9328
+vn 0.8511 0.0940 0.5165
+vn 0.7298 0.1426 0.6686
+vn 0.7349 0.2952 0.6105
+vn 0.7986 0.2608 0.5423
+vn -0.1494 0.1932 0.9697
+vn -0.0002 0.3187 0.9478
+vn -0.0002 0.5611 0.8277
+vn -0.2356 0.4376 0.8677
+vn -0.2796 0.4599 0.8427
+vn -0.1245 0.2579 0.9581
+vn -0.0468 0.1417 0.9888
+vn -0.0344 0.2994 0.9535
+vn 0.2831 0.2507 0.9257
+vn 0.5556 0.2141 0.8034
+vn 0.5726 0.3702 0.7314
+vn 0.9876 -0.0668 0.1421
+vn 0.9851 -0.0138 0.1712
+vn 0.9778 0.0101 0.2091
+vn 0.9519 0.0619 0.2999
+vn 0.9716 -0.2317 0.0472
+vn 0.9615 -0.2031 -0.1852
+vn 0.9527 -0.2558 -0.1638
+vn 0.9453 -0.1385 -0.2951
+vn 0.9861 -0.0878 0.1412
+vn 0.8603 0.2256 0.4572
+vn 0.1733 0.4817 0.8590
+vn -0.0003 0.4824 0.8759
+vn 0.6938 0.3904 0.6052
+vn 0.5276 0.4577 0.7156
+vn 0.3629 0.4737 0.8024
+vn 0.9733 0.0722 0.2177
+vn 0.8965 0.2665 0.3538
+vn 0.7335 0.4720 0.4891
+vn 0.5754 0.5840 0.5726
+vn 0.4160 0.6532 0.6326
+vn 0.2203 0.6996 0.6797
+vn -0.0003 0.7155 0.6986
+vn 0.9843 0.0758 0.1589
+vn 0.8727 0.2265 0.4324
+vn 0.7198 0.6345 0.2814
+vn 0.9867 0.1558 0.0455
+vn 0.9953 -0.0320 0.0910
+vn 0.8187 -0.5516 0.1594
+vn 0.9470 -0.2358 0.2180
+vn 0.9819 -0.0986 0.1617
+vn 0.8855 -0.2559 0.3879
+vn 0.8912 -0.0589 0.4497
+vn 0.9817 -0.0146 0.1897
+vn 0.1102 0.9903 -0.0840
+vn 0.9721 0.2278 -0.0561
+vn 0.9825 0.0748 0.1702
+vn 0.9916 0.0168 0.1278
+vn 0.9982 0.0088 0.0586
+vn 0.9908 0.0696 0.1161
+vn 0.9223 0.2758 0.2707
+vn 0.9426 0.2722 0.1932
+vn 0.7584 0.5297 0.3799
+vn 0.7790 0.5678 0.2660
+vn 0.5808 0.6882 0.4348
+vn 0.5733 0.7639 0.2962
+vn 0.4173 0.7829 0.4613
+vn 0.3999 0.8648 0.3036
+vn 0.2281 0.8453 0.4831
+vn 0.2131 0.9275 0.3070
+vn -0.0004 0.8702 0.4926
+vn -0.0004 0.9512 0.3085
+vn 0.9862 0.0124 0.1651
+vn 0.9927 -0.0243 0.1179
+vn 0.9630 -0.1671 0.2115
+vn 0.9147 -0.2635 0.3062
+vn 0.9081 -0.3343 0.2522
+vn 0.8651 -0.4870 0.1198
+vn 0.8138 -0.5675 0.1252
+vn 0.7233 -0.6749 0.1458
+vn 0.5530 -0.8056 0.2127
+vn 0.3056 -0.9041 0.2986
+vn 0.0005 -0.9414 0.3372
+vn 0.7523 -0.5602 -0.3468
+vn 0.7585 -0.6347 -0.1476
+vn 0.1063 0.8930 0.4373
+vn 0.0349 0.9186 0.3937
+vn 0.0775 0.9284 0.3633
+vn 0.1617 0.8659 0.4733
+vn 0.2545 0.7494 0.6111
+vn 0.3673 0.6561 0.6592
+vn 0.2130 0.7909 0.5737
+vn 0.1453 0.8597 0.4896
+vn 0.1990 0.7491 0.6318
+vn 0.2266 0.6973 0.6800
+vn 0.4455 0.5990 0.6653
+vn 0.4367 0.5471 0.7141
+vn -0.1425 -0.4490 -0.8821
+vn 0.2102 -0.5287 -0.8223
+vn 0.9877 -0.1237 -0.0952
+vn 0.8433 -0.3157 -0.4349
+vn -0.5966 0.5023 -0.6258
+vn -0.4835 0.2249 -0.8459
+vn 0.1132 0.2753 -0.9546
+vn 0.4564 0.5646 -0.6877
+vn -0.4101 -0.3906 -0.8242
+vn 0.5776 -0.4773 -0.6622
+vn -0.4126 -0.1463 -0.8991
+vn -0.4539 -0.3581 -0.8159
+vn 0.2999 -0.4301 -0.8515
+vn 0.0530 -0.1151 -0.9919
+vn -0.4859 0.7632 -0.4259
+vn 0.9001 0.3909 -0.1921
+vn 0.7945 -0.3614 -0.4880
+vn 0.9912 0.0295 0.1287
+vn 0.9997 -0.0249 -0.0060
+vn 0.9976 0.0560 0.0413
+vn 0.9604 0.2673 0.0779
+vn 0.8026 0.5873 0.1041
+vn 0.5779 0.8076 0.1174
+vn 0.3890 0.9136 0.1177
+vn 0.2006 0.9730 0.1140
+vn -0.0004 0.9937 0.1122
+vn 0.1099 -0.1335 -0.9849
+vn -0.0013 -0.1688 -0.9856
+vn -0.0021 -0.2815 -0.9595
+vn 0.1777 -0.2741 -0.9451
+vn 0.2228 0.2255 -0.9484
+vn -0.0019 0.2469 -0.9690
+vn -0.0015 0.4761 -0.8794
+vn 0.2279 0.4626 -0.8567
+vn 0.9266 -0.1050 -0.3609
+vn 0.8503 -0.0323 -0.5253
+vn 0.8820 0.1174 -0.4563
+vn 0.9517 -0.0046 -0.3069
+vn 0.9702 0.1510 -0.1891
+vn 0.8631 0.4317 -0.2619
+vn 0.8317 0.5497 -0.0783
+vn 0.9714 0.2313 -0.0539
+vn 0.9973 -0.0433 -0.0592
+vn 0.9921 -0.0302 -0.1218
+vn 0.9905 -0.0083 -0.1372
+vn 0.9984 0.0272 -0.0489
+vn 0.8845 -0.0619 -0.4624
+vn 0.8536 -0.2029 -0.4797
+vn 0.9547 -0.1487 -0.2577
+vn 0.9726 -0.0816 -0.2176
+vn 0.9643 -0.0119 -0.2644
+vn 0.9814 -0.0383 -0.1882
+vn 0.8812 0.2624 -0.3932
+vn 0.9607 0.0628 -0.2703
+vn -0.0005 0.9091 -0.4166
+vn -0.0005 0.9922 -0.1247
+vn 0.2080 0.9708 -0.1196
+vn 0.2274 0.8871 -0.4016
+vn 0.6017 0.7930 -0.0956
+vn 0.6460 0.6899 -0.3267
+vn 0.4249 0.8261 -0.3701
+vn 0.3981 0.9109 -0.1085
+vn 0.6695 0.0681 -0.7397
+vn 0.4472 0.1622 -0.8795
+vn 0.4550 0.4081 -0.7915
+vn 0.6993 0.2840 -0.6559
+vn 0.4480 0.6412 -0.6230
+vn 0.6867 0.4964 -0.5310
+vn -0.0008 0.7150 -0.6991
+vn 0.2353 0.6986 -0.6756
+vn 0.8272 0.0580 -0.5589
+vn 0.7219 0.0827 -0.6870
+vn 0.7139 -0.1442 -0.6852
+vn 0.8134 -0.0699 -0.5775
+vn 0.8559 -0.2378 -0.4592
+vn 0.7453 -0.2657 -0.6114
+vn 0.7913 -0.1794 -0.5846
+vn 0.8858 -0.2047 -0.4165
+vn 0.9355 -0.2147 -0.2804
+vn 0.9838 -0.0923 -0.1534
+vn 0.9246 -0.1564 -0.3473
+vn 0.9341 -0.1876 -0.3038
+vn 0.9921 0.0409 -0.1186
+vn 0.8987 -0.0174 -0.4381
+vn 0.9939 0.0239 -0.1077
+vn 0.9127 -0.0683 -0.4027
+vn 0.7162 -0.2773 -0.6404
+vn 0.8311 -0.1960 -0.5204
+vn -0.0023 -0.1747 -0.9846
+vn -0.0024 0.0132 -0.9999
+vn 0.2215 -0.0114 -0.9751
+vn 0.2142 -0.1877 -0.9586
+vn 0.6084 -0.1230 -0.7840
+vn 0.5613 -0.2423 -0.7913
+vn 0.3898 -0.2101 -0.8966
+vn 0.4230 -0.0648 -0.9038
+vn 0.5422 0.0598 -0.8381
+vn 0.2660 -0.0318 -0.9634
+vn 0.3533 -0.2477 -0.9021
+vn 0.5500 -0.2034 -0.8100
+vn 0.3727 -0.2710 -0.8875
+vn 0.5468 -0.2907 -0.7851
+vn -0.0020 -0.2572 -0.9663
+vn 0.2035 -0.2591 -0.9442
+vn -0.2736 0.6673 0.6927
+vn -0.2621 0.7474 0.6105
+vn -0.2578 0.6690 0.6971
+vn -0.2536 0.7208 0.6451
+vn -0.0009 0.6898 0.7240
+vn -0.0017 0.7283 0.6852
+vn 0.4770 0.5701 0.6688
+vn 0.6020 0.6883 0.4046
+vn 0.4076 0.6126 -0.6771
+vn 0.5396 0.7326 -0.4147
+vn 0.5414 0.7185 -0.4365
+vn 0.4115 0.5860 -0.6980
+vn 0.3188 0.7439 0.5872
+vn 0.3443 0.7071 0.6176
+vn 0.5740 0.8174 -0.0478
+vn 0.5846 0.8101 -0.0441
+vn 0.5126 0.7874 0.3422
+vn 0.4878 0.8095 0.3265
+vn 0.3878 0.6632 -0.6401
+vn 0.5404 0.7517 -0.3780
+vn 0.6359 0.7716 -0.0160
+vn 0.5855 0.6347 -0.5043
+vn 0.3090 0.6850 -0.6597
+vn 0.8221 0.5492 -0.1501
+vn 0.8868 0.2250 -0.4037
+vn 0.7142 0.3279 -0.6184
+vn -0.0360 0.1549 -0.9872
+vn 0.0003 0.1149 -0.9933
+vn 0.4610 0.3333 -0.8224
+vn 0.0914 0.2518 -0.9634
+vn -0.2069 0.3382 -0.9181
+vn 0.0006 0.3193 -0.9476
+vn 0.2899 0.5476 -0.7849
+vn -0.1165 0.4249 -0.8977
+vn -0.3315 0.3966 -0.8560
+vn 0.0005 0.4023 -0.9155
+vn 0.0374 0.6140 -0.7884
+vn -0.3061 0.4682 -0.8289
+vn -0.3375 0.4068 -0.8489
+vn -0.3328 0.3706 -0.8671
+vn 0.0027 0.3914 -0.9202
+vn 0.0033 0.4318 -0.9019
+vn -0.3330 0.4060 -0.8510
+vn -0.3170 0.3846 -0.8669
+vn -0.1143 0.4408 -0.8903
+vn -0.0972 0.4361 -0.8946
+vn -0.3764 0.4190 -0.8263
+vn 0.0024 0.4577 -0.8891
+vn -0.4048 0.4227 -0.8108
+vn -0.3542 0.4439 -0.8231
+vn -0.3871 0.4146 -0.8236
+vn 0.0028 0.4855 -0.8742
+vn -0.1590 0.5109 -0.8448
+vn -0.1673 0.4494 -0.8775
+vn 0.1023 0.5842 -0.8051
+vn 0.1390 0.5389 -0.8308
+vn 0.1746 0.5078 -0.8436
+vn 0.1820 0.4980 -0.8478
+vn 0.0002 -0.9609 0.2768
+vn 0.0384 -0.9514 0.3056
+vn 0.0774 -0.9317 0.3548
+vn 0.0820 -0.9211 0.3806
+vn 0.0826 0.9966 0.0069
+vn -0.0004 0.9938 -0.1114
+vn 0.3482 0.9025 0.2535
+vn 0.3241 0.8325 0.4493
+vn -0.0356 0.0069 0.9993
+vn -0.0001 -0.2038 0.9790
+vn 0.1049 -0.1682 0.9801
+vn 0.0651 -0.0324 0.9973
+vn -0.0440 0.0190 0.9988
+vn -0.0001 0.0779 0.9969
+vn 0.8638 -0.4530 0.2206
+vn 0.8901 -0.3815 0.2491
+vn 0.8909 -0.2893 0.3501
+vn 0.9586 -0.2387 0.1552
+vn 0.9630 0.0624 0.2621
+vn 0.8904 -0.4506 -0.0646
+vn 0.9232 -0.3580 0.1397
+vn 0.9494 0.3134 0.0179
+vn 0.9470 -0.2390 0.2148
+vn 0.9239 -0.2732 -0.2678
+vn 0.8668 -0.4187 0.2706
+vn 0.9751 -0.2151 -0.0533
+vn 0.9903 -0.1325 0.0421
+vn 0.7928 0.4661 -0.3926
+vn 0.9936 -0.1132 -0.0003
+vn 0.7425 0.2701 -0.6129
+vn 0.9850 -0.1650 -0.0515
+vn 0.6906 0.0520 -0.7214
+vn 0.2201 0.8912 0.3966
+vn -0.3141 0.2509 -0.9156
+vn -0.3352 0.5180 -0.7870
+vn -0.2610 0.8384 -0.4785
+vn -0.0594 0.9981 0.0172
+vn 0.9791 -0.1948 -0.0591
+vn 0.5885 -0.1664 -0.7911
+vn 0.9810 -0.1935 0.0129
+vn 0.5948 -0.3266 -0.7345
+vn 0.9660 -0.1584 0.2042
+vn 0.6543 -0.4228 -0.6270
+vn 0.9621 0.0010 0.2727
+vn 0.7318 -0.4447 -0.5164
+vn -0.4756 -0.3942 -0.7864
+vn -0.4958 -0.3291 -0.8036
+vn -0.4092 -0.2751 -0.8700
+vn -0.3319 -0.0656 -0.9410
+vn 0.9833 0.0629 0.1704
+vn 0.6975 -0.5161 -0.4971
+vn 0.5649 -0.7472 -0.3500
+vn 0.9426 -0.2803 0.1816
+vn -0.3965 -0.5141 -0.7606
+vn -0.0161 -0.6634 -0.7480
+vn 0.9752 0.2024 -0.0894
+vn 0.9228 0.3839 0.0322
+vn 0.9515 0.2336 0.2002
+vn 0.8798 0.3264 0.3454
+vn 0.7342 -0.3280 0.5944
+vn 0.6364 0.5125 0.5764
+vn 0.8796 -0.1671 0.4454
+vn 0.8158 -0.1409 0.5609
+vn 0.8726 0.0760 0.4825
+vn 0.9072 -0.1517 0.3924
+vn 0.9424 -0.2628 0.2069
+vn 0.9701 -0.2418 -0.0198
+vn 0.8577 -0.1611 0.4883
+vn 0.7598 -0.2012 0.6183
+vn 0.8122 -0.3142 0.4915
+vn 0.9293 -0.1915 0.3159
+vn 0.8831 -0.2182 0.4154
+vn 0.9926 -0.0184 0.1202
+vn 0.9953 -0.0960 0.0104
+vn 0.4295 0.8123 0.3944
+vn -0.0378 -0.9143 0.4032
+vn -0.7576 0.2227 0.6135
+vn -0.6259 0.4340 0.6479
+vn -0.7276 0.3501 0.5899
+vn -0.7667 0.2268 0.6006
+vn -0.2808 -0.7982 0.5328
+vn -0.5447 -0.6069 0.5788
+vn -0.3009 -0.3595 0.8833
+vn -0.2294 -0.3709 0.8999
+vn -0.2562 -0.7573 0.6007
+vn -0.4440 -0.2799 0.8512
+vn -0.3703 -0.6155 0.6957
+vn -0.6433 -0.2595 0.7202
+vn -0.4968 -0.4434 0.7460
+vn -0.7762 -0.2223 0.5900
+vn -0.6029 -0.1942 0.7738
+vn -0.8313 -0.1086 0.5451
+vn -0.4238 0.2262 0.8770
+vn -0.5754 0.2423 0.7811
+vn -0.7813 0.1209 0.6123
+vn -0.6026 0.1031 0.7914
+vn -0.3123 0.2925 0.9038
+vn -0.4446 0.1367 0.8852
+vn -0.4102 0.4376 0.8001
+vn -0.5571 0.3085 0.7710
+vn -0.6391 0.4162 0.6467
+vn -0.5991 0.3782 0.7056
+vn -0.7627 0.3644 0.5343
+vn -0.6281 0.4156 0.6578
+vn -0.7784 0.3213 0.5393
+vn -0.5921 0.4064 0.6959
+vn -0.5761 -0.0316 0.8167
+vn -0.5876 -0.1444 0.7961
+vn -0.6862 -0.1626 0.7089
+vn -0.6333 -0.0679 0.7709
+vn -0.7230 0.2553 0.6419
+vn -0.5759 0.0615 0.8152
+vn -0.8471 0.1152 0.5187
+vn -0.6992 -0.1080 0.7067
+vn -0.5145 -0.0621 0.8552
+vn -0.5533 -0.0246 0.8326
+vn -0.1113 0.0935 0.9893
+vn -0.2495 0.2148 0.9442
+vn -0.5246 0.2798 0.8040
+vn -0.7914 0.1979 0.5784
+vn -0.9181 0.0380 0.3945
+vn -0.2009 -0.1287 0.9711
+vn -0.1096 0.0485 0.9928
+vn -0.6452 0.0475 0.7625
+vn -0.7821 -0.0792 0.6181
+vn -0.6719 0.0252 0.7402
+vn -0.5797 0.0903 0.8098
+vn -0.4357 -0.0081 0.9000
+vn -0.4352 0.3398 0.8337
+vn -0.6922 -0.1092 0.7133
+vn -0.8258 -0.1750 0.5360
+vn -0.8386 -0.1669 0.5184
+vn -0.6926 -0.0408 0.7202
+vn -0.7721 -0.1559 0.6161
+vn -0.6697 -0.1072 0.7349
+vn -0.4397 -0.0924 0.8933
+vn -0.3182 0.2236 0.9212
+vn -0.7140 -0.4844 0.5054
+vn -0.4335 -0.5922 0.6792
+vn -0.8407 -0.4060 0.3581
+vn -0.4533 -0.8888 0.0670
+vn -0.4465 -0.8902 0.0908
+vn -0.5992 -0.8000 0.0306
+vn -0.5711 -0.8207 0.0134
+vn -0.2340 -0.9613 0.1451
+vn -0.2555 -0.9551 0.1501
+vn -0.6349 0.1084 0.7649
+vn -0.8309 0.0635 0.5527
+vn -0.7607 -0.1873 0.6215
+vn -0.6735 -0.1411 0.7256
+vn -0.4311 0.0622 0.9001
+vn -0.2803 0.8336 0.4758
+vn -0.4420 0.1303 0.8875
+vn -0.2239 -0.1650 0.9605
+vn -0.4573 -0.1100 0.8824
+vn -0.5394 0.0449 0.8408
+vn -0.4342 0.5429 0.7189
+vn -0.5744 -0.1513 0.8045
+vn -0.6238 -0.0356 0.7808
+vn -0.4010 -0.3059 0.8635
+vn -0.5114 0.6908 0.5111
+vn -0.6380 0.1183 0.7609
+vn -0.1267 -0.7389 0.6618
+vn -0.2820 -0.7669 0.5764
+vn -0.5599 -0.3430 0.7542
+vn -0.4447 -0.2965 0.8451
+vn -0.1833 -0.8026 0.5676
+vn -0.3489 -0.4081 0.8436
+vn -0.2763 -0.7842 0.5555
+vn -0.5560 -0.3713 0.7436
+vn -0.5987 -0.1036 0.7942
+vn -0.6160 -0.0434 0.7865
+vn -0.5998 -0.1215 0.7908
+vn -0.6375 -0.0953 0.7645
+vn -0.5628 0.5601 0.6079
+vn -0.6357 0.1074 0.7644
+vn -0.5751 0.0773 0.8144
+vn -0.6353 0.0852 0.7675
+vn -0.4077 0.2362 0.8820
+vn -0.3772 0.0945 0.9213
+vn -0.4221 0.0623 0.9044
+vn -0.6418 0.0403 0.7658
+vn -0.6374 -0.4831 0.6002
+vn -0.8033 -0.3002 0.5144
+vn -0.8241 -0.0822 0.5604
+vn -0.5837 -0.2004 0.7869
+vn -0.4278 -0.2356 0.8726
+vn -0.4436 -0.2859 0.8494
+vn -0.5491 0.0667 0.8331
+vn -0.7407 -0.3831 0.5518
+vn -0.6600 -0.0395 0.7502
+vn -0.5623 -0.0121 0.8268
+vn -0.3849 -0.1120 0.9161
+vn -0.9272 -0.3687 0.0660
+vn -0.9529 -0.2410 0.1841
+vn -0.9825 -0.0625 0.1751
+vn -0.9412 -0.3139 0.1247
+vn -0.6973 -0.7166 -0.0093
+vn -0.6857 -0.7272 0.0312
+vn -0.7763 -0.6298 -0.0259
+vn -0.7927 -0.6057 0.0688
+vn -0.8666 -0.4901 -0.0936
+vn -0.8968 -0.4424 -0.0073
+vn -0.8911 -0.3421 0.2980
+vn -0.5821 -0.0915 0.8079
+vn -0.8926 -0.2496 0.3754
+vn -0.8054 -0.2300 0.5463
+vn -0.8619 -0.2203 0.4567
+vn -0.7175 -0.2029 0.6664
+vn -0.9344 -0.0171 0.3559
+vn -0.8003 -0.0625 0.5964
+vn -0.9286 -0.0215 0.3704
+vn -0.9335 0.0249 0.3577
+vn -0.8825 -0.1645 0.4405
+vn -0.9063 -0.2065 0.3686
+vn -0.9579 -0.1181 0.2618
+vn -0.9657 -0.1322 0.2236
+vn -0.9125 -0.2247 0.3418
+vn -0.9670 -0.1332 0.2170
+vn -0.6157 -0.5504 0.5638
+vn -0.5809 -0.7841 0.2182
+vn -0.6524 -0.7273 0.2130
+vn -0.6828 -0.7227 -0.1070
+vn -0.2906 -0.9139 0.2834
+vn 0.0897 -0.8253 0.5575
+vn -0.0505 -0.1701 0.9841
+vn -0.4794 -0.8242 -0.3013
+vn -0.1189 -0.9566 -0.2659
+vn 0.1654 -0.9698 -0.1793
+vn -0.3571 -0.9297 -0.0894
+vn -0.6914 -0.7044 0.1605
+vn -0.9109 -0.4119 -0.0250
+vn -0.9349 0.0031 0.3550
+vn -0.6256 0.2243 0.7472
+vn -0.8431 -0.5220 -0.1293
+vn -0.8694 -0.4675 0.1600
+vn -0.7473 -0.3038 0.5910
+vn -0.1331 -0.7736 0.6195
+vn 0.4332 -0.8865 0.1625
+vn -0.6856 0.2907 0.6674
+vn -0.4248 0.5212 0.7402
+vn -0.1718 -0.6532 0.7374
+vn -0.4356 -0.4997 0.7486
+vn -0.1506 -0.6232 0.7674
+vn -0.3353 -0.4684 0.8173
+vn -0.4508 -0.3901 0.8029
+vn -0.4712 -0.2302 0.8514
+vn -0.3449 0.2480 0.9053
+vn -0.4907 0.2334 0.8395
+vn -0.2075 0.3292 0.9212
+vn -0.2059 0.4741 0.8560
+vn -0.5112 0.0741 0.8562
+vn -0.6939 -0.1185 0.7102
+vn -0.1951 0.8438 0.4999
+vn -0.0885 0.8677 0.4892
+vn -0.2856 0.7831 0.5524
+vn -0.6218 0.4335 0.6522
+vn -0.4152 -0.6372 0.6493
+vn -0.6769 -0.2214 0.7019
+vn -0.2639 -0.7885 0.5555
+vn -0.1015 -0.8883 0.4479
+vn -0.0316 -0.8718 0.4888
+vn 0.0266 -0.7700 0.6374
+vn 0.0582 -0.4640 0.8839
+vn 0.0081 0.7206 0.6932
+vn 0.0166 0.1924 0.9812
+vn 0.0016 0.8167 0.5770
+vn -0.4190 -0.9075 -0.0291
+vn -0.5872 -0.7755 0.2318
+vn -0.0971 -0.9887 -0.1138
+vn 0.2620 -0.9584 -0.1130
+vn 0.5482 -0.8304 0.0992
+vn 0.6994 -0.4400 0.5632
+vn 0.3520 0.9144 -0.1998
+vn 0.5500 0.8339 0.0464
+vn 0.0668 0.9422 -0.3284
+vn -0.2325 0.9147 -0.3306
+vn -0.4192 0.9078 0.0064
+vn 0.7430 0.3601 0.5641
+vn -0.4480 -0.8005 0.3980
+vn -0.6027 -0.6745 0.4264
+vn -0.1610 -0.8795 0.4477
+vn 0.1231 -0.8754 0.4674
+vn 0.3726 -0.7715 0.5156
+vn 0.4044 -0.3821 0.8309
+vn 0.2980 0.8817 0.3658
+vn 0.4878 0.7878 0.3760
+vn 0.0038 0.9598 0.2806
+vn -0.3977 0.9028 0.1635
+vn -0.6171 0.7788 0.1122
+vn 0.4848 0.2959 0.8230
+vn -0.4516 -0.3506 0.8204
+vn -0.5798 -0.3049 0.7555
+vn 0.0682 0.2508 0.9656
+vn 0.0383 -0.3904 0.9198
+vn -0.1788 -0.3938 0.9016
+vn -0.4357 0.2477 0.8653
+vn -0.1355 0.2574 0.9567
+vn -0.6651 0.3258 0.6718
+vn -0.2333 0.3243 0.9167
+vn -0.4069 0.3753 0.8328
+vn -0.6210 0.3710 0.6904
+vn -0.8324 0.2431 0.4979
+vn -0.9360 0.0790 0.3430
+vn -0.1051 0.2871 0.9521
+vn -0.9695 0.0083 0.2450
+vn -0.9781 -0.0479 0.2024
+vn -0.9613 0.0141 0.2751
+vn -0.9819 -0.1034 0.1583
+vn -0.9851 -0.1146 0.1282
+vn -0.9919 -0.0842 0.0950
+vn -0.9874 -0.1581 -0.0065
+vn -0.9742 0.0472 0.2204
+vn -0.9300 -0.0407 0.3653
+vn -0.9152 -0.1782 0.3615
+vn -0.8013 -0.2928 0.5217
+vn -0.9819 -0.0320 0.1866
+vn -0.9319 0.0355 0.3608
+vn -0.6979 0.0680 0.7129
+vn -0.8314 -0.0290 0.5549
+vn 0.0406 0.7854 0.6176
+vn 0.1733 0.8108 0.5591
+vn 0.2330 0.7887 0.5688
+vn 0.1187 0.7190 0.6848
+vn -0.2815 0.5347 0.7967
+vn -0.1209 0.4666 0.8761
+vn -0.6158 -0.0837 0.7834
+vn -0.4135 -0.1163 0.9030
+vn -0.6478 -0.3359 0.6836
+vn -0.5490 -0.1726 0.8178
+vn -0.2286 0.0595 0.9717
+vn -0.7679 -0.5433 0.3392
+vn -0.7202 -0.3164 0.6174
+vn -0.6950 -0.6635 0.2768
+vn -0.7258 -0.4304 0.5366
+vn -0.3485 -0.8603 0.3721
+vn -0.3828 -0.6423 0.6640
+vn -0.5817 -0.7566 0.2985
+vn -0.6244 -0.5230 0.5802
+vn -0.3778 0.0647 0.9236
+vn -0.5367 0.1600 0.8284
+vn -0.3951 0.2198 0.8919
+vn -0.1236 0.2130 0.9692
+vn 0.1984 0.6807 0.7052
+vn 0.1141 0.4584 0.8814
+vn 0.2395 0.7730 0.5874
+vn -0.4141 -0.2423 0.8774
+vn -0.5713 -0.4290 0.6997
+vn -0.0623 0.8558 0.5135
+vn 0.0469 0.8608 0.5067
+vn -0.3302 0.6492 0.6851
+vn -0.9360 0.3086 0.1692
+vn -0.8394 0.2729 0.4700
+vn -0.9981 -0.0605 -0.0013
+vn -0.9763 0.0412 -0.2122
+vn -0.9928 -0.0180 -0.1181
+vn -0.9183 -0.0115 -0.3957
+vn -0.2816 -0.3268 0.9022
+vn -0.3581 -0.4982 0.7896
+vn -0.8511 0.0940 0.5164
+vn -0.7298 0.1426 0.6686
+vn -0.7349 0.2952 0.6105
+vn -0.7986 0.2608 0.5423
+vn 0.1492 0.1933 0.9697
+vn 0.2354 0.4377 0.8677
+vn 0.0467 0.1416 0.9888
+vn 0.1244 0.2579 0.9581
+vn 0.2796 0.4599 0.8427
+vn 0.0344 0.2994 0.9535
+vn -0.2831 0.2506 0.9257
+vn -0.5556 0.2141 0.8034
+vn -0.5726 0.3702 0.7314
+vn -0.9857 -0.0034 0.1686
+vn -0.9883 -0.0652 0.1375
+vn -0.9523 0.0604 0.2990
+vn -0.9779 0.0164 0.2083
+vn -0.9706 -0.2356 0.0478
+vn -0.9482 -0.1438 -0.2831
+vn -0.9536 -0.2590 -0.1536
+vn -0.9630 -0.2023 -0.1777
+vn -0.9860 -0.0949 0.1371
+vn -0.8612 0.2244 0.4560
+vn -0.1736 0.4817 0.8589
+vn -0.6938 0.3915 0.6045
+vn -0.5256 0.4593 0.7161
+vn -0.3620 0.4740 0.8026
+vn -0.8971 0.2673 0.3518
+vn -0.9738 0.0715 0.2159
+vn -0.7332 0.4739 0.4876
+vn -0.5746 0.5854 0.5720
+vn -0.4152 0.6537 0.6326
+vn -0.2206 0.6995 0.6796
+vn -0.9844 0.0777 0.1578
+vn -0.9867 0.1562 0.0455
+vn -0.7184 0.6361 0.2815
+vn -0.8713 0.2311 0.4328
+vn -0.9951 -0.0367 0.0910
+vn -0.9434 -0.2402 0.2287
+vn -0.8160 -0.5533 0.1673
+vn -0.9835 -0.0923 0.1558
+vn -0.9827 -0.0066 0.1852
+vn -0.8921 -0.0506 0.4490
+vn -0.8859 -0.2499 0.3907
+vn -0.9720 0.2281 -0.0559
+vn -0.1099 0.9904 -0.0840
+vn -0.9828 0.0746 0.1689
+vn -0.9908 0.0696 0.1156
+vn -0.9982 0.0089 0.0585
+vn -0.9917 0.0175 0.1272
+vn -0.9225 0.2767 0.2691
+vn -0.9427 0.2725 0.1926
+vn -0.7580 0.5308 0.3789
+vn -0.7789 0.5680 0.2658
+vn -0.5806 0.6887 0.4343
+vn -0.5733 0.7639 0.2962
+vn -0.4171 0.7831 0.4612
+vn -0.3999 0.8648 0.3036
+vn -0.2285 0.8452 0.4831
+vn -0.2135 0.9274 0.3070
+vn -0.9864 0.0155 0.1635
+vn -0.9926 -0.0165 0.1201
+vn -0.9622 -0.1663 0.2156
+vn -0.9070 -0.3356 0.2542
+vn -0.9137 -0.2647 0.3083
+vn -0.8639 -0.4888 0.1209
+vn -0.8137 -0.5675 0.1254
+vn -0.7233 -0.6749 0.1458
+vn -0.5529 -0.8056 0.2127
+vn -0.3053 -0.9042 0.2987
+vn -0.7539 -0.6388 -0.1535
+vn -0.7487 -0.5625 -0.3507
+vn -0.1063 0.8930 0.4373
+vn -0.1617 0.8660 0.4733
+vn -0.0775 0.9284 0.3633
+vn -0.0349 0.9185 0.3937
+vn -0.3673 0.6561 0.6592
+vn -0.2545 0.7494 0.6111
+vn -0.2130 0.7909 0.5737
+vn -0.2266 0.6973 0.6800
+vn -0.1990 0.7491 0.6318
+vn -0.1453 0.8597 0.4896
+vn -0.4367 0.5471 0.7141
+vn -0.4455 0.5990 0.6653
+vn 0.1419 -0.4497 -0.8818
+vn -0.8428 -0.3155 -0.4361
+vn -0.9874 -0.1232 -0.0991
+vn -0.2070 -0.5288 -0.8231
+vn 0.5967 0.5022 -0.6258
+vn -0.4561 0.5647 -0.6877
+vn -0.1131 0.2753 -0.9546
+vn 0.4833 0.2247 -0.8461
+vn 0.4110 -0.3905 -0.8238
+vn -0.5776 -0.4773 -0.6622
+vn 0.4122 -0.1464 -0.8992
+vn -0.0529 -0.1151 -0.9919
+vn -0.3002 -0.4301 -0.8514
+vn 0.4535 -0.3587 -0.8159
+vn 0.4860 0.7631 -0.4259
+vn -0.9001 0.3911 -0.1919
+vn -0.9918 0.0285 0.1247
+vn -0.7909 -0.3644 -0.4917
+vn -0.9976 0.0561 0.0413
+vn -0.9997 -0.0248 -0.0059
+vn -0.9604 0.2673 0.0779
+vn -0.8026 0.5873 0.1041
+vn -0.5779 0.8076 0.1174
+vn -0.3890 0.9136 0.1177
+vn -0.2010 0.9729 0.1140
+vn -0.1113 -0.1333 -0.9848
+vn -0.1800 -0.2740 -0.9447
+vn -0.2247 0.2254 -0.9480
+vn -0.2294 0.4626 -0.8564
+vn -0.9266 -0.1050 -0.3610
+vn -0.9517 -0.0045 -0.3069
+vn -0.8820 0.1174 -0.4563
+vn -0.8503 -0.0323 -0.5253
+vn -0.9702 0.1511 -0.1891
+vn -0.9714 0.2313 -0.0539
+vn -0.8317 0.5497 -0.0783
+vn -0.8631 0.4317 -0.2619
+vn -0.9973 -0.0431 -0.0591
+vn -0.9984 0.0273 -0.0489
+vn -0.9905 -0.0082 -0.1372
+vn -0.9921 -0.0300 -0.1218
+vn -0.8844 -0.0618 -0.4625
+vn -0.9726 -0.0815 -0.2177
+vn -0.9546 -0.1487 -0.2579
+vn -0.8536 -0.2029 -0.4798
+vn -0.9814 -0.0382 -0.1883
+vn -0.9643 -0.0117 -0.2645
+vn -0.8812 0.2624 -0.3932
+vn -0.9607 0.0629 -0.2703
+vn -0.2280 0.8871 -0.4014
+vn -0.2085 0.9707 -0.1195
+vn -0.6017 0.7930 -0.0956
+vn -0.3981 0.9109 -0.1085
+vn -0.4249 0.8261 -0.3701
+vn -0.6460 0.6899 -0.3267
+vn -0.6695 0.0681 -0.7397
+vn -0.6993 0.2840 -0.6559
+vn -0.4550 0.4081 -0.7915
+vn -0.4472 0.1622 -0.8795
+vn -0.4480 0.6412 -0.6230
+vn -0.6867 0.4964 -0.5310
+vn -0.2363 0.6986 -0.6753
+vn -0.8272 0.0580 -0.5589
+vn -0.8133 -0.0700 -0.5775
+vn -0.7139 -0.1443 -0.6852
+vn -0.7219 0.0827 -0.6870
+vn -0.8558 -0.2378 -0.4593
+vn -0.8857 -0.2047 -0.4166
+vn -0.7912 -0.1794 -0.5846
+vn -0.7453 -0.2657 -0.6115
+vn -0.9355 -0.2145 -0.2806
+vn -0.9340 -0.1875 -0.3040
+vn -0.9245 -0.1565 -0.3476
+vn -0.9838 -0.0924 -0.1538
+vn -0.9920 0.0407 -0.1194
+vn -0.8986 -0.0175 -0.4383
+vn -0.9126 -0.0684 -0.4030
+vn -0.9938 0.0238 -0.1083
+vn -0.7162 -0.2773 -0.6404
+vn -0.8310 -0.1960 -0.5205
+vn -0.2164 -0.1880 -0.9580
+vn -0.2238 -0.0116 -0.9745
+vn -0.6084 -0.1230 -0.7840
+vn -0.4230 -0.0648 -0.9038
+vn -0.3898 -0.2101 -0.8966
+vn -0.5613 -0.2423 -0.7913
+vn -0.5422 0.0598 -0.8381
+vn -0.5500 -0.2034 -0.8100
+vn -0.3536 -0.2476 -0.9020
+vn -0.2663 -0.0316 -0.9633
+vn -0.3728 -0.2709 -0.8874
+vn -0.5468 -0.2907 -0.7851
+vn -0.2057 -0.2591 -0.9437
+vn 0.2621 0.7474 0.6105
+vn 0.2736 0.6673 0.6927
+vn 0.2569 0.6692 0.6972
+vn 0.2520 0.7212 0.6453
+vn -0.6020 0.6883 0.4046
+vn -0.4770 0.5701 0.6688
+vn -0.4076 0.6126 -0.6771
+vn -0.4115 0.5860 -0.6980
+vn -0.5414 0.7186 -0.4365
+vn -0.5396 0.7326 -0.4147
+vn -0.3188 0.7439 0.5872
+vn -0.3443 0.7071 0.6176
+vn -0.5740 0.8174 -0.0478
+vn -0.4878 0.8095 0.3265
+vn -0.5126 0.7874 0.3422
+vn -0.5846 0.8101 -0.0441
+vn -0.3878 0.6632 -0.6401
+vn -0.5404 0.7517 -0.3780
+vn -0.6359 0.7716 -0.0160
+vn -0.5855 0.6347 -0.5043
+vn -0.3090 0.6850 -0.6597
+vn -0.8221 0.5492 -0.1501
+vn -0.8868 0.2250 -0.4037
+vn -0.7142 0.3279 -0.6184
+vn 0.0362 0.1551 -0.9872
+vn -0.0914 0.2519 -0.9634
+vn -0.4610 0.3333 -0.8224
+vn 0.2075 0.3383 -0.9178
+vn 0.1165 0.4249 -0.8977
+vn -0.2899 0.5476 -0.7849
+vn 0.3323 0.3963 -0.8558
+vn 0.3061 0.4682 -0.8289
+vn -0.0374 0.6140 -0.7884
+vn 0.3404 0.4063 -0.8480
+vn 0.3359 0.3703 -0.8660
+vn 0.3330 0.4060 -0.8510
+vn 0.3170 0.3846 -0.8669
+vn 0.1143 0.4408 -0.8903
+vn 0.0972 0.4361 -0.8946
+vn 0.3783 0.4183 -0.8257
+vn 0.4048 0.4227 -0.8108
+vn 0.3870 0.4146 -0.8236
+vn 0.3569 0.4433 -0.8223
+vn 0.1590 0.5109 -0.8448
+vn 0.1673 0.4494 -0.8775
+vn -0.1023 0.5842 -0.8051
+vn -0.1746 0.5078 -0.8436
+vn -0.1390 0.5389 -0.8308
+vn -0.1820 0.4980 -0.8478
+vn -0.0383 -0.9514 0.3056
+vn -0.0774 -0.9317 0.3549
+vn -0.0820 -0.9210 0.3807
+vn -0.0828 0.9965 0.0068
+vn -0.3481 0.9026 0.2534
+vn -0.3241 0.8326 0.4491
+vn 0.0356 0.0068 0.9993
+vn -0.1052 -0.1686 0.9800
+vn -0.0653 -0.0327 0.9973
+vn 0.0440 0.0191 0.9988
+vn -0.8591 -0.4635 0.2170
+vn -0.9543 -0.2606 0.1462
+vn -0.8896 -0.2932 0.3502
+vn -0.8952 -0.3780 0.2360
+vn -0.9590 0.0819 0.2710
+vn -0.9445 0.3278 0.0207
+vn -0.9386 -0.3172 0.1358
+vn -0.9080 -0.4163 -0.0473
+vn -0.9430 -0.2246 0.2454
+vn -0.9404 -0.2538 -0.2262
+vn -0.8572 -0.4245 0.2914
+vn -0.9717 -0.2338 -0.0339
+vn -0.7827 0.4797 -0.3965
+vn -0.9940 -0.1072 0.0193
+vn -0.7390 0.2726 -0.6161
+vn -0.9946 -0.1015 -0.0223
+vn -0.6915 0.0512 -0.7205
+vn -0.9845 -0.1605 -0.0706
+vn -0.2169 0.8922 0.3960
+vn 0.3349 0.5178 -0.7872
+vn 0.3130 0.2507 -0.9160
+vn 0.2616 0.8382 -0.4785
+vn 0.0611 0.9980 0.0168
+vn -0.5894 -0.1664 -0.7905
+vn -0.9776 -0.1956 -0.0776
+vn -0.5957 -0.3257 -0.7342
+vn -0.9797 -0.2000 -0.0104
+vn -0.6506 -0.4241 -0.6300
+vn -0.9680 -0.1726 0.1818
+vn -0.7290 -0.4457 -0.5195
+vn -0.9651 -0.0133 0.2614
+vn 0.4953 -0.3296 -0.8038
+vn 0.4760 -0.3949 -0.7857
+vn 0.4075 -0.2755 -0.8706
+vn 0.3300 -0.0660 -0.9416
+vn -0.6968 -0.5148 -0.4994
+vn -0.9844 0.0598 0.1653
+vn -0.5655 -0.7459 -0.3518
+vn -0.9438 -0.2784 0.1778
+vn 0.3953 -0.5165 -0.7596
+vn 0.0176 -0.6652 -0.7465
+vn -0.9749 0.2061 -0.0837
+vn -0.9253 0.3772 0.0386
+vn -0.8803 0.3233 0.3471
+vn -0.9504 0.2384 0.1997
+vn -0.7347 -0.3269 0.5944
+vn -0.6359 0.5136 0.5759
+vn -0.8123 -0.1348 0.5673
+vn -0.8770 -0.1678 0.4501
+vn -0.8743 0.0653 0.4809
+vn -0.9090 -0.1593 0.3851
+vn -0.9442 -0.2705 0.1879
+vn -0.9682 -0.2455 -0.0472
+vn -0.8538 -0.1513 0.4981
+vn -0.8040 -0.3254 0.4976
+vn -0.7456 -0.2026 0.6348
+vn -0.9333 -0.1788 0.3115
+vn -0.8843 -0.2327 0.4047
+vn -0.9953 0.0024 0.0963
+vn -0.9958 -0.0881 -0.0215
+vn -0.4295 0.8125 0.3942
+vn 0.0378 -0.9143 0.4032
+vn 0.7009 -0.2227 -0.6775
+vn 0.7507 -0.1354 -0.6466
+vn 0.0158 0.0911 -0.9957
+vn -0.0139 -0.1133 -0.9934
+vn -0.7542 0.1018 -0.6487
+vn -0.7330 -0.0163 -0.6800
+vn -0.9999 -0.0004 0.0144
+vn -1.0000 -0.0049 0.0031
+vn -0.7617 -0.1222 0.6362
+vn -0.7435 -0.0915 0.6624
+vn -0.0387 -0.2729 0.9612
+vn -0.0289 -0.2206 0.9749
+vn 0.6930 -0.3455 0.6327
+vn 0.6909 -0.2953 0.6599
+vn 0.9523 -0.3048 0.0131
+vn 0.9585 -0.2850 0.0026
+vn -0.0241 -0.1111 -0.9935
+vn -0.1103 -0.2661 -0.9576
+vn 0.0000 -0.4858 -0.8740
+vn 0.7055 -0.2544 -0.6614
+vn -0.7425 -0.0121 -0.6697
+vn -0.7738 -0.0472 -0.6316
+vn -1.0000 0.0053 0.0044
+vn -0.9987 0.0507 0.0060
+vn -0.7434 -0.0461 0.6672
+vn -0.7721 -0.0116 0.6354
+vn -0.0388 -0.1682 0.9850
+vn -0.1471 -0.2321 0.9615
+vn 0.6964 -0.2921 0.6555
+vn 0.0000 -0.4816 0.8764
+vn 0.9490 -0.3152 0.0058
+vn 0.0000 -0.9998 0.0206
+vn 0.7694 0.1193 -0.6275
+vn 0.0522 0.4025 -0.9139
+vn 0.7053 0.2607 -0.6592
+vn -0.0031 0.5076 -0.8616
+vn -0.6920 0.4010 -0.6003
+vn -0.6443 0.5223 -0.5585
+vn -0.9798 0.1981 0.0274
+vn -0.9314 0.3637 -0.0124
+vn -0.7489 -0.0432 0.6612
+vn -0.7943 0.0840 0.6016
+vn -0.0193 -0.2656 0.9639
+vn -0.0644 -0.2408 0.9684
+vn 0.7075 -0.3245 0.6278
+vn 0.7505 -0.2868 0.5954
+vn 0.9817 -0.1902 0.0023
+vn 0.9959 -0.0618 -0.0661
+vn -0.7490 0.0587 -0.6599
+vn -0.1558 -0.1548 -0.9756
+vn -0.9841 0.1770 -0.0132
+vn -0.7669 0.0595 0.6390
+vn -0.2355 -0.1804 0.9550
+vn -0.7317 0.2497 -0.6342
+vn -0.1797 0.2153 -0.9598
+vn -0.9853 0.1702 -0.0129
+vn -0.7740 0.0499 0.6312
+vn -0.2623 -0.0431 0.9640
+vn -0.7886 0.2376 -0.5671
+vn -0.2038 0.3414 -0.9175
+vn -0.9967 0.0685 0.0432
+vn -0.7622 -0.0278 0.6467
+vn -0.2533 -0.0563 0.9657
+vn 0.0000 -0.0675 0.9977
+vn 0.0000 -0.0549 0.9985
+vn 0.0000 -0.3066 0.9518
+vn 0.0000 -0.2510 -0.9680
+vn 0.0000 0.1825 -0.9832
+vn 0.0000 0.3395 -0.9406
+vn -0.0137 -0.1017 -0.9947
+vn 0.7148 -0.2085 -0.6674
+vn -0.7429 0.0031 -0.6694
+vn -0.9997 0.0232 -0.0000
+vn -0.7467 -0.0530 0.6630
+vn -0.0230 -0.1830 0.9828
+vn 0.7042 -0.2631 0.6594
+vn 0.9651 -0.2619 -0.0003
+vn -0.0158 0.0911 -0.9957
+vn -0.7507 -0.1354 -0.6466
+vn -0.7009 -0.2227 -0.6775
+vn 0.0139 -0.1133 -0.9934
+vn 0.7542 0.1018 -0.6487
+vn 0.7330 -0.0163 -0.6800
+vn 0.9999 -0.0004 0.0144
+vn 1.0000 -0.0049 0.0031
+vn 0.7617 -0.1222 0.6362
+vn 0.7435 -0.0915 0.6624
+vn 0.0387 -0.2729 0.9612
+vn 0.0289 -0.2206 0.9749
+vn -0.6930 -0.3455 0.6327
+vn -0.6909 -0.2953 0.6599
+vn -0.9523 -0.3048 0.0131
+vn -0.9585 -0.2850 0.0026
+vn 0.0241 -0.1111 -0.9935
+vn -0.7055 -0.2544 -0.6614
+vn 0.1103 -0.2661 -0.9576
+vn 0.7425 -0.0121 -0.6697
+vn 0.7738 -0.0472 -0.6316
+vn 1.0000 0.0053 0.0044
+vn 0.9987 0.0507 0.0060
+vn 0.7434 -0.0461 0.6672
+vn 0.7721 -0.0116 0.6354
+vn 0.0388 -0.1682 0.9850
+vn 0.1471 -0.2321 0.9615
+vn -0.6964 -0.2921 0.6555
+vn -0.9490 -0.3152 0.0058
+vn -0.7694 0.1193 -0.6275
+vn -0.0522 0.4025 -0.9139
+vn 0.0031 0.5076 -0.8616
+vn -0.7053 0.2607 -0.6592
+vn 0.6920 0.4010 -0.6003
+vn 0.6443 0.5223 -0.5585
+vn 0.9798 0.1981 0.0274
+vn 0.9314 0.3637 -0.0124
+vn 0.7489 -0.0432 0.6612
+vn 0.7943 0.0840 0.6016
+vn 0.0193 -0.2656 0.9639
+vn 0.0644 -0.2408 0.9684
+vn -0.7075 -0.3245 0.6278
+vn -0.7505 -0.2868 0.5954
+vn -0.9817 -0.1902 0.0023
+vn -0.9959 -0.0618 -0.0661
+vn 0.1558 -0.1548 -0.9756
+vn 0.7490 0.0587 -0.6599
+vn 0.9841 0.1770 -0.0132
+vn 0.7669 0.0595 0.6390
+vn 0.2355 -0.1804 0.9550
+vn 0.1797 0.2153 -0.9598
+vn 0.7317 0.2497 -0.6342
+vn 0.9853 0.1702 -0.0129
+vn 0.7740 0.0499 0.6312
+vn 0.2623 -0.0431 0.9640
+vn 0.2038 0.3414 -0.9175
+vn 0.7886 0.2376 -0.5671
+vn 0.9967 0.0685 0.0432
+vn 0.7622 -0.0278 0.6467
+vn 0.2533 -0.0563 0.9657
+vn -0.7148 -0.2085 -0.6674
+vn 0.0137 -0.1017 -0.9947
+vn 0.7429 0.0031 -0.6694
+vn 0.9997 0.0232 -0.0000
+vn 0.7467 -0.0530 0.6630
+vn 0.0230 -0.1830 0.9828
+vn -0.7042 -0.2631 0.6594
+vn -0.9651 -0.2619 -0.0003
+vn -0.9305 0.3442 0.1249
+vn -0.7269 0.2687 0.6320
+vn -0.6836 0.2431 0.6882
+vn -0.9388 0.3246 0.1150
+vn -0.8229 0.4189 -0.3837
+vn -0.8218 0.3643 -0.4380
+vn -0.4623 0.3872 -0.7977
+vn -0.4250 0.3146 -0.8487
+vn -0.3871 0.1594 0.9081
+vn -0.4411 0.2060 0.8734
+vn -0.1795 0.2589 -0.9490
+vn -0.1585 0.2797 -0.9469
+vn -0.6629 0.1725 0.7285
+vn -0.9602 0.2648 0.0883
+vn -0.8278 0.2795 -0.4864
+vn -0.4296 0.2507 -0.8675
+vn -0.3178 0.0812 0.9447
+vn 0.0000 0.2257 -0.9742
+vn -0.6545 0.1083 0.7482
+vn -0.9778 0.1840 0.1006
+vn -0.8214 0.2268 -0.5233
+vn -0.3881 0.2433 -0.8889
+vn -0.2732 0.0443 0.9609
+vn 0.0000 0.2517 -0.9678
+vn -0.6199 0.0893 0.7796
+vn -0.9856 0.1431 0.0903
+vn -0.8148 0.1839 -0.5498
+vn -0.3740 0.2535 -0.8921
+vn 0.0000 0.3010 -0.9536
+vn -0.2541 0.0410 0.9663
+vn -0.6076 0.0420 0.7931
+vn -0.5980 -0.0347 0.8007
+vn -0.9375 -0.2623 0.2285
+vn -0.9684 -0.1241 0.2161
+vn -0.7920 -0.4096 -0.4527
+vn -0.8297 -0.3137 -0.4616
+vn -0.2858 -0.3760 -0.8814
+vn -0.2590 -0.2981 -0.9187
+vn -0.2287 0.0641 0.9714
+vn -0.2261 0.0876 0.9701
+vn 0.0000 -0.2554 -0.9668
+vn 0.0000 -0.3327 -0.9430
+vn -0.5301 -0.0882 0.8433
+vn -0.8493 -0.4104 0.3321
+vn -0.7116 -0.6099 -0.3486
+vn -0.2332 -0.4742 -0.8489
+vn -0.2270 0.0645 0.9717
+vn 0.0000 -0.3504 -0.9366
+vn -0.5909 0.2845 0.7549
+vn -0.7041 0.6731 0.2262
+vn -0.6750 0.7067 0.2120
+vn -0.5221 0.3539 0.7760
+vn -0.4721 -0.3063 0.8266
+vn -0.1414 -0.2192 0.9654
+vn -0.4331 -0.7302 0.5285
+vn 0.2356 -0.7827 0.5761
+vn -0.3519 -0.9301 -0.1050
+vn 0.3481 -0.9354 -0.0623
+vn -0.2890 -0.5904 -0.7536
+vn 0.1628 -0.5295 -0.8325
+vn -0.4027 0.2159 -0.8895
+vn -0.2563 0.2367 -0.9371
+vn -0.6033 0.6231 -0.4978
+vn -0.5584 0.6612 -0.5009
+vn -0.2101 0.1086 0.9716
+vn -0.4954 -0.0439 0.8675
+vn -0.6827 -0.2557 0.6844
+vn -0.5014 -0.5441 -0.6727
+vn -0.1398 -0.2956 -0.9450
+vn 0.0000 -0.1463 -0.9892
+vn -0.5453 0.8124 0.2065
+vn -0.4171 0.4386 0.7960
+vn -0.1028 -0.1814 0.9780
+vn 0.3036 -0.7578 0.5774
+vn 0.4383 -0.8970 -0.0575
+vn 0.1599 -0.5565 -0.8153
+vn -0.2808 0.2088 -0.9368
+vn -0.4873 0.6958 -0.5276
+vn -0.6286 0.1609 0.7609
+vn -0.3999 0.0846 -0.9127
+vn -0.1346 0.1483 -0.9797
+vn 0.0000 0.1400 -0.9901
+vn -0.1455 0.3738 0.9160
+vn -0.3840 0.3333 0.8610
+vn -0.5499 0.7781 0.3034
+vn -0.4931 0.7170 -0.4927
+vn -0.0883 0.6438 0.7600
+vn -0.3134 0.6461 0.6959
+vn -0.1995 0.4476 -0.8717
+vn 0.0000 0.3229 -0.9464
+vn 0.8813 0.4724 -0.0088
+vn 0.7941 0.4290 0.4305
+vn -0.0864 0.9856 0.1451
+vn 0.0280 0.9633 0.2670
+vn 0.8173 0.5099 -0.2683
+vn 0.8346 0.5002 -0.2308
+vn 0.1703 0.9413 0.2913
+vn 0.3046 0.8919 0.3341
+vn 0.4281 0.3246 0.8434
+vn 0.0000 0.2474 0.9689
+vn 0.0000 0.9969 0.0780
+vn -0.0873 0.9961 0.0095
+vn -0.7519 0.6446 -0.1379
+vn -0.7108 0.6391 0.2936
+vn -0.4981 0.6461 0.5783
+vn -0.3810 0.6395 0.6677
+vn 0.0000 0.5987 -0.8009
+vn -0.4424 0.6083 -0.6590
+vn -0.3468 0.9035 0.2518
+vn -0.3959 0.8547 -0.3358
+vn -0.3311 0.9086 0.2546
+vn -0.4184 0.8819 -0.2170
+vn -0.1143 0.6544 0.7474
+vn -0.2011 0.7588 0.6194
+vn -0.0993 0.7308 0.6753
+vn -0.1946 0.8158 0.5446
+vn -0.2835 0.6131 -0.7374
+vn 0.0000 0.4652 -0.8852
+vn -0.2913 0.6623 -0.6902
+vn 0.0000 0.5503 -0.8350
+vn -0.5202 0.8349 0.1797
+vn -0.2936 0.5365 0.7912
+vn 0.0479 -0.0916 0.9946
+vn 0.4032 -0.7122 0.5746
+vn 0.4545 -0.8882 -0.0677
+vn 0.1287 -0.5681 -0.8128
+vn -0.3250 0.1772 -0.9290
+vn -0.5206 0.6599 -0.5417
+vn -0.5974 0.7709 0.2210
+vn -0.2542 0.5503 0.7953
+vn 0.1685 -0.0062 0.9857
+vn 0.4398 -0.6721 0.5956
+vn 0.3967 -0.9172 -0.0357
+vn 0.0496 -0.6219 -0.7815
+vn -0.4032 0.1236 -0.9067
+vn -0.6385 0.5749 -0.5116
+vn -0.5685 0.7945 0.2133
+vn -0.2400 0.5868 0.7733
+vn 0.2135 -0.0171 0.9768
+vn 0.4756 -0.6876 0.5486
+vn 0.4152 -0.9088 -0.0402
+vn 0.0716 -0.6156 -0.7848
+vn -0.3941 0.1769 -0.9019
+vn -0.6174 0.6261 -0.4762
+vn -0.4967 0.8361 0.2327
+vn -0.1930 0.6250 0.7564
+vn 0.2468 0.0142 0.9689
+vn 0.5123 -0.6868 0.5157
+vn 0.4545 -0.8877 -0.0728
+vn 0.1032 -0.5467 -0.8309
+vn -0.3741 0.2477 -0.8937
+vn -0.5754 0.6948 -0.4315
+vn -0.6893 0.6571 0.3049
+vn -0.3672 0.4369 0.8211
+vn -0.3961 0.3886 0.8319
+vn -0.7006 0.6366 0.3222
+vn 0.0527 -0.1498 0.9873
+vn -0.0166 -0.2036 0.9789
+vn 0.3432 -0.7831 0.5185
+vn 0.2679 -0.8050 0.5293
+vn 0.3268 -0.9419 -0.0771
+vn 0.2604 -0.9629 -0.0707
+vn -0.0390 -0.6161 -0.7867
+vn -0.1134 -0.6437 -0.7568
+vn -0.5172 0.1429 -0.8438
+vn -0.5643 0.1326 -0.8148
+vn -0.7468 0.5476 -0.3773
+vn -0.7632 0.5405 -0.3542
+vn -0.4188 0.3402 0.8419
+vn -0.7050 0.6152 0.3528
+vn -0.0831 -0.2227 0.9713
+vn 0.1923 -0.7967 0.5729
+vn 0.2002 -0.9780 -0.0580
+vn -0.1858 -0.6495 -0.7373
+vn -0.6026 0.1249 -0.7882
+vn -0.7770 0.5413 -0.3211
+vn 0.9305 0.3442 0.1249
+vn 0.9388 0.3246 0.1150
+vn 0.6836 0.2431 0.6882
+vn 0.7269 0.2687 0.6320
+vn 0.8229 0.4189 -0.3837
+vn 0.8218 0.3643 -0.4380
+vn 0.4623 0.3872 -0.7977
+vn 0.4250 0.3146 -0.8487
+vn 0.3871 0.1594 0.9081
+vn 0.4411 0.2060 0.8734
+vn 0.1585 0.2797 -0.9469
+vn 0.1795 0.2589 -0.9490
+vn 0.9602 0.2648 0.0883
+vn 0.6629 0.1725 0.7285
+vn 0.8278 0.2795 -0.4864
+vn 0.4296 0.2507 -0.8675
+vn 0.3178 0.0812 0.9447
+vn 0.9778 0.1840 0.1006
+vn 0.6545 0.1083 0.7482
+vn 0.8214 0.2268 -0.5233
+vn 0.3881 0.2433 -0.8889
+vn 0.2732 0.0443 0.9609
+vn 0.9856 0.1431 0.0903
+vn 0.6199 0.0893 0.7796
+vn 0.8148 0.1839 -0.5498
+vn 0.3740 0.2535 -0.8921
+vn 0.2541 0.0410 0.9663
+vn 0.6076 0.0420 0.7931
+vn 0.9684 -0.1241 0.2161
+vn 0.9375 -0.2623 0.2285
+vn 0.5980 -0.0347 0.8007
+vn 0.8297 -0.3137 -0.4616
+vn 0.7920 -0.4096 -0.4527
+vn 0.2590 -0.2981 -0.9187
+vn 0.2858 -0.3760 -0.8814
+vn 0.2287 0.0641 0.9714
+vn 0.2261 0.0876 0.9701
+vn 0.8493 -0.4104 0.3321
+vn 0.5301 -0.0882 0.8433
+vn 0.7116 -0.6099 -0.3486
+vn 0.2332 -0.4742 -0.8489
+vn 0.2270 0.0645 0.9717
+vn 0.5909 0.2845 0.7549
+vn 0.5221 0.3539 0.7760
+vn 0.6750 0.7067 0.2120
+vn 0.7041 0.6731 0.2262
+vn 0.4721 -0.3063 0.8266
+vn 0.1414 -0.2192 0.9654
+vn 0.4331 -0.7302 0.5285
+vn -0.2356 -0.7827 0.5761
+vn 0.3519 -0.9301 -0.1050
+vn -0.3481 -0.9354 -0.0623
+vn 0.2890 -0.5904 -0.7536
+vn -0.1628 -0.5295 -0.8325
+vn 0.4027 0.2159 -0.8895
+vn 0.2563 0.2367 -0.9371
+vn 0.6033 0.6231 -0.4978
+vn 0.5584 0.6612 -0.5009
+vn 0.2101 0.1086 0.9716
+vn 0.4954 -0.0439 0.8675
+vn 0.6827 -0.2557 0.6844
+vn 0.5014 -0.5441 -0.6727
+vn 0.1398 -0.2956 -0.9450
+vn 0.4171 0.4386 0.7960
+vn 0.5453 0.8124 0.2065
+vn 0.1028 -0.1814 0.9780
+vn -0.3036 -0.7578 0.5774
+vn -0.4383 -0.8970 -0.0575
+vn -0.1599 -0.5565 -0.8153
+vn 0.2808 0.2088 -0.9368
+vn 0.4873 0.6958 -0.5276
+vn 0.6286 0.1609 0.7609
+vn 0.3999 0.0846 -0.9127
+vn 0.1346 0.1483 -0.9797
+vn 0.1455 0.3738 0.9160
+vn 0.3840 0.3333 0.8610
+vn 0.4931 0.7170 -0.4927
+vn 0.5499 0.7781 0.3034
+vn 0.0883 0.6438 0.7600
+vn 0.3134 0.6461 0.6959
+vn 0.1995 0.4476 -0.8717
+vn -0.8813 0.4724 -0.0088
+vn -0.0280 0.9633 0.2670
+vn 0.0864 0.9856 0.1451
+vn -0.7941 0.4290 0.4305
+vn -0.8173 0.5099 -0.2683
+vn -0.3046 0.8919 0.3341
+vn -0.1703 0.9413 0.2913
+vn -0.8346 0.5002 -0.2308
+vn -0.4281 0.3246 0.8434
+vn 0.0873 0.9961 0.0095
+vn 0.7108 0.6391 0.2936
+vn 0.7519 0.6446 -0.1379
+vn 0.3810 0.6395 0.6677
+vn 0.4981 0.6461 0.5783
+vn 0.4424 0.6083 -0.6590
+vn 0.3959 0.8547 -0.3358
+vn 0.3468 0.9035 0.2518
+vn 0.4184 0.8819 -0.2170
+vn 0.3311 0.9086 0.2546
+vn 0.1143 0.6544 0.7474
+vn 0.2011 0.7588 0.6194
+vn 0.1946 0.8158 0.5446
+vn 0.0993 0.7308 0.6753
+vn 0.2835 0.6131 -0.7374
+vn 0.2913 0.6623 -0.6902
+vn 0.2936 0.5365 0.7912
+vn 0.5202 0.8349 0.1797
+vn -0.0479 -0.0916 0.9946
+vn -0.4032 -0.7122 0.5746
+vn -0.4545 -0.8882 -0.0677
+vn -0.1287 -0.5681 -0.8128
+vn 0.3250 0.1772 -0.9290
+vn 0.5206 0.6599 -0.5417
+vn 0.2542 0.5503 0.7953
+vn 0.5974 0.7709 0.2210
+vn -0.1685 -0.0062 0.9857
+vn -0.4398 -0.6721 0.5956
+vn -0.3967 -0.9172 -0.0357
+vn -0.0496 -0.6219 -0.7815
+vn 0.4032 0.1236 -0.9067
+vn 0.6385 0.5749 -0.5116
+vn 0.2400 0.5868 0.7733
+vn 0.5685 0.7945 0.2133
+vn -0.2135 -0.0171 0.9768
+vn -0.4756 -0.6876 0.5486
+vn -0.4152 -0.9088 -0.0402
+vn -0.0716 -0.6156 -0.7848
+vn 0.3941 0.1769 -0.9019
+vn 0.6174 0.6261 -0.4762
+vn 0.1930 0.6250 0.7564
+vn 0.4967 0.8361 0.2327
+vn -0.2468 0.0142 0.9689
+vn -0.5123 -0.6868 0.5157
+vn -0.4545 -0.8877 -0.0728
+vn -0.1032 -0.5467 -0.8309
+vn 0.3741 0.2477 -0.8937
+vn 0.5754 0.6948 -0.4315
+vn 0.6893 0.6571 0.3049
+vn 0.7006 0.6366 0.3222
+vn 0.3961 0.3886 0.8319
+vn 0.3672 0.4369 0.8211
+vn 0.0166 -0.2036 0.9789
+vn -0.0527 -0.1498 0.9873
+vn -0.2679 -0.8050 0.5293
+vn -0.3432 -0.7831 0.5185
+vn -0.2604 -0.9629 -0.0707
+vn -0.3268 -0.9419 -0.0771
+vn 0.1134 -0.6437 -0.7568
+vn 0.0390 -0.6161 -0.7867
+vn 0.5643 0.1326 -0.8148
+vn 0.5172 0.1429 -0.8438
+vn 0.7632 0.5405 -0.3542
+vn 0.7468 0.5476 -0.3773
+vn 0.7050 0.6152 0.3528
+vn 0.4188 0.3402 0.8419
+vn 0.0831 -0.2227 0.9713
+vn -0.1923 -0.7967 0.5729
+vn -0.2002 -0.9780 -0.0580
+vn 0.1858 -0.6495 -0.7373
+vn 0.6026 0.1249 -0.7882
+vn 0.7770 0.5413 -0.3211
+usemtl Cornea
+s 1
+f 268/1/1 269/2/2 270/3/3 267/4/4
+f 267/4/4 270/3/3 271/5/5 266/6/6
+f 266/6/6 271/5/5 272/7/7 265/8/8
+f 271/5/5 274/9/9 273/10/10 272/7/7
+f 270/3/3 275/11/11 274/9/9 271/5/5
+f 269/2/2 276/12/12 275/11/11 270/3/3
+f 276/12/12 277/13/13 278/14/14 275/11/11
+f 275/11/11 278/14/14 279/15/15 274/9/9
+f 274/9/9 279/15/15 280/16/16 273/10/10
+f 279/15/15 282/17/17 281/18/18 280/16/16
+f 278/14/14 283/19/19 282/17/17 279/15/15
+f 277/13/13 284/20/20 283/19/19 278/14/14
+f 284/20/20 285/21/21 286/22/22 283/19/19
+f 283/19/19 286/22/22 287/23/23 282/17/17
+f 282/17/17 287/23/23 288/24/24 281/18/18
+f 287/23/23 290/25/25 289/26/26 288/24/24
+f 286/22/22 291/27/27 290/25/25 287/23/23
+f 285/21/21 292/28/28 291/27/27 286/22/22
+f 292/28/28 293/29/29 294/30/30 291/27/27
+f 291/27/27 294/30/30 295/31/31 290/25/25
+f 290/25/25 295/31/31 296/32/32 289/26/26
+f 295/31/31 266/6/6 265/8/8 296/32/32
+f 294/30/30 267/4/4 266/6/6 295/31/31
+f 293/29/29 268/1/1 267/4/4 294/30/30
+f 300/33/7 326/34/8 327/35/6 299/36/5
+f 299/36/5 327/35/6 328/37/4 298/38/3
+f 298/38/3 328/37/4 329/39/1 297/40/2
+f 303/41/11 298/38/3 297/40/2 304/42/12
+f 302/43/33 299/36/5 298/38/3 303/41/11
+f 301/44/10 300/33/7 299/36/5 302/43/33
+f 308/45/16 301/44/10 302/43/33 307/46/15
+f 307/46/15 302/43/33 303/41/11 306/47/14
+f 306/47/14 303/41/11 304/42/12 305/48/13
+f 312/49/19 306/47/14 305/48/13 313/50/20
+f 311/51/17 307/46/15 306/47/14 312/49/19
+f 310/52/18 308/45/16 307/46/15 311/51/17
+f 317/53/24 310/52/18 311/51/17 316/54/23
+f 316/54/23 311/51/17 312/49/19 315/55/22
+f 315/55/22 312/49/19 313/50/20 314/56/21
+f 320/57/27 315/55/22 314/56/21 321/58/28
+f 319/59/25 316/54/23 315/55/22 320/57/27
+f 318/60/26 317/53/24 316/54/23 319/59/25
+f 325/61/32 318/60/26 319/59/25 324/62/31
+f 324/62/31 319/59/25 320/57/27 323/63/30
+f 323/63/30 320/57/27 321/58/28 322/64/29
+f 328/37/4 323/63/30 322/64/29 329/39/1
+f 327/35/6 324/62/31 323/63/30 328/37/4
+f 326/34/8 325/61/32 324/62/31 327/35/6
+usemtl Iris
+f 272/7/7 264/65/34 265/8/8
+f 273/10/10 264/65/34 272/7/7
+f 280/16/16 264/65/34 273/10/10
+f 281/18/18 264/65/34 280/16/16
+f 288/24/24 264/65/34 281/18/18
+f 289/26/26 264/65/34 288/24/24
+f 296/32/32 264/65/34 289/26/26
+f 265/8/8 264/65/34 296/32/32
+f 309/66/34 326/34/8 300/33/7
+f 309/66/34 300/33/7 301/44/10
+f 309/66/34 301/44/10 308/45/16
+f 309/66/34 308/45/16 310/52/18
+f 309/66/34 310/52/18 317/53/24
+f 309/66/34 317/53/24 318/60/26
+f 309/66/34 318/60/26 325/61/32
+f 309/66/34 325/61/32 326/34/8
+usemtl Leather
+f 17/67/35 22/68/36 24/69/37 20/70/38
+f 22/68/36 18/71/39 21/72/40 24/69/37
+f 23/73/41 16/74/42 25/75/43 26/76/44
+f 19/77/45 23/73/41 26/76/44 27/78/46
+f 16/74/42 28/79/47 30/80/48 25/75/43
+f 28/79/47 32/81/49 31/82/50 30/80/48
+f 31/82/50 32/81/49 34/83/51 33/84/52
+f 33/85/52 34/86/51 36/87/53 35/88/54
+f 35/88/54 36/87/53 38/89/55 37/90/56
+f 19/77/45 27/78/46 37/90/56 38/89/55
+f 17/67/35 20/70/38 40/91/57 29/92/58
+f 18/71/39 39/93/59 41/94/60 21/72/40
+f 21/72/40 41/94/60 42/95/61 24/69/37
+f 20/70/38 24/69/37 42/95/61 40/91/57
+f 32/81/49 28/79/47 2661/96/62 2662/97/63
+f 34/83/51 32/81/49 2662/97/63 2663/98/64
+f 36/87/53 34/86/51 2663/99/64 2664/100/65
+f 38/89/55 36/87/53 2664/100/65 2665/101/66
+f 29/92/58 40/91/57 2667/102/67 2666/103/68
+f 41/94/60 39/93/59 2668/104/69 2669/105/70
+f 42/95/61 41/94/60 2669/105/70 2670/106/71
+f 40/91/57 42/95/61 2670/106/71 2667/102/67
+f 45/107/72 43/108/73 2671/109/74 2672/110/75
+f 46/111/76 45/107/72 2672/110/75 2673/112/76
+f 47/113/77 46/114/76 2673/115/76 2674/116/78
+f 48/117/79 47/113/77 2674/116/78 2675/118/80
+f 44/119/81 50/120/76 2677/121/76 2676/122/82
+f 51/123/76 49/124/83 2678/125/84 2679/126/76
+f 52/127/76 51/123/76 2679/126/76 2680/128/76
+f 50/120/76 52/129/76 2680/130/76 2677/121/76
+f 55/131/85 53/132/86 2681/133/87 2684/134/88
+f 56/135/89 55/131/85 2684/134/88 2685/136/89
+f 57/137/90 56/138/89 2685/139/89 2686/140/91
+f 58/141/92 57/137/90 2686/140/91 2687/142/93
+f 54/143/94 60/144/95 2691/145/96 2690/146/97
+f 61/147/98 59/148/99 2692/149/100 2693/150/101
+f 62/151/102 61/147/98 2693/150/101 2694/152/102
+f 60/144/95 62/153/102 2694/152/102 2691/145/96
+f 65/154/103 2682/155/104 2695/156/104 2697/157/105
+f 66/158/89 65/154/103 2697/157/105 2698/159/89
+f 67/160/106 66/161/89 2698/159/89 2699/162/107
+f 2688/163/108 67/160/106 2699/162/107 2700/164/108
+f 2696/165/109 2701/166/109 76/167/110 74/168/111
+f 74/168/111 76/167/110 75/169/112
+f 2683/170/113 2689/171/113 77/172/113 73/173/113
+f 63/174/114 70/175/115 71/176/116 69/177/117
+f 70/175/115 72/178/112 71/176/116
+f 78/179/118 16/74/42 23/73/41 80/180/119
+f 80/180/119 22/68/36 17/67/35 78/179/118
+f 19/77/45 79/181/120 80/180/119 23/73/41
+f 79/181/120 18/71/39 22/68/36 80/180/119
+f 16/74/42 78/179/118 81/182/121 28/79/47
+f 78/179/118 17/67/35 29/92/58 81/182/121
+f 18/71/39 79/181/120 82/183/122 39/93/59
+f 79/181/120 19/77/45 38/89/55 82/183/122
+f 28/79/47 81/182/121 2702/184/123 2661/96/62
+f 81/182/121 29/92/58 2666/103/68 2702/184/123
+f 39/93/59 82/183/122 2703/185/124 2668/104/69
+f 82/183/122 38/89/55 2665/101/66 2703/185/124
+f 43/108/73 83/186/125 2704/187/126 2671/109/74
+f 83/186/125 44/119/81 2676/122/82 2704/187/126
+f 49/124/83 84/188/127 2705/189/128 2678/125/84
+f 84/188/127 48/117/79 2675/118/80 2705/189/128
+f 53/132/86 85/190/129 2706/191/130 2681/133/87
+f 85/190/129 54/143/94 2690/146/97 2706/191/130
+f 59/148/99 86/192/131 2707/193/132 2692/149/100
+f 86/192/131 58/141/92 2687/142/93 2707/193/132
+f 69/177/117 88/194/133 87/195/134 63/174/114
+f 88/194/133 68/196/135 64/197/135 87/195/134
+f 26/76/44 25/75/43 89/198/136 90/199/137
+f 27/78/46 26/76/44 90/199/137 91/200/138
+f 25/75/43 30/80/48 92/201/139 89/198/136
+f 30/80/48 31/82/50 93/202/140 92/201/139
+f 31/82/50 33/84/52 94/203/141 93/202/140
+f 33/85/52 35/88/54 95/204/142 94/205/141
+f 35/88/54 37/90/56 96/206/143 95/204/142
+f 37/90/56 27/78/46 91/200/138 96/206/143
+f 90/199/137 89/198/136 98/207/144 97/208/145
+f 91/200/138 90/199/137 97/208/145 99/209/146
+f 89/198/136 92/201/139 100/210/147 98/207/144
+f 92/201/139 93/202/140 101/211/148 100/210/147
+f 93/202/140 94/203/141 102/212/149 101/211/148
+f 94/205/141 95/204/142 103/213/150 102/214/149
+f 95/204/142 96/206/143 104/215/151 103/213/150
+f 96/206/143 91/200/138 99/209/146 104/215/151
+f 97/208/145 98/207/144 106/216/152 105/217/153
+f 99/209/146 97/208/145 105/217/153 107/218/154
+f 98/207/144 100/210/147 108/219/155 106/216/152
+f 100/210/147 101/211/148 109/220/156 108/219/155
+f 101/211/148 102/212/149 110/221/157 109/220/156
+f 102/214/149 103/213/150 111/222/158 110/223/157
+f 103/213/150 104/215/151 112/224/159 111/222/158
+f 104/215/151 99/209/146 107/218/154 112/224/159
+f 154/225/160 116/226/161 117/227/162 151/228/163
+f 154/225/160 153/229/164 118/230/165 116/226/161
+f 153/229/164 2708/231/166 119/232/167 118/230/165
+f 2708/233/166 2709/234/168 120/235/169 119/236/167
+f 2709/234/168 152/237/170 121/238/171 120/235/169
+f 152/237/170 150/239/172 122/240/173 121/238/171
+f 151/228/163 117/227/162 123/241/174 2715/242/175
+f 150/239/172 2715/242/175 123/241/174 122/240/173
+f 116/226/161 124/243/176 125/244/177 117/227/162
+f 116/226/161 118/230/165 126/245/178 124/243/176
+f 118/230/165 119/232/167 127/246/179 126/245/178
+f 119/236/167 120/235/169 128/247/180 127/248/179
+f 120/235/169 121/238/171 129/249/181 128/247/180
+f 121/238/171 122/240/173 130/250/182 129/249/181
+f 117/227/162 125/244/177 131/251/183 123/241/174
+f 122/240/173 123/241/174 131/251/183 130/250/182
+f 124/243/176 142/252/184 141/253/185 125/244/177
+f 142/252/184 132/254/186 133/255/187 141/253/185
+f 126/245/178 143/256/188 142/252/184 124/243/176
+f 143/256/188 134/257/189 132/254/186 142/252/184
+f 129/249/181 145/258/190 144/259/191 128/247/180
+f 145/258/190 136/260/192 135/261/193 144/259/191
+f 130/250/182 146/262/194 145/258/190 129/249/181
+f 146/262/194 137/263/195 136/260/192 145/258/190
+f 125/244/177 141/253/185 147/264/196 131/251/183
+f 141/253/185 133/255/187 138/265/197 147/264/196
+f 131/251/183 147/264/196 146/262/194 130/250/182
+f 147/264/196 138/265/197 137/263/195 146/262/194
+f 128/247/180 144/259/191 148/266/198 127/248/179
+f 144/259/191 135/261/193 139/267/199 148/266/198
+f 127/246/179 149/268/200 143/256/188 126/245/178
+f 149/268/200 140/269/201 134/257/189 143/256/188
+f 105/217/153 106/216/152 2710/270/202 115/271/203
+f 107/218/154 105/217/153 115/271/203 2714/272/204
+f 106/216/152 108/219/155 2711/273/205 2710/270/202
+f 108/219/155 109/220/156 114/274/206 2711/273/205
+f 109/220/156 110/221/157 113/275/207 114/274/206
+f 110/223/157 111/222/158 2712/276/208 113/277/207
+f 111/222/158 112/224/159 2713/278/209 2712/276/208
+f 112/224/159 107/218/154 2714/272/204 2713/278/209
+f 173/279/210 174/280/211 156/281/212 155/282/213
+f 157/283/214 156/281/212 174/280/211 175/284/215
+f 158/285/216 157/283/214 175/284/215 176/286/217
+f 159/287/218 158/285/216 176/286/217 177/288/219
+f 160/289/220 159/287/218 177/288/219 178/290/221
+f 161/291/222 160/289/220 178/290/221 179/292/223
+f 162/293/224 161/291/222 179/292/223 180/294/225
+f 163/295/226 162/293/224 180/294/225 181/296/227
+f 164/297/228 163/295/226 181/296/227 182/298/229
+f 165/299/230 164/297/228 182/298/229 183/300/231
+f 166/301/232 165/299/230 183/300/231 184/302/233
+f 167/303/234 166/301/232 184/302/233 185/304/235
+f 168/305/236 167/303/234 185/304/235 186/306/237
+f 169/307/238 168/305/236 186/306/237 187/308/239
+f 170/309/240 169/307/238 187/308/239 188/310/241
+f 171/311/242 170/309/240 188/310/241 189/312/243
+f 172/313/244 171/311/242 189/312/243 190/314/245
+f 172/313/244 190/314/245 173/279/210 155/282/213
+f 174/280/211 173/279/210 192/315/246 191/316/247
+f 175/284/215 174/280/211 191/316/247 193/317/248
+f 176/286/217 175/284/215 193/317/248 194/318/249
+f 177/288/219 176/286/217 194/318/249 195/319/250
+f 178/290/221 177/288/219 195/319/250 196/320/251
+f 179/292/223 178/290/221 196/320/251 197/321/252
+f 180/294/225 179/292/223 197/321/252 198/322/253
+f 181/296/227 180/294/225 198/322/253 199/323/254
+f 182/298/229 181/296/227 199/323/254 200/324/255
+f 183/300/231 182/298/229 200/324/255 201/325/256
+f 184/302/233 183/300/231 201/325/256 202/326/257
+f 185/304/235 184/302/233 202/326/257 203/327/258
+f 186/306/237 185/304/235 203/327/258 204/328/259
+f 187/308/239 186/306/237 204/328/259 205/329/260
+f 188/310/241 187/308/239 205/329/260 206/330/261
+f 189/312/243 188/310/241 206/330/261 207/331/262
+f 190/314/245 189/312/243 207/331/262 208/332/263
+f 190/314/245 208/332/263 192/315/246 173/279/210
+f 191/316/247 192/315/246 209/333/264
+f 193/317/248 191/316/247 209/333/264
+f 194/318/249 193/317/248 209/333/264
+f 195/319/250 194/318/249 209/333/264
+f 196/320/251 195/319/250 209/333/264
+f 197/321/252 196/320/251 209/333/264
+f 198/322/253 197/321/252 209/333/264
+f 199/323/254 198/322/253 209/333/264
+f 200/324/255 199/323/254 209/333/264
+f 201/325/256 200/324/255 209/333/264
+f 202/326/257 201/325/256 209/333/264
+f 203/327/258 202/326/257 209/333/264
+f 204/328/259 203/327/258 209/333/264
+f 205/329/260 204/328/259 209/333/264
+f 206/330/261 205/329/260 209/333/264
+f 207/331/262 206/330/261 209/333/264
+f 208/332/263 207/331/262 209/333/264
+f 208/332/263 209/333/264 192/315/246
+f 170/309/240 171/311/242 220/334/265 221/335/266
+f 169/307/238 170/309/240 221/335/266 222/336/267
+f 168/305/236 169/307/238 222/336/267 213/337/268
+f 171/311/242 172/313/244 219/338/269 220/334/265
+f 155/282/213 218/339/270 219/338/269 172/313/244
+f 155/282/213 156/281/212 211/340/271 218/339/270
+f 156/281/212 157/283/214 223/341/272 211/340/271
+f 157/283/214 158/285/216 224/342/273 223/341/272
+f 158/285/216 159/287/218 225/343/274 224/342/273
+f 159/287/218 160/289/220 226/344/275 225/343/274
+f 160/289/220 161/291/222 227/345/276 226/344/275
+f 161/291/222 162/293/224 212/346/277 227/345/276
+f 162/293/224 163/295/226 228/347/278 212/346/277
+f 163/295/226 164/297/228 229/348/279 228/347/278
+f 164/297/228 165/299/230 230/349/280 229/348/279
+f 165/299/230 166/301/232 231/350/281 230/349/280
+f 166/301/232 167/303/234 232/351/282 231/350/281
+f 167/303/234 168/305/236 213/337/268 232/351/282
+f 235/352/283 234/353/284 214/354/285
+f 222/336/267 213/337/268 234/353/284 235/352/283
+f 214/354/285 215/355/286 236/356/287 235/352/283
+f 235/352/283 236/356/287 221/335/266 222/336/267
+f 215/355/286 216/357/288 237/358/289 236/356/287
+f 236/356/287 237/358/289 220/334/265 221/335/266
+f 216/357/288 217/359/290 238/360/291 237/358/289
+f 237/358/289 238/360/291 219/338/269 220/334/265
+f 217/359/290 210/361/292 239/362/293 238/360/291
+f 238/360/291 239/362/293 218/339/270 219/338/269
+f 233/363/294 239/362/293 210/361/292
+f 211/340/271 218/339/270 239/362/293 233/363/294
+f 212/346/277 227/345/276 240/364/295 246/365/296
+f 246/365/296 240/364/295 251/366/297
+f 241/367/298 240/364/295 227/345/276 226/344/275
+f 247/368/299 251/366/297 240/364/295 241/367/298
+f 242/369/300 241/367/298 226/344/275 225/343/274
+f 248/370/301 247/368/299 241/367/298 242/369/300
+f 243/371/302 242/369/300 225/343/274 224/342/273
+f 249/372/303 248/370/301 242/369/300 243/371/302
+f 244/373/304 243/371/302 224/342/273 223/341/272
+f 250/374/305 249/372/303 243/371/302 244/373/304
+f 223/341/272 211/340/271 245/375/306 244/373/304
+f 244/373/304 245/375/306 250/374/305
+f 259/376/307 258/377/308 253/378/309
+f 228/347/278 212/346/277 258/377/308 259/376/307
+f 253/378/309 254/379/310 260/380/311 259/376/307
+f 259/376/307 260/380/311 229/348/279 228/347/278
+f 254/379/310 255/381/312 261/382/313 260/380/311
+f 260/380/311 261/382/313 230/349/280 229/348/279
+f 255/381/312 256/383/314 262/384/315 261/382/313
+f 261/382/313 262/384/315 231/350/281 230/349/280
+f 256/383/314 252/385/316 263/386/317 262/384/315
+f 262/384/315 263/386/317 232/351/282 231/350/281
+f 257/387/318 263/386/317 252/385/316
+f 213/337/268 232/351/282 263/386/317 257/387/318
+f 2717/388/319 2716/389/320 2740/390/321 2741/391/322
+f 2718/392/323 2717/388/319 2741/391/322 2742/393/324
+f 2718/392/323 2742/393/324 2743/394/325 2719/395/326
+f 2719/395/326 2743/394/325 2744/396/327 2720/397/328
+f 2721/398/329 2720/397/328 2744/396/327 2745/399/330
+f 2721/398/329 2745/399/330 2746/400/331 2722/401/332
+f 2722/401/332 2746/400/331 2747/402/333 2723/403/334
+f 2723/403/334 2747/402/333 2748/404/335 2724/405/336
+f 2724/405/336 2748/404/335 2749/406/337 2725/407/338
+f 2726/408/339 2725/407/338 2749/406/337 2750/409/340
+f 2727/410/341 2726/411/339 2750/412/340 2751/413/342
+f 2728/414/343 2727/410/341 2751/413/342 2752/415/344
+f 2728/414/343 2752/415/344 2753/416/345 2729/417/346
+f 2729/417/346 2753/416/345 2754/418/347 2730/419/348
+f 2730/419/348 2754/418/347 2755/420/349 2731/421/350
+f 2732/422/351 2731/421/350 2755/420/349 2756/423/352
+f 2732/422/351 2756/423/352 2757/424/353 2733/425/354
+f 2734/426/355 2733/425/354 2757/424/353 2758/427/356
+f 2735/428/357 2734/426/355 2758/427/356 2759/429/358
+f 2736/430/359 2735/428/357 2759/429/358 2760/431/360
+f 2736/430/359 2760/431/360 2761/432/361 2737/433/362
+f 2738/434/363 2737/433/362 2761/432/361 2762/435/364
+f 2739/436/365 2738/434/363 2762/435/364 2763/437/366
+f 2740/390/321 2716/389/320 2739/436/365 2763/437/366
+f 500/438/367 499/439/368 523/440/369 524/441/370
+f 501/442/371 500/438/367 524/441/370 525/443/372
+f 502/444/373 501/442/371 525/443/372 526/445/374
+f 503/446/375 502/444/373 526/445/374 527/447/376
+f 504/448/377 503/446/375 527/447/376 528/449/378
+f 505/450/379 504/448/377 528/449/378 529/451/380
+f 506/452/381 505/450/379 529/451/380 530/453/382
+f 507/454/383 506/452/381 530/453/382 531/455/384
+f 508/456/385 507/454/383 531/455/384 532/457/386
+f 509/458/387 508/456/385 532/457/386 533/459/388
+f 510/460/389 509/461/387 533/462/388 534/463/390
+f 511/464/391 510/460/389 534/463/390 535/465/392
+f 512/466/393 511/464/391 535/465/392 536/467/393
+f 513/468/394 512/466/393 536/467/393 537/469/395
+f 514/470/396 513/468/394 537/469/395 538/471/397
+f 515/472/398 514/470/396 538/471/397 539/473/399
+f 516/474/400 515/472/398 539/473/399 540/475/401
+f 517/476/402 516/474/400 540/475/401 541/477/403
+f 518/478/404 517/476/402 541/477/403 542/479/405
+f 519/480/406 518/478/404 542/479/405 543/481/407
+f 520/482/408 519/480/406 543/481/407 544/483/409
+f 521/484/410 520/482/408 544/483/409 545/485/411
+f 522/486/412 521/484/410 545/485/411 546/487/413
+f 499/439/368 522/486/412 546/487/413 523/440/369
+f 475/488/414 476/489/415 548/490/416 547/491/417
+f 476/489/415 477/492/418 549/493/419 548/490/416
+f 477/492/418 478/494/420 550/495/421 549/493/419
+f 478/494/420 479/496/422 551/497/423 550/495/421
+f 479/496/422 480/498/424 552/499/425 551/497/423
+f 480/498/424 481/500/426 553/501/427 552/499/425
+f 481/500/426 482/502/428 554/503/429 553/501/427
+f 482/502/428 483/504/430 555/505/431 554/503/429
+f 483/504/430 484/506/432 556/507/433 555/505/431
+f 484/506/432 485/508/434 557/509/435 556/507/433
+f 485/510/434 486/511/436 558/512/437 557/513/435
+f 486/511/436 487/514/438 559/515/439 558/512/437
+f 487/514/438 488/516/440 560/517/441 559/515/439
+f 488/516/440 489/518/442 561/519/443 560/517/441
+f 489/518/442 490/520/444 562/521/445 561/519/443
+f 490/520/444 491/522/446 563/523/447 562/521/445
+f 491/522/446 492/524/448 564/525/449 563/523/447
+f 492/524/448 493/526/450 565/527/451 564/525/449
+f 493/526/450 494/528/452 566/529/453 565/527/451
+f 494/528/452 495/530/454 567/531/455 566/529/453
+f 495/530/454 496/532/456 568/533/457 567/531/455
+f 496/532/456 497/534/458 569/535/459 568/533/457
+f 497/534/458 498/536/460 570/537/461 569/535/459
+f 498/536/460 475/488/414 547/491/417 570/537/461
+f 572/538/462 575/539/463 579/540/464 577/541/465
+f 577/541/465 579/540/464 576/542/466 573/543/467
+f 580/544/468 571/545/469 578/546/470 581/547/471
+f 574/548/472 582/549/473 581/547/471 578/546/470
+f 571/545/469 580/544/468 585/550/474 583/551/475
+f 583/551/475 585/550/474 586/552/476 587/553/477
+f 586/552/476 588/554/478 589/555/479 587/553/477
+f 588/556/478 590/557/480 591/558/481 589/559/479
+f 590/557/480 592/560/482 593/561/483 591/558/481
+f 574/548/472 593/561/483 592/560/482 582/549/473
+f 572/538/462 584/562/484 595/563/485 575/539/463
+f 573/543/467 576/542/466 596/564/486 594/565/487
+f 576/542/466 579/540/464 597/566/488 596/564/486
+f 575/539/463 595/563/485 597/566/488 579/540/464
+f 587/553/477 2765/567/489 2764/568/490 583/551/475
+f 589/555/479 2766/569/491 2765/567/489 587/553/477
+f 591/558/481 2767/570/492 2766/571/491 589/559/479
+f 593/561/483 2768/572/493 2767/570/492 591/558/481
+f 584/562/484 2769/573/494 2770/574/495 595/563/485
+f 596/564/486 2772/575/496 2771/576/497 594/565/487
+f 597/566/488 2773/577/498 2772/575/496 596/564/486
+f 595/563/485 2770/574/495 2773/577/498 597/566/488
+f 600/578/499 2775/579/500 2774/580/501 598/581/502
+f 601/582/76 2776/583/76 2775/579/500 600/578/499
+f 602/584/503 2777/585/504 2776/586/76 601/587/76
+f 603/588/505 2778/589/506 2777/585/504 602/584/503
+f 599/590/507 2779/591/508 2780/592/76 605/593/76
+f 606/594/76 2782/595/76 2781/596/509 604/597/510
+f 607/598/76 2783/599/76 2782/595/76 606/594/76
+f 605/593/76 2780/592/76 2783/600/76 607/601/76
+f 610/602/511 2787/603/512 2784/604/513 608/605/514
+f 611/606/515 2788/607/515 2787/603/512 610/602/511
+f 612/608/516 2789/609/517 2788/610/515 611/611/515
+f 613/612/518 2790/613/519 2789/609/517 612/608/516
+f 609/614/520 2793/615/521 2794/616/522 615/617/523
+f 616/618/524 2796/619/525 2795/620/526 614/621/527
+f 617/622/528 2797/623/528 2796/619/525 616/618/524
+f 615/617/523 2794/616/522 2797/623/528 617/624/528
+f 620/625/529 2800/626/530 2798/627/531 2785/628/531
+f 621/629/515 2801/630/515 2800/626/530 620/625/529
+f 622/631/532 2802/632/533 2801/630/515 621/633/515
+f 2791/634/534 2803/635/534 2802/632/533 622/631/532
+f 2799/636/535 629/637/536 631/638/537 2804/639/535
+f 629/637/536 630/640/112 631/638/537
+f 2786/641/538 628/642/538 632/643/538 2792/644/538
+f 618/645/539 624/646/540 626/647/541 625/648/542
+f 625/648/542 626/647/541 627/649/112
+f 578/546/470 571/545/469 633/650/543 635/651/544
+f 635/651/544 633/650/543 572/538/462 577/541/465
+f 574/548/472 578/546/470 635/651/544 634/652/545
+f 634/652/545 635/651/544 577/541/465 573/543/467
+f 571/545/469 583/551/475 636/653/546 633/650/543
+f 633/650/543 636/653/546 584/562/484 572/538/462
+f 573/543/467 594/565/487 637/654/547 634/652/545
+f 634/652/545 637/654/547 593/561/483 574/548/472
+f 583/551/475 2764/568/490 2805/655/548 636/653/546
+f 636/653/546 2805/655/548 2769/573/494 584/562/484
+f 594/565/487 2771/576/497 2806/656/549 637/654/547
+f 637/654/547 2806/656/549 2768/572/493 593/561/483
+f 598/581/502 2774/580/501 2807/657/550 638/658/551
+f 638/658/551 2807/657/550 2779/591/508 599/590/507
+f 604/597/510 2781/596/509 2808/659/552 639/660/553
+f 639/660/553 2808/659/552 2778/589/506 603/588/505
+f 608/605/514 2784/604/513 2809/661/554 640/662/555
+f 640/662/555 2809/661/554 2793/615/521 609/614/520
+f 614/621/527 2795/620/526 2810/663/556 641/664/557
+f 641/664/557 2810/663/556 2790/613/519 613/612/518
+f 624/646/540 618/645/539 642/665/558 643/666/559
+f 643/666/559 642/665/558 619/667/560 623/668/560
+f 581/547/471 645/669/561 644/670/562 580/544/468
+f 582/549/473 646/671/563 645/669/561 581/547/471
+f 580/544/468 644/670/562 647/672/564 585/550/474
+f 585/550/474 647/672/564 648/673/565 586/552/476
+f 586/552/476 648/673/565 649/674/566 588/554/478
+f 588/556/478 649/675/566 650/676/567 590/557/480
+f 590/557/480 650/676/567 651/677/568 592/560/482
+f 592/560/482 651/677/568 646/671/563 582/549/473
+f 645/669/561 652/678/569 653/679/570 644/670/562
+f 646/671/563 654/680/571 652/678/569 645/669/561
+f 644/670/562 653/679/570 655/681/572 647/672/564
+f 647/672/564 655/681/572 656/682/573 648/673/565
+f 648/673/565 656/682/573 657/683/574 649/674/566
+f 649/675/566 657/684/574 658/685/575 650/676/567
+f 650/676/567 658/685/575 659/686/576 651/677/568
+f 651/677/568 659/686/576 654/680/571 646/671/563
+f 652/678/569 660/687/577 661/688/578 653/679/570
+f 654/680/571 662/689/579 660/687/577 652/678/569
+f 653/679/570 661/688/578 663/690/580 655/681/572
+f 655/681/572 663/690/580 664/691/581 656/682/573
+f 656/682/573 664/691/581 665/692/582 657/683/574
+f 657/684/574 665/693/582 666/694/583 658/685/575
+f 658/685/575 666/694/583 667/695/584 659/686/576
+f 659/686/576 667/695/584 662/689/579 654/680/571
+f 709/696/585 706/697/586 672/698/587 671/699/588
+f 709/696/585 671/699/588 673/700/589 708/701/590
+f 708/701/590 673/700/589 674/702/591 2811/703/592
+f 2811/704/592 674/705/591 675/706/593 2812/707/594
+f 2812/707/594 675/706/593 676/708/595 707/709/596
+f 707/709/596 676/708/595 677/710/597 705/711/598
+f 706/697/586 2818/712/599 678/713/600 672/698/587
+f 705/711/598 677/710/597 678/713/600 2818/712/599
+f 671/699/588 672/698/587 680/714/601 679/715/602
+f 671/699/588 679/715/602 681/716/603 673/700/589
+f 673/700/589 681/716/603 682/717/604 674/702/591
+f 674/705/591 682/718/604 683/719/605 675/706/593
+f 675/706/593 683/719/605 684/720/606 676/708/595
+f 676/708/595 684/720/606 685/721/607 677/710/597
+f 672/698/587 678/713/600 686/722/608 680/714/601
+f 677/710/597 685/721/607 686/722/608 678/713/600
+f 679/715/602 680/714/601 696/723/609 697/724/610
+f 697/724/610 696/723/609 688/725/611 687/726/612
+f 681/716/603 679/715/602 697/724/610 698/727/613
+f 698/727/613 697/724/610 687/726/612 689/728/614
+f 684/720/606 683/719/605 699/729/615 700/730/616
+f 700/730/616 699/729/615 690/731/617 691/732/618
+f 685/721/607 684/720/606 700/730/616 701/733/619
+f 701/733/619 700/730/616 691/732/618 692/734/620
+f 680/714/601 686/722/608 702/735/621 696/723/609
+f 696/723/609 702/735/621 693/736/622 688/725/611
+f 686/722/608 685/721/607 701/733/619 702/735/621
+f 702/735/621 701/733/619 692/734/620 693/736/622
+f 683/719/605 682/718/604 703/737/623 699/729/615
+f 699/729/615 703/737/623 694/738/624 690/731/617
+f 682/717/604 681/716/603 698/727/613 704/739/625
+f 704/739/625 698/727/613 689/728/614 695/740/626
+f 660/687/577 670/741/627 2813/742/628 661/688/578
+f 662/689/579 2817/743/629 670/741/627 660/687/577
+f 661/688/578 2813/742/628 2814/744/630 663/690/580
+f 663/690/580 2814/744/630 669/745/631 664/691/581
+f 664/691/581 669/745/631 668/746/632 665/692/582
+f 665/693/582 668/747/632 2815/748/633 666/694/583
+f 666/694/583 2815/748/633 2816/749/634 667/695/584
+f 667/695/584 2816/749/634 2817/743/629 662/689/579
+f 902/750/112 728/751/112 2869/752/112 2868/753/112
+f 730/754/76 906/755/76 2870/756/76 2871/757/76
+f 903/758/76 873/759/76 2873/760/76 2872/761/76
+f 906/755/76 905/762/76 2874/763/76 2870/756/76
+f 905/762/76 904/764/76 2875/765/76 2874/763/76
+f 904/764/76 903/758/76 2872/761/76 2875/765/76
+f 874/766/112 899/767/112 2876/768/112 2877/769/112
+f 901/770/112 902/750/112 2868/753/112 2878/771/112
+f 900/772/112 901/770/112 2878/771/112 2879/773/112
+f 899/767/112 900/772/112 2879/773/112 2876/768/112
+f 753/774/76 730/754/76 2871/757/76 2880/775/76
+f 715/776/76 750/777/76 2881/778/76 2882/779/76
+f 752/780/76 753/774/76 2880/775/76 2883/781/76
+f 751/782/76 752/780/76 2883/781/76 2884/783/76
+f 750/777/76 751/782/76 2884/783/76 2881/778/76
+f 746/784/112 716/785/112 2886/786/112 2885/787/112
+f 728/751/112 749/788/112 2887/789/112 2869/752/112
+f 749/788/112 748/790/112 2888/791/112 2887/789/112
+f 748/790/112 747/792/112 2889/793/112 2888/791/112
+f 747/792/112 746/784/112 2885/787/112 2889/793/112
+f 1038/794/635 1034/795/636 1033/796/637 1037/797/638
+f 1037/797/638 1033/796/637 1032/798/639 1036/799/640
+f 1036/799/640 1032/798/639 1031/800/641 1035/801/642
+f 1042/802/643 1034/795/636 1038/794/635 1041/803/644
+f 1040/804/645 1035/801/642 1031/800/641 1039/805/645
+f 1028/806/646 1027/807/647 1023/808/648 1024/809/649
+f 1027/807/647 1026/810/650 1022/811/651 1023/808/648
+f 1026/810/650 1025/812/652 1021/813/653 1022/811/651
+f 1030/814/654 1029/815/655 1028/806/646 1024/809/649
+f 1040/804/645 1039/805/645 1021/813/653 1025/812/652
+f 715/776/76 2882/779/76 2873/816/76 873/817/76
+f 716/785/112 874/818/112 2877/819/112 2886/786/112
+f 1029/820/655 1030/821/654 1042/802/643 1041/803/644
+usemtl WhiteCloth
+f 1208/822/656 1207/823/657 1085/824/658 1145/825/659
+f 1165/826/660 1164/827/661 1189/828/662 1188/829/663
+f 1234/830/664 1233/831/665 1210/832/666 1209/833/667
+f 1144/834/668 1059/835/669 1231/836/670 1232/837/671
+f 1096/838/672 1095/839/673 1211/840/674 1212/841/675
+f 1095/839/673 1136/842/676 1210/832/666 1211/840/674
+f 1084/843/677 1163/844/678 1186/845/679 1187/846/680
+f 1085/824/658 1084/843/677 1187/846/680 1188/829/663
+f 1145/825/659 1085/824/658 1188/829/663 1189/828/662
+f 1187/846/680 1186/845/679 1167/847/681 1166/848/682
+f 1192/849/683 1191/850/684 1146/851/685 1147/852/686
+f 1191/850/684 1190/853/687 1140/854/688 1146/851/685
+f 1144/834/668 1142/855/689 1190/853/687 1191/850/684
+f 1059/835/669 1144/834/668 1191/850/684 1192/849/683
+f 1190/853/687 1141/856/690 1086/857/691 1140/854/688
+f 1206/858/692 1205/859/693 1163/844/678 1084/843/677
+f 1207/823/657 1206/858/692 1084/843/677 1085/824/658
+f 1147/852/686 1146/851/685 1166/860/682 1167/861/681
+f 1146/851/685 1140/854/688 1165/862/660 1166/860/682
+f 1142/855/689 1087/863/694 1141/856/690 1190/853/687
+f 1095/839/673 1096/838/672 1205/859/693 1206/858/692
+f 1137/864/695 1136/842/676 1207/823/657 1208/822/656
+f 1136/842/676 1095/839/673 1206/858/692 1207/823/657
+f 1136/842/676 1137/864/695 1209/833/667 1210/832/666
+f 1142/855/689 1144/834/668 1232/837/671 1233/831/665
+f 1087/863/694 1142/855/689 1233/831/665 1234/830/664
+f 1140/854/688 1086/857/691 1164/865/661 1165/862/660
+f 1212/841/675 1211/840/674 1232/837/671 1231/836/670
+f 1211/840/674 1210/832/666 1233/831/665 1232/837/671
+f 1165/826/660 1188/829/663 1187/846/680 1166/848/682
+f 1424/866/696 1361/867/697 1301/868/698 1423/869/699
+f 1381/870/700 1404/871/701 1405/872/702 1380/873/703
+f 1450/874/704 1425/875/705 1426/876/706 1449/877/707
+f 1360/878/708 1448/879/709 1447/880/710 1275/881/711
+f 1312/882/712 1428/883/713 1427/884/714 1311/885/715
+f 1311/885/715 1427/884/714 1426/876/706 1352/886/716
+f 1300/887/717 1403/888/718 1402/889/719 1379/890/720
+f 1301/868/698 1404/871/701 1403/888/718 1300/887/717
+f 1361/867/697 1405/872/702 1404/871/701 1301/868/698
+f 1403/888/718 1382/891/721 1383/892/722 1402/889/719
+f 1408/893/723 1363/894/724 1362/895/725 1407/896/726
+f 1407/896/726 1362/895/725 1356/897/727 1406/898/728
+f 1360/878/708 1407/896/726 1406/898/728 1358/899/729
+f 1275/881/711 1408/893/723 1407/896/726 1360/878/708
+f 1406/898/728 1356/897/727 1302/900/730 1357/901/731
+f 1422/902/732 1300/887/717 1379/890/720 1421/903/733
+f 1423/869/699 1301/868/698 1300/887/717 1422/902/732
+f 1363/894/724 1383/904/722 1382/905/721 1362/895/725
+f 1362/895/725 1382/905/721 1381/906/700 1356/897/727
+f 1358/899/729 1406/898/728 1357/901/731 1303/907/734
+f 1311/885/715 1422/902/732 1421/903/733 1312/882/712
+f 1353/908/735 1424/866/696 1423/869/699 1352/886/716
+f 1352/886/716 1423/869/699 1422/902/732 1311/885/715
+f 1352/886/716 1426/876/706 1425/875/705 1353/908/735
+f 1358/899/729 1449/877/707 1448/879/709 1360/878/708
+f 1303/907/734 1450/874/704 1449/877/707 1358/899/729
+f 1356/897/727 1381/906/700 1380/909/703 1302/900/730
+f 1428/883/713 1447/880/710 1448/879/709 1427/884/714
+f 1427/884/714 1448/879/709 1449/877/707 1426/876/706
+f 1381/870/700 1382/891/721 1403/888/718 1404/871/701
+usemtl WhiteCloth_NONE
+f 2/910/736 1/911/737 4/912/738 5/913/739
+f 5/913/739 6/914/740 3/915/741 2/910/736
+f 7/916/742 8/917/743 5/913/739 4/912/738
+f 8/917/743 9/918/744 6/914/740 5/913/739
+f 10/919/745 11/920/746 8/917/743 7/916/742
+f 11/920/746 12/921/747 9/918/744 8/917/743
+f 15/922/748 13/923/749 11/920/746 10/919/745
+f 13/923/749 14/924/750 12/921/747 11/920/746
+usemtl Skin
+f 1093/925/751 1058/926/752 1088/927/753 1118/928/754
+f 1059/929/669 1089/930/755 1230/931/756 1231/932/670
+f 1230/931/756 1089/930/755 1242/933/757 1243/934/758
+f 1091/935/759 1060/936/760 1058/926/752 1093/925/751
+f 1091/937/759 1061/938/761 1103/939/762 1102/940/763
+f 1061/941/761 1091/935/759 1093/925/751 1193/942/764
+f 1090/943/765 1061/941/761 1193/942/764 1194/944/766
+f 1061/938/761 1090/945/765 1104/946/767 1103/939/762
+f 1104/946/767 1090/945/765 1092/947/768 1106/948/769
+f 1060/936/760 1091/935/759 1228/949/770 1229/950/771
+f 1090/943/765 1194/944/766 1195/951/772 1092/952/768
+f 1194/953/766 1203/954/773 1202/955/774 1195/956/772
+f 1194/953/766 1193/957/764 1204/958/775 1203/954/773
+f 1193/957/764 1093/959/751 1108/960/776 1204/958/775
+f 1094/961/777 1062/962/778 1226/963/779 1227/964/780
+f 1226/963/779 1062/962/778 1068/965/781 1225/966/782
+f 1062/967/778 1094/968/777 1098/969/783 1099/970/784
+f 1062/967/778 1099/970/784 1100/971/785 1068/972/781
+f 1243/973/758 1063/974/786 1253/975/787 1244/976/788
+f 1214/977/789 1063/974/786 1243/973/758 1229/978/771
+f 1063/974/786 1214/977/789 1107/979/790 1235/980/791
+f 1064/981/792 1253/975/787 1063/974/786 1213/982/793
+f 1066/983/794 1064/981/792 1213/982/793 1230/984/756
+f 1253/975/787 1064/981/792 1097/985/795 1252/986/796
+f 1064/981/792 1066/983/794 1073/987/797 1097/985/795
+f 1065/988/798 1213/982/793 1063/974/786 1235/980/791
+f 1065/988/798 1096/989/672 1212/990/675 1213/982/793
+f 1066/991/794 1244/992/788 1245/993/799 1073/994/797
+f 1244/976/788 1253/975/787 1252/986/796 1245/995/799
+f 1252/986/796 1251/996/800 1246/997/801 1245/995/799
+f 1251/996/800 1250/998/802 1247/999/803 1246/997/801
+f 1250/998/802 1249/1000/804 1248/1001/805 1247/999/803
+f 1098/969/783 1102/940/763 1215/1002/806 1216/1003/807
+f 1091/937/759 1102/940/763 1098/969/783 1094/968/777
+f 1102/940/763 1107/979/790 1214/977/789 1215/1002/806
+f 1068/972/781 1100/971/785 1101/1004/808 1067/1005/809
+f 1100/971/785 1218/1006/810 1219/1007/811 1101/1004/808
+f 1134/1008/812 1067/1005/809 1101/1004/808 1135/1009/813
+f 1067/1010/809 1134/1011/812 1223/1012/814 1224/1013/815
+f 1225/966/782 1068/965/781 1067/1010/809 1224/1013/815
+f 1237/1014/816 1162/1015/817 1184/1016/818 1238/1017/819
+f 1181/1018/820 1110/1019/821 1121/1020/822 1180/1021/823
+f 1110/1019/821 1117/1022/824 1120/1023/825 1121/1020/822
+f 1184/1016/818 1183/1024/826 1170/1025/827 1169/1026/828
+f 1183/1024/826 1182/1027/829 1171/1028/830 1170/1025/827
+f 1182/1027/829 1181/1018/820 1172/1029/831 1171/1028/830
+f 1172/1029/831 1181/1018/820 1180/1021/823 1173/1030/832
+f 1150/1031/833 1159/1032/834 1158/1033/835 1151/1034/836
+f 1160/1035/837 1159/1032/834 1150/1031/833 1149/1036/838
+f 1151/1034/836 1158/1033/835 1157/1037/839 1152/1038/840
+f 1159/1032/834 1114/1039/841 1116/1040/842 1158/1033/835
+f 1114/1039/841 1112/1041/843 1070/1042/844 1116/1040/842
+f 1112/1043/843 1150/1044/833 1151/1045/836 1070/1046/844
+f 1093/959/751 1113/1047/845 1115/1048/846 1108/960/776
+f 1113/1047/845 1112/1041/843 1114/1039/841 1115/1048/846
+f 1069/1049/847 1157/1037/839 1158/1033/835 1116/1040/842
+f 1069/1049/847 1128/1050/848 1156/1051/849 1157/1037/839
+f 1128/1050/848 1069/1049/847 1071/1052/850 1072/1053/851
+f 1069/1049/847 1116/1040/842 1070/1042/844 1071/1052/850
+f 1070/1046/844 1151/1045/836 1152/1054/840 1071/1055/850
+f 1160/1035/837 1149/1036/838 1118/1056/754 1161/1057/852
+f 1072/1058/851 1071/1055/850 1152/1054/840 1153/1059/853
+f 1129/1060/854 1072/1058/851 1153/1059/853 1154/1061/855
+f 1128/1050/848 1072/1053/851 1129/1062/854 1080/1063/856
+f 1110/1019/821 1111/1064/857 1119/1065/858 1117/1022/824
+f 1117/1066/824 1172/1029/831 1173/1030/832 1120/1067/825
+f 1123/1068/859 1075/1069/860 1122/1070/861 1125/1071/862
+f 1124/1072/863 1123/1068/859 1125/1071/862 1074/1073/864
+f 1073/987/797 1122/1070/861 1075/1069/860 1097/985/795
+f 1122/1074/861 1073/994/797 1245/993/799 1246/1075/801
+f 1074/1076/864 1125/1077/862 1247/1078/803 1248/1079/805
+f 1075/1069/860 1123/1068/859 1250/998/802 1251/996/800
+f 1097/985/795 1075/1069/860 1251/996/800 1252/986/796
+f 1126/1080/865 1076/1081/866 1177/1082/867 1178/1083/868
+f 1177/1082/867 1076/1081/866 1079/1084/869 1176/1085/870
+f 1076/1081/866 1126/1080/865 1078/1086/871 1079/1084/869
+f 1078/1087/871 1077/1088/872 1174/1089/873 1175/1090/874
+f 1077/1091/872 1078/1086/871 1126/1080/865 1127/1092/875
+f 1079/1093/869 1078/1087/871 1175/1090/874 1176/1085/870
+f 1128/1050/848 1080/1063/856 1155/1094/876 1156/1051/849
+f 1129/1062/854 1154/1095/855 1155/1094/876 1080/1063/856
+f 1130/1096/877 1131/1097/878 1132/1098/879 1081/1099/880
+f 1133/1100/881 1132/1098/879 1131/1097/878 1105/1101/882
+f 1198/1102/883 1199/1103/884 1130/1096/877 1081/1099/880
+f 1081/1104/880 1132/1105/879 1197/1106/885 1198/1107/883
+f 1198/1102/883 1197/1108/885 1200/1109/886 1199/1103/884
+f 1197/1108/885 1196/1110/887 1201/1111/888 1200/1109/886
+f 1195/956/772 1202/955/774 1201/1111/888 1196/1110/887
+f 1082/1112/889 1134/1008/812 1135/1009/813 1083/1113/890
+f 1134/1011/812 1082/1114/889 1222/1115/891 1223/1012/814
+f 1082/1112/889 1083/1113/890 1221/1116/892 1222/1117/891
+f 1083/1113/890 1135/1009/813 1220/1118/893 1221/1116/892
+f 1186/1119/679 1185/1120/894 1168/1121/895 1167/1122/681
+f 1143/1123/896 1192/1124/683 1147/1125/686 1148/1126/897
+f 1143/1123/896 1148/1126/897 1240/1127/898 1241/1128/899
+f 1058/926/752 1241/1128/899 1240/1127/898 1088/927/753
+f 1108/960/776 1115/1048/846 1160/1035/837 1161/1057/852
+f 1115/1048/846 1114/1039/841 1159/1032/834 1160/1035/837
+f 1109/1129/900 1108/960/776 1161/1057/852 1162/1015/817
+f 1205/1130/693 1139/1131/901 1138/1132/902 1163/1133/678
+f 1138/1132/902 1139/1131/901 1236/1134/903 1237/1014/816
+f 1148/1126/897 1147/1125/686 1167/1122/681 1168/1121/895
+f 1148/1126/897 1168/1121/895 1239/1135/904 1240/1127/898
+f 1088/927/753 1240/1127/898 1239/1135/904 1169/1026/828
+f 1117/1066/824 1119/1136/858 1171/1028/830 1172/1029/831
+f 1119/1136/858 1118/928/754 1170/1025/827 1171/1028/830
+f 1127/1092/875 1126/1080/865 1178/1083/868 1179/1137/905
+f 1127/1092/875 1179/1137/905 1180/1021/823 1121/1020/822
+f 1111/1064/857 1110/1019/821 1181/1018/820 1182/1027/829
+f 1161/1057/852 1111/1064/857 1182/1027/829 1183/1024/826
+f 1162/1015/817 1161/1057/852 1183/1024/826 1184/1016/818
+f 1163/1133/678 1138/1132/902 1185/1120/894 1186/1119/679
+f 1089/930/755 1059/929/669 1192/1124/683 1143/1123/896
+f 1089/930/755 1143/1123/896 1241/1128/899 1242/933/757
+f 1060/936/760 1242/933/757 1241/1128/899 1058/926/752
+f 1195/951/772 1196/1138/887 1133/1139/881 1092/952/768
+f 1132/1105/879 1133/1139/881 1196/1138/887 1197/1106/885
+f 1131/1097/878 1130/1096/877 1199/1103/884 1200/1109/886
+f 1105/1101/882 1131/1097/878 1200/1109/886 1201/1111/888
+f 1105/1101/882 1201/1111/888 1202/955/774 1106/948/769
+f 1104/946/767 1106/948/769 1202/955/774 1203/954/773
+f 1103/939/762 1104/946/767 1203/954/773 1204/958/775
+f 1102/940/763 1103/939/762 1204/958/775 1108/960/776
+f 1235/980/791 1107/979/790 1109/1129/900 1236/1134/903
+f 1096/989/672 1065/988/798 1139/1131/901 1205/1130/693
+f 1139/1131/901 1065/988/798 1235/980/791 1236/1134/903
+f 1218/1006/810 1100/971/785 1099/970/784 1217/1140/906
+f 1091/935/759 1094/961/777 1227/964/780 1228/949/770
+f 1185/1120/894 1238/1017/819 1239/1135/904 1168/1121/895
+f 1185/1120/894 1138/1132/902 1237/1014/816 1238/1017/819
+f 1125/1077/862 1122/1074/861 1246/1075/801 1247/1078/803
+f 1249/1000/804 1124/1072/863 1074/1073/864 1248/1001/805
+f 1123/1068/859 1124/1072/863 1249/1000/804 1250/998/802
+f 1242/933/757 1060/936/760 1229/950/771 1243/934/758
+f 1118/928/754 1088/927/753 1169/1026/828 1170/1025/827
+f 1113/1141/845 1093/925/751 1118/928/754 1149/1142/838
+f 1228/1143/770 1227/1144/780 1216/1003/807 1215/1002/806
+f 1227/1144/780 1226/1145/779 1217/1140/906 1216/1003/807
+f 1229/978/771 1228/1143/770 1215/1002/806 1214/977/789
+f 1213/982/793 1212/990/675 1231/1146/670 1230/984/756
+f 1066/991/794 1230/931/756 1243/934/758 1244/992/788
+f 1099/970/784 1098/969/783 1216/1003/807 1217/1140/906
+f 1135/1009/813 1101/1004/808 1219/1007/811 1220/1118/893
+f 1218/1006/810 1217/1140/906 1226/1145/779 1225/1147/782
+f 1218/1006/810 1225/1147/782 1224/1148/815 1219/1007/811
+f 1107/979/790 1102/940/763 1108/960/776 1109/1129/900
+f 1133/1100/881 1105/1101/882 1106/948/769 1092/947/768
+f 1236/1134/903 1109/1129/900 1162/1015/817 1237/1014/816
+f 1111/1064/857 1161/1057/852 1118/1056/754 1119/1065/858
+f 1238/1017/819 1184/1016/818 1169/1026/828 1239/1135/904
+f 1112/1043/843 1113/1141/845 1149/1142/838 1150/1044/833
+f 1153/1149/853 1152/1038/840 1157/1037/839 1156/1051/849
+f 1154/1095/855 1153/1149/853 1156/1051/849 1155/1094/876
+f 1077/1088/872 1120/1067/825 1173/1030/832 1174/1089/873
+f 1127/1092/875 1121/1020/822 1120/1023/825 1077/1091/872
+f 1179/1137/905 1174/1089/873 1173/1030/832 1180/1021/823
+f 1179/1137/905 1178/1083/868 1175/1090/874 1174/1089/873
+f 1178/1083/868 1177/1082/867 1176/1085/870 1175/1090/874
+f 1219/1007/811 1224/1148/815 1223/1150/814 1220/1118/893
+f 1221/1116/892 1220/1118/893 1223/1150/814 1222/1117/891
+f 1309/1151/907 1334/1152/908 1304/1153/909 1274/1154/910
+f 1275/1155/711 1447/1156/710 1446/1157/911 1305/1158/912
+f 1446/1157/911 1459/1159/913 1458/1160/914 1305/1158/912
+f 1307/1161/915 1309/1151/907 1274/1154/910 1276/1162/916
+f 1307/1163/915 1318/1164/917 1319/1165/918 1277/1166/919
+f 1277/1167/919 1409/1168/920 1309/1151/907 1307/1161/915
+f 1306/1169/921 1410/1170/922 1409/1168/920 1277/1167/919
+f 1277/1166/919 1319/1165/918 1320/1171/923 1306/1172/921
+f 1320/1171/923 1322/1173/924 1308/1174/925 1306/1172/921
+f 1276/1162/916 1445/1175/926 1444/1176/927 1307/1161/915
+f 1306/1169/921 1308/1177/925 1411/1178/928 1410/1170/922
+f 1410/1179/922 1411/1180/928 1418/1181/929 1419/1182/930
+f 1410/1179/922 1419/1182/930 1420/1183/931 1409/1184/920
+f 1409/1184/920 1420/1183/931 1324/1185/932 1309/1186/907
+f 1310/1187/933 1443/1188/934 1442/1189/935 1278/1190/936
+f 1442/1189/935 1441/1191/937 1284/1192/938 1278/1190/936
+f 1278/1193/936 1315/1194/939 1314/1195/940 1310/1196/933
+f 1278/1193/936 1284/1197/938 1316/1198/941 1315/1194/939
+f 1459/1199/913 1460/1200/942 1469/1201/943 1279/1202/944
+f 1430/1203/945 1445/1204/926 1459/1199/913 1279/1202/944
+f 1279/1202/944 1451/1205/946 1323/1206/947 1430/1203/945
+f 1280/1207/948 1429/1208/949 1279/1202/944 1469/1201/943
+f 1282/1209/950 1446/1210/911 1429/1208/949 1280/1207/948
+f 1469/1201/943 1468/1211/951 1313/1212/952 1280/1207/948
+f 1280/1207/948 1313/1212/952 1289/1213/953 1282/1209/950
+f 1281/1214/954 1451/1205/946 1279/1202/944 1429/1208/949
+f 1281/1214/954 1429/1208/949 1428/1215/713 1312/1216/712
+f 1282/1217/950 1289/1218/953 1461/1219/955 1460/1220/942
+f 1460/1200/942 1461/1221/955 1468/1211/951 1469/1201/943
+f 1468/1211/951 1461/1221/955 1462/1222/956 1467/1223/957
+f 1467/1223/957 1462/1222/956 1463/1224/958 1466/1225/959
+f 1466/1225/959 1463/1224/958 1464/1226/960 1465/1227/961
+f 1314/1195/940 1432/1228/962 1431/1229/963 1318/1164/917
+f 1307/1163/915 1310/1196/933 1314/1195/940 1318/1164/917
+f 1318/1164/917 1431/1229/963 1430/1203/945 1323/1206/947
+f 1284/1197/938 1283/1230/964 1317/1231/965 1316/1198/941
+f 1316/1198/941 1317/1231/965 1435/1232/966 1434/1233/967
+f 1350/1234/968 1351/1235/969 1317/1231/965 1283/1230/964
+f 1283/1236/964 1440/1237/970 1439/1238/971 1350/1239/968
+f 1441/1191/937 1440/1237/970 1283/1236/964 1284/1192/938
+f 1453/1240/972 1454/1241/973 1400/1242/974 1378/1243/975
+f 1397/1244/976 1396/1245/977 1337/1246/978 1326/1247/979
+f 1326/1247/979 1337/1246/978 1336/1248/980 1333/1249/981
+f 1400/1242/974 1385/1250/982 1386/1251/983 1399/1252/984
+f 1399/1252/984 1386/1251/983 1387/1253/985 1398/1254/986
+f 1398/1254/986 1387/1253/985 1388/1255/987 1397/1244/976
+f 1388/1255/987 1389/1256/988 1396/1245/977 1397/1244/976
+f 1366/1257/989 1367/1258/990 1374/1259/991 1375/1260/992
+f 1376/1261/993 1365/1262/994 1366/1257/989 1375/1260/992
+f 1367/1258/990 1368/1263/995 1373/1264/996 1374/1259/991
+f 1375/1260/992 1374/1259/991 1332/1265/997 1330/1266/998
+f 1330/1266/998 1332/1265/997 1286/1267/999 1328/1268/1000
+f 1328/1269/1000 1286/1270/999 1367/1271/990 1366/1272/989
+f 1309/1186/907 1324/1185/932 1331/1273/1001 1329/1274/1002
+f 1329/1274/1002 1331/1273/1001 1330/1266/998 1328/1268/1000
+f 1285/1275/1003 1332/1265/997 1374/1259/991 1373/1264/996
+f 1285/1275/1003 1373/1264/996 1372/1276/1004 1344/1277/1005
+f 1344/1277/1005 1288/1278/1006 1287/1279/1007 1285/1275/1003
+f 1285/1275/1003 1287/1279/1007 1286/1267/999 1332/1265/997
+f 1286/1270/999 1287/1280/1007 1368/1281/995 1367/1271/990
+f 1376/1261/993 1377/1282/1008 1334/1283/908 1365/1262/994
+f 1288/1284/1006 1369/1285/1009 1368/1281/995 1287/1280/1007
+f 1345/1286/1010 1370/1287/1011 1369/1285/1009 1288/1284/1006
+f 1344/1277/1005 1296/1288/1012 1345/1289/1010 1288/1278/1006
+f 1326/1247/979 1333/1249/981 1335/1290/1013 1327/1291/1014
+f 1333/1292/981 1336/1293/980 1389/1256/988 1388/1255/987
+f 1339/1294/1015 1341/1295/1016 1338/1296/1017 1291/1297/1018
+f 1340/1298/1019 1290/1299/1020 1341/1295/1016 1339/1294/1015
+f 1289/1213/953 1313/1212/952 1291/1297/1018 1338/1296/1017
+f 1338/1300/1017 1462/1301/956 1461/1219/955 1289/1218/953
+f 1290/1302/1020 1464/1303/960 1463/1304/958 1341/1305/1016
+f 1291/1297/1018 1467/1223/957 1466/1225/959 1339/1294/1015
+f 1313/1212/952 1468/1211/951 1467/1223/957 1291/1297/1018
+f 1342/1306/1021 1394/1307/1022 1393/1308/1023 1292/1309/1024
+f 1393/1308/1023 1392/1310/1025 1295/1311/1026 1292/1309/1024
+f 1292/1309/1024 1295/1311/1026 1294/1312/1027 1342/1306/1021
+f 1294/1313/1027 1391/1314/1028 1390/1315/1029 1293/1316/1030
+f 1293/1317/1030 1343/1318/1031 1342/1306/1021 1294/1312/1027
+f 1295/1319/1026 1392/1310/1025 1391/1314/1028 1294/1313/1027
+f 1344/1277/1005 1372/1276/1004 1371/1320/1032 1296/1288/1012
+f 1345/1289/1010 1296/1288/1012 1371/1320/1032 1370/1321/1011
+f 1346/1322/1033 1297/1323/1034 1348/1324/1035 1347/1325/1036
+f 1349/1326/1037 1321/1327/1038 1347/1325/1036 1348/1324/1035
+f 1414/1328/1039 1297/1323/1034 1346/1322/1033 1415/1329/1040
+f 1297/1330/1034 1414/1331/1039 1413/1332/1041 1348/1333/1035
+f 1414/1328/1039 1415/1329/1040 1416/1334/1042 1413/1335/1041
+f 1413/1335/1041 1416/1334/1042 1417/1336/1043 1412/1337/1044
+f 1411/1180/928 1412/1337/1044 1417/1336/1043 1418/1181/929
+f 1298/1338/1045 1299/1339/1046 1351/1235/969 1350/1234/968
+f 1350/1239/968 1439/1238/971 1438/1340/1047 1298/1341/1045
+f 1298/1338/1045 1438/1342/1047 1437/1343/1048 1299/1339/1046
+f 1299/1339/1046 1437/1343/1048 1436/1344/1049 1351/1235/969
+f 1402/1345/719 1383/1346/722 1384/1347/1050 1401/1348/1051
+f 1359/1349/1052 1364/1350/1053 1363/1351/724 1408/1352/723
+f 1359/1349/1052 1457/1353/1054 1456/1354/1055 1364/1350/1053
+f 1274/1154/910 1304/1153/909 1456/1354/1055 1457/1353/1054
+f 1324/1185/932 1377/1282/1008 1376/1261/993 1331/1273/1001
+f 1331/1273/1001 1376/1261/993 1375/1260/992 1330/1266/998
+f 1325/1355/1056 1378/1243/975 1377/1282/1008 1324/1185/932
+f 1421/1356/733 1379/1357/720 1354/1358/1057 1355/1359/1058
+f 1354/1358/1057 1453/1240/972 1452/1360/1059 1355/1359/1058
+f 1364/1350/1053 1384/1347/1050 1383/1346/722 1363/1351/724
+f 1364/1350/1053 1456/1354/1055 1455/1361/1060 1384/1347/1050
+f 1304/1153/909 1385/1250/982 1455/1361/1060 1456/1354/1055
+f 1333/1292/981 1388/1255/987 1387/1253/985 1335/1362/1013
+f 1335/1362/1013 1387/1253/985 1386/1251/983 1334/1152/908
+f 1343/1318/1031 1395/1363/1061 1394/1307/1022 1342/1306/1021
+f 1343/1318/1031 1337/1246/978 1396/1245/977 1395/1363/1061
+f 1327/1291/1014 1398/1254/986 1397/1244/976 1326/1247/979
+f 1377/1282/1008 1399/1252/984 1398/1254/986 1327/1291/1014
+f 1378/1243/975 1400/1242/974 1399/1252/984 1377/1282/1008
+f 1379/1357/720 1402/1345/719 1401/1348/1051 1354/1358/1057
+f 1305/1158/912 1359/1349/1052 1408/1352/723 1275/1155/711
+f 1305/1158/912 1458/1160/914 1457/1353/1054 1359/1349/1052
+f 1276/1162/916 1274/1154/910 1457/1353/1054 1458/1160/914
+f 1411/1178/928 1308/1177/925 1349/1364/1037 1412/1365/1044
+f 1348/1333/1035 1413/1332/1041 1412/1365/1044 1349/1364/1037
+f 1347/1325/1036 1416/1334/1042 1415/1329/1040 1346/1322/1033
+f 1321/1327/1038 1417/1336/1043 1416/1334/1042 1347/1325/1036
+f 1321/1327/1038 1322/1173/924 1418/1181/929 1417/1336/1043
+f 1320/1171/923 1419/1182/930 1418/1181/929 1322/1173/924
+f 1319/1165/918 1420/1183/931 1419/1182/930 1320/1171/923
+f 1318/1164/917 1324/1185/932 1420/1183/931 1319/1165/918
+f 1451/1205/946 1452/1360/1059 1325/1355/1056 1323/1206/947
+f 1312/1216/712 1421/1356/733 1355/1359/1058 1281/1214/954
+f 1355/1359/1058 1452/1360/1059 1451/1205/946 1281/1214/954
+f 1434/1233/967 1433/1366/1062 1315/1194/939 1316/1198/941
+f 1307/1161/915 1444/1176/927 1443/1188/934 1310/1187/933
+f 1401/1348/1051 1384/1347/1050 1455/1361/1060 1454/1241/973
+f 1401/1348/1051 1454/1241/973 1453/1240/972 1354/1358/1057
+f 1341/1305/1016 1463/1304/958 1462/1301/956 1338/1300/1017
+f 1465/1227/961 1464/1226/960 1290/1299/1020 1340/1298/1019
+f 1339/1294/1015 1466/1225/959 1465/1227/961 1340/1298/1019
+f 1458/1160/914 1459/1159/913 1445/1175/926 1276/1162/916
+f 1334/1152/908 1386/1251/983 1385/1250/982 1304/1153/909
+f 1329/1367/1002 1365/1368/994 1334/1152/908 1309/1151/907
+f 1444/1369/927 1431/1229/963 1432/1228/962 1443/1370/934
+f 1443/1370/934 1432/1228/962 1433/1366/1062 1442/1371/935
+f 1445/1204/926 1430/1203/945 1431/1229/963 1444/1369/927
+f 1429/1208/949 1446/1210/911 1447/1372/710 1428/1215/713
+f 1282/1217/950 1460/1220/942 1459/1159/913 1446/1157/911
+f 1315/1194/939 1433/1366/1062 1432/1228/962 1314/1195/940
+f 1351/1235/969 1436/1344/1049 1435/1232/966 1317/1231/965
+f 1434/1233/967 1441/1373/937 1442/1371/935 1433/1366/1062
+f 1434/1233/967 1435/1232/966 1440/1374/970 1441/1373/937
+f 1323/1206/947 1325/1355/1056 1324/1185/932 1318/1164/917
+f 1349/1326/1037 1308/1174/925 1322/1173/924 1321/1327/1038
+f 1452/1360/1059 1453/1240/972 1378/1243/975 1325/1355/1056
+f 1327/1291/1014 1335/1290/1013 1334/1283/908 1377/1282/1008
+f 1454/1241/973 1455/1361/1060 1385/1250/982 1400/1242/974
+f 1328/1269/1000 1366/1272/989 1365/1368/994 1329/1367/1002
+f 1369/1375/1009 1372/1276/1004 1373/1264/996 1368/1263/995
+f 1370/1321/1011 1371/1320/1032 1372/1276/1004 1369/1375/1009
+f 1293/1316/1030 1390/1315/1029 1389/1256/988 1336/1293/980
+f 1343/1318/1031 1293/1317/1030 1336/1248/980 1337/1246/978
+f 1395/1363/1061 1396/1245/977 1389/1256/988 1390/1315/1029
+f 1395/1363/1061 1390/1315/1029 1391/1314/1028 1394/1307/1022
+f 1394/1307/1022 1391/1314/1028 1392/1310/1025 1393/1308/1023
+f 1435/1232/966 1436/1344/1049 1439/1376/971 1440/1374/970
+f 1437/1343/1048 1438/1342/1047 1439/1376/971 1436/1344/1049
+f 2044/1377/1063 2045/1378/1064 1485/1379/1065 1475/1380/1066
+f 1477/1381/1067 1487/1382/1068 1486/1383/1069 1476/1384/1070
+f 1478/1385/1071 1488/1386/1072 1487/1382/1068 1477/1381/1067
+f 1479/1387/1073 1489/1388/1074 1488/1386/1072 1478/1385/1071
+f 1480/1389/1075 1490/1390/1076 1489/1388/1074 1479/1387/1073
+f 1537/1391/1077 1538/1392/1078 1490/1390/1076 1480/1389/1075
+f 1482/1393/1079 1492/1394/1080 1491/1395/1081 1481/1396/1082
+f 1483/1397/1083 1493/1398/1084 1492/1394/1080 1482/1393/1079
+f 1484/1399/1085 1494/1400/1086 1493/1398/1084 1483/1397/1083
+f 1475/1380/1066 1485/1379/1065 1494/1400/1086 1484/1399/1085
+f 2045/1378/1064 2046/1401/1087 1495/1402/1088 1485/1379/1065
+f 2046/1401/1087 2047/1403/1089 1497/1404/1090 1495/1402/1088
+f 1495/1402/1088 1503/1405/1091 1502/1406/1092 1485/1379/1065
+f 1497/1404/1090 1504/1407/1093 1503/1405/1091 1495/1402/1088
+f 1503/1405/1091 1500/1408/1094 1499/1409/1095 1502/1406/1092
+f 1504/1407/1093 1501/1410/1096 1500/1408/1094 1503/1405/1091
+f 2073/1411/1097 1509/1412/1098 1508/1413/1099 2072/1414/1100
+f 1505/1415/1101 1494/1400/1086 1485/1379/1065 1502/1406/1092
+f 1506/1416/1102 1493/1398/1084 1494/1400/1086 1505/1415/1101
+f 1499/1409/1095 1512/1417/1103 1505/1415/1101 1502/1406/1092
+f 1512/1417/1103 1511/1418/1104 1506/1416/1102 1505/1415/1101
+f 1511/1418/1104 1510/1419/1105 1507/1420/1106 1506/1416/1102
+f 1487/1382/1068 1514/1421/1107 1513/1422/1108 1486/1383/1069
+f 1488/1386/1072 1515/1423/1109 1514/1421/1107 1487/1382/1068
+f 1489/1388/1074 1516/1424/1110 1515/1423/1109 1488/1386/1072
+f 1490/1390/1076 1517/1425/1111 1516/1424/1110 1489/1388/1074
+f 1486/1383/1069 1513/1422/1108 1518/1426/1112 1496/1427/1113
+f 1496/1427/1113 1518/1426/1112 1519/1428/1114 1498/1429/1115
+f 1528/1430/1116 1527/1431/1117 1522/1432/1118 1521/1433/1119
+f 1526/1434/1120 1525/1435/1121 1524/1436/1122 1523/1437/1123
+f 1527/1431/1117 1526/1434/1120 1523/1437/1123 1522/1432/1118
+f 1941/1438/1124 1561/1439/1125 1562/1440/1126 1940/1441/1127
+f 1520/1442/1128 1508/1413/1099 1509/1412/1098 1529/1443/1129
+f 1523/1437/1123 1611/1444/1130 1582/1445/1131 1522/1432/1118
+f 1582/1445/1131 1583/1446/1132 1535/1447/1133 1522/1432/1118
+f 1535/1447/1133 1534/1448/1134 1521/1433/1119 1522/1432/1118
+f 1531/1449/1135 1533/1450/1136 1787/1451/1137 1788/1452/1138
+f 1789/1453/1139 1584/1454/1140 1531/1449/1135 1788/1452/1138
+f 1481/1396/1082 1491/1395/1081 2032/1455/1141 2033/1456/1142
+f 1476/1384/1070 1486/1383/1069 1540/1457/1143 1539/1458/1144
+f 1486/1383/1069 1496/1427/1113 1541/1459/1145 1540/1457/1143
+f 1496/1427/1113 1498/1429/1115 1542/1460/1146 1541/1459/1145
+f 1585/1461/1147 1586/1462/1148 1545/1463/1149 1546/1464/1150
+f 1944/1465/1151 1559/1466/1152 1589/1467/1153 1943/1468/1154
+f 1550/1469/1155 1527/1431/1117 1528/1430/1116 1547/1470/1156
+f 1525/1435/1121 1526/1434/1120 1549/1471/1157 1548/1472/1158
+f 1545/1463/1149 1586/1462/1148 1587/1473/1159 1544/1474/1160
+f 1549/1471/1157 1526/1434/1120 1527/1431/1117 1550/1469/1155
+f 1543/1475/1161 1590/1476/1162 1591/1477/1163 1566/1478/1164
+f 1557/1479/1165 1593/1480/1166 1594/1481/1167 1556/1482/1168
+f 1553/1483/1169 1592/1484/1170 1593/1480/1166 1557/1479/1165
+f 1942/1485/1171 1560/1486/1172 1561/1439/1125 1941/1438/1124
+f 1529/1443/1129 1509/1412/1098 1551/1487/1173 1558/1488/1174
+f 1544/1474/1160 1587/1473/1159 1588/1489/1175 1565/1490/1176
+f 1528/1430/1116 1561/1439/1125 1560/1486/1172 1547/1470/1156
+f 1521/1433/1119 1562/1440/1126 1561/1439/1125 1528/1430/1116
+f 2074/1491/1177 2075/1492/1178 1563/1493/1179 1578/1494/1180
+f 1555/1495/1181 1554/1496/1182 1563/1493/1179 1564/1497/1183
+f 1559/1466/1152 1565/1490/1176 1588/1489/1175 1589/1467/1153
+f 1566/1478/1164 1591/1477/1163 1592/1484/1170 1553/1483/1169
+f 1568/1498/1184 1500/1408/1094 1501/1410/1096 1567/1499/1185
+f 1511/1418/1104 1512/1417/1103 1570/1500/1186 1571/1501/1187
+f 1570/1500/1186 1512/1417/1103 1499/1409/1095 1569/1502/1188
+f 1569/1502/1188 1499/1409/1095 1500/1408/1094 1568/1498/1184
+f 1511/1418/1104 1571/1501/1187 1572/1503/1189 1573/1504/1190
+f 1573/1504/1190 1572/1503/1189 1574/1505/1191 1575/1506/1192
+f 1575/1506/1192 1574/1505/1191 1576/1507/1193 1577/1508/1194
+f 2075/1492/1178 2076/1509/1195 1564/1497/1183 1563/1493/1179
+f 1554/1496/1182 1552/1510/1196 1578/1494/1180 1563/1493/1179
+f 1552/1510/1196 1551/1487/1173 1509/1412/1098 1578/1494/1180
+f 2074/1491/1177 1578/1494/1180 1509/1412/1098 2073/1411/1097
+f 1573/1504/1190 1579/1511/1197 1510/1419/1105 1511/1418/1104
+f 1573/1504/1190 1575/1506/1192 1580/1512/1198 1579/1511/1197
+f 1575/1506/1192 1577/1508/1194 1581/1513/1199 1580/1512/1198
+f 1612/1514/1200 1530/1515/1201 1582/1445/1131 1611/1444/1130
+f 1530/1515/1201 1536/1516/1202 1583/1446/1132 1582/1445/1131
+f 1790/1517/1203 1532/1518/1204 1584/1454/1140 1789/1453/1139
+f 1548/1472/1158 1549/1471/1157 1586/1462/1148 1585/1461/1147
+f 1587/1473/1159 1586/1462/1148 1549/1471/1157 1550/1469/1155
+f 1588/1489/1175 1587/1473/1159 1550/1469/1155 1547/1470/1156
+f 1589/1467/1153 1588/1489/1175 1547/1470/1156 1560/1486/1172
+f 1943/1468/1154 1589/1467/1153 1560/1486/1172 1942/1485/1171
+f 1591/1477/1163 1590/1476/1162 1558/1488/1174 1551/1487/1173
+f 1592/1484/1170 1591/1477/1163 1551/1487/1173 1552/1510/1196
+f 1593/1480/1166 1592/1484/1170 1552/1510/1196 1554/1496/1182
+f 1594/1481/1167 1593/1480/1166 1554/1496/1182 1555/1495/1181
+f 1967/1519/1205 1599/1520/1206 1776/1521/1207 1777/1522/1208
+f 1787/1451/1137 1533/1450/1136 1595/1523/1209 1786/1524/1210
+f 1786/1524/1210 1595/1523/1209 1596/1525/1211 1785/1526/1212
+f 1596/1525/1211 1597/1527/1213 1784/1528/1214 1785/1526/1212
+f 1562/1440/1126 1521/1433/1119 1534/1448/1134 1600/1529/1215
+f 1507/1420/1106 1603/1530/1216 1493/1398/1084 1506/1416/1102
+f 1940/1441/1127 1562/1440/1126 1600/1529/1215 1939/1531/1217
+f 1520/1442/1128 1601/1532/1218 1602/1533/1219 1508/1413/1099
+f 1508/1413/1099 1602/1533/1219 2071/1534/1220 2072/1414/1100
+f 1538/1392/1078 1606/1535/1221 1517/1425/1111 1490/1390/1076
+f 1493/1398/1084 1603/1530/1216 1604/1536/1222 1492/1394/1080
+f 1492/1394/1080 1604/1536/1222 1605/1537/1223 1491/1395/1081
+f 1491/1395/1081 1605/1537/1223 2031/1538/1224 2032/1455/1141
+f 2070/1539/1225 2071/1534/1220 1602/1533/1219 1608/1540/1226
+f 2069/1541/1227 2070/1539/1225 1608/1540/1226 1610/1542/1228
+f 1608/1540/1226 1602/1533/1219 1601/1532/1218 1607/1543/1229
+f 1610/1542/1228 1608/1540/1226 1607/1543/1229 1609/1544/1230
+f 1524/1436/1122 1612/1514/1200 1611/1444/1130 1523/1437/1123
+f 1614/1545/1231 1613/1546/1232 1615/1547/1233 1616/1548/1234
+f 1616/1548/1234 1615/1547/1233 1568/1498/1184 1567/1499/1185
+f 1613/1546/1232 1621/1549/1235 1617/1550/1236 1615/1547/1233
+f 1615/1547/1233 1617/1550/1236 1569/1502/1188 1568/1498/1184
+f 1617/1550/1236 1618/1551/1237 1570/1500/1186 1569/1502/1188
+f 1619/1552/1238 1620/1553/1239 1572/1503/1189 1571/1501/1187
+f 1618/1551/1237 1619/1552/1238 1571/1501/1187 1570/1500/1186
+f 1624/1554/1240 1631/1555/1241 1629/1556/1242 1630/1557/1243
+f 1576/1507/1193 1622/1558/1244 1633/1559/1245 1634/1560/1246
+f 1623/1561/1247 1574/1505/1191 1572/1503/1189 1620/1553/1239
+f 1576/1507/1193 1574/1505/1191 1623/1561/1247 1622/1558/1244
+f 1633/1559/1245 1622/1558/1244 1625/1562/1248 1632/1563/1249
+f 1623/1561/1247 1620/1553/1239 1627/1564/1250 1626/1565/1251
+f 1620/1553/1239 1619/1552/1238 1628/1566/1252 1627/1564/1250
+f 1619/1552/1238 1618/1551/1237 1629/1556/1242 1628/1566/1252
+f 1618/1551/1237 1617/1550/1236 1630/1557/1243 1629/1556/1242
+f 1617/1550/1236 1621/1549/1235 1624/1554/1240 1630/1557/1243
+f 1629/1556/1242 1631/1555/1241 1627/1564/1250 1628/1566/1252
+f 1624/1554/1240 1632/1563/1249 1625/1562/1248 1631/1555/1241
+f 1627/1564/1250 1631/1555/1241 1625/1562/1248 1626/1565/1251
+f 1621/1549/1235 1633/1559/1245 1632/1563/1249 1624/1554/1240
+f 1634/1560/1246 1633/1559/1245 1621/1549/1235 1613/1546/1232
+f 1635/1567/1253 1634/1560/1246 1613/1546/1232 1614/1545/1231
+f 2044/1377/1063 1475/1380/1066 1650/1568/1254 2043/1569/1255
+f 1477/1381/1067 1476/1384/1070 1652/1570/1256 1653/1571/1257
+f 1478/1385/1071 1477/1381/1067 1653/1571/1257 1654/1572/1258
+f 1479/1387/1073 1478/1385/1071 1654/1572/1258 1655/1573/1259
+f 1480/1389/1075 1479/1387/1073 1655/1573/1259 1656/1574/1260
+f 1537/1391/1077 1480/1389/1075 1656/1574/1260 1657/1575/1261
+f 1482/1393/1079 1481/1396/1082 1658/1576/1262 1659/1577/1263
+f 1483/1397/1083 1482/1393/1079 1659/1577/1263 1648/1578/1264
+f 1484/1399/1085 1483/1397/1083 1648/1578/1264 1649/1579/1265
+f 1475/1380/1066 1484/1399/1085 1649/1579/1265 1650/1568/1254
+f 1481/1396/1082 2033/1456/1142 2034/1580/1266 1658/1576/1262
+f 1476/1384/1070 1539/1458/1144 1651/1581/1267 1652/1570/1256
+f 1649/1579/1265 1648/1578/1264 1646/1582/1268 1647/1583/1269
+f 1650/1568/1254 1649/1579/1265 1647/1583/1269 1636/1584/1270
+f 2043/1569/1255 1650/1568/1254 1636/1584/1270 2042/1585/1271
+f 1652/1570/1256 1651/1581/1267 1637/1586/1272 1638/1587/1273
+f 1653/1571/1257 1652/1570/1256 1638/1587/1273 1639/1588/1274
+f 1654/1572/1258 1653/1571/1257 1639/1588/1274 1640/1589/1275
+f 1655/1573/1259 1654/1572/1258 1640/1589/1275 1641/1590/1276
+f 1656/1574/1260 1655/1573/1259 1641/1590/1276 1642/1591/1277
+f 1657/1575/1261 1656/1574/1260 1642/1591/1277 1643/1592/1278
+f 1658/1576/1262 2034/1580/1266 2035/1593/1279 1644/1594/1280
+f 1659/1577/1263 1658/1576/1262 1644/1594/1280 1645/1595/1281
+f 1648/1578/1264 1659/1577/1263 1645/1595/1281 1646/1582/1268
+f 1639/1588/1274 1638/1587/1273 1661/1596/1282 1662/1597/1283
+f 1640/1589/1275 1639/1588/1274 1662/1597/1283 1663/1598/1284
+f 1641/1590/1276 1640/1589/1275 1663/1598/1284 1664/1599/1285
+f 1642/1591/1277 1641/1590/1276 1664/1599/1285 1665/1600/1286
+f 1643/1592/1278 1642/1591/1277 1665/1600/1286 1666/1601/1287
+f 1645/1595/1281 1644/1594/1280 1667/1602/1288 1668/1603/1289
+f 1646/1582/1268 1645/1595/1281 1668/1603/1289 1669/1604/1290
+f 1647/1583/1269 1646/1582/1268 1669/1604/1290 1670/1605/1291
+f 1636/1584/1270 1647/1583/1269 1670/1605/1291 1660/1606/1292
+f 1644/1594/1280 2035/1593/1279 2036/1607/1293 1667/1602/1288
+f 1662/1597/1283 1661/1596/1282 1673/1608/1294 1674/1609/1295
+f 1663/1598/1284 1662/1597/1283 1674/1609/1295 1675/1610/1296
+f 1664/1599/1285 1663/1598/1284 1675/1610/1296 1676/1611/1297
+f 1665/1600/1286 1664/1599/1285 1676/1611/1297 1677/1612/1298
+f 1666/1601/1287 1665/1600/1286 1677/1612/1298 1678/1613/1299
+f 1668/1603/1289 1667/1602/1288 1679/1614/1300 1680/1615/1301
+f 1669/1604/1290 1668/1603/1289 1680/1615/1301 1681/1616/1302
+f 1670/1605/1291 1669/1604/1290 1681/1616/1302 1682/1617/1303
+f 1660/1606/1292 1670/1605/1291 1682/1617/1303 1671/1618/1304
+f 1667/1602/1288 2036/1607/1293 2037/1619/1305 1679/1614/1300
+f 1674/1609/1295 1673/1608/1294 1672/1620/1306 1685/1621/1307
+f 2037/1619/1305 2038/1622/1308 1680/1615/1301 1679/1614/1300
+f 1675/1610/1296 1683/1623/1309 1684/1624/1310 1676/1611/1297
+f 1681/1616/1302 2039/1625/1311 2040/1626/1312 1682/1617/1303
+f 2038/1622/1308 2039/1625/1311 1681/1616/1302 1680/1615/1301
+f 1676/1611/1297 1684/1624/1310 1678/1613/1299 1677/1612/1298
+f 1674/1609/1295 1685/1621/1307 1683/1623/1309 1675/1610/1296
+f 1682/1617/1303 2040/1626/1312 2041/1627/1313 1671/1618/1304
+f 1513/1422/1108 1514/1421/1107 1687/1628/1314 1686/1629/1315
+f 1514/1421/1107 1515/1423/1109 1688/1630/1316 1687/1628/1314
+f 1515/1423/1109 1516/1424/1110 1689/1631/1317 1688/1630/1316
+f 1516/1424/1110 1517/1425/1111 1690/1632/1318 1689/1631/1317
+f 1518/1426/1112 1513/1422/1108 1686/1629/1315 1691/1633/1319
+f 1519/1428/1114 1518/1426/1112 1691/1633/1319 1692/1634/1320
+f 2031/1538/1224 1605/1537/1223 1693/1635/1321 2030/1636/1322
+f 1517/1425/1111 1606/1535/1221 1694/1637/1323 1690/1632/1318
+f 2068/1638/1324 2069/1541/1227 1610/1542/1228 1696/1639/1325
+f 1696/1639/1325 1610/1542/1228 1609/1544/1230 1695/1640/1326
+f 2011/1641/1327 2012/1642/1328 2013/1643/1329 2014/1644/1330
+f 1707/1645/1331 2012/1642/1328 1597/1527/1213 1596/1525/1211
+f 1718/1646/1332 1699/1647/1333 2085/1648/1334 2086/1649/1335
+f 1047/1650/1336 1043/1651/1337 1716/1652/1338 1704/1653/1339
+f 1717/1654/1340 1700/1655/1341 1704/1653/1339 1716/1652/1338
+f 1699/1647/1333 1707/1645/1331 2084/1656/1342 2085/1648/1334
+f 1949/1657/1343 1950/1658/1344 1725/1659/1345 1724/1660/1346
+f 1595/1523/1209 1708/1661/1347 1707/1645/1331 1596/1525/1211
+f 2084/1656/1342 1707/1645/1331 1708/1661/1347 2083/1662/1348
+f 1595/1523/1209 1533/1450/1136 1711/1663/1349 1708/1661/1347
+f 2083/1662/1348 1708/1661/1347 1711/1663/1349 2082/1664/1350
+f 1709/1665/1351 1584/1454/1140 1532/1518/1204 1705/1666/1352
+f 2080/1667/1353 1709/1665/1351 1705/1666/1352 2079/1668/1354
+f 1710/1669/1355 1531/1449/1135 1584/1454/1140 1709/1665/1351
+f 2081/1670/1356 1710/1669/1355 1709/1665/1351 2080/1667/1353
+f 1533/1450/1136 1531/1449/1135 1710/1669/1355 1711/1663/1349
+f 2082/1664/1350 1711/1663/1349 1710/1669/1355 2081/1670/1356
+f 1726/1671/1357 1951/1672/1358 1952/1673/1359 1727/1674/1360
+f 1700/1655/1341 1712/1675/1361 1713/1676/1362 1704/1653/1339
+f 1704/1653/1339 1713/1676/1362 1046/1677/1363 1047/1650/1336
+f 1725/1659/1345 1950/1658/1344 1951/1672/1358 1726/1671/1357
+f 1948/1678/1364 1949/1657/1343 1724/1660/1346 1723/1679/1365
+f 1043/1651/1337 1049/1680/1366 1703/1681/1367 1716/1652/1338
+f 1701/1682/1368 1717/1654/1340 1716/1652/1338 1703/1681/1367
+f 1702/1683/1369 1718/1646/1332 2086/1649/1335 2087/1684/1370
+f 1718/1646/1332 1702/1683/1369 1697/1685/1371 1719/1686/1372
+f 1720/1687/1373 1719/1686/1372 1697/1685/1371 1698/1688/1374
+f 1947/1689/1375 1948/1678/1364 1723/1679/1365 1722/1690/1376
+f 1721/1691/1377 1946/1692/1378 1947/1689/1375 1722/1690/1376
+f 1728/1693/1379 1727/1674/1360 1952/1673/1359 1953/1694/1380
+f 1954/1695/1381 1729/1696/1382 1728/1693/1379 1953/1694/1380
+f 1957/1697/1383 1958/1698/1384 1706/1699/1385 1715/1700/1386
+f 1715/1700/1386 1714/1701/1387 1734/1702/1388 1733/1703/1389
+f 1735/1704/1390 1734/1702/1388 1714/1701/1387 1712/1675/1361
+f 1736/1705/1391 1735/1704/1390 1712/1675/1361 1700/1655/1341
+f 1737/1706/1392 1736/1705/1391 1700/1655/1341 1717/1654/1340
+f 1738/1707/1393 1737/1706/1392 1717/1654/1340 1701/1682/1368
+f 2030/1636/1322 1693/1635/1321 1765/1708/1394 2029/1709/1395
+f 1690/1632/1318 1694/1637/1323 1766/1710/1396 1740/1711/1397
+f 1742/1712/1398 1774/1713/1399 1741/1714/1400 1764/1715/1401
+f 2068/1638/1324 1696/1639/1325 1742/1712/1398 2067/1716/1402
+f 1689/1631/1317 1690/1632/1318 1740/1711/1397 1743/1717/1403
+f 1692/1634/1320 1691/1633/1319 1749/1718/1404 1747/1719/1405
+f 1745/1720/1406 1688/1630/1316 1689/1631/1317 1743/1717/1403
+f 1746/1721/1407 1687/1628/1314 1688/1630/1316 1745/1720/1406
+f 1748/1722/1408 1686/1629/1315 1687/1628/1314 1746/1721/1407
+f 1749/1718/1404 1691/1633/1319 1686/1629/1315 1748/1722/1408
+f 1743/1717/1403 1740/1711/1397 1767/1723/1409 1768/1724/1410
+f 1745/1720/1406 1743/1717/1403 1768/1724/1410 1769/1725/1411
+f 1746/1721/1407 1745/1720/1406 1769/1725/1411 1770/1726/1412
+f 1748/1722/1408 1746/1721/1407 1770/1726/1412 1771/1727/1413
+f 1749/1718/1404 1748/1722/1408 1771/1727/1413 1772/1728/1414
+f 1747/1719/1405 1749/1718/1404 1772/1728/1414 1773/1729/1415
+f 2026/1730/1416 1935/1731/1417 1782/1732/1418 2025/1733/1419
+f 2066/1734/1420 1764/1715/1401 1779/1735/1421 2065/1736/1422
+f 2028/1737/1423 1780/1738/1424 1781/1739/1425 2027/1740/1426
+f 2025/1733/1419 1782/1732/1418 1945/1741/1427 2024/1742/1428
+f 1933/1743/1429 1934/1744/1430 1750/1745/1431 1751/1746/1432
+f 1932/1747/1433 1933/1743/1429 1751/1746/1432 1752/1748/1434
+f 1931/1749/1435 1932/1747/1433 1752/1748/1434 1753/1750/1436
+f 1930/1751/1437 1931/1749/1435 1753/1750/1436 1754/1752/1438
+f 1929/1753/1439 1930/1751/1437 1754/1752/1438 1755/1754/1440
+f 1928/1755/1441 1929/1753/1439 1755/1754/1440 1756/1756/1442
+f 1927/1757/1443 1928/1755/1441 1756/1756/1442 1757/1758/1444
+f 1740/1711/1397 1766/1710/1396 1739/1759/1445 1767/1723/1409
+f 1696/1639/1325 1695/1640/1326 1774/1713/1399 1742/1712/1398
+f 1936/1760/1446 1937/1761/1447 1777/1522/1208 1776/1521/1207
+f 1937/1761/1447 1938/1762/1448 1778/1763/1449 1777/1522/1208
+f 1938/1762/1448 1939/1531/1217 1600/1529/1215 1778/1763/1449
+f 1966/1764/1450 1967/1519/1205 1777/1522/1208 1778/1763/1449
+f 1600/1529/1215 1965/1765/1451 1966/1764/1450 1778/1763/1449
+f 1534/1448/1134 1964/1766/1452 1965/1765/1451 1600/1529/1215
+f 1963/1767/1453 1964/1766/1452 1534/1448/1134 1535/1447/1133
+f 1583/1446/1132 1962/1768/1454 1963/1767/1453 1535/1447/1133
+f 1536/1516/1202 1961/1769/1455 1962/1768/1454 1583/1446/1132
+f 1597/1527/1213 1598/1770/1456 1783/1771/1457 1784/1528/1214
+f 1792/1772/1458 1254/1773/1459 1050/1774/1460 1793/1775/1461
+f 1738/1707/1393 1701/1682/1368 1794/1776/1462 1796/1777/1463
+f 1956/1778/1464 1051/1779/1465 1056/1780/1466 1795/1781/1467
+f 1729/1696/1382 1954/1695/1381 1955/1782/1468 1797/1783/1469
+f 1794/1776/1462 1792/1772/1458 1793/1775/1461 1796/1777/1463
+f 1956/1778/1464 1795/1781/1467 1797/1783/1469 1955/1782/1468
+f 1758/1784/1470 1744/1785/1471 2016/1786/1472 2017/1787/1473
+f 1763/1788/1474 1760/1789/1475 2021/1790/1476 2022/1791/1477
+f 1791/1792/1478 1758/1784/1470 2017/1787/1473 2018/1793/1479
+f 1761/1794/1480 1762/1795/1481 2019/1796/1482 2020/1797/1483
+f 1760/1789/1475 1761/1794/1480 2020/1797/1483 2021/1790/1476
+f 1759/1798/1484 1763/1788/1474 2022/1791/1477 2023/1799/1485
+f 1744/1785/1471 1775/1800/1486 2015/1801/1487 2016/1786/1472
+f 1762/1795/1481 1791/1792/1478 2018/1793/1479 2019/1796/1482
+f 2015/1801/1487 1775/1800/1486 2011/1641/1327 2014/1644/1330
+f 1751/1746/1432 1750/1745/1431 1807/1802/1488 1808/1803/1489
+f 1752/1748/1434 1751/1746/1432 1808/1803/1489 1809/1804/1490
+f 1753/1750/1436 1752/1748/1434 1809/1804/1490 1810/1805/1491
+f 1754/1752/1438 1753/1750/1436 1810/1805/1491 1811/1806/1492
+f 1755/1754/1440 1754/1752/1438 1811/1806/1492 1812/1807/1493
+f 1756/1756/1442 1755/1754/1440 1812/1807/1493 1813/1808/1494
+f 1757/1758/1444 1756/1756/1442 1813/1808/1494 1814/1809/1495
+f 1881/1810/1496 1815/1811/1497 1883/1812/1498 1882/1813/1499
+f 1848/1814/1500 1816/1815/1501 1850/1816/1502 1849/1817/1503
+f 1829/1818/1504 1817/1819/1505 1831/1820/1506 1830/1821/1507
+f 1821/1822/1508 1818/1823/1509 1823/1824/1510 1822/1825/1511
+f 1805/1826/1512 1801/1827/1513 1819/1828/1514 1820/1829/1515
+f 1807/1802/1488 1805/1826/1512 1820/1829/1515 1808/1803/1489
+f 1819/1828/1514 1821/1822/1508 1822/1825/1511 1820/1829/1515
+f 1822/1825/1511 1809/1804/1490 1808/1803/1489 1820/1829/1515
+f 1823/1824/1510 1810/1805/1491 1809/1804/1490 1822/1825/1511
+f 1804/1830/1516 1803/1831/1517 1824/1832/1518 1826/1833/1519
+f 1801/1827/1513 1800/1834/1520 1825/1835/1521 1819/1828/1514
+f 1800/1834/1520 1804/1830/1516 1826/1833/1519 1825/1835/1521
+f 1827/1836/1522 1818/1823/1509 1821/1822/1508 1828/1837/1523
+f 1821/1822/1508 1819/1828/1514 1825/1835/1521 1828/1837/1523
+f 1824/1832/1518 1829/1818/1504 1830/1821/1507 1826/1833/1519
+f 1830/1821/1507 1828/1837/1523 1825/1835/1521 1826/1833/1519
+f 1831/1820/1506 1827/1836/1522 1828/1837/1523 1830/1821/1507
+f 1832/1838/1524 1839/1839/1525 1838/1840/1526 1837/1841/1527
+f 1835/1842/1528 1834/1843/1529 1833/1844/1530 1836/1845/1531
+f 1823/1824/1510 1818/1823/1509 1834/1843/1529 1835/1842/1528
+f 1811/1806/1492 1810/1805/1491 1823/1824/1510 1835/1842/1528
+f 1812/1807/1493 1811/1806/1492 1835/1842/1528 1836/1845/1531
+f 1836/1845/1531 1833/1844/1530 1837/1841/1527 1838/1840/1526
+f 1813/1808/1494 1812/1807/1493 1836/1845/1531 1838/1840/1526
+f 1839/1839/1525 1814/1809/1495 1813/1808/1494 1838/1840/1526
+f 1843/1846/1532 1840/1847/1533 1845/1848/1534 1844/1849/1535
+f 1841/1850/1536 1833/1844/1530 1834/1843/1529 1842/1851/1537
+f 1834/1843/1529 1818/1823/1509 1827/1836/1522 1842/1851/1537
+f 1817/1819/1505 1843/1846/1532 1844/1849/1535 1831/1820/1506
+f 1844/1849/1535 1842/1851/1537 1827/1836/1522 1831/1820/1506
+f 1845/1848/1534 1841/1850/1536 1842/1851/1537 1844/1849/1535
+f 1846/1852/1538 1832/1838/1524 1837/1841/1527 1847/1853/1539
+f 1837/1841/1527 1833/1844/1530 1841/1850/1536 1847/1853/1539
+f 1840/1847/1533 1848/1814/1500 1849/1817/1503 1845/1848/1534
+f 1849/1817/1503 1847/1853/1539 1841/1850/1536 1845/1848/1534
+f 1850/1816/1502 1846/1852/1538 1847/1853/1539 1849/1817/1503
+f 1862/1854/1540 1851/1855/1541 1864/1856/1542 1863/1857/1543
+f 1855/1858/1544 1852/1859/1545 1857/1860/1546 1856/1861/1547
+f 1802/1862/1548 1799/1863/1549 1853/1864/1550 1854/1865/1551
+f 1803/1831/1517 1802/1862/1548 1854/1865/1551 1824/1832/1518
+f 1853/1864/1550 1855/1858/1544 1856/1861/1547 1854/1865/1551
+f 1856/1861/1547 1829/1818/1504 1824/1832/1518 1854/1865/1551
+f 1857/1860/1546 1817/1819/1505 1829/1818/1504 1856/1861/1547
+f 1806/1866/1552 1720/1687/1373 1698/1688/1374 1859/1867/1553
+f 1799/1863/1549 1798/1868/1554 1858/1869/1555 1853/1864/1550
+f 1798/1868/1554 1806/1866/1552 1859/1867/1553 1858/1869/1555
+f 1860/1870/1556 1852/1859/1545 1855/1858/1544 1861/1871/1557
+f 1855/1858/1544 1853/1864/1550 1858/1869/1555 1861/1871/1557
+f 1698/1688/1374 1862/1854/1540 1863/1857/1543 1859/1867/1553
+f 1863/1857/1543 1861/1871/1557 1858/1869/1555 1859/1867/1553
+f 1864/1856/1542 1860/1870/1556 1861/1871/1557 1863/1857/1543
+f 1865/1872/1558 1872/1873/1559 1871/1874/1560 1870/1875/1561
+f 1868/1876/1562 1867/1877/1563 1866/1878/1564 1869/1879/1565
+f 1857/1860/1546 1852/1859/1545 1867/1877/1563 1868/1876/1562
+f 1843/1846/1532 1817/1819/1505 1857/1860/1546 1868/1876/1562
+f 1840/1847/1533 1843/1846/1532 1868/1876/1562 1869/1879/1565
+f 1869/1879/1565 1866/1878/1564 1870/1875/1561 1871/1874/1560
+f 1848/1814/1500 1840/1847/1533 1869/1879/1565 1871/1874/1560
+f 1872/1873/1559 1816/1815/1501 1848/1814/1500 1871/1874/1560
+f 1876/1880/1566 1873/1881/1567 1878/1882/1568 1877/1883/1569
+f 1874/1884/1570 1866/1878/1564 1867/1877/1563 1875/1885/1571
+f 1867/1877/1563 1852/1859/1545 1860/1870/1556 1875/1885/1571
+f 1851/1855/1541 1876/1880/1566 1877/1883/1569 1864/1856/1542
+f 1877/1883/1569 1875/1885/1571 1860/1870/1556 1864/1856/1542
+f 1878/1882/1568 1874/1884/1570 1875/1885/1571 1877/1883/1569
+f 1879/1886/1572 1865/1872/1558 1870/1875/1561 1880/1887/1573
+f 1870/1875/1561 1866/1878/1564 1874/1884/1570 1880/1887/1573
+f 1873/1881/1567 1881/1810/1496 1882/1813/1499 1878/1882/1568
+f 1882/1813/1499 1880/1887/1573 1874/1884/1570 1878/1882/1568
+f 1883/1812/1498 1879/1886/1572 1880/1887/1573 1882/1813/1499
+f 1046/1677/1363 1713/1676/1362 1885/1888/1574 1045/1889/1575
+f 1885/1888/1574 1713/1676/1362 1712/1675/1361 1714/1701/1387
+f 1886/1890/1576 1885/1888/1574 1714/1701/1387 1715/1700/1386
+f 1045/1889/1575 1885/1888/1574 1886/1890/1576 1048/1891/1577
+f 1886/1890/1576 1715/1700/1386 1706/1699/1385 1884/1892/1578
+f 1884/1892/1578 1044/1893/1579 1048/1891/1577 1886/1890/1576
+f 1792/1772/1458 1703/1681/1367 1049/1680/1366 1254/1773/1459
+f 1792/1772/1458 1794/1776/1462 1701/1682/1368 1703/1681/1367
+f 1702/1683/1369 2087/1684/1370 1895/1894/1580 2077/1895/1581
+f 1887/1896/1582 1899/1897/1583 1052/1898/1584 1057/1899/1585
+f 1055/1900/1586 1892/1901/1587 1795/1781/1467 1056/1780/1466
+f 1053/1902/1588 1891/1903/1589 2078/1904/1590 1054/1905/1591
+f 1893/1906/1592 1898/1907/1593 1899/1897/1583 1887/1896/1582
+f 1894/1908/1594 2077/1895/1581 2078/1904/1590 1891/1903/1589
+f 1895/1894/1580 1797/1783/1469 1795/1781/1467 1892/1901/1587
+f 1889/1909/1595 1898/1907/1593 1893/1906/1592 1888/1910/1596
+f 1702/1683/1369 2077/1895/1581 1894/1908/1594 1890/1911/1597
+f 1702/1683/1369 1890/1911/1597 1896/1912/1598 1697/1685/1371
+f 1890/1911/1597 1889/1909/1595 1897/1913/1599 1896/1912/1598
+f 1862/1854/1540 1698/1688/1374 1697/1685/1371 1896/1912/1598
+f 1851/1855/1541 1862/1854/1540 1896/1912/1598 1897/1913/1599
+f 1890/1911/1597 1894/1908/1594 1898/1907/1593 1889/1909/1595
+f 1899/1897/1583 1898/1907/1593 1894/1908/1594 1891/1903/1589
+f 1052/1898/1584 1899/1897/1583 1891/1903/1589 1053/1902/1588
+f 1815/1811/1497 1881/1810/1496 1900/1914/1600 1901/1915/1601
+f 1873/1881/1567 1876/1880/1566 1902/1916/1602 1903/1917/1603
+f 1876/1880/1566 1851/1855/1541 1897/1913/1599 1902/1916/1602
+f 1881/1810/1496 1873/1881/1567 1903/1917/1603 1900/1914/1600
+f 1900/1914/1600 1904/1918/1604 1905/1919/1605 1901/1915/1601
+f 1902/1916/1602 1906/1920/1606 1907/1921/1607 1903/1917/1603
+f 1889/1909/1595 1906/1920/1606 1902/1916/1602 1897/1913/1599
+f 1907/1921/1607 1904/1918/1604 1900/1914/1600 1903/1917/1603
+f 1905/1919/1605 1904/1918/1604 1908/1922/1608 1909/1923/1609
+f 1907/1921/1607 1906/1920/1606 1910/1924/1610 1911/1925/1611
+f 1906/1920/1606 1889/1909/1595 1888/1910/1596 1910/1924/1610
+f 1904/1918/1604 1907/1921/1607 1911/1925/1611 1908/1922/1608
+f 1913/1926/1612 1256/1927/1613 1255/1928/1614 1912/1929/1615
+f 1914/1930/1616 1257/1931/1617 1256/1927/1613 1913/1926/1612
+f 1919/1932/1618 1258/1933/1619 1257/1931/1617 1914/1930/1616
+f 1925/1934/1620 1926/1935/1621 1909/1923/1609 1908/1922/1608
+f 1925/1934/1620 1908/1922/1608 1911/1925/1611 1924/1936/1622
+f 1913/1926/1612 1915/1937/1623 1917/1938/1624 1914/1930/1616
+f 1913/1926/1612 1912/1929/1615 1916/1939/1625 1915/1937/1623
+f 1924/1936/1622 1911/1925/1611 1910/1924/1610 1923/1940/1626
+f 1914/1930/1616 1917/1938/1624 1918/1941/1627 1919/1932/1618
+f 1923/1940/1626 1910/1924/1610 1888/1910/1596 1922/1942/1628
+f 1919/1932/1618 1918/1941/1627 1920/1943/1629 1921/1944/1630
+f 1259/1945/1631 1258/1933/1619 1919/1932/1618 1921/1944/1630
+f 1920/1943/1629 1922/1942/1628 1888/1910/1596 1893/1906/1592
+f 1921/1944/1630 1920/1943/1629 1893/1906/1592 1887/1896/1582
+f 1057/1899/1585 1259/1945/1631 1921/1944/1630 1887/1896/1582
+f 1918/1941/1627 1923/1940/1626 1922/1942/1628 1920/1943/1629
+f 1917/1938/1624 1924/1936/1622 1923/1940/1626 1918/1941/1627
+f 1915/1937/1623 1925/1934/1620 1924/1936/1622 1917/1938/1624
+f 1915/1937/1623 1916/1939/1625 1926/1935/1621 1925/1934/1620
+f 1773/1729/1415 1772/1728/1414 1928/1755/1441 1927/1757/1443
+f 1772/1728/1414 1771/1727/1413 1929/1753/1439 1928/1755/1441
+f 1771/1727/1413 1770/1726/1412 1930/1751/1437 1929/1753/1439
+f 1770/1726/1412 1769/1725/1411 1931/1749/1435 1930/1751/1437
+f 1769/1725/1411 1768/1724/1410 1932/1747/1433 1931/1749/1435
+f 1768/1724/1410 1767/1723/1409 1933/1743/1429 1932/1747/1433
+f 1767/1723/1409 1739/1759/1445 1934/1744/1430 1933/1743/1429
+f 2027/1740/1426 1781/1739/1425 1935/1731/1417 2026/1730/1416
+f 1695/1640/1326 1609/1544/1230 1937/1761/1447 1936/1760/1446
+f 1609/1544/1230 1607/1543/1229 1938/1762/1448 1937/1761/1447
+f 1607/1543/1229 1601/1532/1218 1939/1531/1217 1938/1762/1448
+f 1520/1442/1128 1940/1441/1127 1939/1531/1217 1601/1532/1218
+f 1529/1443/1129 1941/1438/1124 1940/1441/1127 1520/1442/1128
+f 1558/1488/1174 1942/1485/1171 1941/1438/1124 1529/1443/1129
+f 1590/1476/1162 1943/1468/1154 1942/1485/1171 1558/1488/1174
+f 1543/1475/1161 1944/1465/1151 1943/1468/1154 1590/1476/1162
+f 1557/1479/1165 1556/1482/1168 2093/1946/1632 2094/1947/1633
+f 1553/1483/1169 1557/1479/1165 2094/1947/1633 2095/1948/1634
+f 1566/1478/1164 1553/1483/1169 2095/1948/1634 2091/1949/1635
+f 1546/1464/1150 1545/1463/1149 2097/1950/1636 2098/1951/1637
+f 1545/1463/1149 1544/1474/1160 2096/1952/1638 2097/1950/1636
+f 2090/1953/1639 1559/1466/1152 1944/1465/1151 2088/1954/1640
+f 2024/1742/1428 1945/1741/1427 1759/1798/1484 2023/1799/1485
+f 1946/1692/1378 1730/1955/1641 1731/1956/1642 1947/1689/1375
+f 1731/1956/1642 1732/1957/1643 1948/1678/1364 1947/1689/1375
+f 1732/1957/1643 1733/1703/1389 1949/1657/1343 1948/1678/1364
+f 1733/1703/1389 1734/1702/1388 1950/1658/1344 1949/1657/1343
+f 1951/1672/1358 1950/1658/1344 1734/1702/1388 1735/1704/1390
+f 1952/1673/1359 1951/1672/1358 1735/1704/1390 1736/1705/1391
+f 1953/1694/1380 1952/1673/1359 1736/1705/1391 1737/1706/1392
+f 1738/1707/1393 1954/1695/1381 1953/1694/1380 1737/1706/1392
+f 1955/1782/1468 1954/1695/1381 1738/1707/1393 1796/1777/1463
+f 1793/1775/1461 1956/1778/1464 1955/1782/1468 1796/1777/1463
+f 1793/1775/1461 1050/1774/1460 1051/1779/1465 1956/1778/1464
+f 1957/1697/1383 1715/1700/1386 1733/1703/1389 1732/1957/1643
+f 1731/1956/1642 1960/1958/1644 1957/1697/1383 1732/1957/1643
+f 1731/1956/1642 1730/1955/1641 1959/1959/1645 1960/1958/1644
+f 1957/1697/1383 1960/1958/1644 1959/1959/1645 1958/1698/1384
+f 1961/1769/1455 1790/1517/1203 1789/1453/1139 1962/1768/1454
+f 1963/1767/1453 1962/1768/1454 1789/1453/1139 1788/1452/1138
+f 1788/1452/1138 1787/1451/1137 1964/1766/1452 1963/1767/1453
+f 1965/1765/1451 1964/1766/1452 1787/1451/1137 1786/1524/1210
+f 1966/1764/1450 1965/1765/1451 1786/1524/1210 1785/1526/1212
+f 1785/1526/1212 1784/1528/1214 1967/1519/1205 1966/1764/1450
+f 1784/1528/1214 1783/1771/1457 1599/1520/1206 1967/1519/1205
+f 2064/1960/1646 1983/1961/1647 1968/1962/1648 2063/1963/1649
+f 1973/1964/1650 1970/1965/1651 1971/1966/1652 1972/1967/1653
+f 1974/1968/1654 1975/1969/1655 1970/1965/1651 1973/1964/1650
+f 1982/1970/1656 1969/1971/1657 1975/1969/1655 1974/1968/1654
+f 1972/1967/1653 1971/1966/1652 1976/1972/1658 1981/1973/1659
+f 1981/1973/1659 1976/1972/1658 1977/1974/1660 1980/1975/1661
+f 1980/1975/1661 1977/1974/1660 1978/1976/1662 1979/1977/1663
+f 2065/1736/1422 1779/1735/1421 1983/1961/1647 2064/1960/1646
+f 1935/1731/1417 1973/1964/1650 1988/1978/1664 1782/1732/1418
+f 1974/1968/1654 1973/1964/1650 1935/1731/1417 1781/1739/1425
+f 1980/1975/1661 1979/1977/1663 1985/1979/1665 1986/1980/1666
+f 1981/1973/1659 1980/1975/1661 1986/1980/1666 1987/1981/1667
+f 1972/1967/1653 1981/1973/1659 1987/1981/1667 1984/1982/1668
+f 1982/1970/1656 1974/1968/1654 1781/1739/1425 1780/1738/1424
+f 1973/1964/1650 1972/1967/1653 1984/1982/1668 1988/1978/1664
+f 1945/1741/1427 1782/1732/1418 1988/1978/1664 1984/1982/1668
+f 1759/1798/1484 1945/1741/1427 1984/1982/1668 1987/1981/1667
+f 1763/1788/1474 1759/1798/1484 1987/1981/1667 1986/1980/1666
+f 1760/1789/1475 1763/1788/1474 1986/1980/1666 1985/1979/1665
+f 1979/1977/1663 1978/1976/1662 1989/1983/1669 1996/1984/1670
+f 1996/1984/1670 1989/1983/1669 1990/1985/1671 1995/1986/1672
+f 1995/1986/1672 1990/1985/1671 1991/1987/1673 1994/1988/1674
+f 1994/1988/1674 1991/1987/1673 1992/1989/1675 1993/1990/1676
+f 1994/1988/1674 1993/1990/1676 1997/1991/1677 1998/1992/1678
+f 1995/1986/1672 1994/1988/1674 1998/1992/1678 1999/1993/1679
+f 1996/1984/1670 1995/1986/1672 1999/1993/1679 2000/1994/1680
+f 1979/1977/1663 1996/1984/1670 2000/1994/1680 1985/1979/1665
+f 1999/1993/1679 1762/1795/1481 1761/1794/1480 2000/1994/1680
+f 2000/1994/1680 1761/1794/1480 1760/1789/1475 1985/1979/1665
+f 1758/1784/1470 1791/1792/1478 1998/1992/1678 1997/1991/1677
+f 1998/1992/1678 1791/1792/1478 1762/1795/1481 1999/1993/1679
+f 1993/1990/1676 1992/1989/1675 2001/1995/1681 2004/1996/1682
+f 2003/1997/1683 2002/1998/1684 1599/1520/1206 1783/1771/1457
+f 2004/1996/1682 2001/1995/1681 2002/1998/1684 2003/1997/1683
+f 1758/1784/1470 1997/1991/1677 2005/1999/1685 1744/1785/1471
+f 2003/1997/1683 2006/2000/1686 2005/1999/1685 2004/1996/1682
+f 1744/1785/1471 2005/1999/1685 2006/2000/1686 1775/1800/1486
+f 1598/1770/1456 2006/2000/1686 2003/1997/1683 1783/1771/1457
+f 2004/1996/1682 2005/1999/1685 1997/1991/1677 1993/1990/1676
+f 2007/2001/1687 1774/1713/1399 1695/1640/1326 1936/1760/1446
+f 1741/1714/1400 1774/1713/1399 2007/2001/1687 2008/2002/1688
+f 2008/2002/1688 2007/2001/1687 2009/2003/1689 2010/2004/1690
+f 2009/2003/1689 2007/2001/1687 1936/1760/1446 1776/1521/1207
+f 2002/1998/1684 2009/2003/1689 1776/1521/1207 1599/1520/1206
+f 2010/2004/1690 2009/2003/1689 2002/1998/1684 2001/1995/1681
+f 1775/1800/1486 2006/2000/1686 1598/1770/1456 2011/1641/1327
+f 1598/1770/1456 1597/1527/1213 2012/1642/1328 2011/1641/1327
+f 2012/1642/1328 1707/1645/1331 1699/1647/1333 2013/1643/1329
+f 2014/1644/1330 2013/1643/1329 1719/1686/1372 1720/1687/1373
+f 1806/1866/1552 2015/1801/1487 2014/1644/1330 1720/1687/1373
+f 2016/1786/1472 2015/1801/1487 1806/1866/1552 1798/1868/1554
+f 2017/1787/1473 2016/1786/1472 1798/1868/1554 1799/1863/1549
+f 2018/1793/1479 2017/1787/1473 1799/1863/1549 1802/1862/1548
+f 2019/1796/1482 2018/1793/1479 1802/1862/1548 1803/1831/1517
+f 2020/1797/1483 2019/1796/1482 1803/1831/1517 1804/1830/1516
+f 2021/1790/1476 2020/1797/1483 1804/1830/1516 1800/1834/1520
+f 2022/1791/1477 2021/1790/1476 1800/1834/1520 1801/1827/1513
+f 2023/1799/1485 2022/1791/1477 1801/1827/1513 1805/1826/1512
+f 1807/1802/1488 2024/1742/1428 2023/1799/1485 1805/1826/1512
+f 1750/1745/1431 2025/1733/1419 2024/1742/1428 1807/1802/1488
+f 1934/1744/1430 2026/1730/1416 2025/1733/1419 1750/1745/1431
+f 1739/1759/1445 2027/1740/1426 2026/1730/1416 1934/1744/1430
+f 2029/1709/1395 2027/1740/1426 1739/1759/1445 1766/1710/1396
+f 1764/1715/1401 2066/1734/1420 2067/1716/1402 1742/1712/1398
+f 2013/1643/1329 1699/1647/1333 1718/1646/1332 1719/1686/1372
+f 1694/1637/1323 2030/1636/1322 2029/1709/1395 1766/1710/1396
+f 1606/1535/1221 2031/1538/1224 2030/1636/1322 1694/1637/1323
+f 2032/1455/1141 2031/1538/1224 1606/1535/1221 1538/1392/1078
+f 2033/1456/1142 2032/1455/1141 1538/1392/1078 1537/1391/1077
+f 2034/1580/1266 2033/1456/1142 1537/1391/1077 1657/1575/1261
+f 2035/1593/1279 2034/1580/1266 1657/1575/1261 1643/1592/1278
+f 2036/1607/1293 2035/1593/1279 1643/1592/1278 1666/1601/1287
+f 2037/1619/1305 2036/1607/1293 1666/1601/1287 1678/1613/1299
+f 1678/1613/1299 1684/1624/1310 2038/1622/1308 2037/1619/1305
+f 1684/1624/1310 1683/1623/1309 2039/1625/1311 2038/1622/1308
+f 2040/1626/1312 2039/1625/1311 1683/1623/1309 1685/1621/1307
+f 2041/1627/1313 2040/1626/1312 1685/1621/1307 1672/1620/1306
+f 1765/1708/1394 2028/1737/1423 2027/1740/1426 2029/1709/1395
+f 1651/1581/1267 2043/1569/1255 2042/1585/1271 1637/1586/1272
+f 1539/1458/1144 2044/1377/1063 2043/1569/1255 1651/1581/1267
+f 1539/1458/1144 1540/1457/1143 2045/1378/1064 2044/1377/1063
+f 1540/1457/1143 1541/1459/1145 2046/1401/1087 2045/1378/1064
+f 1541/1459/1145 1542/1460/1146 2047/1403/1089 2046/1401/1087
+f 1661/1596/1282 2048/2005/1691 1672/1620/1306 1673/1608/1294
+f 1637/1586/1272 2048/2005/1691 1661/1596/1282 1638/1587/1273
+f 2042/1585/1271 2049/2006/1692 2048/2005/1691 1637/1586/1272
+f 1672/1620/1306 2048/2005/1691 2049/2006/1692 2041/1627/1313
+f 1636/1584/1270 1660/1606/1292 2049/2006/1692 2042/1585/1271
+f 2041/1627/1313 2049/2006/1692 1660/1606/1292 1671/1618/1304
+f 1779/1735/1421 2054/2007/1693 2055/2008/1694 1983/1961/1647
+f 2010/2004/1690 2001/1995/1681 1992/1989/1675 2053/2009/1695
+f 2053/2009/1695 1992/1989/1675 1991/1987/1673 2052/2010/1696
+f 2052/2010/1696 1991/1987/1673 1990/1985/1671 2051/2011/1697
+f 2051/2011/1697 1990/1985/1671 1989/1983/1669 2050/2012/1698
+f 2056/2013/1699 2058/2014/1700 2057/2015/1701 1968/1962/1648
+f 2056/2013/1699 1968/1962/1648 1983/1961/1647 2055/2008/1694
+f 1741/1714/1400 2054/2007/1693 1779/1735/1421 1764/1715/1401
+f 1741/1714/1400 2008/2002/1688 2010/2004/1690 2054/2007/1693
+f 2055/2008/1694 2054/2007/1693 2010/2004/1690 2053/2009/1695
+f 2052/2010/1696 2056/2013/1699 2055/2008/1694 2053/2009/1695
+f 2051/2011/1697 2050/2012/1698 2057/2015/1701 2058/2014/1700
+f 2051/2011/1697 2058/2014/1700 2056/2013/1699 2052/2010/1696
+f 1970/1965/1651 1975/1969/1655 1969/1971/1657 2059/2016/1702
+f 2062/2017/1703 2063/1963/1649 1968/1962/1648 2057/2015/1701
+f 1971/1966/1652 1970/1965/1651 2059/2016/1702 2060/2018/1704
+f 2061/2019/1705 2062/2017/1703 2057/2015/1701 2050/2012/1698
+f 1977/1974/1660 1976/1972/1658 1971/1966/1652 2060/2018/1704
+f 2061/2019/1705 1978/1976/1662 1977/1974/1660 2060/2018/1704
+f 2060/2018/1704 2059/2016/1702 2062/2017/1703 2061/2019/1705
+f 2059/2016/1702 1969/1971/1657 2063/1963/1649 2062/2017/1703
+f 1982/1970/1656 2064/1960/1646 2063/1963/1649 1969/1971/1657
+f 1780/1738/1424 2065/1736/1422 2064/1960/1646 1982/1970/1656
+f 2028/1737/1423 2066/1734/1420 2065/1736/1422 1780/1738/1424
+f 2067/1716/1402 2066/1734/1420 2028/1737/1423 1765/1708/1394
+f 1693/1635/1321 2068/1638/1324 2067/1716/1402 1765/1708/1394
+f 1693/1635/1321 1605/1537/1223 2069/1541/1227 2068/1638/1324
+f 1605/1537/1223 1604/1536/1222 2070/1539/1225 2069/1541/1227
+f 1604/1536/1222 1603/1530/1216 2071/1534/1220 2070/1539/1225
+f 2072/1414/1100 2071/1534/1220 1603/1530/1216 1507/1420/1106
+f 1510/1419/1105 2073/1411/1097 2072/1414/1100 1507/1420/1106
+f 1579/1511/1197 2074/1491/1177 2073/1411/1097 1510/1419/1105
+f 1579/1511/1197 1580/1512/1198 2075/1492/1178 2074/1491/1177
+f 1580/1512/1198 1581/1513/1199 2076/1509/1195 2075/1492/1178
+f 1989/1983/1669 1978/1976/1662 2061/2019/1705 2050/2012/1698
+f 1577/1508/1194 1576/1507/1193 1634/1560/1246 1635/1567/1253
+f 1622/1558/1244 1623/1561/1247 1626/1565/1251 1625/1562/1248
+f 2078/1904/1590 2077/1895/1581 1895/1894/1580 1892/1901/1587
+f 1054/1905/1591 2078/1904/1590 1892/1901/1587 1055/1900/1586
+f 1722/1690/1376 2080/1667/1353 2079/1668/1354 1721/1691/1377
+f 1723/1679/1365 2081/1670/1356 2080/1667/1353 1722/1690/1376
+f 1724/1660/1346 2082/1664/1350 2081/1670/1356 1723/1679/1365
+f 1725/1659/1345 2083/1662/1348 2082/1664/1350 1724/1660/1346
+f 1726/1671/1357 2084/1656/1342 2083/1662/1348 1725/1659/1345
+f 2085/1648/1334 2084/1656/1342 1726/1671/1357 1727/1674/1360
+f 2086/1649/1335 2085/1648/1334 1727/1674/1360 1728/1693/1379
+f 2087/1684/1370 2086/1649/1335 1728/1693/1379 1729/1696/1382
+f 1895/1894/1580 2087/1684/1370 1729/1696/1382 1797/1783/1469
+f 2089/2020/1706 1565/1490/1176 1559/1466/1152 2090/1953/1639
+f 2092/2021/1707 1543/1475/1161 1566/1478/1164 2091/1949/1635
+f 1944/1465/1151 1543/1475/1161 2092/2021/1707 2088/2022/1640
+f 1544/1474/1160 1565/1490/1176 2089/2020/1706 2096/1952/1638
+f 2611/2023/1708 2099/2024/1709 2109/2025/1710 2612/2026/1711
+f 2101/2027/1712 2100/2028/1713 2110/2029/1714 2111/2030/1715
+f 2102/2031/1716 2101/2027/1712 2111/2030/1715 2112/2032/1717
+f 2103/2033/1718 2102/2031/1716 2112/2032/1717 2113/2034/1719
+f 2104/2035/1720 2103/2033/1718 2113/2034/1719 2114/2036/1721
+f 2151/2037/1722 2104/2035/1720 2114/2036/1721 2152/2038/1723
+f 2106/2039/1724 2105/2040/1725 2115/2041/1726 2116/2042/1727
+f 2107/2043/1728 2106/2039/1724 2116/2042/1727 2117/2044/1729
+f 2108/2045/1730 2107/2043/1728 2117/2044/1729 2118/2046/1731
+f 2099/2024/1709 2108/2045/1730 2118/2046/1731 2109/2025/1710
+f 2612/2026/1711 2109/2025/1710 2119/2047/1732 2613/2048/1733
+f 2613/2048/1733 2119/2047/1732 1497/1404/1090 2047/1403/1089
+f 2119/2047/1732 2109/2025/1710 2123/2049/1734 2124/2050/1735
+f 1497/1404/1090 2119/2047/1732 2124/2050/1735 1504/1407/1093
+f 2124/2050/1735 2123/2049/1734 2121/2051/1736 2122/2052/1737
+f 1504/1407/1093 2124/2050/1735 2122/2052/1737 1501/1410/1096
+f 2639/2053/1738 2638/2054/1739 2128/2055/1740 2129/2056/1741
+f 2125/2057/1742 2123/2049/1734 2109/2025/1710 2118/2046/1731
+f 2126/2058/1743 2125/2057/1742 2118/2046/1731 2117/2044/1729
+f 2121/2051/1736 2123/2049/1734 2125/2057/1742 2132/2059/1744
+f 2132/2059/1744 2125/2057/1742 2126/2058/1743 2131/2060/1745
+f 2131/2060/1745 2126/2058/1743 2127/2061/1746 2130/2062/1747
+f 2111/2030/1715 2110/2029/1714 2133/2063/1748 2134/2064/1749
+f 2112/2032/1717 2111/2030/1715 2134/2064/1749 2135/2065/1750
+f 2113/2034/1719 2112/2032/1717 2135/2065/1750 2136/2066/1751
+f 2114/2036/1721 2113/2034/1719 2136/2066/1751 2137/2067/1752
+f 2110/2029/1714 2120/2068/1753 2138/2069/1754 2133/2063/1748
+f 2120/2068/1753 1498/1429/1115 1519/1428/1114 2138/2069/1754
+f 2145/2070/1755 2140/2071/1756 2141/2072/1757 2144/2073/1758
+f 2143/2074/1759 2142/2075/1760 1524/1436/1122 1525/1435/1121
+f 2144/2073/1758 2141/2072/1757 2142/2075/1760 2143/2074/1759
+f 2512/2076/1761 2511/2077/1762 2171/2078/1763 2170/2079/1764
+f 2139/2080/1765 2146/2081/1766 2129/2056/1741 2128/2055/1740
+f 2142/2075/1760 2141/2072/1757 2187/2082/1767 2214/2083/1768
+f 2187/2082/1767 2141/2072/1757 2150/2084/1769 2188/2085/1770
+f 2150/2084/1769 2141/2072/1757 2140/2071/1756 2149/2086/1771
+f 2147/2087/1772 2379/2088/1773 2378/2089/1774 2148/2090/1775
+f 2380/2091/1776 2379/2088/1773 2147/2087/1772 2189/2092/1777
+f 2105/2040/1725 2600/2093/1778 2599/2094/1779 2115/2041/1726
+f 2100/2028/1713 2153/2095/1780 2154/2096/1781 2110/2029/1714
+f 2110/2029/1714 2154/2096/1781 2155/2097/1782 2120/2068/1753
+f 2120/2068/1753 2155/2097/1782 1542/1460/1146 1498/1429/1115
+f 1585/1461/1147 1546/1464/1150 2158/2098/1783 2190/2099/1784
+f 2515/2100/1785 2514/2101/1786 2193/2102/1787 2168/2103/1788
+f 2161/2104/1789 2159/2105/1790 2145/2070/1755 2144/2073/1758
+f 1525/1435/1121 1548/1472/1158 2160/2106/1791 2143/2074/1759
+f 2158/2098/1783 2157/2107/1792 2191/2108/1793 2190/2099/1784
+f 2160/2106/1791 2161/2104/1789 2144/2073/1758 2143/2074/1759
+f 2156/2109/1794 2174/2110/1795 2195/2111/1796 2194/2112/1797
+f 2166/2113/1798 1556/1482/1168 1594/1481/1167 2197/2114/1799
+f 2164/2115/1800 2166/2113/1798 2197/2114/1799 2196/2116/1801
+f 2513/2117/1802 2512/2076/1761 2170/2079/1764 2169/2118/1803
+f 2146/2081/1766 2167/2119/1804 2162/2120/1805 2129/2056/1741
+f 2157/2107/1792 2173/2121/1806 2192/2122/1807 2191/2108/1793
+f 2145/2070/1755 2159/2105/1790 2169/2118/1803 2170/2079/1764
+f 2140/2071/1756 2145/2070/1755 2170/2079/1764 2171/2078/1763
+f 2640/2123/1808 2184/2124/1809 2172/2125/1810 2641/2126/1811
+f 1555/1495/1181 1564/1497/1183 2172/2125/1810 2165/2127/1812
+f 2168/2103/1788 2193/2102/1787 2192/2122/1807 2173/2121/1806
+f 2174/2110/1795 2164/2115/1800 2196/2116/1801 2195/2111/1796
+f 2175/2128/1813 1567/1499/1185 1501/1410/1096 2122/2052/1737
+f 2131/2060/1745 2178/2129/1814 2177/2130/1815 2132/2059/1744
+f 2177/2130/1815 2176/2131/1816 2121/2051/1736 2132/2059/1744
+f 2176/2131/1816 2175/2128/1813 2122/2052/1737 2121/2051/1736
+f 2131/2060/1745 2180/2132/1817 2179/2133/1818 2178/2129/1814
+f 2180/2132/1817 2182/2134/1819 2181/2135/1820 2179/2133/1818
+f 2182/2134/1819 1577/1508/1194 2183/2136/1821 2181/2135/1820
+f 2641/2126/1811 2172/2125/1810 1564/1497/1183 2076/1509/1195
+f 2165/2127/1812 2172/2125/1810 2184/2124/1809 2163/2137/1822
+f 2163/2137/1822 2184/2124/1809 2129/2056/1741 2162/2120/1805
+f 2640/2123/1808 2639/2053/1738 2129/2056/1741 2184/2124/1809
+f 2180/2132/1817 2131/2060/1745 2130/2062/1747 2185/2138/1823
+f 2180/2132/1817 2185/2138/1823 2186/2139/1824 2182/2134/1819
+f 2182/2134/1819 2186/2139/1824 1581/1513/1199 1577/1508/1194
+f 1612/1514/1200 2214/2083/1768 2187/2082/1767 1530/1515/1201
+f 1530/1515/1201 2187/2082/1767 2188/2085/1770 1536/1516/1202
+f 1790/1517/1203 2380/2091/1776 2189/2092/1777 1532/1518/1204
+f 1548/1472/1158 1585/1461/1147 2190/2099/1784 2160/2106/1791
+f 2191/2108/1793 2161/2104/1789 2160/2106/1791 2190/2099/1784
+f 2192/2122/1807 2159/2105/1790 2161/2104/1789 2191/2108/1793
+f 2193/2102/1787 2169/2118/1803 2159/2105/1790 2192/2122/1807
+f 2514/2101/1786 2513/2117/1802 2169/2118/1803 2193/2102/1787
+f 2195/2111/1796 2162/2120/1805 2167/2119/1804 2194/2112/1797
+f 2196/2116/1801 2163/2137/1822 2162/2120/1805 2195/2111/1796
+f 2197/2114/1799 2165/2127/1812 2163/2137/1822 2196/2116/1801
+f 1594/1481/1167 1555/1495/1181 2165/2127/1812 2197/2114/1799
+f 2534/2140/1825 2368/2141/1826 2367/2142/1827 2202/2143/1828
+f 2378/2089/1774 2377/2144/1829 2198/2145/1830 2148/2090/1775
+f 2377/2144/1829 2376/2146/1831 2199/2147/1832 2198/2145/1830
+f 2199/2147/1832 2376/2146/1831 2375/2148/1833 2200/2149/1834
+f 2171/2078/1763 2203/2150/1835 2149/2086/1771 2140/2071/1756
+f 2127/2061/1746 2126/2058/1743 2117/2044/1729 2206/2151/1836
+f 2511/2077/1762 2510/2152/1837 2203/2150/1835 2171/2078/1763
+f 2139/2080/1765 2128/2055/1740 2205/2153/1838 2204/2154/1839
+f 2128/2055/1740 2638/2054/1739 2637/2155/1840 2205/2153/1838
+f 2152/2038/1723 2114/2036/1721 2137/2067/1752 2209/2156/1841
+f 2117/2044/1729 2116/2042/1727 2207/2157/1842 2206/2151/1836
+f 2116/2042/1727 2115/2041/1726 2208/2158/1843 2207/2157/1842
+f 2115/2041/1726 2599/2094/1779 2598/2159/1844 2208/2158/1843
+f 2636/2160/1845 2211/2161/1846 2205/2153/1838 2637/2155/1840
+f 2635/2162/1847 2213/2163/1848 2211/2161/1846 2636/2160/1845
+f 2211/2161/1846 2210/2164/1849 2204/2154/1839 2205/2153/1838
+f 2213/2163/1848 2212/2165/1850 2210/2164/1849 2211/2161/1846
+f 1524/1436/1122 2142/2075/1760 2214/2083/1768 1612/1514/1200
+f 1614/1545/1231 1616/1548/1234 2216/2166/1851 2215/2167/1852
+f 1616/1548/1234 1567/1499/1185 2175/2128/1813 2216/2166/1851
+f 2215/2167/1852 2216/2166/1851 2217/2168/1853 2221/2169/1854
+f 2216/2166/1851 2175/2128/1813 2176/2131/1816 2217/2168/1853
+f 2217/2168/1853 2176/2131/1816 2177/2130/1815 2218/2170/1855
+f 2219/2171/1856 2178/2129/1814 2179/2133/1818 2220/2172/1857
+f 2218/2170/1855 2177/2130/1815 2178/2129/1814 2219/2171/1856
+f 2224/2173/1858 2230/2174/1859 2229/2175/1860 2231/2176/1861
+f 2183/2136/1821 2234/2177/1862 2233/2178/1863 2222/2179/1864
+f 2223/2180/1865 2220/2172/1857 2179/2133/1818 2181/2135/1820
+f 2183/2136/1821 2222/2179/1864 2223/2180/1865 2181/2135/1820
+f 2233/2178/1863 2232/2181/1866 2225/2182/1867 2222/2179/1864
+f 2223/2180/1865 2226/2183/1868 2227/2184/1869 2220/2172/1857
+f 2220/2172/1857 2227/2184/1869 2228/2185/1870 2219/2171/1856
+f 2219/2171/1856 2228/2185/1870 2229/2175/1860 2218/2170/1855
+f 2218/2170/1855 2229/2175/1860 2230/2174/1859 2217/2168/1853
+f 2217/2168/1853 2230/2174/1859 2224/2173/1858 2221/2169/1854
+f 2229/2175/1860 2228/2185/1870 2227/2184/1869 2231/2176/1861
+f 2224/2173/1858 2231/2176/1861 2225/2182/1867 2232/2181/1866
+f 2227/2184/1869 2226/2183/1868 2225/2182/1867 2231/2176/1861
+f 2221/2169/1854 2224/2173/1858 2232/2181/1866 2233/2178/1863
+f 2234/2177/1862 2215/2167/1852 2221/2169/1854 2233/2178/1863
+f 1635/1567/1253 1614/1545/1231 2215/2167/1852 2234/2177/1862
+f 2611/2023/1708 2610/2186/1871 2249/2187/1872 2099/2024/1709
+f 2101/2027/1712 2252/2188/1873 2251/2189/1874 2100/2028/1713
+f 2102/2031/1716 2253/2190/1875 2252/2188/1873 2101/2027/1712
+f 2103/2033/1718 2254/2191/1876 2253/2190/1875 2102/2031/1716
+f 2104/2035/1720 2255/2192/1877 2254/2191/1876 2103/2033/1718
+f 2151/2037/1722 2256/2193/1878 2255/2192/1877 2104/2035/1720
+f 2106/2039/1724 2258/2194/1879 2257/2195/1880 2105/2040/1725
+f 2107/2043/1728 2247/2196/1881 2258/2194/1879 2106/2039/1724
+f 2108/2045/1730 2248/2197/1882 2247/2196/1881 2107/2043/1728
+f 2099/2024/1709 2249/2187/1872 2248/2197/1882 2108/2045/1730
+f 2105/2040/1725 2257/2195/1880 2601/2198/1883 2600/2093/1778
+f 2100/2028/1713 2251/2189/1874 2250/2199/1884 2153/2095/1780
+f 2248/2197/1882 2246/2200/1885 2245/2201/1886 2247/2196/1881
+f 2249/2187/1872 2235/2202/1887 2246/2200/1885 2248/2197/1882
+f 2610/2186/1871 2609/2203/1888 2235/2202/1887 2249/2187/1872
+f 2251/2189/1874 2237/2204/1889 2236/2205/1890 2250/2199/1884
+f 2252/2188/1873 2238/2206/1891 2237/2204/1889 2251/2189/1874
+f 2253/2190/1875 2239/2207/1892 2238/2206/1891 2252/2188/1873
+f 2254/2191/1876 2240/2208/1893 2239/2207/1892 2253/2190/1875
+f 2255/2192/1877 2241/2209/1894 2240/2208/1893 2254/2191/1876
+f 2256/2193/1878 2242/2210/1895 2241/2209/1894 2255/2192/1877
+f 2257/2195/1880 2243/2211/1896 2602/2212/1897 2601/2198/1883
+f 2258/2194/1879 2244/2213/1898 2243/2211/1896 2257/2195/1880
+f 2247/2196/1881 2245/2201/1886 2244/2213/1898 2258/2194/1879
+f 2238/2206/1891 2261/2214/1899 2260/2215/1900 2237/2204/1889
+f 2239/2207/1892 2262/2216/1901 2261/2214/1899 2238/2206/1891
+f 2240/2208/1893 2263/2217/1902 2262/2216/1901 2239/2207/1892
+f 2241/2209/1894 2264/2218/1903 2263/2217/1902 2240/2208/1893
+f 2242/2210/1895 2265/2219/1904 2264/2218/1903 2241/2209/1894
+f 2244/2213/1898 2267/2220/1905 2266/2221/1906 2243/2211/1896
+f 2245/2201/1886 2268/2222/1907 2267/2220/1905 2244/2213/1898
+f 2246/2200/1885 2269/2223/1908 2268/2222/1907 2245/2201/1886
+f 2235/2202/1887 2259/2224/1909 2269/2223/1908 2246/2200/1885
+f 2243/2211/1896 2266/2221/1906 2603/2225/1910 2602/2212/1897
+f 2261/2214/1899 2273/2226/1911 2272/2227/1912 2260/2215/1900
+f 2262/2216/1901 2274/2228/1913 2273/2226/1911 2261/2214/1899
+f 2263/2217/1902 2275/2229/1914 2274/2228/1913 2262/2216/1901
+f 2264/2218/1903 2276/2230/1915 2275/2229/1914 2263/2217/1902
+f 2265/2219/1904 2277/2231/1916 2276/2230/1915 2264/2218/1903
+f 2267/2220/1905 2279/2232/1917 2278/2233/1918 2266/2221/1906
+f 2268/2222/1907 2280/2234/1919 2279/2232/1917 2267/2220/1905
+f 2269/2223/1908 2281/2235/1920 2280/2234/1919 2268/2222/1907
+f 2259/2224/1909 2270/2236/1921 2281/2235/1920 2269/2223/1908
+f 2266/2221/1906 2278/2233/1918 2604/2237/1922 2603/2225/1910
+f 2273/2226/1911 2284/2238/1923 2271/2239/1924 2272/2227/1912
+f 2604/2237/1922 2278/2233/1918 2279/2232/1917 2605/2240/1925
+f 2274/2228/1913 2275/2229/1914 2283/2241/1926 2282/2242/1927
+f 2280/2234/1919 2281/2235/1920 2607/2243/1928 2606/2244/1929
+f 2605/2240/1925 2279/2232/1917 2280/2234/1919 2606/2244/1929
+f 2275/2229/1914 2276/2230/1915 2277/2231/1916 2283/2241/1926
+f 2273/2226/1911 2274/2228/1913 2282/2242/1927 2284/2238/1923
+f 2281/2235/1920 2270/2236/1921 2608/2245/1930 2607/2243/1928
+f 2133/2063/1748 2285/2246/1931 2286/2247/1932 2134/2064/1749
+f 2134/2064/1749 2286/2247/1932 2287/2248/1933 2135/2065/1750
+f 2135/2065/1750 2287/2248/1933 2288/2249/1934 2136/2066/1751
+f 2136/2066/1751 2288/2249/1934 2289/2250/1935 2137/2067/1752
+f 2138/2069/1754 2290/2251/1936 2285/2246/1931 2133/2063/1748
+f 1519/1428/1114 1692/1634/1320 2290/2251/1936 2138/2069/1754
+f 2598/2159/1844 2597/2252/1937 2291/2253/1938 2208/2158/1843
+f 2137/2067/1752 2289/2250/1935 2292/2254/1939 2209/2156/1841
+f 2634/2255/1940 2294/2256/1941 2213/2163/1848 2635/2162/1847
+f 2294/2256/1941 2293/2257/1942 2212/2165/1850 2213/2163/1848
+f 2578/2258/1943 2581/2259/1944 2580/2260/1945 2579/2261/1946
+f 2303/2262/1947 2199/2147/1832 2200/2149/1834 2579/2261/1946
+f 2314/2263/1948 2650/2264/1949 2649/2265/1950 2297/2266/1951
+f 2312/2267/1952 1260/2268/1953 1263/2269/1954 2302/2270/1955
+f 2313/2271/1956 2312/2267/1952 2302/2270/1955 2298/2272/1957
+f 2297/2266/1951 2649/2265/1950 2648/2273/1958 2303/2262/1947
+f 2519/2274/1959 2319/2275/1960 2320/2276/1961 2520/2277/1962
+f 2198/2145/1830 2199/2147/1832 2303/2262/1947 2304/2278/1963
+f 2648/2273/1958 2647/2279/1964 2304/2278/1963 2303/2262/1947
+f 2198/2145/1830 2304/2278/1963 2307/2280/1965 2148/2090/1775
+f 2647/2279/1964 2646/2281/1966 2307/2280/1965 2304/2278/1963
+f 2305/2282/1967 1705/1666/1352 1532/1518/1204 2189/2092/1777
+f 2644/2283/1968 2079/1668/1354 1705/1666/1352 2305/2282/1967
+f 2306/2284/1969 2305/2282/1967 2189/2092/1777 2147/2087/1772
+f 2645/2285/1970 2644/2283/1968 2305/2282/1967 2306/2284/1969
+f 2148/2090/1775 2307/2280/1965 2306/2284/1969 2147/2087/1772
+f 2646/2281/1966 2645/2285/1970 2306/2284/1969 2307/2280/1965
+f 2321/2286/1971 2322/2287/1972 2522/2288/1973 2521/2289/1974
+f 2298/2272/1957 2302/2270/1955 2309/2290/1975 2308/2291/1976
+f 2302/2270/1955 1263/2269/1954 1262/2292/1977 2309/2290/1975
+f 2320/2276/1961 2321/2286/1971 2521/2289/1974 2520/2277/1962
+f 2518/2293/1978 2318/2294/1979 2319/2275/1960 2519/2274/1959
+f 2301/2295/1980 1265/2296/1981 1260/2268/1953 2312/2267/1952
+f 2299/2297/1982 2301/2295/1980 2312/2267/1952 2313/2271/1956
+f 2300/2298/1983 2651/2299/1984 2650/2264/1949 2314/2263/1948
+f 2314/2263/1948 2315/2300/1985 2295/2301/1986 2300/2298/1983
+f 2316/2302/1987 2296/2303/1988 2295/2301/1986 2315/2300/1985
+f 2517/2304/1989 2317/2305/1990 2318/2294/1979 2518/2293/1978
+f 1721/1691/1377 2317/2305/1990 2517/2304/1989 1946/1692/1378
+f 2323/2306/1991 2523/2307/1992 2522/2288/1973 2322/2287/1972
+f 2524/2308/1993 2523/2307/1992 2323/2306/1991 2324/2309/1994
+f 2527/2310/1995 2311/2311/1996 1706/1699/1385 1958/1698/1384
+f 2311/2311/1996 2327/2312/1997 2328/2313/1998 2310/2314/1999
+f 2329/2315/2000 2308/2291/1976 2310/2314/1999 2328/2313/1998
+f 2330/2316/2001 2298/2272/1957 2308/2291/1976 2329/2315/2000
+f 2331/2317/2002 2313/2271/1956 2298/2272/1957 2330/2316/2001
+f 2332/2318/2003 2299/2297/1982 2313/2271/1956 2331/2317/2002
+f 2597/2252/1937 2596/2319/2004 2357/2320/2005 2291/2253/1938
+f 2289/2250/1935 2334/2321/2006 2358/2322/2007 2292/2254/1939
+f 2336/2323/2008 2356/2324/2009 2335/2325/2010 2365/2326/2011
+f 2634/2255/1940 2633/2327/2012 2336/2323/2008 2294/2256/1941
+f 2288/2249/1934 2337/2328/2013 2334/2321/2006 2289/2250/1935
+f 1692/1634/1320 1747/1719/1405 2342/2329/2014 2290/2251/1936
+f 2339/2330/2015 2337/2328/2013 2288/2249/1934 2287/2248/1933
+f 2340/2331/2016 2339/2330/2015 2287/2248/1933 2286/2247/1932
+f 2341/2332/2017 2340/2331/2016 2286/2247/1932 2285/2246/1931
+f 2342/2329/2014 2341/2332/2017 2285/2246/1931 2290/2251/1936
+f 2337/2328/2013 2360/2333/2018 2359/2334/2019 2334/2321/2006
+f 2339/2330/2015 2361/2335/2020 2360/2333/2018 2337/2328/2013
+f 2340/2331/2016 2362/2336/2021 2361/2335/2020 2339/2330/2015
+f 2341/2332/2017 2363/2337/2022 2362/2336/2021 2340/2331/2016
+f 2342/2329/2014 2364/2338/2023 2363/2337/2022 2341/2332/2017
+f 1747/1719/1405 1773/1729/1415 2364/2338/2023 2342/2329/2014
+f 2593/2339/2024 2592/2340/2025 2373/2341/2026 2506/2342/2027
+f 2632/2343/2028 2631/2344/2029 2370/2345/2030 2356/2324/2009
+f 2595/2346/2031 2594/2347/2032 2372/2348/2033 2371/2349/2034
+f 2592/2340/2025 2591/2350/2035 2516/2351/2036 2373/2341/2026
+f 2504/2352/2037 2344/2353/2038 2343/2354/2039 2505/2355/2040
+f 2503/2356/2041 2345/2357/2042 2344/2353/2038 2504/2352/2037
+f 2502/2358/2043 2346/2359/2044 2345/2357/2042 2503/2356/2041
+f 2501/2360/2045 2347/2361/2046 2346/2359/2044 2502/2358/2043
+f 2500/2362/2047 2348/2363/2048 2347/2361/2046 2501/2360/2045
+f 2499/2364/2049 2349/2365/2050 2348/2363/2048 2500/2362/2047
+f 1927/2366/1443 1757/2367/1444 2349/2365/2050 2499/2364/2049
+f 2334/2321/2006 2359/2334/2019 2333/2368/2051 2358/2322/2007
+f 2294/2256/1941 2336/2323/2008 2365/2326/2011 2293/2257/1942
+f 2507/2369/2052 2367/2142/1827 2368/2141/1826 2508/2370/2053
+f 2508/2370/2053 2368/2141/1826 2369/2371/2054 2509/2372/2055
+f 2509/2372/2055 2369/2371/2054 2203/2150/1835 2510/2152/1837
+f 2533/2373/2056 2369/2371/2054 2368/2141/1826 2534/2140/1825
+f 2203/2150/1835 2369/2371/2054 2533/2373/2056 2532/2374/2057
+f 2149/2086/1771 2203/2150/1835 2532/2374/2057 2531/2375/2058
+f 2530/2376/2059 2150/2084/1769 2149/2086/1771 2531/2375/2058
+f 2188/2085/1770 2150/2084/1769 2530/2376/2059 2529/2377/2060
+f 1536/1516/1202 2188/2085/1770 2529/2377/2060 1961/1769/1455
+f 2200/2149/1834 2375/2148/1833 2374/2378/2061 2201/2379/2062
+f 2382/2380/2063 2383/2381/2064 1266/2382/2065 1470/2383/2066
+f 2332/2318/2003 2386/2384/2067 2384/2385/2068 2299/2297/1982
+f 2526/2386/2069 2385/2387/2070 1272/2388/2071 1267/2389/2072
+f 2324/2309/1994 2387/2390/2073 2525/2391/2074 2524/2308/1993
+f 2384/2385/2068 2386/2384/2067 2383/2381/2064 2382/2380/2063
+f 2526/2386/2069 2525/2391/2074 2387/2390/2073 2385/2387/2070
+f 2350/2392/2075 2584/2393/2076 2583/2394/2077 2338/2395/2078
+f 2355/2396/2079 2589/2397/2080 2588/2398/2081 2352/2399/2082
+f 2381/2400/2083 2585/2401/2084 2584/2393/2076 2350/2392/2075
+f 2353/2402/2085 2587/2403/2086 2586/2404/2087 2354/2405/2088
+f 2352/2399/2082 2588/2398/2081 2587/2403/2086 2353/2402/2085
+f 2351/2406/2089 2590/2407/2090 2589/2397/2080 2355/2396/2079
+f 2338/2395/2078 2583/2394/2077 2582/2408/2091 2366/2409/2092
+f 2354/2405/2088 2586/2404/2087 2585/2401/2084 2381/2400/2083
+f 2582/2408/2091 2581/2259/1944 2578/2258/1943 2366/2409/2092
+f 2344/2353/2038 2398/2410/2093 2397/2411/2094 2343/2354/2039
+f 2345/2357/2042 2399/2412/2095 2398/2410/2093 2344/2353/2038
+f 2346/2359/2044 2400/2413/2096 2399/2412/2095 2345/2357/2042
+f 2347/2361/2046 2401/2414/2097 2400/2413/2096 2346/2359/2044
+f 2348/2363/2048 2402/2415/2098 2401/2414/2097 2347/2361/2046
+f 2349/2365/2050 2403/2416/2099 2402/2415/2098 2348/2363/2048
+f 1757/2367/1444 1814/2417/1495 2403/2416/2099 2349/2365/2050
+f 2461/2418/2100 2462/2419/2101 1883/2420/1498 1815/2421/1497
+f 2432/2422/2102 2433/2423/2103 1850/2424/1502 1816/2425/1501
+f 2416/2426/2104 2417/2427/2105 2418/2428/2106 2404/2429/2107
+f 2408/2430/2108 2409/2431/2109 2410/2432/2110 2405/2433/2111
+f 2395/2434/2112 2407/2435/2113 2406/2436/2114 2391/2437/2115
+f 2397/2411/2094 2398/2410/2093 2407/2435/2113 2395/2434/2112
+f 2406/2436/2114 2407/2435/2113 2409/2431/2109 2408/2430/2108
+f 2409/2431/2109 2407/2435/2113 2398/2410/2093 2399/2412/2095
+f 2410/2432/2110 2409/2431/2109 2399/2412/2095 2400/2413/2096
+f 2394/2438/2116 2413/2439/2117 2411/2440/2118 2393/2441/2119
+f 2391/2437/2115 2406/2436/2114 2412/2442/2120 2390/2443/2121
+f 2390/2443/2121 2412/2442/2120 2413/2439/2117 2394/2438/2116
+f 2414/2444/2122 2415/2445/2123 2408/2430/2108 2405/2433/2111
+f 2408/2430/2108 2415/2445/2123 2412/2442/2120 2406/2436/2114
+f 2411/2440/2118 2413/2439/2117 2417/2427/2105 2416/2426/2104
+f 2417/2427/2105 2413/2439/2117 2412/2442/2120 2415/2445/2123
+f 2418/2428/2106 2417/2427/2105 2415/2445/2123 2414/2444/2122
+f 1832/2446/1524 2423/2447/2124 2424/2448/2125 1839/2449/1525
+f 2421/2450/2126 2422/2451/2127 2419/2452/2128 2420/2453/2129
+f 2410/2432/2110 2421/2450/2126 2420/2453/2129 2405/2433/2111
+f 2401/2414/2097 2421/2450/2126 2410/2432/2110 2400/2413/2096
+f 2402/2415/2098 2422/2451/2127 2421/2450/2126 2401/2414/2097
+f 2422/2451/2127 2424/2448/2125 2423/2447/2124 2419/2452/2128
+f 2403/2416/2099 2424/2448/2125 2422/2451/2127 2402/2415/2098
+f 1839/2449/1525 2424/2448/2125 2403/2416/2099 1814/2417/1495
+f 2428/2454/2130 2429/2455/2131 2430/2456/2132 2425/2457/2133
+f 2426/2458/2134 2427/2459/2135 2420/2453/2129 2419/2452/2128
+f 2420/2453/2129 2427/2459/2135 2414/2444/2122 2405/2433/2111
+f 2404/2429/2107 2418/2428/2106 2429/2455/2131 2428/2454/2130
+f 2429/2455/2131 2418/2428/2106 2414/2444/2122 2427/2459/2135
+f 2430/2456/2132 2429/2455/2131 2427/2459/2135 2426/2458/2134
+f 1846/2460/1538 2431/2461/2136 2423/2447/2124 1832/2446/1524
+f 2423/2447/2124 2431/2461/2136 2426/2458/2134 2419/2452/2128
+f 2425/2457/2133 2430/2456/2132 2433/2423/2103 2432/2422/2102
+f 2433/2423/2103 2430/2456/2132 2426/2458/2134 2431/2461/2136
+f 1850/2424/1502 2433/2423/2103 2431/2461/2136 1846/2460/1538
+f 2445/2462/2137 2446/2463/2138 2447/2464/2139 2434/2465/2140
+f 2438/2466/2141 2439/2467/2142 2440/2468/2143 2435/2469/2144
+f 2392/2470/2145 2437/2471/2146 2436/2472/2147 2389/2473/2148
+f 2393/2441/2119 2411/2440/2118 2437/2471/2146 2392/2470/2145
+f 2436/2472/2147 2437/2471/2146 2439/2467/2142 2438/2466/2141
+f 2439/2467/2142 2437/2471/2146 2411/2440/2118 2416/2426/2104
+f 2440/2468/2143 2439/2467/2142 2416/2426/2104 2404/2429/2107
+f 2396/2474/2149 2442/2475/2150 2296/2303/1988 2316/2302/1987
+f 2389/2473/2148 2436/2472/2147 2441/2476/2151 2388/2477/2152
+f 2388/2477/2152 2441/2476/2151 2442/2475/2150 2396/2474/2149
+f 2443/2478/2153 2444/2479/2154 2438/2466/2141 2435/2469/2144
+f 2438/2466/2141 2444/2479/2154 2441/2476/2151 2436/2472/2147
+f 2296/2303/1988 2442/2475/2150 2446/2463/2138 2445/2462/2137
+f 2446/2463/2138 2442/2475/2150 2441/2476/2151 2444/2479/2154
+f 2447/2464/2139 2446/2463/2138 2444/2479/2154 2443/2478/2153
+f 1865/2480/1558 2452/2481/2155 2453/2482/2156 1872/2483/1559
+f 2450/2484/2157 2451/2485/2158 2448/2486/2159 2449/2487/2160
+f 2440/2468/2143 2450/2484/2157 2449/2487/2160 2435/2469/2144
+f 2428/2454/2130 2450/2484/2157 2440/2468/2143 2404/2429/2107
+f 2425/2457/2133 2451/2485/2158 2450/2484/2157 2428/2454/2130
+f 2451/2485/2158 2453/2482/2156 2452/2481/2155 2448/2486/2159
+f 2432/2422/2102 2453/2482/2156 2451/2485/2158 2425/2457/2133
+f 1872/2483/1559 2453/2482/2156 2432/2422/2102 1816/2425/1501
+f 2457/2488/2161 2458/2489/2162 2459/2490/2163 2454/2491/2164
+f 2455/2492/2165 2456/2493/2166 2449/2487/2160 2448/2486/2159
+f 2449/2487/2160 2456/2493/2166 2443/2478/2153 2435/2469/2144
+f 2434/2465/2140 2447/2464/2139 2458/2489/2162 2457/2488/2161
+f 2458/2489/2162 2447/2464/2139 2443/2478/2153 2456/2493/2166
+f 2459/2490/2163 2458/2489/2162 2456/2493/2166 2455/2492/2165
+f 1879/2494/1572 2460/2495/2167 2452/2481/2155 1865/2480/1558
+f 2452/2481/2155 2460/2495/2167 2455/2492/2165 2448/2486/2159
+f 2454/2491/2164 2459/2490/2163 2462/2419/2101 2461/2418/2100
+f 2462/2419/2101 2459/2490/2163 2455/2492/2165 2460/2495/2167
+f 1883/2420/1498 2462/2419/2101 2460/2495/2167 1879/2494/1572
+f 1262/2292/1977 1261/2496/2168 2463/2497/2169 2309/2290/1975
+f 2463/2497/2169 2310/2314/1999 2308/2291/1976 2309/2290/1975
+f 2464/2498/2170 2311/2311/1996 2310/2314/1999 2463/2497/2169
+f 1261/2496/2168 1264/2499/2171 2464/2498/2170 2463/2497/2169
+f 2464/2498/2170 1884/1892/1578 1706/1699/1385 2311/2311/1996
+f 1884/1892/1578 2464/2498/2170 1264/2499/2171 1044/1893/1579
+f 2382/2380/2063 1470/2383/2066 1265/2296/1981 2301/2295/1980
+f 2382/2380/2063 2301/2295/1980 2299/2297/1982 2384/2385/2068
+f 2300/2298/1983 2642/2500/2172 2473/2501/2173 2651/2299/1984
+f 2465/2502/2174 1273/2503/2175 1268/2504/2176 2477/2505/2177
+f 1271/2506/2178 1272/2388/2071 2385/2387/2070 2470/2507/2179
+f 1269/2508/2180 1270/2509/2181 2643/2510/2182 2469/2511/2183
+f 2471/2512/2184 2465/2502/2174 2477/2505/2177 2476/2513/2185
+f 2472/2514/2186 2469/2511/2183 2643/2510/2182 2642/2500/2172
+f 2473/2501/2173 2470/2507/2179 2385/2387/2070 2387/2390/2073
+f 2467/2515/2187 2466/2516/2188 2471/2512/2184 2476/2513/2185
+f 2300/2298/1983 2468/2517/2189 2472/2514/2186 2642/2500/2172
+f 2300/2298/1983 2295/2301/1986 2474/2518/2190 2468/2517/2189
+f 2468/2517/2189 2474/2518/2190 2475/2519/2191 2467/2515/2187
+f 2445/2462/2137 2474/2518/2190 2295/2301/1986 2296/2303/1988
+f 2434/2465/2140 2475/2519/2191 2474/2518/2190 2445/2462/2137
+f 2468/2517/2189 2467/2515/2187 2476/2513/2185 2472/2514/2186
+f 2477/2505/2177 2469/2511/2183 2472/2514/2186 2476/2513/2185
+f 1268/2504/2176 1269/2508/2180 2469/2511/2183 2477/2505/2177
+f 1815/2421/1497 1901/2520/1601 2478/2521/2192 2461/2418/2100
+f 2454/2491/2164 2480/2522/2193 2479/2523/2194 2457/2488/2161
+f 2457/2488/2161 2479/2523/2194 2475/2519/2191 2434/2465/2140
+f 2461/2418/2100 2478/2521/2192 2480/2522/2193 2454/2491/2164
+f 2478/2521/2192 1901/2520/1601 1905/2524/1605 2481/2525/2195
+f 2479/2523/2194 2480/2522/2193 2483/2526/2196 2482/2527/2197
+f 2467/2515/2187 2475/2519/2191 2479/2523/2194 2482/2527/2197
+f 2483/2526/2196 2480/2522/2193 2478/2521/2192 2481/2525/2195
+f 1905/2524/1605 1909/2528/1609 2484/2529/2198 2481/2525/2195
+f 2483/2526/2196 2486/2530/2199 2485/2531/2200 2482/2527/2197
+f 2482/2527/2197 2485/2531/2200 2466/2516/2188 2467/2515/2187
+f 2481/2525/2195 2484/2529/2198 2486/2530/2199 2483/2526/2196
+f 2487/2532/2201 1912/2533/1615 1255/2534/1614 1471/2535/2202
+f 2488/2536/2203 2487/2532/2201 1471/2535/2202 1472/2537/2204
+f 2492/2538/2205 2488/2536/2203 1472/2537/2204 1473/2539/2206
+f 2498/2540/2207 2484/2529/2198 1909/2528/1609 1926/2541/1621
+f 2498/2540/2207 2497/2542/2208 2486/2530/2199 2484/2529/2198
+f 2487/2532/2201 2488/2536/2203 2490/2543/2209 2489/2544/2210
+f 2487/2532/2201 2489/2544/2210 1916/2545/1625 1912/2533/1615
+f 2497/2542/2208 2496/2546/2211 2485/2531/2200 2486/2530/2199
+f 2488/2536/2203 2492/2538/2205 2491/2547/2212 2490/2543/2209
+f 2496/2546/2211 2495/2548/2213 2466/2516/2188 2485/2531/2200
+f 2492/2538/2205 2494/2549/2214 2493/2550/2215 2491/2547/2212
+f 1474/2551/2216 2494/2549/2214 2492/2538/2205 1473/2539/2206
+f 2493/2550/2215 2471/2512/2184 2466/2516/2188 2495/2548/2213
+f 2494/2549/2214 2465/2502/2174 2471/2512/2184 2493/2550/2215
+f 1273/2503/2175 2465/2502/2174 2494/2549/2214 1474/2551/2216
+f 2491/2547/2212 2493/2550/2215 2495/2548/2213 2496/2546/2211
+f 2490/2543/2209 2491/2547/2212 2496/2546/2211 2497/2542/2208
+f 2489/2544/2210 2490/2543/2209 2497/2542/2208 2498/2540/2207
+f 2489/2544/2210 2498/2540/2207 1926/2541/1621 1916/2545/1625
+f 1773/1729/1415 1927/2366/1443 2499/2364/2049 2364/2338/2023
+f 2364/2338/2023 2499/2364/2049 2500/2362/2047 2363/2337/2022
+f 2363/2337/2022 2500/2362/2047 2501/2360/2045 2362/2336/2021
+f 2362/2336/2021 2501/2360/2045 2502/2358/2043 2361/2335/2020
+f 2361/2335/2020 2502/2358/2043 2503/2356/2041 2360/2333/2018
+f 2360/2333/2018 2503/2356/2041 2504/2352/2037 2359/2334/2019
+f 2359/2334/2019 2504/2352/2037 2505/2355/2040 2333/2368/2051
+f 2594/2347/2032 2593/2339/2024 2506/2342/2027 2372/2348/2033
+f 2293/2257/1942 2507/2369/2052 2508/2370/2053 2212/2165/1850
+f 2212/2165/1850 2508/2370/2053 2509/2372/2055 2210/2164/1849
+f 2210/2164/1849 2509/2372/2055 2510/2152/1837 2204/2154/1839
+f 2139/2080/1765 2204/2154/1839 2510/2152/1837 2511/2077/1762
+f 2146/2081/1766 2139/2080/1765 2511/2077/1762 2512/2076/1761
+f 2167/2119/1804 2146/2081/1766 2512/2076/1761 2513/2117/1802
+f 2194/2112/1797 2167/2119/1804 2513/2117/1802 2514/2101/1786
+f 2156/2109/1794 2194/2112/1797 2514/2101/1786 2515/2100/1785
+f 2166/2113/1798 2657/2552/2217 2093/1946/1632 1556/1482/1168
+f 2164/2115/1800 2658/2553/2218 2657/2552/2217 2166/2113/1798
+f 2174/2110/1795 2655/2554/2219 2658/2553/2218 2164/2115/1800
+f 1546/1464/1150 2098/1951/1637 2660/2555/2220 2158/2098/1783
+f 2158/2098/1783 2660/2555/2220 2659/2556/2221 2157/2107/1792
+f 2654/2557/2222 2652/2558/2223 2515/2100/1785 2168/2103/1788
+f 2591/2350/2035 2590/2407/2090 2351/2406/2089 2516/2351/2036
+f 1946/1692/1378 2517/2304/1989 2325/2559/2224 1730/1955/1641
+f 2325/2559/2224 2517/2304/1989 2518/2293/1978 2326/2560/2225
+f 2326/2560/2225 2518/2293/1978 2519/2274/1959 2327/2312/1997
+f 2327/2312/1997 2519/2274/1959 2520/2277/1962 2328/2313/1998
+f 2521/2289/1974 2329/2315/2000 2328/2313/1998 2520/2277/1962
+f 2522/2288/1973 2330/2316/2001 2329/2315/2000 2521/2289/1974
+f 2523/2307/1992 2331/2317/2002 2330/2316/2001 2522/2288/1973
+f 2332/2318/2003 2331/2317/2002 2523/2307/1992 2524/2308/1993
+f 2525/2391/2074 2386/2384/2067 2332/2318/2003 2524/2308/1993
+f 2383/2381/2064 2386/2384/2067 2525/2391/2074 2526/2386/2069
+f 2383/2381/2064 2526/2386/2069 1267/2389/2072 1266/2382/2065
+f 2527/2310/1995 2326/2560/2225 2327/2312/1997 2311/2311/1996
+f 2325/2559/2224 2326/2560/2225 2527/2310/1995 2528/2561/2226
+f 2325/2559/2224 2528/2561/2226 1959/1959/1645 1730/1955/1641
+f 2527/2310/1995 1958/1698/1384 1959/1959/1645 2528/2561/2226
+f 1961/1769/1455 2529/2377/2060 2380/2091/1776 1790/1517/1203
+f 2530/2376/2059 2379/2088/1773 2380/2091/1776 2529/2377/2060
+f 2379/2088/1773 2530/2376/2059 2531/2375/2058 2378/2089/1774
+f 2532/2374/2057 2377/2144/1829 2378/2089/1774 2531/2375/2058
+f 2533/2373/2056 2376/2146/1831 2377/2144/1829 2532/2374/2057
+f 2376/2146/1831 2533/2373/2056 2534/2140/1825 2375/2148/1833
+f 2375/2148/1833 2534/2140/1825 2202/2143/1828 2374/2378/2061
+f 2630/2562/2227 2629/2563/2228 2535/2564/2229 2550/2565/2230
+f 2540/2566/2231 2539/2567/2232 2538/2568/2233 2537/2569/2234
+f 2541/2570/2235 2540/2566/2231 2537/2569/2234 2542/2571/2236
+f 2549/2572/2237 2541/2570/2235 2542/2571/2236 2536/2573/2238
+f 2539/2567/2232 2548/2574/2239 2543/2575/2240 2538/2568/2233
+f 2548/2574/2239 2547/2576/2241 2544/2577/2242 2543/2575/2240
+f 2547/2576/2241 2546/2578/2243 2545/2579/2244 2544/2577/2242
+f 2631/2344/2029 2630/2562/2227 2550/2565/2230 2370/2345/2030
+f 2506/2342/2027 2373/2341/2026 2555/2580/2245 2540/2566/2231
+f 2541/2570/2235 2372/2348/2033 2506/2342/2027 2540/2566/2231
+f 2547/2576/2241 2553/2581/2246 2552/2582/2247 2546/2578/2243
+f 2548/2574/2239 2554/2583/2248 2553/2581/2246 2547/2576/2241
+f 2539/2567/2232 2551/2584/2249 2554/2583/2248 2548/2574/2239
+f 2549/2572/2237 2371/2349/2034 2372/2348/2033 2541/2570/2235
+f 2540/2566/2231 2555/2580/2245 2551/2584/2249 2539/2567/2232
+f 2516/2351/2036 2551/2584/2249 2555/2580/2245 2373/2341/2026
+f 2351/2406/2089 2554/2583/2248 2551/2584/2249 2516/2351/2036
+f 2355/2396/2079 2553/2581/2246 2554/2583/2248 2351/2406/2089
+f 2352/2399/2082 2552/2582/2247 2553/2581/2246 2355/2396/2079
+f 2546/2578/2243 2563/2585/2250 2556/2586/2251 2545/2579/2244
+f 2563/2585/2250 2562/2587/2252 2557/2588/2253 2556/2586/2251
+f 2562/2587/2252 2561/2589/2254 2558/2590/2255 2557/2588/2253
+f 2561/2589/2254 2560/2591/2256 2559/2592/2257 2558/2590/2255
+f 2561/2589/2254 2565/2593/2258 2564/2594/2259 2560/2591/2256
+f 2562/2587/2252 2566/2595/2260 2565/2593/2258 2561/2589/2254
+f 2563/2585/2250 2567/2596/2261 2566/2595/2260 2562/2587/2252
+f 2546/2578/2243 2552/2582/2247 2567/2596/2261 2563/2585/2250
+f 2566/2595/2260 2567/2596/2261 2353/2402/2085 2354/2405/2088
+f 2567/2596/2261 2552/2582/2247 2352/2399/2082 2353/2402/2085
+f 2350/2392/2075 2564/2594/2259 2565/2593/2258 2381/2400/2083
+f 2565/2593/2258 2566/2595/2260 2354/2405/2088 2381/2400/2083
+f 2560/2591/2256 2571/2597/2262 2568/2598/2263 2559/2592/2257
+f 2570/2599/2264 2374/2378/2061 2202/2143/1828 2569/2600/2265
+f 2571/2597/2262 2570/2599/2264 2569/2600/2265 2568/2598/2263
+f 2350/2392/2075 2338/2395/2078 2572/2601/2266 2564/2594/2259
+f 2570/2599/2264 2571/2597/2262 2572/2601/2266 2573/2602/2267
+f 2338/2395/2078 2366/2409/2092 2573/2602/2267 2572/2601/2266
+f 2201/2379/2062 2374/2378/2061 2570/2599/2264 2573/2602/2267
+f 2571/2597/2262 2560/2591/2256 2564/2594/2259 2572/2601/2266
+f 2574/2603/2268 2507/2369/2052 2293/2257/1942 2365/2326/2011
+f 2335/2325/2010 2575/2604/2269 2574/2603/2268 2365/2326/2011
+f 2575/2604/2269 2577/2605/2270 2576/2606/2271 2574/2603/2268
+f 2576/2606/2271 2367/2142/1827 2507/2369/2052 2574/2603/2268
+f 2569/2600/2265 2202/2143/1828 2367/2142/1827 2576/2606/2271
+f 2577/2605/2270 2568/2598/2263 2569/2600/2265 2576/2606/2271
+f 2366/2409/2092 2578/2258/1943 2201/2379/2062 2573/2602/2267
+f 2201/2379/2062 2578/2258/1943 2579/2261/1946 2200/2149/1834
+f 2579/2261/1946 2580/2260/1945 2297/2266/1951 2303/2262/1947
+f 2581/2259/1944 2316/2302/1987 2315/2300/1985 2580/2260/1945
+f 2396/2474/2149 2316/2302/1987 2581/2259/1944 2582/2408/2091
+f 2583/2394/2077 2388/2477/2152 2396/2474/2149 2582/2408/2091
+f 2584/2393/2076 2389/2473/2148 2388/2477/2152 2583/2394/2077
+f 2585/2401/2084 2392/2470/2145 2389/2473/2148 2584/2393/2076
+f 2586/2404/2087 2393/2441/2119 2392/2470/2145 2585/2401/2084
+f 2587/2403/2086 2394/2438/2116 2393/2441/2119 2586/2404/2087
+f 2588/2398/2081 2390/2443/2121 2394/2438/2116 2587/2403/2086
+f 2589/2397/2080 2391/2437/2115 2390/2443/2121 2588/2398/2081
+f 2590/2407/2090 2395/2434/2112 2391/2437/2115 2589/2397/2080
+f 2397/2411/2094 2395/2434/2112 2590/2407/2090 2591/2350/2035
+f 2343/2354/2039 2397/2411/2094 2591/2350/2035 2592/2340/2025
+f 2505/2355/2040 2343/2354/2039 2592/2340/2025 2593/2339/2024
+f 2333/2368/2051 2505/2355/2040 2593/2339/2024 2594/2347/2032
+f 2596/2319/2004 2358/2322/2007 2333/2368/2051 2594/2347/2032
+f 2356/2324/2009 2336/2323/2008 2633/2327/2012 2632/2343/2028
+f 2580/2260/1945 2315/2300/1985 2314/2263/1948 2297/2266/1951
+f 2292/2254/1939 2358/2322/2007 2596/2319/2004 2597/2252/1937
+f 2209/2156/1841 2292/2254/1939 2597/2252/1937 2598/2159/1844
+f 2599/2094/1779 2152/2038/1723 2209/2156/1841 2598/2159/1844
+f 2600/2093/1778 2151/2037/1722 2152/2038/1723 2599/2094/1779
+f 2601/2198/1883 2256/2193/1878 2151/2037/1722 2600/2093/1778
+f 2602/2212/1897 2242/2210/1895 2256/2193/1878 2601/2198/1883
+f 2603/2225/1910 2265/2219/1904 2242/2210/1895 2602/2212/1897
+f 2604/2237/1922 2277/2231/1916 2265/2219/1904 2603/2225/1910
+f 2277/2231/1916 2604/2237/1922 2605/2240/1925 2283/2241/1926
+f 2283/2241/1926 2605/2240/1925 2606/2244/1929 2282/2242/1927
+f 2607/2243/1928 2284/2238/1923 2282/2242/1927 2606/2244/1929
+f 2608/2245/1930 2271/2239/1924 2284/2238/1923 2607/2243/1928
+f 2357/2320/2005 2596/2319/2004 2594/2347/2032 2595/2346/2031
+f 2250/2199/1884 2236/2205/1890 2609/2203/1888 2610/2186/1871
+f 2153/2095/1780 2250/2199/1884 2610/2186/1871 2611/2023/1708
+f 2153/2095/1780 2611/2023/1708 2612/2026/1711 2154/2096/1781
+f 2154/2096/1781 2612/2026/1711 2613/2048/1733 2155/2097/1782
+f 2155/2097/1782 2613/2048/1733 2047/1403/1089 1542/1460/1146
+f 2260/2215/1900 2272/2227/1912 2271/2239/1924 2614/2607/2272
+f 2236/2205/1890 2237/2204/1889 2260/2215/1900 2614/2607/2272
+f 2609/2203/1888 2236/2205/1890 2614/2607/2272 2615/2608/2273
+f 2271/2239/1924 2608/2245/1930 2615/2608/2273 2614/2607/2272
+f 2235/2202/1887 2609/2203/1888 2615/2608/2273 2259/2224/1909
+f 2608/2245/1930 2270/2236/1921 2259/2224/1909 2615/2608/2273
+f 2370/2345/2030 2550/2565/2230 2621/2609/2274 2620/2610/2275
+f 2577/2605/2270 2619/2611/2276 2559/2592/2257 2568/2598/2263
+f 2619/2611/2276 2618/2612/2277 2558/2590/2255 2559/2592/2257
+f 2618/2612/2277 2617/2613/2278 2557/2588/2253 2558/2590/2255
+f 2617/2613/2278 2616/2614/2279 2556/2586/2251 2557/2588/2253
+f 2622/2615/2280 2535/2564/2229 2623/2616/2281 2624/2617/2282
+f 2622/2615/2280 2621/2609/2274 2550/2565/2230 2535/2564/2229
+f 2335/2325/2010 2356/2324/2009 2370/2345/2030 2620/2610/2275
+f 2335/2325/2010 2620/2610/2275 2577/2605/2270 2575/2604/2269
+f 2621/2609/2274 2619/2611/2276 2577/2605/2270 2620/2610/2275
+f 2618/2612/2277 2619/2611/2276 2621/2609/2274 2622/2615/2280
+f 2617/2613/2278 2624/2617/2282 2623/2616/2281 2616/2614/2279
+f 2617/2613/2278 2618/2612/2277 2622/2615/2280 2624/2617/2282
+f 2537/2569/2234 2625/2618/2283 2536/2573/2238 2542/2571/2236
+f 2628/2619/2284 2623/2616/2281 2535/2564/2229 2629/2563/2228
+f 2538/2568/2233 2626/2620/2285 2625/2618/2283 2537/2569/2234
+f 2627/2621/2286 2616/2614/2279 2623/2616/2281 2628/2619/2284
+f 2544/2577/2242 2626/2620/2285 2538/2568/2233 2543/2575/2240
+f 2627/2621/2286 2626/2620/2285 2544/2577/2242 2545/2579/2244
+f 2626/2620/2285 2627/2621/2286 2628/2619/2284 2625/2618/2283
+f 2625/2618/2283 2628/2619/2284 2629/2563/2228 2536/2573/2238
+f 2549/2572/2237 2536/2573/2238 2629/2563/2228 2630/2562/2227
+f 2371/2349/2034 2549/2572/2237 2630/2562/2227 2631/2344/2029
+f 2595/2346/2031 2371/2349/2034 2631/2344/2029 2632/2343/2028
+f 2633/2327/2012 2357/2320/2005 2595/2346/2031 2632/2343/2028
+f 2291/2253/1938 2357/2320/2005 2633/2327/2012 2634/2255/1940
+f 2291/2253/1938 2634/2255/1940 2635/2162/1847 2208/2158/1843
+f 2208/2158/1843 2635/2162/1847 2636/2160/1845 2207/2157/1842
+f 2207/2157/1842 2636/2160/1845 2637/2155/1840 2206/2151/1836
+f 2638/2054/1739 2127/2061/1746 2206/2151/1836 2637/2155/1840
+f 2130/2062/1747 2127/2061/1746 2638/2054/1739 2639/2053/1738
+f 2185/2138/1823 2130/2062/1747 2639/2053/1738 2640/2123/1808
+f 2185/2138/1823 2640/2123/1808 2641/2126/1811 2186/2139/1824
+f 2186/2139/1824 2641/2126/1811 2076/1509/1195 1581/1513/1199
+f 2556/2586/2251 2616/2614/2279 2627/2621/2286 2545/2579/2244
+f 1577/1508/1194 1635/1567/1253 2234/2177/1862 2183/2136/1821
+f 2222/2179/1864 2225/2182/1867 2226/2183/1868 2223/2180/1865
+f 2643/2510/2182 2470/2507/2179 2473/2501/2173 2642/2500/2172
+f 1270/2509/2181 1271/2506/2178 2470/2507/2179 2643/2510/2182
+f 2317/2305/1990 1721/1691/1377 2079/1668/1354 2644/2283/1968
+f 2318/2294/1979 2317/2305/1990 2644/2283/1968 2645/2285/1970
+f 2319/2275/1960 2318/2294/1979 2645/2285/1970 2646/2281/1966
+f 2320/2276/1961 2319/2275/1960 2646/2281/1966 2647/2279/1964
+f 2321/2286/1971 2320/2276/1961 2647/2279/1964 2648/2273/1958
+f 2649/2265/1950 2322/2287/1972 2321/2286/1971 2648/2273/1958
+f 2650/2264/1949 2323/2306/1991 2322/2287/1972 2649/2265/1950
+f 2651/2299/1984 2324/2309/1994 2323/2306/1991 2650/2264/1949
+f 2473/2501/2173 2387/2390/2073 2324/2309/1994 2651/2299/1984
+f 2653/2622/2287 2654/2557/2222 2168/2103/1788 2173/2121/1806
+f 2656/2623/2288 2655/2554/2219 2174/2110/1795 2156/2109/1794
+f 2515/2100/1785 2652/2624/2223 2656/2623/2288 2156/2109/1794
+f 2157/2107/1792 2659/2556/2221 2653/2622/2287 2173/2121/1806
+usemtl BlackCloth
+f 338/2625/2289 330/2626/2290 331/2627/2291 339/2628/2292
+f 332/2629/2293 340/2630/2294 339/2628/2292 331/2627/2291
+f 333/2631/2295 341/2632/2296 340/2630/2294 332/2629/2293
+f 334/2633/2297 342/2634/2298 341/2632/2296 333/2631/2295
+f 335/2635/2299 343/2636/2300 342/2634/2298 334/2633/2297
+f 336/2637/2301 344/2638/2302 343/2636/2300 335/2635/2299
+f 337/2639/2303 345/2640/2304 344/2638/2302 336/2637/2301
+f 330/2626/2290 338/2625/2289 345/2641/2304 337/2642/2303
+f 347/2643/2305 354/2644/2306 426/2645/2307 346/2646/2308
+f 348/2647/2309 355/2648/2310 354/2644/2306 347/2643/2305
+f 349/2649/2311 356/2650/2312 355/2648/2310 348/2647/2309
+f 350/2651/2313 357/2652/2314 356/2650/2312 349/2649/2311
+f 351/2653/2315 358/2654/2316 357/2652/2314 350/2651/2313
+f 352/2655/2317 432/2656/2318 358/2654/2316 351/2653/2315
+f 353/2657/2319 359/2658/2320 432/2656/2318 352/2655/2317
+f 346/2646/2308 426/2645/2307 359/2659/2320 353/2660/2319
+f 331/2627/2291 330/2626/2290 369/2661/2321 368/2662/2322
+f 368/2662/2322 369/2661/2321 360/2663/2323 361/2664/2324
+f 332/2629/2293 331/2627/2291 368/2662/2322 370/2665/2325
+f 370/2665/2325 368/2662/2322 361/2664/2324 362/2666/2326
+f 333/2631/2295 332/2629/2293 370/2665/2325 371/2667/2327
+f 371/2667/2327 370/2665/2325 362/2666/2326 363/2668/2328
+f 334/2633/2297 333/2631/2295 371/2667/2327 372/2669/2329
+f 372/2669/2329 371/2667/2327 363/2668/2328 364/2670/2330
+f 335/2635/2299 334/2633/2297 372/2669/2329 373/2671/2331
+f 373/2671/2331 372/2669/2329 364/2670/2330 365/2672/2332
+f 336/2637/2301 335/2635/2299 373/2671/2331 374/2673/2333
+f 374/2673/2333 373/2671/2331 365/2672/2332 366/2674/2334
+f 337/2639/2303 336/2637/2301 374/2673/2333 375/2675/2335
+f 375/2675/2335 374/2673/2333 366/2674/2334 367/2676/2336
+f 330/2626/2290 337/2642/2303 375/2677/2335 369/2661/2321
+f 369/2661/2321 375/2677/2335 367/2678/2336 360/2663/2323
+f 355/2648/2310 377/2679/2337 376/2680/2338 354/2644/2306
+f 356/2650/2312 378/2681/2339 377/2679/2337 355/2648/2310
+f 357/2652/2314 379/2682/2340 378/2681/2339 356/2650/2312
+f 358/2654/2316 380/2683/2341 379/2682/2340 357/2652/2314
+f 377/2679/2337 382/2684/2342 381/2685/2343 376/2680/2338
+f 378/2681/2339 383/2686/2344 382/2684/2342 377/2679/2337
+f 379/2682/2340 384/2687/2345 383/2686/2344 378/2681/2339
+f 380/2683/2341 385/2688/2346 384/2687/2345 379/2682/2340
+f 382/2684/2342 387/2689/2347 386/2690/2348 381/2685/2343
+f 383/2686/2344 388/2691/2349 387/2689/2347 382/2684/2342
+f 384/2687/2345 389/2692/2350 388/2691/2349 383/2686/2344
+f 385/2688/2346 390/2693/2351 389/2692/2350 384/2687/2345
+f 385/2688/2346 465/2694/2352 466/2695/2353 390/2693/2351
+f 380/2683/2341 464/2696/2354 465/2694/2352 385/2688/2346
+f 358/2654/2316 432/2656/2318 464/2696/2354 380/2683/2341
+f 426/2645/2307 354/2644/2306 376/2680/2338 391/2697/2355
+f 376/2680/2338 381/2685/2343 392/2698/2356 391/2697/2355
+f 381/2685/2343 386/2690/2348 393/2699/2357 392/2698/2356
+f 338/2625/2289 339/2628/2292 395/2700/2358 394/2701/2359
+f 394/2701/2359 395/2700/2358 347/2643/2305 346/2646/2308
+f 339/2628/2292 340/2630/2294 396/2702/2360 395/2700/2358
+f 395/2700/2358 396/2702/2360 348/2647/2309 347/2643/2305
+f 340/2630/2294 341/2632/2296 397/2703/2361 396/2702/2360
+f 396/2702/2360 397/2703/2361 349/2649/2311 348/2647/2309
+f 341/2632/2296 342/2634/2298 398/2704/2362 397/2703/2361
+f 397/2703/2361 398/2704/2362 350/2651/2313 349/2649/2311
+f 342/2634/2298 343/2636/2300 399/2705/2363 398/2704/2362
+f 398/2704/2362 399/2705/2363 351/2653/2315 350/2651/2313
+f 343/2636/2300 344/2638/2302 400/2706/2364 399/2705/2363
+f 399/2705/2363 400/2706/2364 352/2655/2317 351/2653/2315
+f 344/2638/2302 345/2640/2304 401/2707/2365 400/2706/2364
+f 400/2706/2364 401/2707/2365 353/2657/2319 352/2655/2317
+f 345/2641/2304 338/2625/2289 394/2701/2359 401/2708/2365
+f 401/2708/2365 394/2701/2359 346/2646/2308 353/2660/2319
+f 403/2709/2366 402/2710/2367 410/2711/2368 411/2712/2369
+f 404/2713/2370 403/2709/2366 411/2712/2369 412/2714/2371
+f 405/2715/2372 404/2713/2370 412/2714/2371 413/2716/2373
+f 406/2717/2374 405/2715/2372 413/2716/2373 414/2718/2375
+f 407/2719/2376 406/2717/2374 414/2718/2375 415/2720/2377
+f 408/2721/2378 407/2719/2376 415/2720/2377 416/2722/2379
+f 409/2723/2380 408/2721/2378 416/2722/2379 417/2724/2381
+f 402/2710/2367 409/2725/2380 417/2726/2381 410/2711/2368
+f 419/2727/2382 418/2728/2383 426/2729/2307 427/2730/2384
+f 420/2731/2385 419/2727/2382 427/2730/2384 428/2732/2386
+f 421/2733/2387 420/2731/2385 428/2732/2386 429/2734/2388
+f 422/2735/2389 421/2733/2387 429/2734/2388 430/2736/2390
+f 423/2737/2391 422/2735/2389 430/2736/2390 431/2738/2392
+f 424/2739/2393 423/2737/2391 431/2738/2392 432/2740/2318
+f 425/2741/2394 424/2739/2393 432/2740/2318 359/2742/2320
+f 418/2728/2383 425/2743/2394 359/2744/2320 426/2729/2307
+f 442/2745/2395 402/2710/2367 403/2709/2366 441/2746/2396
+f 441/2746/2396 434/2747/2397 433/2748/2398 442/2745/2395
+f 404/2713/2370 443/2749/2399 441/2746/2396 403/2709/2366
+f 443/2749/2399 435/2750/2400 434/2747/2397 441/2746/2396
+f 405/2715/2372 444/2751/2401 443/2749/2399 404/2713/2370
+f 444/2751/2401 436/2752/2402 435/2750/2400 443/2749/2399
+f 406/2717/2374 445/2753/2403 444/2751/2401 405/2715/2372
+f 445/2753/2403 437/2754/2404 436/2752/2402 444/2751/2401
+f 407/2719/2376 446/2755/2405 445/2753/2403 406/2717/2374
+f 446/2755/2405 438/2756/2406 437/2754/2404 445/2753/2403
+f 408/2721/2378 447/2757/2407 446/2755/2405 407/2719/2376
+f 447/2757/2407 439/2758/2408 438/2756/2406 446/2755/2405
+f 409/2723/2380 448/2759/2409 447/2757/2407 408/2721/2378
+f 448/2759/2409 440/2760/2410 439/2758/2408 447/2757/2407
+f 402/2710/2367 442/2745/2395 448/2761/2409 409/2725/2380
+f 442/2745/2395 433/2748/2398 440/2762/2410 448/2761/2409
+f 428/2732/2386 427/2730/2384 449/2763/2411 450/2764/2412
+f 429/2734/2388 428/2732/2386 450/2764/2412 451/2765/2413
+f 430/2736/2390 429/2734/2388 451/2765/2413 452/2766/2414
+f 431/2738/2392 430/2736/2390 452/2766/2414 453/2767/2415
+f 450/2764/2412 449/2763/2411 454/2768/2416 455/2769/2417
+f 451/2765/2413 450/2764/2412 455/2769/2417 456/2770/2418
+f 452/2766/2414 451/2765/2413 456/2770/2418 457/2771/2419
+f 453/2767/2415 452/2766/2414 457/2771/2419 458/2772/2420
+f 455/2769/2417 454/2768/2416 459/2773/2421 460/2774/2422
+f 456/2770/2418 455/2769/2417 460/2774/2422 461/2775/2423
+f 457/2771/2419 456/2770/2418 461/2775/2423 462/2776/2424
+f 458/2772/2420 457/2771/2419 462/2776/2424 463/2777/2425
+f 458/2772/2420 463/2777/2425 466/2778/2353 465/2779/2352
+f 453/2767/2415 458/2772/2420 465/2779/2352 464/2780/2354
+f 431/2738/2392 453/2767/2415 464/2780/2354 432/2740/2318
+f 426/2729/2307 391/2781/2355 449/2763/2411 427/2730/2384
+f 449/2763/2411 391/2781/2355 392/2782/2356 454/2768/2416
+f 454/2768/2416 392/2782/2356 393/2783/2357 459/2773/2421
+f 410/2711/2368 467/2784/2426 468/2785/2427 411/2712/2369
+f 467/2784/2426 418/2728/2383 419/2727/2382 468/2785/2427
+f 411/2712/2369 468/2785/2427 469/2786/2428 412/2714/2371
+f 468/2785/2427 419/2727/2382 420/2731/2385 469/2786/2428
+f 412/2714/2371 469/2786/2428 470/2787/2429 413/2716/2373
+f 469/2786/2428 420/2731/2385 421/2733/2387 470/2787/2429
+f 413/2716/2373 470/2787/2429 471/2788/2430 414/2718/2375
+f 470/2787/2429 421/2733/2387 422/2735/2389 471/2788/2430
+f 414/2718/2375 471/2788/2430 472/2789/2431 415/2720/2377
+f 471/2788/2430 422/2735/2389 423/2737/2391 472/2789/2431
+f 415/2720/2377 472/2789/2431 473/2790/2432 416/2722/2379
+f 472/2789/2431 423/2737/2391 424/2739/2393 473/2790/2432
+f 416/2722/2379 473/2790/2432 474/2791/2433 417/2724/2381
+f 473/2790/2432 424/2739/2393 425/2741/2394 474/2791/2433
+f 417/2726/2381 474/2792/2433 467/2784/2426 410/2711/2368
+f 474/2792/2433 425/2743/2394 418/2728/2383 467/2784/2426
+f 722/2793/2434 721/2794/2435 734/2795/2436 735/2796/2437
+f 723/2797/2438 722/2793/2434 735/2796/2437 736/2798/2439
+f 724/2799/2440 723/2797/2438 736/2798/2439 737/2800/2441
+f 719/2801/2442 734/2795/2436 721/2794/2435 720/2802/2443
+f 724/2799/2440 737/2800/2441 729/2803/2444 725/2804/2445
+f 735/2796/2437 734/2795/2436 738/2805/2446 739/2806/2447
+f 736/2798/2439 735/2796/2437 739/2806/2447 740/2807/2448
+f 737/2800/2441 736/2798/2439 740/2807/2448 741/2808/2449
+f 718/2809/2450 738/2805/2446 734/2795/2436 719/2801/2442
+f 726/2810/2451 729/2803/2444 737/2800/2441 741/2808/2449
+f 738/2805/2446 742/2811/2452 743/2812/2453 739/2806/2447
+f 739/2806/2447 743/2812/2453 744/2813/2454 740/2807/2448
+f 740/2807/2448 744/2813/2454 745/2814/2455 741/2808/2449
+f 717/2815/2456 742/2811/2452 738/2805/2446 718/2809/2450
+f 726/2810/2451 741/2808/2449 745/2814/2455 727/2816/2457
+f 742/2811/2452 2819/2817/2458 2820/2818/2459 743/2812/2453
+f 743/2812/2453 2820/2818/2459 2821/2819/2460 744/2813/2454
+f 744/2813/2454 2821/2819/2460 2822/2820/2461 745/2814/2455
+f 727/2816/2457 745/2814/2455 2822/2820/2461 2823/2821/2462
+f 2824/2822/2463 2819/2817/2458 742/2811/2452 717/2815/2456
+f 2825/2823/2464 754/2824/2465 755/2825/2466 2826/2826/2467
+f 2826/2826/2467 755/2825/2466 756/2827/2468 2827/2828/2469
+f 2827/2829/2469 756/2830/2468 757/2831/2470 2828/2832/2471
+f 714/2833/2472 754/2824/2465 2825/2823/2464 2829/2834/2473
+f 2830/2835/2474 2828/2832/2471 757/2831/2470 885/2836/2475
+f 754/2824/2465 758/2837/2476 759/2838/2477 755/2825/2466
+f 755/2825/2466 759/2838/2477 760/2839/2478 756/2827/2468
+f 756/2830/2468 760/2840/2478 761/2841/2479 757/2831/2470
+f 713/2842/2480 758/2837/2476 754/2824/2465 714/2833/2472
+f 885/2836/2475 757/2831/2470 761/2841/2479 886/2843/2481
+f 763/2844/2482 762/2845/2483 770/2846/2484 771/2847/2485
+f 764/2848/2486 763/2844/2482 771/2847/2485 772/2849/2487
+f 765/2850/2488 764/2848/2486 772/2849/2487 773/2851/2489
+f 766/2852/2490 765/2850/2488 773/2851/2489 774/2853/2491
+f 767/2854/2492 766/2855/2490 774/2856/2491 775/2857/2493
+f 768/2858/2494 767/2854/2492 775/2857/2493 776/2859/2495
+f 769/2860/2496 768/2858/2494 776/2859/2495 777/2861/2497
+f 762/2845/2483 769/2860/2496 777/2861/2497 770/2846/2484
+f 759/2838/2477 765/2850/2488 766/2852/2490 760/2839/2478
+f 712/2862/2498 778/2863/2499 758/2837/2476 713/2842/2480
+f 758/2837/2476 778/2863/2499 779/2864/2500 759/2838/2477
+f 759/2838/2477 779/2864/2500 764/2848/2486 765/2850/2488
+f 760/2840/2478 766/2855/2490 767/2854/2492 780/2865/2501
+f 760/2840/2478 780/2865/2501 781/2866/2502 761/2841/2479
+f 886/2843/2481 761/2841/2479 781/2866/2502 731/2867/2503
+f 770/2846/2484 782/2868/2504 783/2869/2505 771/2847/2485
+f 771/2847/2485 783/2869/2505 784/2870/2506 772/2849/2487
+f 772/2849/2487 784/2870/2506 785/2871/2507 773/2851/2489
+f 773/2851/2489 785/2871/2507 786/2872/2508 774/2853/2491
+f 774/2856/2491 786/2873/2508 787/2874/2509 775/2857/2493
+f 775/2857/2493 787/2874/2509 788/2875/2510 776/2859/2495
+f 776/2859/2495 788/2875/2510 789/2876/2511 777/2861/2497
+f 777/2861/2497 789/2876/2511 782/2868/2504 770/2846/2484
+f 763/2844/2482 764/2848/2486 779/2864/2500 790/2877/2512
+f 767/2854/2492 768/2858/2494 791/2878/2513 780/2865/2501
+f 780/2865/2501 791/2878/2513 792/2879/2514 781/2866/2502
+f 731/2867/2503 781/2866/2502 792/2879/2514 732/2880/2515
+f 711/2881/2516 793/2882/2517 778/2863/2499 712/2862/2498
+f 778/2863/2499 793/2882/2517 790/2877/2512 779/2864/2500
+f 762/2845/2483 794/2883/2518 795/2884/2519 769/2860/2496
+f 762/2845/2483 763/2844/2482 790/2877/2512 794/2883/2518
+f 768/2858/2494 769/2860/2496 795/2884/2519 791/2878/2513
+f 710/2885/2520 796/2886/2521 793/2882/2517 711/2881/2516
+f 790/2877/2512 793/2882/2517 796/2886/2521 794/2883/2518
+f 791/2878/2513 795/2884/2519 797/2887/2522 792/2879/2514
+f 732/2880/2515 792/2879/2514 797/2887/2522 733/2888/2523
+f 2831/2889/2524 2832/2890/2525 804/2891/2526 803/2892/2527
+f 2834/2893/2528 2833/2894/2529 805/2895/2530 806/2896/2531
+f 2833/2894/2529 2831/2889/2524 803/2892/2527 805/2895/2530
+f 2835/2897/2532 2859/2898/2533 808/2899/2534 807/2900/2535
+f 2832/2890/2525 2835/2897/2532 807/2900/2535 804/2891/2526
+f 803/2892/2527 804/2891/2526 809/2901/2536 810/2902/2537
+f 806/2896/2531 805/2895/2530 812/2903/2538 811/2904/2539
+f 805/2895/2530 803/2892/2527 810/2902/2537 812/2903/2538
+f 807/2900/2535 808/2899/2534 814/2905/2540 813/2906/2541
+f 804/2891/2526 807/2900/2535 813/2906/2541 809/2901/2536
+f 795/2884/2519 794/2883/2518 816/2907/2542 815/2908/2543
+f 815/2908/2543 816/2907/2542 798/2909/2544 799/2910/2545
+f 796/2886/2521 710/2885/2520 818/2911/2546 817/2912/2547
+f 817/2912/2547 818/2911/2546 801/2913/2548 800/2914/2549
+f 794/2883/2518 796/2886/2521 817/2912/2547 816/2907/2542
+f 816/2907/2542 817/2912/2547 800/2914/2549 798/2909/2544
+f 733/2888/2523 797/2887/2522 819/2915/2550 971/2916/2551
+f 971/2916/2551 819/2915/2550 802/2917/2552 956/2918/2553
+f 797/2887/2522 795/2884/2519 815/2908/2543 819/2915/2550
+f 819/2915/2550 815/2908/2543 799/2910/2545 802/2917/2552
+f 782/2868/2504 820/2919/2554 821/2920/2555 783/2869/2505
+f 783/2869/2505 821/2920/2555 822/2921/2556 784/2870/2506
+f 784/2870/2506 822/2921/2556 823/2922/2557 785/2871/2507
+f 785/2871/2507 823/2922/2557 824/2923/2558 786/2872/2508
+f 786/2873/2508 824/2924/2558 825/2925/2559 787/2874/2509
+f 787/2874/2509 825/2925/2559 826/2926/2560 788/2875/2510
+f 788/2875/2510 826/2926/2560 827/2927/2561 789/2876/2511
+f 789/2876/2511 827/2927/2561 820/2919/2554 782/2868/2504
+f 820/2919/2554 829/2928/2562 828/2929/2563 821/2920/2555
+f 821/2920/2555 828/2929/2563 830/2930/2564 822/2921/2556
+f 822/2921/2556 830/2930/2564 831/2931/2565 823/2922/2557
+f 823/2922/2557 831/2931/2565 832/2932/2566 824/2923/2558
+f 824/2924/2558 832/2933/2566 833/2934/2567 825/2925/2559
+f 825/2925/2559 833/2934/2567 834/2935/2568 826/2926/2560
+f 826/2926/2560 834/2935/2568 835/2936/2569 827/2927/2561
+f 827/2927/2561 835/2936/2569 829/2928/2562 820/2919/2554
+f 829/2928/2562 836/2937/2570 837/2938/2571 828/2929/2563
+f 828/2929/2563 837/2938/2571 838/2939/2572 830/2930/2564
+f 830/2930/2564 838/2939/2572 839/2940/2573 831/2931/2565
+f 831/2931/2565 839/2940/2573 840/2941/2574 832/2932/2566
+f 832/2933/2566 840/2942/2574 841/2943/2575 833/2934/2567
+f 833/2934/2567 841/2943/2575 842/2944/2576 834/2935/2568
+f 834/2935/2568 842/2944/2576 843/2945/2577 835/2936/2569
+f 835/2936/2569 843/2945/2577 836/2937/2570 829/2928/2562
+f 836/2937/2570 2836/2946/2578 2837/2947/2579 837/2938/2571
+f 837/2938/2571 2837/2947/2579 2838/2948/2580 838/2939/2572
+f 838/2939/2572 2838/2948/2580 2839/2949/2581 839/2940/2573
+f 839/2940/2573 2839/2949/2581 2840/2950/2582 840/2941/2574
+f 840/2942/2574 2840/2951/2582 2841/2952/2583 841/2943/2575
+f 841/2943/2575 2841/2952/2583 2842/2953/2584 842/2944/2576
+f 842/2944/2576 2842/2953/2584 2843/2954/2585 843/2945/2577
+f 843/2945/2577 2843/2954/2585 2836/2946/2578 836/2937/2570
+f 844/2955/2586 845/2956/2587 852/2957/2588 853/2958/2589
+f 845/2956/2587 846/2959/2590 854/2960/2591 852/2957/2588
+f 846/2959/2590 847/2961/2592 855/2962/2593 854/2960/2591
+f 847/2961/2592 848/2963/2594 856/2964/2595 855/2962/2593
+f 848/2965/2594 849/2966/2596 857/2967/2597 856/2968/2595
+f 849/2966/2596 850/2969/2598 858/2970/2599 857/2967/2597
+f 850/2969/2598 851/2971/2600 859/2972/2601 858/2970/2599
+f 851/2971/2600 844/2955/2586 853/2958/2589 859/2972/2601
+f 853/2958/2589 852/2957/2588 861/2973/2602 860/2974/2603
+f 852/2957/2588 854/2960/2591 862/2975/2604 861/2973/2602
+f 854/2960/2591 855/2962/2593 863/2976/2605 862/2975/2604
+f 855/2962/2593 856/2964/2595 864/2977/2606 863/2976/2605
+f 856/2968/2595 857/2967/2597 865/2978/2607 864/2979/2606
+f 857/2967/2597 858/2970/2599 866/2980/2608 865/2978/2607
+f 858/2970/2599 859/2972/2601 867/2981/2609 866/2980/2608
+f 859/2972/2601 853/2958/2589 860/2974/2603 867/2981/2609
+f 880/2982/2610 888/2983/2611 887/2984/2612 879/2985/2613
+f 881/2986/2614 889/2987/2615 888/2983/2611 880/2982/2610
+f 882/2988/2616 890/2989/2617 889/2987/2615 881/2986/2614
+f 877/2990/2618 878/2991/2619 879/2985/2613 887/2984/2612
+f 882/2988/2616 883/2992/2620 884/2993/2621 890/2989/2617
+f 888/2983/2611 892/2994/2622 891/2995/2623 887/2984/2612
+f 889/2987/2615 893/2996/2624 892/2994/2622 888/2983/2611
+f 890/2989/2617 894/2997/2625 893/2996/2624 889/2987/2615
+f 876/2998/2626 877/2990/2618 887/2984/2612 891/2995/2623
+f 726/2810/2451 894/2997/2625 890/2989/2617 884/2993/2621
+f 891/2995/2623 892/2994/2622 896/2999/2627 895/3000/2628
+f 892/2994/2622 893/2996/2624 897/3001/2629 896/2999/2627
+f 893/2996/2624 894/2997/2625 898/3002/2630 897/3001/2629
+f 875/3003/2631 876/2998/2626 891/2995/2623 895/3000/2628
+f 726/2810/2451 727/2816/2457 898/3002/2630 894/2997/2625
+f 895/3000/2628 896/2999/2627 2845/3004/2632 2844/3005/2633
+f 896/2999/2627 897/3001/2629 2846/3006/2634 2845/3004/2632
+f 897/3001/2629 898/3002/2630 2847/3007/2635 2846/3006/2634
+f 727/2816/2457 2823/2821/2462 2847/3007/2635 898/3002/2630
+f 2848/3008/2636 875/3003/2631 895/3000/2628 2844/3005/2633
+f 2849/3009/2637 2850/3010/2638 908/3011/2639 907/3012/2640
+f 2850/3010/2638 2851/3013/2641 909/3014/2642 908/3011/2639
+f 2851/3015/2641 2852/3016/2643 910/3017/2644 909/3018/2642
+f 872/3019/2645 2853/3020/2646 2849/3009/2637 907/3012/2640
+f 2830/2835/2474 885/2836/2475 910/3017/2644 2852/3016/2643
+f 907/3012/2640 908/3011/2639 912/3021/2647 911/3022/2648
+f 908/3011/2639 909/3014/2642 913/3023/2649 912/3021/2647
+f 909/3018/2642 910/3017/2644 914/3024/2650 913/3025/2649
+f 871/3026/2651 872/3019/2645 907/3012/2640 911/3022/2648
+f 885/2836/2475 886/2843/2481 914/3024/2650 910/3017/2644
+f 916/3027/2652 924/3028/2653 923/3029/2654 915/3030/2655
+f 917/3031/2656 925/3032/2657 924/3028/2653 916/3027/2652
+f 918/3033/2658 926/3034/2659 925/3032/2657 917/3031/2656
+f 919/3035/2660 927/3036/2661 926/3034/2659 918/3033/2658
+f 920/3037/2662 928/3038/2663 927/3039/2661 919/3040/2660
+f 921/3041/2664 929/3042/2665 928/3038/2663 920/3037/2662
+f 922/3043/2666 930/3044/2667 929/3042/2665 921/3041/2664
+f 915/3030/2655 923/3029/2654 930/3044/2667 922/3043/2666
+f 912/3021/2647 913/3023/2649 919/3035/2660 918/3033/2658
+f 870/3045/2668 871/3026/2651 911/3022/2648 931/3046/2669
+f 911/3022/2648 912/3021/2647 932/3047/2670 931/3046/2669
+f 912/3021/2647 918/3033/2658 917/3031/2656 932/3047/2670
+f 913/3025/2649 933/3048/2671 920/3037/2662 919/3040/2660
+f 913/3025/2649 914/3024/2650 934/3049/2672 933/3048/2671
+f 886/2843/2481 731/2867/2503 934/3049/2672 914/3024/2650
+f 923/3029/2654 924/3028/2653 936/3050/2673 935/3051/2674
+f 924/3028/2653 925/3032/2657 937/3052/2675 936/3050/2673
+f 925/3032/2657 926/3034/2659 938/3053/2676 937/3052/2675
+f 926/3034/2659 927/3036/2661 939/3054/2677 938/3053/2676
+f 927/3039/2661 928/3038/2663 940/3055/2678 939/3056/2677
+f 928/3038/2663 929/3042/2665 941/3057/2679 940/3055/2678
+f 929/3042/2665 930/3044/2667 942/3058/2680 941/3057/2679
+f 930/3044/2667 923/3029/2654 935/3051/2674 942/3058/2680
+f 916/3027/2652 943/3059/2681 932/3047/2670 917/3031/2656
+f 920/3037/2662 933/3048/2671 944/3060/2682 921/3041/2664
+f 933/3048/2671 934/3049/2672 945/3061/2683 944/3060/2682
+f 731/2867/2503 732/2880/2515 945/3061/2683 934/3049/2672
+f 869/3062/2684 870/3045/2668 931/3046/2669 946/3063/2685
+f 931/3046/2669 932/3047/2670 943/3059/2681 946/3063/2685
+f 915/3030/2655 922/3043/2666 948/3064/2686 947/3065/2687
+f 915/3030/2655 947/3065/2687 943/3059/2681 916/3027/2652
+f 921/3041/2664 944/3060/2682 948/3064/2686 922/3043/2666
+f 868/3066/2688 869/3062/2684 946/3063/2685 949/3067/2689
+f 943/3059/2681 947/3065/2687 949/3067/2689 946/3063/2685
+f 944/3060/2682 945/3061/2683 950/3068/2690 948/3064/2686
+f 732/2880/2515 733/2888/2523 950/3068/2690 945/3061/2683
+f 2854/3069/2691 957/3070/2692 958/3071/2693 2855/3072/2694
+f 2857/3073/2695 960/3074/2696 959/3075/2697 2856/3076/2698
+f 2856/3076/2698 959/3075/2697 957/3070/2692 2854/3069/2691
+f 2858/3077/2699 961/3078/2700 808/2899/2534 2859/2898/2533
+f 2855/3072/2694 958/3071/2693 961/3078/2700 2858/3077/2699
+f 957/3070/2692 963/3079/2701 962/3080/2702 958/3071/2693
+f 960/3074/2696 964/3081/2703 965/3082/2704 959/3075/2697
+f 959/3075/2697 965/3082/2704 963/3079/2701 957/3070/2692
+f 961/3078/2700 966/3083/2705 814/2905/2540 808/2899/2534
+f 958/3071/2693 962/3080/2702 966/3083/2705 961/3078/2700
+f 948/3064/2686 967/3084/2706 968/3085/2707 947/3065/2687
+f 967/3084/2706 952/3086/2708 951/3087/2709 968/3085/2707
+f 970/3088/2710 868/3066/2688 949/3067/2689 969/3089/2711
+f 969/3089/2711 953/3090/2712 954/3091/2713 970/3088/2710
+f 947/3065/2687 968/3085/2707 969/3089/2711 949/3067/2689
+f 968/3085/2707 951/3087/2709 953/3090/2712 969/3089/2711
+f 733/2888/2523 971/2916/2551 972/3092/2714 950/3068/2690
+f 971/2916/2551 956/2918/2553 955/3093/2715 972/3092/2714
+f 950/3068/2690 972/3092/2714 967/3084/2706 948/3064/2686
+f 972/3092/2714 955/3093/2715 952/3086/2708 967/3084/2706
+f 935/3051/2674 936/3050/2673 974/3094/2716 973/3095/2717
+f 936/3050/2673 937/3052/2675 975/3096/2718 974/3094/2716
+f 937/3052/2675 938/3053/2676 976/3097/2719 975/3096/2718
+f 938/3053/2676 939/3054/2677 977/3098/2720 976/3097/2719
+f 939/3056/2677 940/3055/2678 978/3099/2721 977/3100/2720
+f 940/3055/2678 941/3057/2679 979/3101/2722 978/3099/2721
+f 941/3057/2679 942/3058/2680 980/3102/2723 979/3101/2722
+f 942/3058/2680 935/3051/2674 973/3095/2717 980/3102/2723
+f 973/3095/2717 974/3094/2716 981/3103/2724 982/3104/2725
+f 974/3094/2716 975/3096/2718 983/3105/2726 981/3103/2724
+f 975/3096/2718 976/3097/2719 984/3106/2727 983/3105/2726
+f 976/3097/2719 977/3098/2720 985/3107/2728 984/3106/2727
+f 977/3100/2720 978/3099/2721 986/3108/2729 985/3109/2728
+f 978/3099/2721 979/3101/2722 987/3110/2730 986/3108/2729
+f 979/3101/2722 980/3102/2723 988/3111/2731 987/3110/2730
+f 980/3102/2723 973/3095/2717 982/3104/2725 988/3111/2731
+f 982/3104/2725 981/3103/2724 990/3112/2732 989/3113/2733
+f 981/3103/2724 983/3105/2726 991/3114/2734 990/3112/2732
+f 983/3105/2726 984/3106/2727 992/3115/2735 991/3114/2734
+f 984/3106/2727 985/3107/2728 993/3116/2736 992/3115/2735
+f 985/3109/2728 986/3108/2729 994/3117/2737 993/3118/2736
+f 986/3108/2729 987/3110/2730 995/3119/2738 994/3117/2737
+f 987/3110/2730 988/3111/2731 996/3120/2739 995/3119/2738
+f 988/3111/2731 982/3104/2725 989/3113/2733 996/3120/2739
+f 989/3113/2733 990/3112/2732 2861/3121/2740 2860/3122/2741
+f 990/3112/2732 991/3114/2734 2862/3123/2742 2861/3121/2740
+f 991/3114/2734 992/3115/2735 2863/3124/2743 2862/3123/2742
+f 992/3115/2735 993/3116/2736 2864/3125/2744 2863/3124/2743
+f 993/3118/2736 994/3117/2737 2865/3126/2745 2864/3127/2744
+f 994/3117/2737 995/3119/2738 2866/3128/2746 2865/3126/2745
+f 995/3119/2738 996/3120/2739 2867/3129/2747 2866/3128/2746
+f 996/3120/2739 989/3113/2733 2860/3122/2741 2867/3129/2747
+f 997/3130/2748 1006/3131/2749 1005/3132/2750 998/3133/2751
+f 998/3133/2751 1005/3132/2750 1007/3134/2752 999/3135/2753
+f 999/3135/2753 1007/3134/2752 1008/3136/2754 1000/3137/2755
+f 1000/3137/2755 1008/3136/2754 1009/3138/2756 1001/3139/2757
+f 1001/3140/2757 1009/3141/2756 1010/3142/2758 1002/3143/2759
+f 1002/3143/2759 1010/3142/2758 1011/3144/2760 1003/3145/2761
+f 1003/3145/2761 1011/3144/2760 1012/3146/2762 1004/3147/2763
+f 1004/3147/2763 1012/3146/2762 1006/3131/2749 997/3130/2748
+f 1006/3131/2749 1013/3148/2764 1014/3149/2765 1005/3132/2750
+f 1005/3132/2750 1014/3149/2765 1015/3150/2766 1007/3134/2752
+f 1007/3134/2752 1015/3150/2766 1016/3151/2767 1008/3136/2754
+f 1008/3136/2754 1016/3151/2767 1017/3152/2768 1009/3138/2756
+f 1009/3141/2756 1017/3153/2768 1018/3154/2769 1010/3142/2758
+f 1010/3142/2758 1018/3154/2769 1019/3155/2770 1011/3144/2760
+f 1011/3144/2760 1019/3155/2770 1020/3156/2771 1012/3146/2762
+f 1012/3146/2762 1020/3156/2771 1013/3148/2764 1006/3131/2749

BIN
3rdparty/meshoptimizer/demo/pirate.optmesh


+ 280 - 0
3rdparty/meshoptimizer/demo/tests.cpp

@@ -0,0 +1,280 @@
+#include "../src/meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <vector>
+
+// This file uses assert() to verify algorithm correctness
+#undef NDEBUG
+#include <assert.h>
+
+struct PV
+{
+	unsigned short px, py, pz;
+	unsigned char nu, nv; // octahedron encoded normal, aliases .pw
+	unsigned short tx, ty;
+};
+
+// note: 4 6 5 triangle here is a combo-breaker:
+// we encode it without rotating, a=next, c=next - this means we do *not* bump next to 6
+// which means that the next triangle can't be encoded via next sequencing!
+static const unsigned int kIndexBuffer[] = {0, 1, 2, 2, 1, 3, 4, 6, 5, 7, 8, 9};
+
+static const unsigned char kIndexDataV0[] = {
+    0xe0, 0xf0, 0x10, 0xfe, 0xff, 0xf0, 0x0c, 0xff, 0x02, 0x02, 0x02, 0x00, 0x76, 0x87, 0x56, 0x67,
+    0x78, 0xa9, 0x86, 0x65, 0x89, 0x68, 0x98, 0x01, 0x69, 0x00, 0x00, // clang-format :-/
+};
+
+static const PV kVertexBuffer[] = {
+    {0, 0, 0, 0, 0, 0, 0},
+    {300, 0, 0, 0, 0, 500, 0},
+    {0, 300, 0, 0, 0, 0, 500},
+    {300, 300, 0, 0, 0, 500, 500},
+};
+
+static const unsigned char kVertexDataV0[] = {
+    0xa0, 0x01, 0x3f, 0x00, 0x00, 0x00, 0x58, 0x57, 0x58, 0x01, 0x26, 0x00, 0x00, 0x00, 0x01,
+    0x0c, 0x00, 0x00, 0x00, 0x58, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x3f, 0x00, 0x00, 0x00, 0x17, 0x18, 0x17, 0x01, 0x26, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00,
+    0x00, 0x00, 0x17, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // clang-format :-/
+};
+
+static void decodeIndexV0()
+{
+	const size_t index_count = sizeof(kIndexBuffer) / sizeof(kIndexBuffer[0]);
+
+	std::vector<unsigned char> buffer(kIndexDataV0, kIndexDataV0 + sizeof(kIndexDataV0));
+
+	unsigned int decoded[index_count];
+	assert(meshopt_decodeIndexBuffer(decoded, index_count, &buffer[0], buffer.size()) == 0);
+	assert(memcmp(decoded, kIndexBuffer, sizeof(kIndexBuffer)) == 0);
+}
+
+static void decodeIndex16()
+{
+	const size_t index_count = sizeof(kIndexBuffer) / sizeof(kIndexBuffer[0]);
+	const size_t vertex_count = 10;
+
+	std::vector<unsigned char> buffer(meshopt_encodeIndexBufferBound(index_count, vertex_count));
+	buffer.resize(meshopt_encodeIndexBuffer(&buffer[0], buffer.size(), kIndexBuffer, index_count));
+
+	unsigned short decoded[index_count];
+	assert(meshopt_decodeIndexBuffer(decoded, index_count, &buffer[0], buffer.size()) == 0);
+
+	for (size_t i = 0; i < index_count; ++i)
+		assert(decoded[i] == kIndexBuffer[i]);
+}
+
+static void encodeIndexMemorySafe()
+{
+	const size_t index_count = sizeof(kIndexBuffer) / sizeof(kIndexBuffer[0]);
+	const size_t vertex_count = 10;
+
+	std::vector<unsigned char> buffer(meshopt_encodeIndexBufferBound(index_count, vertex_count));
+	buffer.resize(meshopt_encodeIndexBuffer(&buffer[0], buffer.size(), kIndexBuffer, index_count));
+
+	// check that encode is memory-safe; note that we reallocate the buffer for each try to make sure ASAN can verify buffer access
+	for (size_t i = 0; i <= buffer.size(); ++i)
+	{
+		std::vector<unsigned char> shortbuffer(i);
+		size_t result = meshopt_encodeIndexBuffer(i == 0 ? 0 : &shortbuffer[0], i, kIndexBuffer, index_count);
+
+		if (i == buffer.size())
+			assert(result == buffer.size());
+		else
+			assert(result == 0);
+	}
+}
+
+static void decodeIndexMemorySafe()
+{
+	const size_t index_count = sizeof(kIndexBuffer) / sizeof(kIndexBuffer[0]);
+	const size_t vertex_count = 10;
+
+	std::vector<unsigned char> buffer(meshopt_encodeIndexBufferBound(index_count, vertex_count));
+	buffer.resize(meshopt_encodeIndexBuffer(&buffer[0], buffer.size(), kIndexBuffer, index_count));
+
+	// check that decode is memory-safe; note that we reallocate the buffer for each try to make sure ASAN can verify buffer access
+	unsigned int decoded[index_count];
+
+	for (size_t i = 0; i <= buffer.size(); ++i)
+	{
+		std::vector<unsigned char> shortbuffer(buffer.begin(), buffer.begin() + i);
+		int result = meshopt_decodeIndexBuffer(decoded, index_count, i == 0 ? 0 : &shortbuffer[0], i);
+
+		if (i == buffer.size())
+			assert(result == 0);
+		else
+			assert(result < 0);
+	}
+}
+
+static void decodeIndexRejectExtraBytes()
+{
+	const size_t index_count = sizeof(kIndexBuffer) / sizeof(kIndexBuffer[0]);
+	const size_t vertex_count = 10;
+
+	std::vector<unsigned char> buffer(meshopt_encodeIndexBufferBound(index_count, vertex_count));
+	buffer.resize(meshopt_encodeIndexBuffer(&buffer[0], buffer.size(), kIndexBuffer, index_count));
+
+	// check that decoder doesn't accept extra bytes after a valid stream
+	std::vector<unsigned char> largebuffer(buffer);
+	largebuffer.push_back(0);
+
+	unsigned int decoded[index_count];
+	assert(meshopt_decodeIndexBuffer(decoded, index_count, &largebuffer[0], largebuffer.size()) < 0);
+}
+
+static void decodeIndexRejectMalformedHeaders()
+{
+	const size_t index_count = sizeof(kIndexBuffer) / sizeof(kIndexBuffer[0]);
+	const size_t vertex_count = 10;
+
+	std::vector<unsigned char> buffer(meshopt_encodeIndexBufferBound(index_count, vertex_count));
+	buffer.resize(meshopt_encodeIndexBuffer(&buffer[0], buffer.size(), kIndexBuffer, index_count));
+
+	// check that decoder doesn't accept malformed headers
+	std::vector<unsigned char> brokenbuffer(buffer);
+	brokenbuffer[0] = 0;
+
+	unsigned int decoded[index_count];
+	assert(meshopt_decodeIndexBuffer(decoded, index_count, &brokenbuffer[0], brokenbuffer.size()) < 0);
+}
+
+static void decodeVertexV0()
+{
+	const size_t vertex_count = sizeof(kVertexBuffer) / sizeof(kVertexBuffer[0]);
+
+	std::vector<unsigned char> buffer(kVertexDataV0, kVertexDataV0 + sizeof(kVertexDataV0));
+
+	PV decoded[vertex_count];
+	assert(meshopt_decodeVertexBuffer(decoded, vertex_count, sizeof(PV), &buffer[0], buffer.size()) == 0);
+	assert(memcmp(decoded, kVertexBuffer, sizeof(kVertexBuffer)) == 0);
+}
+
+static void encodeVertexMemorySafe()
+{
+	const size_t vertex_count = sizeof(kVertexBuffer) / sizeof(kVertexBuffer[0]);
+
+	std::vector<unsigned char> buffer(meshopt_encodeVertexBufferBound(vertex_count, sizeof(PV)));
+	buffer.resize(meshopt_encodeVertexBuffer(&buffer[0], buffer.size(), kVertexBuffer, vertex_count, sizeof(PV)));
+
+	// check that encode is memory-safe; note that we reallocate the buffer for each try to make sure ASAN can verify buffer access
+	for (size_t i = 0; i <= buffer.size(); ++i)
+	{
+		std::vector<unsigned char> shortbuffer(i);
+		size_t result = meshopt_encodeVertexBuffer(i == 0 ? 0 : &shortbuffer[0], i, kVertexBuffer, vertex_count, sizeof(PV));
+
+		if (i == buffer.size())
+			assert(result == buffer.size());
+		else
+			assert(result == 0);
+	}
+}
+
+static void decodeVertexMemorySafe()
+{
+	const size_t vertex_count = sizeof(kVertexBuffer) / sizeof(kVertexBuffer[0]);
+
+	std::vector<unsigned char> buffer(meshopt_encodeVertexBufferBound(vertex_count, sizeof(PV)));
+	buffer.resize(meshopt_encodeVertexBuffer(&buffer[0], buffer.size(), kVertexBuffer, vertex_count, sizeof(PV)));
+
+	// check that decode is memory-safe; note that we reallocate the buffer for each try to make sure ASAN can verify buffer access
+	PV decoded[vertex_count];
+
+	for (size_t i = 0; i <= buffer.size(); ++i)
+	{
+		std::vector<unsigned char> shortbuffer(buffer.begin(), buffer.begin() + i);
+		int result = meshopt_decodeVertexBuffer(decoded, vertex_count, sizeof(PV), i == 0 ? 0 : &shortbuffer[0], i);
+		(void)result;
+
+		if (i == buffer.size())
+			assert(result == 0);
+		else
+			assert(result < 0);
+	}
+}
+
+static void decodeVertexRejectExtraBytes()
+{
+	const size_t vertex_count = sizeof(kVertexBuffer) / sizeof(kVertexBuffer[0]);
+
+	std::vector<unsigned char> buffer(meshopt_encodeVertexBufferBound(vertex_count, sizeof(PV)));
+	buffer.resize(meshopt_encodeVertexBuffer(&buffer[0], buffer.size(), kVertexBuffer, vertex_count, sizeof(PV)));
+
+	// check that decoder doesn't accept extra bytes after a valid stream
+	std::vector<unsigned char> largebuffer(buffer);
+	largebuffer.push_back(0);
+
+	PV decoded[vertex_count];
+	assert(meshopt_decodeVertexBuffer(decoded, vertex_count, sizeof(PV), &largebuffer[0], largebuffer.size()) < 0);
+}
+
+static void decodeVertexRejectMalformedHeaders()
+{
+	const size_t vertex_count = sizeof(kVertexBuffer) / sizeof(kVertexBuffer[0]);
+
+	std::vector<unsigned char> buffer(meshopt_encodeVertexBufferBound(vertex_count, sizeof(PV)));
+	buffer.resize(meshopt_encodeVertexBuffer(&buffer[0], buffer.size(), kVertexBuffer, vertex_count, sizeof(PV)));
+
+	// check that decoder doesn't accept malformed headers
+	std::vector<unsigned char> brokenbuffer(buffer);
+	brokenbuffer[0] = 0;
+
+	PV decoded[vertex_count];
+	assert(meshopt_decodeVertexBuffer(decoded, vertex_count, sizeof(PV), &brokenbuffer[0], brokenbuffer.size()) < 0);
+}
+
+static void clusterBoundsDegenerate()
+{
+	const float vbd[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+	const unsigned int ibd[] = {0, 0, 0};
+	const unsigned int ib1[] = {0, 1, 2};
+
+	// all of the bounds below are degenerate as they use 0 triangles, one topology-degenerate triangle and one position-degenerate triangle respectively
+	meshopt_Bounds bounds0 = meshopt_computeClusterBounds(0, 0, 0, 0, 12);
+	meshopt_Bounds boundsd = meshopt_computeClusterBounds(ibd, 3, vbd, 3, 12);
+	meshopt_Bounds bounds1 = meshopt_computeClusterBounds(ib1, 3, vbd, 3, 12);
+
+	assert(bounds0.center[0] == 0 && bounds0.center[1] == 0 && bounds0.center[2] == 0 && bounds0.radius == 0);
+	assert(boundsd.center[0] == 0 && boundsd.center[1] == 0 && boundsd.center[2] == 0 && boundsd.radius == 0);
+	assert(bounds1.center[0] == 0 && bounds1.center[1] == 0 && bounds1.center[2] == 0 && bounds1.radius == 0);
+
+	const float vb1[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
+	const unsigned int ib2[] = {0, 1, 2, 0, 2, 1};
+
+	// these bounds have a degenerate cone since the cluster has two triangles with opposite normals
+	meshopt_Bounds bounds2 = meshopt_computeClusterBounds(ib2, 6, vb1, 3, 12);
+
+	assert(bounds2.cone_apex[0] == 0 && bounds2.cone_apex[1] == 0 && bounds2.cone_apex[2] == 0);
+	assert(bounds2.cone_axis[0] == 0 && bounds2.cone_axis[1] == 0 && bounds2.cone_axis[2] == 0);
+	assert(bounds2.cone_cutoff == 1);
+	assert(bounds2.cone_axis_s8[0] == 0 && bounds2.cone_axis_s8[1] == 0 && bounds2.cone_axis_s8[2] == 0);
+	assert(bounds2.cone_cutoff_s8 == 127);
+
+	// however, the bounding sphere needs to be in tact (here we only check bbox for simplicity)
+	assert(bounds2.center[0] - bounds2.radius <= 0 && bounds2.center[0] + bounds2.radius >= 1);
+	assert(bounds2.center[1] - bounds2.radius <= 0 && bounds2.center[1] + bounds2.radius >= 1);
+	assert(bounds2.center[2] - bounds2.radius <= 0 && bounds2.center[2] + bounds2.radius >= 1);
+}
+
+void runTests()
+{
+	decodeIndexV0();
+	decodeIndex16();
+	encodeIndexMemorySafe();
+	decodeIndexMemorySafe();
+	decodeIndexRejectExtraBytes();
+	decodeIndexRejectMalformedHeaders();
+
+	decodeVertexV0();
+	encodeVertexMemorySafe();
+	decodeVertexMemorySafe();
+	decodeVertexRejectExtraBytes();
+	decodeVertexRejectMalformedHeaders();
+
+	clusterBoundsDegenerate();
+}

Plik diff jest za duży
+ 4 - 0
3rdparty/meshoptimizer/js/decoder.js


+ 7 - 0
3rdparty/meshoptimizer/src/allocator.cpp

@@ -0,0 +1,7 @@
+#include "meshoptimizer.h"
+
+void meshopt_setAllocator(void* (*allocate)(size_t), void (*deallocate)(void*))
+{
+	meshopt_Allocator::Storage::allocate = allocate;
+	meshopt_Allocator::Storage::deallocate = deallocate;
+}

+ 351 - 0
3rdparty/meshoptimizer/src/clusterizer.cpp

@@ -0,0 +1,351 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+
+// This work is based on:
+// Graham Wihlidal. Optimizing the Graphics Pipeline with Compute. 2016
+// Matthaeus Chajdas. GeometryFX 1.2 - Cluster Culling. 2016
+// Jack Ritter. An Efficient Bounding Sphere. 1990
+namespace meshopt
+{
+
+static void computeBoundingSphere(float result[4], const float points[][3], size_t count)
+{
+	assert(count > 0);
+
+	// find extremum points along all 3 axes; for each axis we get a pair of points with min/max coordinates
+	size_t pmin[3] = {0, 0, 0};
+	size_t pmax[3] = {0, 0, 0};
+
+	for (size_t i = 0; i < count; ++i)
+	{
+		const float* p = points[i];
+
+		for (int axis = 0; axis < 3; ++axis)
+		{
+			pmin[axis] = (p[axis] < points[pmin[axis]][axis]) ? i : pmin[axis];
+			pmax[axis] = (p[axis] > points[pmax[axis]][axis]) ? i : pmax[axis];
+		}
+	}
+
+	// find the pair of points with largest distance
+	float paxisd2 = 0;
+	int paxis = 0;
+
+	for (int axis = 0; axis < 3; ++axis)
+	{
+		const float* p1 = points[pmin[axis]];
+		const float* p2 = points[pmax[axis]];
+
+		float d2 = (p2[0] - p1[0]) * (p2[0] - p1[0]) + (p2[1] - p1[1]) * (p2[1] - p1[1]) + (p2[2] - p1[2]) * (p2[2] - p1[2]);
+
+		if (d2 > paxisd2)
+		{
+			paxisd2 = d2;
+			paxis = axis;
+		}
+	}
+
+	// use the longest segment as the initial sphere diameter
+	const float* p1 = points[pmin[paxis]];
+	const float* p2 = points[pmax[paxis]];
+
+	float center[3] = {(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2, (p1[2] + p2[2]) / 2};
+	float radius = sqrtf(paxisd2) / 2;
+
+	// iteratively adjust the sphere up until all points fit
+	for (size_t i = 0; i < count; ++i)
+	{
+		const float* p = points[i];
+		float d2 = (p[0] - center[0]) * (p[0] - center[0]) + (p[1] - center[1]) * (p[1] - center[1]) + (p[2] - center[2]) * (p[2] - center[2]);
+
+		if (d2 > radius * radius)
+		{
+			float d = sqrtf(d2);
+			assert(d > 0);
+
+			float k = 0.5f + (radius / d) / 2;
+
+			center[0] = center[0] * k + p[0] * (1 - k);
+			center[1] = center[1] * k + p[1] * (1 - k);
+			center[2] = center[2] * k + p[2] * (1 - k);
+			radius = (radius + d) / 2;
+		}
+	}
+
+	result[0] = center[0];
+	result[1] = center[1];
+	result[2] = center[2];
+	result[3] = radius;
+}
+
+} // namespace meshopt
+
+size_t meshopt_buildMeshletsBound(size_t index_count, size_t max_vertices, size_t max_triangles)
+{
+	assert(index_count % 3 == 0);
+	assert(max_vertices >= 3);
+	assert(max_triangles >= 1);
+
+	// meshlet construction is limited by max vertices and max triangles per meshlet
+	// the worst case is that the input is an unindexed stream since this equally stresses both limits
+	// note that we assume that in the worst case, we leave 2 vertices unpacked in each meshlet - if we have space for 3 we can pack any triangle
+	size_t max_vertices_conservative = max_vertices - 2;
+	size_t meshlet_limit_vertices = (index_count + max_vertices_conservative - 1) / max_vertices_conservative;
+	size_t meshlet_limit_triangles = (index_count / 3 + max_triangles - 1) / max_triangles;
+
+	return meshlet_limit_vertices > meshlet_limit_triangles ? meshlet_limit_vertices : meshlet_limit_triangles;
+}
+
+size_t meshopt_buildMeshlets(meshopt_Meshlet* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles)
+{
+	assert(index_count % 3 == 0);
+	assert(max_vertices >= 3);
+	assert(max_triangles >= 1);
+
+	meshopt_Allocator allocator;
+
+	meshopt_Meshlet meshlet;
+	memset(&meshlet, 0, sizeof(meshlet));
+
+	assert(max_vertices <= sizeof(meshlet.vertices) / sizeof(meshlet.vertices[0]));
+	assert(max_triangles <= sizeof(meshlet.indices) / 3);
+
+	// index of the vertex in the meshlet, 0xff if the vertex isn't used
+	unsigned char* used = allocator.allocate<unsigned char>(vertex_count);
+	memset(used, -1, vertex_count);
+
+	size_t offset = 0;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
+		assert(a < vertex_count && b < vertex_count && c < vertex_count);
+
+		unsigned char& av = used[a];
+		unsigned char& bv = used[b];
+		unsigned char& cv = used[c];
+
+		unsigned int used_extra = (av == 0xff) + (bv == 0xff) + (cv == 0xff);
+
+		if (meshlet.vertex_count + used_extra > max_vertices || meshlet.triangle_count >= max_triangles)
+		{
+			destination[offset++] = meshlet;
+
+			for (size_t j = 0; j < meshlet.vertex_count; ++j)
+				used[meshlet.vertices[j]] = 0xff;
+
+			memset(&meshlet, 0, sizeof(meshlet));
+		}
+
+		if (av == 0xff)
+		{
+			av = meshlet.vertex_count;
+			meshlet.vertices[meshlet.vertex_count++] = a;
+		}
+
+		if (bv == 0xff)
+		{
+			bv = meshlet.vertex_count;
+			meshlet.vertices[meshlet.vertex_count++] = b;
+		}
+
+		if (cv == 0xff)
+		{
+			cv = meshlet.vertex_count;
+			meshlet.vertices[meshlet.vertex_count++] = c;
+		}
+
+		meshlet.indices[meshlet.triangle_count][0] = av;
+		meshlet.indices[meshlet.triangle_count][1] = bv;
+		meshlet.indices[meshlet.triangle_count][2] = cv;
+		meshlet.triangle_count++;
+	}
+
+	if (meshlet.triangle_count)
+		destination[offset++] = meshlet;
+
+	assert(offset <= meshopt_buildMeshletsBound(index_count, max_vertices, max_triangles));
+
+	return offset;
+}
+
+meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+	assert(vertex_positions_stride % sizeof(float) == 0);
+
+	assert(index_count / 3 <= 256);
+
+	(void)vertex_count;
+
+	size_t vertex_stride_float = vertex_positions_stride / sizeof(float);
+
+	// compute triangle normals and gather triangle corners
+	float normals[256][3];
+	float corners[256][3][3];
+	unsigned int triangles = 0;
+
+	for (unsigned int i = 0; i < index_count; i += 3)
+	{
+		unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
+		assert(a < vertex_count && b < vertex_count && c < vertex_count);
+
+		const float* p0 = vertex_positions + vertex_stride_float * a;
+		const float* p1 = vertex_positions + vertex_stride_float * b;
+		const float* p2 = vertex_positions + vertex_stride_float * c;
+
+		float p10[3] = {p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]};
+		float p20[3] = {p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]};
+
+		float normalx = p10[1] * p20[2] - p10[2] * p20[1];
+		float normaly = p10[2] * p20[0] - p10[0] * p20[2];
+		float normalz = p10[0] * p20[1] - p10[1] * p20[0];
+
+		float area = sqrtf(normalx * normalx + normaly * normaly + normalz * normalz);
+
+		// no need to include degenerate triangles - they will be invisible anyway
+		if (area == 0.f)
+			continue;
+
+		// record triangle normals & corners for future use; normal and corner 0 define a plane equation
+		normals[triangles][0] = normalx / area;
+		normals[triangles][1] = normaly / area;
+		normals[triangles][2] = normalz / area;
+		memcpy(corners[triangles][0], p0, 3 * sizeof(float));
+		memcpy(corners[triangles][1], p1, 3 * sizeof(float));
+		memcpy(corners[triangles][2], p2, 3 * sizeof(float));
+		triangles++;
+	}
+
+	meshopt_Bounds bounds = {};
+
+	// degenerate cluster, no valid triangles => trivial reject (cone data is 0)
+	if (triangles == 0)
+		return bounds;
+
+	// compute cluster bounding sphere; we'll use the center to determine normal cone apex as well
+	float psphere[4] = {};
+	computeBoundingSphere(psphere, corners[0], triangles * 3);
+
+	float center[3] = {psphere[0], psphere[1], psphere[2]};
+
+	// treating triangle normals as points, find the bounding sphere - the sphere center determines the optimal cone axis
+	float nsphere[4] = {};
+	computeBoundingSphere(nsphere, normals, triangles);
+
+	float axis[3] = {nsphere[0], nsphere[1], nsphere[2]};
+	float axislength = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+	float invaxislength = axislength == 0.f ? 0.f : 1.f / axislength;
+
+	axis[0] *= invaxislength;
+	axis[1] *= invaxislength;
+	axis[2] *= invaxislength;
+
+	// compute a tight cone around all normals, mindp = cos(angle/2)
+	float mindp = 1.f;
+
+	for (unsigned int i = 0; i < triangles; ++i)
+	{
+		float dp = normals[i][0] * axis[0] + normals[i][1] * axis[1] + normals[i][2] * axis[2];
+
+		mindp = (dp < mindp) ? dp : mindp;
+	}
+
+	// fill bounding sphere info; note that below we can return bounds without cone information for degenerate cones
+	bounds.center[0] = center[0];
+	bounds.center[1] = center[1];
+	bounds.center[2] = center[2];
+	bounds.radius = psphere[3];
+
+	// degenerate cluster, normal cone is larger than a hemisphere => trivial accept
+	// note that if mindp is positive but close to 0, the triangle intersection code below gets less stable
+	// we arbitrarily decide that if a normal cone is ~168 degrees wide or more, the cone isn't useful
+	if (mindp <= 0.1f)
+	{
+		bounds.cone_cutoff = 1;
+		bounds.cone_cutoff_s8 = 127;
+		return bounds;
+	}
+
+	float maxt = 0;
+
+	// we need to find the point on center-t*axis ray that lies in negative half-space of all triangles
+	for (unsigned int i = 0; i < triangles; ++i)
+	{
+		// dot(center-t*axis-corner, trinormal) = 0
+		// dot(center-corner, trinormal) - t * dot(axis, trinormal) = 0
+		float cx = center[0] - corners[i][0][0];
+		float cy = center[1] - corners[i][0][1];
+		float cz = center[2] - corners[i][0][2];
+
+		float dc = cx * normals[i][0] + cy * normals[i][1] + cz * normals[i][2];
+		float dn = axis[0] * normals[i][0] + axis[1] * normals[i][1] + axis[2] * normals[i][2];
+
+		// dn should be larger than mindp cutoff above
+		assert(dn > 0.f);
+		float t = dc / dn;
+
+		maxt = (t > maxt) ? t : maxt;
+	}
+
+	// cone apex should be in the negative half-space of all cluster triangles by construction
+	bounds.cone_apex[0] = center[0] - axis[0] * maxt;
+	bounds.cone_apex[1] = center[1] - axis[1] * maxt;
+	bounds.cone_apex[2] = center[2] - axis[2] * maxt;
+
+	// note: this axis is the axis of the normal cone, but our test for perspective camera effectively negates the axis
+	bounds.cone_axis[0] = axis[0];
+	bounds.cone_axis[1] = axis[1];
+	bounds.cone_axis[2] = axis[2];
+
+	// cos(a) for normal cone is mindp; we need to add 90 degrees on both sides and invert the cone
+	// which gives us -cos(a+90) = -(-sin(a)) = sin(a) = sqrt(1 - cos^2(a))
+	bounds.cone_cutoff = sqrtf(1 - mindp * mindp);
+
+	// quantize axis & cutoff to 8-bit SNORM format
+	bounds.cone_axis_s8[0] = (signed char)(meshopt_quantizeSnorm(bounds.cone_axis[0], 8));
+	bounds.cone_axis_s8[1] = (signed char)(meshopt_quantizeSnorm(bounds.cone_axis[1], 8));
+	bounds.cone_axis_s8[2] = (signed char)(meshopt_quantizeSnorm(bounds.cone_axis[2], 8));
+
+	// for the 8-bit test to be conservative, we need to adjust the cutoff by measuring the max. error
+	float cone_axis_s8_e0 = fabsf(bounds.cone_axis_s8[0] / 127.f - bounds.cone_axis[0]);
+	float cone_axis_s8_e1 = fabsf(bounds.cone_axis_s8[1] / 127.f - bounds.cone_axis[1]);
+	float cone_axis_s8_e2 = fabsf(bounds.cone_axis_s8[2] / 127.f - bounds.cone_axis[2]);
+
+	// note that we need to round this up instead of rounding to nearest, hence +1
+	int cone_cutoff_s8 = int(127 * (bounds.cone_cutoff + cone_axis_s8_e0 + cone_axis_s8_e1 + cone_axis_s8_e2) + 1);
+
+	bounds.cone_cutoff_s8 = (cone_cutoff_s8 > 127) ? 127 : (signed char)(cone_cutoff_s8);
+
+	return bounds;
+}
+
+meshopt_Bounds meshopt_computeMeshletBounds(const meshopt_Meshlet* meshlet, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
+{
+	assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+	assert(vertex_positions_stride % sizeof(float) == 0);
+
+	unsigned int indices[sizeof(meshlet->indices) / sizeof(meshlet->indices[0][0])];
+
+	for (unsigned int i = 0; i < meshlet->triangle_count; ++i)
+	{
+		unsigned int a = meshlet->vertices[meshlet->indices[i][0]];
+		unsigned int b = meshlet->vertices[meshlet->indices[i][1]];
+		unsigned int c = meshlet->vertices[meshlet->indices[i][2]];
+
+		assert(a < vertex_count && b < vertex_count && c < vertex_count);
+
+		indices[i * 3 + 0] = a;
+		indices[i * 3 + 1] = b;
+		indices[i * 3 + 2] = c;
+	}
+
+	return meshopt_computeClusterBounds(indices, meshlet->triangle_count * 3, vertex_positions, vertex_count, vertex_positions_stride);
+}

+ 582 - 0
3rdparty/meshoptimizer/src/indexcodec.cpp

@@ -0,0 +1,582 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+#ifndef TRACE
+#define TRACE 0
+#endif
+
+#if TRACE
+#include <stdio.h>
+#endif
+
+// This work is based on:
+// Fabian Giesen. Simple lossless index buffer compression & follow-up. 2013
+// Conor Stokes. Vertex Cache Optimised Index Buffer Compression. 2014
+namespace meshopt
+{
+
+const unsigned char kIndexHeader = 0xe0;
+
+typedef unsigned int VertexFifo[16];
+typedef unsigned int EdgeFifo[16][2];
+
+static const unsigned int kTriangleIndexOrder[3][3] = {
+    {0, 1, 2},
+    {1, 2, 0},
+    {2, 0, 1},
+};
+
+static const unsigned char kCodeAuxEncodingTable[16] = {
+    0x00, 0x76, 0x87, 0x56, 0x67, 0x78, 0xa9, 0x86, 0x65, 0x89, 0x68, 0x98, 0x01, 0x69,
+    0, 0, // last two entries aren't used for encoding
+};
+
+static int rotateTriangle(unsigned int a, unsigned int b, unsigned int c, unsigned int next)
+{
+	(void)a;
+
+	return (b == next) ? 1 : (c == next) ? 2 : 0;
+}
+
+static int getEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, unsigned int c, size_t offset)
+{
+	for (int i = 0; i < 16; ++i)
+	{
+		size_t index = (offset - 1 - i) & 15;
+
+		unsigned int e0 = fifo[index][0];
+		unsigned int e1 = fifo[index][1];
+
+		if (e0 == a && e1 == b)
+			return (i << 2) | 0;
+		if (e0 == b && e1 == c)
+			return (i << 2) | 1;
+		if (e0 == c && e1 == a)
+			return (i << 2) | 2;
+	}
+
+	return -1;
+}
+
+static void pushEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, size_t& offset)
+{
+	fifo[offset][0] = a;
+	fifo[offset][1] = b;
+	offset = (offset + 1) & 15;
+}
+
+static int getVertexFifo(VertexFifo fifo, unsigned int v, size_t offset)
+{
+	for (int i = 0; i < 16; ++i)
+	{
+		size_t index = (offset - 1 - i) & 15;
+
+		if (fifo[index] == v)
+			return i;
+	}
+
+	return -1;
+}
+
+static void pushVertexFifo(VertexFifo fifo, unsigned int v, size_t& offset, int cond = 1)
+{
+	fifo[offset] = v;
+	offset = (offset + cond) & 15;
+}
+
+static void encodeVByte(unsigned char*& data, unsigned int v)
+{
+	// encode 32-bit value in up to 5 7-bit groups
+	do
+	{
+		*data++ = (v & 127) | (v > 127 ? 128 : 0);
+		v >>= 7;
+	} while (v);
+}
+
+static unsigned int decodeVByte(const unsigned char*& data)
+{
+	unsigned char lead = *data++;
+
+	// fast path: single byte
+	if (lead < 128)
+		return lead;
+
+	// slow path: up to 4 extra bytes
+	// note that this loop always terminates, which is important for malformed data
+	unsigned int result = lead & 127;
+	unsigned int shift = 7;
+
+	for (int i = 0; i < 4; ++i)
+	{
+		unsigned char group = *data++;
+		result |= (group & 127) << shift;
+		shift += 7;
+
+		if (group < 128)
+			break;
+	}
+
+	return result;
+}
+
+static void encodeIndex(unsigned char*& data, unsigned int index, unsigned int next, unsigned int last)
+{
+	(void)next;
+
+	unsigned int d = index - last;
+	unsigned int v = (d << 1) ^ (int(d) >> 31);
+
+	encodeVByte(data, v);
+}
+
+static unsigned int decodeIndex(const unsigned char*& data, unsigned int next, unsigned int last)
+{
+	(void)next;
+
+	unsigned int v = decodeVByte(data);
+	unsigned int d = (v >> 1) ^ -int(v & 1);
+
+	return last + d;
+}
+
+static int getCodeAuxIndex(unsigned char v, const unsigned char* table)
+{
+	for (int i = 0; i < 16; ++i)
+		if (table[i] == v)
+			return i;
+
+	return -1;
+}
+
+static void writeTriangle(void* destination, size_t offset, size_t index_size, unsigned int a, unsigned int b, unsigned int c)
+{
+	if (index_size == 2)
+	{
+		static_cast<unsigned short*>(destination)[offset + 0] = (unsigned short)(a);
+		static_cast<unsigned short*>(destination)[offset + 1] = (unsigned short)(b);
+		static_cast<unsigned short*>(destination)[offset + 2] = (unsigned short)(c);
+	}
+	else
+#ifdef __EMSCRIPTEN__
+	if (index_size == 4) // work around Edge (ChakraCore) bug - without this compiler assumes index_size==2
+#endif
+	{
+		static_cast<unsigned int*>(destination)[offset + 0] = a;
+		static_cast<unsigned int*>(destination)[offset + 1] = b;
+		static_cast<unsigned int*>(destination)[offset + 2] = c;
+	}
+}
+
+#if TRACE
+static size_t sortTop16(unsigned char dest[16], size_t stats[256])
+{
+	size_t destsize = 0;
+
+	for (size_t i = 0; i < 256; ++i)
+	{
+		size_t j = 0;
+		for (; j < destsize; ++j)
+		{
+			if (stats[i] >= stats[dest[j]])
+			{
+				if (destsize < 16)
+					destsize++;
+
+				memmove(&dest[j + 1], &dest[j], destsize - 1 - j);
+				dest[j] = (unsigned char)i;
+				break;
+			}
+		}
+
+		if (j == destsize && destsize < 16)
+		{
+			dest[destsize] = (unsigned char)i;
+			destsize++;
+		}
+	}
+
+	return destsize;
+}
+#endif
+
+} // namespace meshopt
+
+size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+
+#if TRACE
+	size_t codestats[256] = {};
+	size_t codeauxstats[256] = {};
+#endif
+
+	// the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
+	if (buffer_size < 1 + index_count / 3 + 16)
+		return 0;
+
+	buffer[0] = kIndexHeader;
+
+	EdgeFifo edgefifo;
+	memset(edgefifo, -1, sizeof(edgefifo));
+
+	VertexFifo vertexfifo;
+	memset(vertexfifo, -1, sizeof(vertexfifo));
+
+	size_t edgefifooffset = 0;
+	size_t vertexfifooffset = 0;
+
+	unsigned int next = 0;
+	unsigned int last = 0;
+
+	unsigned char* code = buffer + 1;
+	unsigned char* data = code + index_count / 3;
+	unsigned char* data_safe_end = buffer + buffer_size - 16;
+
+	// use static encoding table; it's possible to pack the result and then build an optimal table and repack
+	// for now we keep it simple and use the table that has been generated based on symbol frequency on a training mesh set
+	const unsigned char* codeaux_table = kCodeAuxEncodingTable;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		// make sure we have enough space to write a triangle
+		// each triangle writes at most 16 bytes: 1b for codeaux and 5b for each free index
+		// after this we can be sure we can write without extra bounds checks
+		if (data > data_safe_end)
+			return 0;
+
+		int fer = getEdgeFifo(edgefifo, indices[i + 0], indices[i + 1], indices[i + 2], edgefifooffset);
+
+		if (fer >= 0 && (fer >> 2) < 15)
+		{
+			const unsigned int* order = kTriangleIndexOrder[fer & 3];
+
+			unsigned int a = indices[i + order[0]], b = indices[i + order[1]], c = indices[i + order[2]];
+
+			// encode edge index and vertex fifo index, next or free index
+			int fe = fer >> 2;
+			int fc = getVertexFifo(vertexfifo, c, vertexfifooffset);
+
+			int fec = (fc >= 1 && fc < 15) ? fc : (c == next) ? (next++, 0) : 15;
+
+			*code++ = (unsigned char)((fe << 4) | fec);
+
+#if TRACE
+			codestats[code[-1]]++;
+#endif
+
+			// note that we need to update the last index since free indices are delta-encoded
+			if (fec == 15)
+				encodeIndex(data, c, next, last), last = c;
+
+			// we only need to push third vertex since first two are likely already in the vertex fifo
+			if (fec == 0 || fec == 15)
+				pushVertexFifo(vertexfifo, c, vertexfifooffset);
+
+			// we only need to push two new edges to edge fifo since the third one is already there
+			pushEdgeFifo(edgefifo, c, b, edgefifooffset);
+			pushEdgeFifo(edgefifo, a, c, edgefifooffset);
+		}
+		else
+		{
+			int rotation = rotateTriangle(indices[i + 0], indices[i + 1], indices[i + 2], next);
+			const unsigned int* order = kTriangleIndexOrder[rotation];
+
+			unsigned int a = indices[i + order[0]], b = indices[i + order[1]], c = indices[i + order[2]];
+
+			int fb = getVertexFifo(vertexfifo, b, vertexfifooffset);
+			int fc = getVertexFifo(vertexfifo, c, vertexfifooffset);
+
+			// after rotation, a is almost always equal to next, so we don't waste bits on FIFO encoding for a
+			int fea = (a == next) ? (next++, 0) : 15;
+			int feb = (fb >= 0 && fb < 14) ? (fb + 1) : (b == next) ? (next++, 0) : 15;
+			int fec = (fc >= 0 && fc < 14) ? (fc + 1) : (c == next) ? (next++, 0) : 15;
+
+			// we encode feb & fec in 4 bits using a table if possible, and as a full byte otherwise
+			unsigned char codeaux = (unsigned char)((feb << 4) | fec);
+			int codeauxindex = getCodeAuxIndex(codeaux, codeaux_table);
+
+			// <14 encodes an index into codeaux table, 14 encodes fea=0, 15 encodes fea=15
+			if (fea == 0 && codeauxindex >= 0 && codeauxindex < 14)
+			{
+				*code++ = (unsigned char)((15 << 4) | codeauxindex);
+			}
+			else
+			{
+				*code++ = (unsigned char)((15 << 4) | 14 | fea);
+				*data++ = codeaux;
+			}
+
+#if TRACE
+			codestats[code[-1]]++;
+			codeauxstats[codeaux]++;
+#endif
+
+			// note that we need to update the last index since free indices are delta-encoded
+			if (fea == 15)
+				encodeIndex(data, a, next, last), last = a;
+
+			if (feb == 15)
+				encodeIndex(data, b, next, last), last = b;
+
+			if (fec == 15)
+				encodeIndex(data, c, next, last), last = c;
+
+			// only push vertices that weren't already in fifo
+			if (fea == 0 || fea == 15)
+				pushVertexFifo(vertexfifo, a, vertexfifooffset);
+
+			if (feb == 0 || feb == 15)
+				pushVertexFifo(vertexfifo, b, vertexfifooffset);
+
+			if (fec == 0 || fec == 15)
+				pushVertexFifo(vertexfifo, c, vertexfifooffset);
+
+			// all three edges aren't in the fifo; pushing all of them is important so that we can match them for later triangles
+			pushEdgeFifo(edgefifo, b, a, edgefifooffset);
+			pushEdgeFifo(edgefifo, c, b, edgefifooffset);
+			pushEdgeFifo(edgefifo, a, c, edgefifooffset);
+		}
+	}
+
+	// make sure we have enough space to write codeaux table
+	if (data > data_safe_end)
+		return 0;
+
+	// add codeaux encoding table to the end of the stream; this is used for decoding codeaux *and* as padding
+	// we need padding for decoding to be able to assume that each triangle is encoded as <= 16 bytes of extra data
+	// this is enough space for aux byte + 5 bytes per varint index which is the absolute worst case for any input
+	for (size_t i = 0; i < 16; ++i)
+	{
+		// decoder assumes that table entries never refer to separately encoded indices
+		assert((codeaux_table[i] & 0xf) != 0xf && (codeaux_table[i] >> 4) != 0xf);
+
+		*data++ = codeaux_table[i];
+	}
+
+	assert(data >= buffer + index_count / 3 + 16);
+	assert(data <= buffer + buffer_size);
+
+#if TRACE
+	unsigned char codetop[16], codeauxtop[16];
+	size_t codetopsize = sortTop16(codetop, codestats);
+	size_t codeauxtopsize = sortTop16(codeauxtop, codeauxstats);
+
+	size_t sumcode = 0, sumcodeaux = 0;
+	for (size_t i = 0; i < 256; ++i)
+		sumcode += codestats[i], sumcodeaux += codeauxstats[i];
+
+	size_t acccode = 0, acccodeaux = 0;
+
+	printf("code\t\t\t\t\tcodeaux\n");
+
+	for (size_t i = 0; i < codetopsize && i < codeauxtopsize; ++i)
+	{
+		acccode += codestats[codetop[i]];
+		acccodeaux += codeauxstats[codeauxtop[i]];
+
+		printf("%2d: %02x = %d (%.1f%% ..%.1f%%)\t\t%2d: %02x = %d (%.1f%% ..%.1f%%)\n",
+		       int(i), codetop[i], int(codestats[codetop[i]]), double(codestats[codetop[i]]) / double(sumcode) * 100, double(acccode) / double(sumcode) * 100,
+		       int(i), codeauxtop[i], int(codeauxstats[codeauxtop[i]]), double(codeauxstats[codeauxtop[i]]) / double(sumcodeaux) * 100, double(acccodeaux) / double(sumcodeaux) * 100);
+	}
+#endif
+
+	return data - buffer;
+}
+
+size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count)
+{
+	assert(index_count % 3 == 0);
+
+	// compute number of bits required for each index
+	unsigned int vertex_bits = 1;
+
+	while (vertex_bits < 32 && vertex_count > size_t(1) << vertex_bits)
+		vertex_bits++;
+
+	// worst-case encoding is 2 header bytes + 3 varint-7 encoded index deltas
+	unsigned int vertex_groups = (vertex_bits + 1 + 6) / 7;
+
+	return 1 + (index_count / 3) * (2 + 3 * vertex_groups) + 16;
+}
+
+int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(index_size == 2 || index_size == 4);
+
+	// the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
+	if (buffer_size < 1 + index_count / 3 + 16)
+		return -2;
+
+	if (buffer[0] != kIndexHeader)
+		return -1;
+
+	EdgeFifo edgefifo;
+	memset(edgefifo, -1, sizeof(edgefifo));
+
+	VertexFifo vertexfifo;
+	memset(vertexfifo, -1, sizeof(vertexfifo));
+
+	size_t edgefifooffset = 0;
+	size_t vertexfifooffset = 0;
+
+	unsigned int next = 0;
+	unsigned int last = 0;
+
+	// since we store 16-byte codeaux table at the end, triangle data has to begin before data_safe_end
+	const unsigned char* code = buffer + 1;
+	const unsigned char* data = code + index_count / 3;
+	const unsigned char* data_safe_end = buffer + buffer_size - 16;
+
+	const unsigned char* codeaux_table = data_safe_end;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		// make sure we have enough data to read for a triangle
+		// each triangle reads at most 16 bytes of data: 1b for codeaux and 5b for each free index
+		// after this we can be sure we can read without extra bounds checks
+		if (data > data_safe_end)
+			return -2;
+
+		unsigned char codetri = *code++;
+
+		if (codetri < 0xf0)
+		{
+			int fe = codetri >> 4;
+
+			// fifo reads are wrapped around 16 entry buffer
+			unsigned int a = edgefifo[(edgefifooffset - 1 - fe) & 15][0];
+			unsigned int b = edgefifo[(edgefifooffset - 1 - fe) & 15][1];
+
+			int fec = codetri & 15;
+
+			// note: this is the most common path in the entire decoder
+			// inside this if we try to stay branchless (by using cmov/etc.) since these aren't predictable
+			if (fec != 15)
+			{
+				// fifo reads are wrapped around 16 entry buffer
+				unsigned int cf = vertexfifo[(vertexfifooffset - 1 - fec) & 15];
+				unsigned int c = (fec == 0) ? next : cf;
+
+				int fec0 = fec == 0;
+				next += fec0;
+
+				// output triangle
+				writeTriangle(destination, i, index_size, a, b, c);
+
+				// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
+				pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
+
+				pushEdgeFifo(edgefifo, c, b, edgefifooffset);
+				pushEdgeFifo(edgefifo, a, c, edgefifooffset);
+			}
+			else
+			{
+				unsigned int c = 0;
+
+				// note that we need to update the last index since free indices are delta-encoded
+				last = c = decodeIndex(data, next, last);
+
+				// output triangle
+				writeTriangle(destination, i, index_size, a, b, c);
+
+				// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
+				pushVertexFifo(vertexfifo, c, vertexfifooffset);
+
+				pushEdgeFifo(edgefifo, c, b, edgefifooffset);
+				pushEdgeFifo(edgefifo, a, c, edgefifooffset);
+			}
+		}
+		else
+		{
+			// fast path: read codeaux from the table
+			if (codetri < 0xfe)
+			{
+				unsigned char codeaux = codeaux_table[codetri & 15];
+
+				// note: table can't contain feb/fec=15
+				int feb = codeaux >> 4;
+				int fec = codeaux & 15;
+
+				// fifo reads are wrapped around 16 entry buffer
+				// also note that we increment next for all three vertices before decoding indices - this matches encoder behavior
+				unsigned int a = next++;
+
+				unsigned int bf = vertexfifo[(vertexfifooffset - feb) & 15];
+				unsigned int b = (feb == 0) ? next : bf;
+
+				int feb0 = feb == 0;
+				next += feb0;
+
+				unsigned int cf = vertexfifo[(vertexfifooffset - fec) & 15];
+				unsigned int c = (fec == 0) ? next : cf;
+
+				int fec0 = fec == 0;
+				next += fec0;
+
+				// output triangle
+				writeTriangle(destination, i, index_size, a, b, c);
+
+				// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
+				pushVertexFifo(vertexfifo, a, vertexfifooffset);
+				pushVertexFifo(vertexfifo, b, vertexfifooffset, feb0);
+				pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
+
+				pushEdgeFifo(edgefifo, b, a, edgefifooffset);
+				pushEdgeFifo(edgefifo, c, b, edgefifooffset);
+				pushEdgeFifo(edgefifo, a, c, edgefifooffset);
+			}
+			else
+			{
+				// slow path: read a full byte for codeaux instead of using a table lookup
+				unsigned char codeaux = *data++;
+
+				int fea = codetri == 0xfe ? 0 : 15;
+				int feb = codeaux >> 4;
+				int fec = codeaux & 15;
+
+				// fifo reads are wrapped around 16 entry buffer
+				// also note that we increment next for all three vertices before decoding indices - this matches encoder behavior
+				unsigned int a = (fea == 0) ? next++ : 0;
+				unsigned int b = (feb == 0) ? next++ : vertexfifo[(vertexfifooffset - feb) & 15];
+				unsigned int c = (fec == 0) ? next++ : vertexfifo[(vertexfifooffset - fec) & 15];
+
+				// note that we need to update the last index since free indices are delta-encoded
+				if (fea == 15)
+					last = a = decodeIndex(data, next, last);
+
+				if (feb == 15)
+					last = b = decodeIndex(data, next, last);
+
+				if (fec == 15)
+					last = c = decodeIndex(data, next, last);
+
+				// output triangle
+				writeTriangle(destination, i, index_size, a, b, c);
+
+				// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
+				pushVertexFifo(vertexfifo, a, vertexfifooffset);
+				pushVertexFifo(vertexfifo, b, vertexfifooffset, (feb == 0) | (feb == 15));
+				pushVertexFifo(vertexfifo, c, vertexfifooffset, (fec == 0) | (fec == 15));
+
+				pushEdgeFifo(edgefifo, b, a, edgefifooffset);
+				pushEdgeFifo(edgefifo, c, b, edgefifooffset);
+				pushEdgeFifo(edgefifo, a, c, edgefifooffset);
+			}
+		}
+	}
+
+	// we should've read all data bytes and stopped at the boundary between data and codeaux table
+	if (data != data_safe_end)
+		return -3;
+
+	return 0;
+}

+ 347 - 0
3rdparty/meshoptimizer/src/indexgenerator.cpp

@@ -0,0 +1,347 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+namespace meshopt
+{
+
+static unsigned int hashUpdate4(unsigned int h, const unsigned char* key, size_t len)
+{
+	// MurmurHash2
+	const unsigned int m = 0x5bd1e995;
+	const int r = 24;
+
+	while (len >= 4)
+	{
+		unsigned int k = *reinterpret_cast<const unsigned int*>(key);
+
+		k *= m;
+		k ^= k >> r;
+		k *= m;
+
+		h *= m;
+		h ^= k;
+
+		key += 4;
+		len -= 4;
+	}
+
+	return h;
+}
+
+struct VertexHasher
+{
+	const unsigned char* vertices;
+	size_t vertex_size;
+	size_t vertex_stride;
+
+	size_t hash(unsigned int index) const
+	{
+		return hashUpdate4(0, vertices + index * vertex_stride, vertex_size);
+	}
+
+	bool equal(unsigned int lhs, unsigned int rhs) const
+	{
+		return memcmp(vertices + lhs * vertex_stride, vertices + rhs * vertex_stride, vertex_size) == 0;
+	}
+};
+
+struct VertexStreamHasher
+{
+	const meshopt_Stream* streams;
+	size_t stream_count;
+
+	size_t hash(unsigned int index) const
+	{
+		unsigned int h = 0;
+
+		for (size_t i = 0; i < stream_count; ++i)
+		{
+			const meshopt_Stream& s = streams[i];
+			const unsigned char* data = static_cast<const unsigned char*>(s.data);
+
+			h = hashUpdate4(h, data + index * s.stride, s.size);
+		}
+
+		return h;
+	}
+
+	bool equal(unsigned int lhs, unsigned int rhs) const
+	{
+		for (size_t i = 0; i < stream_count; ++i)
+		{
+			const meshopt_Stream& s = streams[i];
+			const unsigned char* data = static_cast<const unsigned char*>(s.data);
+
+			if (memcmp(data + lhs * s.stride, data + rhs * s.stride, s.size) != 0)
+				return false;
+		}
+
+		return true;
+	}
+};
+
+static size_t hashBuckets(size_t count)
+{
+	size_t buckets = 1;
+	while (buckets < count)
+		buckets *= 2;
+
+	return buckets;
+}
+
+template <typename T, typename Hash>
+static T* hashLookup(T* table, size_t buckets, const Hash& hash, const T& key, const T& empty)
+{
+	assert(buckets > 0);
+	assert((buckets & (buckets - 1)) == 0);
+
+	size_t hashmod = buckets - 1;
+	size_t bucket = hash.hash(key) & hashmod;
+
+	for (size_t probe = 0; probe <= hashmod; ++probe)
+	{
+		T& item = table[bucket];
+
+		if (item == empty)
+			return &item;
+
+		if (hash.equal(item, key))
+			return &item;
+
+		// hash collision, quadratic probing
+		bucket = (bucket + probe + 1) & hashmod;
+	}
+
+	assert(false && "Hash table is full"); // unreachable
+	return 0;
+}
+
+} // namespace meshopt
+
+size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
+{
+	using namespace meshopt;
+
+	assert(indices || index_count == vertex_count);
+	assert(index_count % 3 == 0);
+	assert(vertex_size > 0 && vertex_size <= 256);
+
+	meshopt_Allocator allocator;
+
+	memset(destination, -1, vertex_count * sizeof(unsigned int));
+
+	VertexHasher hasher = {static_cast<const unsigned char*>(vertices), vertex_size, vertex_size};
+
+	size_t table_size = hashBuckets(vertex_count);
+	unsigned int* table = allocator.allocate<unsigned int>(table_size);
+	memset(table, -1, table_size * sizeof(unsigned int));
+
+	unsigned int next_vertex = 0;
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices ? indices[i] : unsigned(i);
+		assert(index < vertex_count);
+
+		if (destination[index] == ~0u)
+		{
+			unsigned int* entry = hashLookup(table, table_size, hasher, index, ~0u);
+
+			if (*entry == ~0u)
+			{
+				*entry = index;
+
+				destination[index] = next_vertex++;
+			}
+			else
+			{
+				assert(destination[*entry] != ~0u);
+
+				destination[index] = destination[*entry];
+			}
+		}
+	}
+
+	assert(next_vertex <= vertex_count);
+
+	return next_vertex;
+}
+
+size_t meshopt_generateVertexRemapMulti(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, const struct meshopt_Stream* streams, size_t stream_count)
+{
+	using namespace meshopt;
+
+	assert(indices || index_count == vertex_count);
+	assert(index_count % 3 == 0);
+	assert(stream_count > 0 && stream_count <= 16);
+
+	for (size_t i = 0; i < stream_count; ++i)
+	{
+		assert(streams[i].size > 0 && streams[i].size <= 256);
+		assert(streams[i].size <= streams[i].stride);
+	}
+
+	meshopt_Allocator allocator;
+
+	memset(destination, -1, vertex_count * sizeof(unsigned int));
+
+	VertexStreamHasher hasher = {streams, stream_count};
+
+	size_t table_size = hashBuckets(vertex_count);
+	unsigned int* table = allocator.allocate<unsigned int>(table_size);
+	memset(table, -1, table_size * sizeof(unsigned int));
+
+	unsigned int next_vertex = 0;
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices ? indices[i] : unsigned(i);
+		assert(index < vertex_count);
+
+		if (destination[index] == ~0u)
+		{
+			unsigned int* entry = hashLookup(table, table_size, hasher, index, ~0u);
+
+			if (*entry == ~0u)
+			{
+				*entry = index;
+
+				destination[index] = next_vertex++;
+			}
+			else
+			{
+				assert(destination[*entry] != ~0u);
+
+				destination[index] = destination[*entry];
+			}
+		}
+	}
+
+	assert(next_vertex <= vertex_count);
+
+	return next_vertex;
+}
+
+void meshopt_remapVertexBuffer(void* destination, const void* vertices, size_t vertex_count, size_t vertex_size, const unsigned int* remap)
+{
+	assert(vertex_size > 0 && vertex_size <= 256);
+
+	meshopt_Allocator allocator;
+
+	// support in-place remap
+	if (destination == vertices)
+	{
+		unsigned char* vertices_copy = allocator.allocate<unsigned char>(vertex_count * vertex_size);
+		memcpy(vertices_copy, vertices, vertex_count * vertex_size);
+		vertices = vertices_copy;
+	}
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		if (remap[i] != ~0u)
+		{
+			assert(remap[i] < vertex_count);
+
+			memcpy(static_cast<unsigned char*>(destination) + remap[i] * vertex_size, static_cast<const unsigned char*>(vertices) + i * vertex_size, vertex_size);
+		}
+	}
+}
+
+void meshopt_remapIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const unsigned int* remap)
+{
+	assert(index_count % 3 == 0);
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices ? indices[i] : unsigned(i);
+		assert(remap[index] != ~0u);
+
+		destination[i] = remap[index];
+	}
+}
+
+void meshopt_generateShadowIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size, size_t vertex_stride)
+{
+	using namespace meshopt;
+
+	assert(indices);
+	assert(index_count % 3 == 0);
+	assert(vertex_size > 0 && vertex_size <= 256);
+	assert(vertex_size <= vertex_stride);
+
+	meshopt_Allocator allocator;
+
+	unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
+	memset(remap, -1, vertex_count * sizeof(unsigned int));
+
+	VertexHasher hasher = {static_cast<const unsigned char*>(vertices), vertex_size, vertex_stride};
+
+	size_t table_size = hashBuckets(vertex_count);
+	unsigned int* table = allocator.allocate<unsigned int>(table_size);
+	memset(table, -1, table_size * sizeof(unsigned int));
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		if (remap[index] == ~0u)
+		{
+			unsigned int* entry = hashLookup(table, table_size, hasher, index, ~0u);
+
+			if (*entry == ~0u)
+				*entry = index;
+
+			remap[index] = *entry;
+		}
+
+		destination[i] = remap[index];
+	}
+}
+
+void meshopt_generateShadowIndexBufferMulti(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, const struct meshopt_Stream* streams, size_t stream_count)
+{
+	using namespace meshopt;
+
+	assert(indices);
+	assert(index_count % 3 == 0);
+	assert(stream_count > 0 && stream_count <= 16);
+
+	for (size_t i = 0; i < stream_count; ++i)
+	{
+		assert(streams[i].size > 0 && streams[i].size <= 256);
+		assert(streams[i].size <= streams[i].stride);
+	}
+
+	meshopt_Allocator allocator;
+
+	unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
+	memset(remap, -1, vertex_count * sizeof(unsigned int));
+
+	VertexStreamHasher hasher = {streams, stream_count};
+
+	size_t table_size = hashBuckets(vertex_count);
+	unsigned int* table = allocator.allocate<unsigned int>(table_size);
+	memset(table, -1, table_size * sizeof(unsigned int));
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		if (remap[index] == ~0u)
+		{
+			unsigned int* entry = hashLookup(table, table_size, hasher, index, ~0u);
+
+			if (*entry == ~0u)
+				*entry = index;
+
+			remap[index] = *entry;
+		}
+
+		destination[i] = remap[index];
+	}
+}

+ 759 - 0
3rdparty/meshoptimizer/src/meshoptimizer.h

@@ -0,0 +1,759 @@
+/**
+ * meshoptimizer - version 0.11
+ *
+ * Copyright (C) 2016-2019, by Arseny Kapoulkine ([email protected])
+ * Report bugs and download new versions at https://github.com/zeux/meshoptimizer
+ *
+ * This library is distributed under the MIT License. See notice at the end of this file.
+ */
+#pragma once
+
+#include <assert.h>
+#include <stddef.h>
+
+/* Version macro; major * 1000 + minor * 10 + patch */
+#define MESHOPTIMIZER_VERSION 110
+
+/* If no API is defined, assume default */
+#ifndef MESHOPTIMIZER_API
+#define MESHOPTIMIZER_API
+#endif
+
+/* Experimental APIs have unstable interface and might have implementation that's not fully tested or optimized */
+#define MESHOPTIMIZER_EXPERIMENTAL MESHOPTIMIZER_API
+
+/* C interface */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Vertex attribute stream, similar to glVertexPointer
+ * Each element takes size bytes, with stride controlling the spacing between successive elements.
+ */
+struct meshopt_Stream
+{
+	const void* data;
+	size_t size;
+	size_t stride;
+};
+
+/**
+ * Generates a vertex remap table from the vertex buffer and an optional index buffer and returns number of unique vertices
+ * As a result, all vertices that are binary equivalent map to the same (new) location, with no gaps in the resulting sequence.
+ * Resulting remap table maps old vertices to new vertices and can be used in meshopt_remapVertexBuffer/meshopt_remapIndexBuffer.
+ *
+ * destination must contain enough space for the resulting remap table (vertex_count elements)
+ * indices can be NULL if the input is unindexed
+ */
+MESHOPTIMIZER_API size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size);
+
+/**
+ * Experimental: Generates a vertex remap table from multiple vertex streams and an optional index buffer and returns number of unique vertices
+ * As a result, all vertices that are binary equivalent map to the same (new) location, with no gaps in the resulting sequence.
+ * Resulting remap table maps old vertices to new vertices and can be used in meshopt_remapVertexBuffer/meshopt_remapIndexBuffer.
+ * To remap vertex buffers, you will need to call meshopt_remapVertexBuffer for each vertex stream.
+ *
+ * destination must contain enough space for the resulting remap table (vertex_count elements)
+ * indices can be NULL if the input is unindexed
+ */
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_generateVertexRemapMulti(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, const struct meshopt_Stream* streams, size_t stream_count);
+
+/**
+ * Generates vertex buffer from the source vertex buffer and remap table generated by meshopt_generateVertexRemap
+ *
+ * destination must contain enough space for the resulting vertex buffer (unique_vertex_count elements, returned by meshopt_generateVertexRemap)
+ * vertex_count should be the initial vertex count and not the value returned by meshopt_generateVertexRemap
+ */
+MESHOPTIMIZER_API void meshopt_remapVertexBuffer(void* destination, const void* vertices, size_t vertex_count, size_t vertex_size, const unsigned int* remap);
+
+/**
+ * Generate index buffer from the source index buffer and remap table generated by meshopt_generateVertexRemap
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ * indices can be NULL if the input is unindexed
+ */
+MESHOPTIMIZER_API void meshopt_remapIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const unsigned int* remap);
+
+/**
+ * Experimental: Generate index buffer that can be used for more efficient rendering when only a subset of the vertex attributes is necessary
+ * All vertices that are binary equivalent (wrt first vertex_size bytes) map to the first vertex in the original vertex buffer.
+ * This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using the original index buffer for regular rendering.
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ */
+MESHOPTIMIZER_EXPERIMENTAL void meshopt_generateShadowIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size, size_t vertex_stride);
+
+/**
+ * Experimental: Generate index buffer that can be used for more efficient rendering when only a subset of the vertex attributes is necessary
+ * All vertices that are binary equivalent (wrt specified streams) map to the first vertex in the original vertex buffer.
+ * This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using the original index buffer for regular rendering.
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ */
+MESHOPTIMIZER_EXPERIMENTAL void meshopt_generateShadowIndexBufferMulti(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, const struct meshopt_Stream* streams, size_t stream_count);
+
+/**
+ * Vertex transform cache optimizer
+ * Reorders indices to reduce the number of GPU vertex shader invocations
+ * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually.
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ */
+MESHOPTIMIZER_API void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count);
+
+/**
+ * Vertex transform cache optimizer for FIFO caches
+ * Reorders indices to reduce the number of GPU vertex shader invocations
+ * Generally takes ~3x less time to optimize meshes but produces inferior results compared to meshopt_optimizeVertexCache
+ * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually.
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ * cache_size should be less than the actual GPU cache size to avoid cache thrashing
+ */
+MESHOPTIMIZER_API void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size);
+
+/**
+ * Overdraw optimizer
+ * Reorders indices to reduce the number of GPU vertex shader invocations and the pixel overdraw
+ * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually.
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ * indices must contain index data that is the result of meshopt_optimizeVertexCache (*not* the original mesh indices!)
+ * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
+ * threshold indicates how much the overdraw optimizer can degrade vertex cache efficiency (1.05 = up to 5%) to reduce overdraw more efficiently
+ */
+MESHOPTIMIZER_API void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold);
+
+/**
+ * Vertex fetch cache optimizer
+ * Reorders vertices and changes indices to reduce the amount of GPU memory fetches during vertex processing
+ * Returns the number of unique vertices, which is the same as input vertex count unless some vertices are unused
+ * This functions works for a single vertex stream; for multiple vertex streams, use meshopt_optimizeVertexFetchRemap + meshopt_remapVertexBuffer for each stream.
+ *
+ * destination must contain enough space for the resulting vertex buffer (vertex_count elements)
+ * indices is used both as an input and as an output index buffer
+ */
+MESHOPTIMIZER_API size_t meshopt_optimizeVertexFetch(void* destination, unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size);
+
+/**
+ * Vertex fetch cache optimizer
+ * Generates vertex remap to reduce the amount of GPU memory fetches during vertex processing
+ * Returns the number of unique vertices, which is the same as input vertex count unless some vertices are unused
+ * The resulting remap table should be used to reorder vertex/index buffers using meshopt_remapVertexBuffer/meshopt_remapIndexBuffer
+ *
+ * destination must contain enough space for the resulting remap table (vertex_count elements)
+ */
+MESHOPTIMIZER_API size_t meshopt_optimizeVertexFetchRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count);
+
+/**
+ * Index buffer encoder
+ * Encodes index data into an array of bytes that is generally much smaller (<1.5 bytes/triangle) and compresses better (<1 bytes/triangle) compared to original.
+ * Returns encoded data size on success, 0 on error; the only error condition is if buffer doesn't have enough space
+ * For maximum efficiency the index buffer being encoded has to be optimized for vertex cache and vertex fetch first.
+ *
+ * buffer must contain enough space for the encoded index buffer (use meshopt_encodeIndexBufferBound to compute worst case size)
+ */
+MESHOPTIMIZER_API size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count);
+MESHOPTIMIZER_API size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count);
+
+/**
+ * Index buffer decoder
+ * Decodes index data from an array of bytes generated by meshopt_encodeIndexBuffer
+ * Returns 0 if decoding was successful, and an error code otherwise
+ * The decoder is safe to use for untrusted input, but it may produce garbage data (e.g. out of range indices).
+ *
+ * destination must contain enough space for the resulting index buffer (index_count elements)
+ */
+MESHOPTIMIZER_API int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size);
+
+/**
+ * Vertex buffer encoder
+ * Encodes vertex data into an array of bytes that is generally smaller and compresses better compared to original.
+ * Returns encoded data size on success, 0 on error; the only error condition is if buffer doesn't have enough space
+ * This function works for a single vertex stream; for multiple vertex streams, call meshopt_encodeVertexBuffer for each stream.
+ *
+ * buffer must contain enough space for the encoded vertex buffer (use meshopt_encodeVertexBufferBound to compute worst case size)
+ */
+MESHOPTIMIZER_API size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, const void* vertices, size_t vertex_count, size_t vertex_size);
+MESHOPTIMIZER_API size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size);
+
+/**
+ * Vertex buffer decoder
+ * Decodes vertex data from an array of bytes generated by meshopt_encodeVertexBuffer
+ * Returns 0 if decoding was successful, and an error code otherwise
+ * The decoder is safe to use for untrusted input, but it may produce garbage data.
+ *
+ * destination must contain enough space for the resulting vertex buffer (vertex_count * vertex_size bytes)
+ */
+MESHOPTIMIZER_API int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t vertex_size, const unsigned char* buffer, size_t buffer_size);
+
+/**
+ * Experimental: Mesh simplifier
+ * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible
+ * The algorithm tries to preserve mesh topology and can stop short of the target goal based on topology constraints or target error.
+ * If not all attributes from the input mesh are required, it's recommended to reindex the mesh using meshopt_generateShadowIndexBuffer prior to simplification.
+ * Returns the number of indices after simplification, with destination containing new index data
+ * The resulting index buffer references vertices from the original vertex buffer.
+ * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
+ *
+ * destination must contain enough space for the *source* index buffer (since optimization is iterative, this means index_count elements - *not* target_index_count!)
+ * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
+ */
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error);
+
+/**
+ * Experimental: Mesh simplifier (sloppy)
+ * Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
+ * The algorithm doesn't preserve mesh topology but is always able to reach target triangle count.
+ * Returns the number of indices after simplification, with destination containing new index data
+ * The resulting index buffer references vertices from the original vertex buffer.
+ * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
+ *
+ * destination must contain enough space for the target index buffer
+ * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
+ */
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count);
+
+/**
+ * Mesh stripifier
+ * Converts a previously vertex cache optimized triangle list to triangle strip, stitching strips using restart index
+ * Returns the number of indices in the resulting strip, with destination containing new index data
+ * For maximum efficiency the index buffer being converted has to be optimized for vertex cache first.
+ *
+ * destination must contain enough space for the target index buffer, worst case can be computed with meshopt_stripifyBound
+ */
+MESHOPTIMIZER_API size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count);
+MESHOPTIMIZER_API size_t meshopt_stripifyBound(size_t index_count);
+
+/**
+ * Mesh unstripifier
+ * Converts a triangle strip to a triangle list
+ * Returns the number of indices in the resulting list, with destination containing new index data
+ *
+ * destination must contain enough space for the target index buffer, worst case can be computed with meshopt_unstripifyBound
+ */
+MESHOPTIMIZER_API size_t meshopt_unstripify(unsigned int* destination, const unsigned int* indices, size_t index_count);
+MESHOPTIMIZER_API size_t meshopt_unstripifyBound(size_t index_count);
+
+struct meshopt_VertexCacheStatistics
+{
+	unsigned int vertices_transformed;
+	unsigned int warps_executed;
+	float acmr; /* transformed vertices / triangle count; best case 0.5, worst case 3.0, optimum depends on topology */
+	float atvr; /* transformed vertices / vertex count; best case 1.0, worst case 6.0, optimum is 1.0 (each vertex is transformed once) */
+};
+
+/**
+ * Vertex transform cache analyzer
+ * Returns cache hit statistics using a simplified FIFO model
+ * Results may not match actual GPU performance
+ */
+MESHOPTIMIZER_API struct meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int primgroup_size);
+
+struct meshopt_OverdrawStatistics
+{
+	unsigned int pixels_covered;
+	unsigned int pixels_shaded;
+	float overdraw; /* shaded pixels / covered pixels; best case 1.0 */
+};
+
+/**
+ * Overdraw analyzer
+ * Returns overdraw statistics using a software rasterizer
+ * Results may not match actual GPU performance
+ *
+ * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
+ */
+MESHOPTIMIZER_API struct meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+
+struct meshopt_VertexFetchStatistics
+{
+	unsigned int bytes_fetched;
+	float overfetch; /* fetched bytes / vertex buffer size; best case 1.0 (each byte is fetched once) */
+};
+
+/**
+ * Vertex fetch cache analyzer
+ * Returns cache hit statistics using a simplified direct mapped model
+ * Results may not match actual GPU performance
+ */
+MESHOPTIMIZER_API struct meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const unsigned int* indices, size_t index_count, size_t vertex_count, size_t vertex_size);
+
+struct meshopt_Meshlet
+{
+	unsigned int vertices[64];
+	unsigned char indices[126][3];
+	unsigned char triangle_count;
+	unsigned char vertex_count;
+};
+
+/**
+ * Experimental: Meshlet builder
+ * Splits the mesh into a set of meshlets where each meshlet has a micro index buffer indexing into meshlet vertices that refer to the original vertex buffer
+ * The resulting data can be used to render meshes using NVidia programmable mesh shading pipeline, or in other cluster-based renderers.
+ * For maximum efficiency the index buffer being converted has to be optimized for vertex cache first.
+ *
+ * destination must contain enough space for all meshlets, worst case size can be computed with meshopt_buildMeshletsBound
+ * max_vertices and max_triangles can't exceed limits statically declared in meshopt_Meshlet (max_vertices <= 64, max_triangles <= 126)
+ */
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshlets(struct meshopt_Meshlet* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles);
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshletsBound(size_t index_count, size_t max_vertices, size_t max_triangles);
+
+struct meshopt_Bounds
+{
+	/* bounding sphere, useful for frustum and occlusion culling */
+	float center[3];
+	float radius;
+
+	/* normal cone, useful for backface culling */
+	float cone_apex[3];
+	float cone_axis[3];
+	float cone_cutoff; /* = cos(angle/2) */
+
+	/* normal cone axis and cutoff, stored in 8-bit SNORM format; decode using x/127.0 */
+	signed char cone_axis_s8[3];
+	signed char cone_cutoff_s8;
+};
+
+/**
+ * Experimental: Cluster bounds generator
+ * Creates bounding volumes that can be used for frustum, backface and occlusion culling.
+ *
+ * For backface culling with orthographic projection, use the following formula to reject backfacing clusters:
+ *   dot(view, cone_axis) >= cone_cutoff
+ *
+ * For perspective projection, you can the formula that needs cone apex in addition to axis & cutoff:
+ *   dot(normalize(cone_apex - camera_position), cone_axis) >= cone_cutoff
+ *
+ * Alternatively, you can use the formula that doesn't need cone apex and uses bounding sphere instead:
+ *   dot(normalize(center - camera_position), cone_axis) >= cone_cutoff + radius / length(center - camera_position)
+ * or an equivalent formula that doesn't have a singularity at center = camera_position:
+ *   dot(center - camera_position, cone_axis) >= cone_cutoff * length(center - camera_position) + radius
+ *
+ * The formula that uses the apex is slightly more accurate but needs the apex; if you are already using bounding sphere
+ * to do frustum/occlusion culling, the formula that doesn't use the apex may be preferable.
+ *
+ * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
+ * index_count should be less than or equal to 256*3 (the function assumes clusters of limited size)
+ */
+MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeMeshletBounds(const struct meshopt_Meshlet* meshlet, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+
+/**
+ * Experimental: Set allocation callbacks
+ * These callbacks will be used instead of the default operator new/operator delete for all temporary allocations in the library.
+ * Note that all algorithms only allocate memory for temporary use.
+ * allocate/deallocate are always called in a stack-like order - last pointer to be allocated is deallocated first.
+ */
+MESHOPTIMIZER_EXPERIMENTAL void meshopt_setAllocator(void* (*allocate)(size_t), void (*deallocate)(void*));
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+/* Quantization into commonly supported data formats */
+#ifdef __cplusplus
+/**
+ * Quantize a float in [0..1] range into an N-bit fixed point unorm value
+ * Assumes reconstruction function (q / (2^N-1)), which is the case for fixed-function normalized fixed point conversion
+ * Maximum reconstruction error: 1/2^(N+1)
+ */
+inline int meshopt_quantizeUnorm(float v, int N);
+
+/**
+ * Quantize a float in [-1..1] range into an N-bit fixed point snorm value
+ * Assumes reconstruction function (q / (2^(N-1)-1)), which is the case for fixed-function normalized fixed point conversion (except early OpenGL versions)
+ * Maximum reconstruction error: 1/2^N
+ */
+inline int meshopt_quantizeSnorm(float v, int N);
+
+/**
+ * Quantize a float into half-precision floating point value
+ * Generates +-inf for overflow, preserves NaN, flushes denormals to zero, rounds to nearest
+ * Representable magnitude range: [6e-5; 65504]
+ * Maximum relative reconstruction error: 5e-4
+ */
+inline unsigned short meshopt_quantizeHalf(float v);
+
+/**
+ * Quantize a float into a floating point value with a limited number of significant mantissa bits
+ * Generates +-inf for overflow, preserves NaN, flushes denormals to zero, rounds to nearest
+ * Assumes N is in a valid mantissa precision range, which is 1..23
+ */
+inline float meshopt_quantizeFloat(float v, int N);
+#endif
+
+/**
+ * C++ template interface
+ *
+ * These functions mirror the C interface the library provides, providing template-based overloads so that
+ * the caller can use an arbitrary type for the index data, both for input and output.
+ * When the supplied type is the same size as that of unsigned int, the wrappers are zero-cost; when it's not,
+ * the wrappers end up allocating memory and copying index data to convert from one type to another.
+ */
+#ifdef __cplusplus
+template <typename T, bool ZeroCopy = sizeof(T) == sizeof(unsigned int)>
+struct meshopt_IndexAdapter;
+
+template <typename T>
+struct meshopt_IndexAdapter<T, false>
+{
+	T* result;
+	unsigned int* data;
+	size_t count;
+
+	meshopt_IndexAdapter(T* result_, const T* input, size_t count_)
+	    : result(result_)
+	    , data(0)
+	    , count(count_)
+	{
+		data = new unsigned int[count];
+
+		if (input)
+		{
+			for (size_t i = 0; i < count; ++i)
+				data[i] = input[i];
+		}
+	}
+
+	~meshopt_IndexAdapter()
+	{
+		if (result)
+		{
+			for (size_t i = 0; i < count; ++i)
+				result[i] = T(data[i]);
+		}
+
+		delete[] data;
+	}
+};
+
+template <typename T>
+struct meshopt_IndexAdapter<T, true>
+{
+	unsigned int* data;
+
+	meshopt_IndexAdapter(T* result, const T* input, size_t)
+	    : data(reinterpret_cast<unsigned int*>(result ? result : const_cast<T*>(input)))
+	{
+	}
+};
+
+template <typename T>
+inline size_t meshopt_generateVertexRemap(unsigned int* destination, const T* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
+{
+	meshopt_IndexAdapter<T> in(0, indices, indices ? index_count : 0);
+
+	return meshopt_generateVertexRemap(destination, indices ? in.data : 0, index_count, vertices, vertex_count, vertex_size);
+}
+
+template <typename T>
+inline size_t meshopt_generateVertexRemapMulti(unsigned int* destination, const T* indices, size_t index_count, size_t vertex_count, const meshopt_Stream* streams, size_t stream_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, indices ? index_count : 0);
+
+	return meshopt_generateVertexRemapMulti(destination, indices ? in.data : 0, index_count, vertex_count, streams, stream_count);
+}
+
+template <typename T>
+inline void meshopt_remapIndexBuffer(T* destination, const T* indices, size_t index_count, const unsigned int* remap)
+{
+	meshopt_IndexAdapter<T> in(0, indices, indices ? index_count : 0);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	meshopt_remapIndexBuffer(out.data, indices ? in.data : 0, index_count, remap);
+}
+
+template <typename T>
+void meshopt_generateShadowIndexBuffer(T* destination, const T* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size, size_t vertex_stride)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	meshopt_generateShadowIndexBuffer(out.data, in.data, index_count, vertices, vertex_count, vertex_size, vertex_stride);
+}
+
+template <typename T>
+void meshopt_generateShadowIndexBufferMulti(T* destination, const T* indices, size_t index_count, size_t vertex_count, const meshopt_Stream* streams, size_t stream_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	meshopt_generateShadowIndexBufferMulti(out.data, in.data, index_count, vertex_count, streams, stream_count);
+}
+
+template <typename T>
+inline void meshopt_optimizeVertexCache(T* destination, const T* indices, size_t index_count, size_t vertex_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	meshopt_optimizeVertexCache(out.data, in.data, index_count, vertex_count);
+}
+
+template <typename T>
+inline void meshopt_optimizeVertexCacheFifo(T* destination, const T* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	meshopt_optimizeVertexCacheFifo(out.data, in.data, index_count, vertex_count, cache_size);
+}
+
+template <typename T>
+inline void meshopt_optimizeOverdraw(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	meshopt_optimizeOverdraw(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, threshold);
+}
+
+template <typename T>
+inline size_t meshopt_optimizeVertexFetchRemap(unsigned int* destination, const T* indices, size_t index_count, size_t vertex_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_optimizeVertexFetchRemap(destination, in.data, index_count, vertex_count);
+}
+
+template <typename T>
+inline size_t meshopt_optimizeVertexFetch(void* destination, T* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
+{
+	meshopt_IndexAdapter<T> inout(indices, indices, index_count);
+
+	return meshopt_optimizeVertexFetch(destination, inout.data, index_count, vertices, vertex_count, vertex_size);
+}
+
+template <typename T>
+inline size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, const T* indices, size_t index_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_encodeIndexBuffer(buffer, buffer_size, in.data, index_count);
+}
+
+template <typename T>
+inline int meshopt_decodeIndexBuffer(T* destination, size_t index_count, const unsigned char* buffer, size_t buffer_size)
+{
+	char index_size_valid[sizeof(T) == 2 || sizeof(T) == 4 ? 1 : -1];
+	(void)index_size_valid;
+
+	return meshopt_decodeIndexBuffer(destination, index_count, sizeof(T), buffer, buffer_size);
+}
+
+template <typename T>
+inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, index_count);
+
+	return meshopt_simplify(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error);
+}
+
+template <typename T>
+inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, target_index_count);
+
+	return meshopt_simplifySloppy(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count);
+}
+
+template <typename T>
+inline size_t meshopt_stripify(T* destination, const T* indices, size_t index_count, size_t vertex_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, (index_count / 3) * 4);
+
+	return meshopt_stripify(out.data, in.data, index_count, vertex_count);
+}
+
+template <typename T>
+inline size_t meshopt_unstripify(T* destination, const T* indices, size_t index_count)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+	meshopt_IndexAdapter<T> out(destination, 0, (index_count - 2) * 3);
+
+	return meshopt_unstripify(out.data, in.data, index_count);
+}
+
+template <typename T>
+inline meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const T* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int buffer_size)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_analyzeVertexCache(in.data, index_count, vertex_count, cache_size, warp_size, buffer_size);
+}
+
+template <typename T>
+inline meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_analyzeOverdraw(in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride);
+}
+
+template <typename T>
+inline meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const T* indices, size_t index_count, size_t vertex_count, size_t vertex_size)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_analyzeVertexFetch(in.data, index_count, vertex_count, vertex_size);
+}
+
+template <typename T>
+inline size_t meshopt_buildMeshlets(meshopt_Meshlet* destination, const T* indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_buildMeshlets(destination, in.data, index_count, vertex_count, max_vertices, max_triangles);
+}
+
+template <typename T>
+inline meshopt_Bounds meshopt_computeClusterBounds(const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
+{
+	meshopt_IndexAdapter<T> in(0, indices, index_count);
+
+	return meshopt_computeClusterBounds(in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride);
+}
+#endif
+
+/* Inline implementation */
+#ifdef __cplusplus
+inline int meshopt_quantizeUnorm(float v, int N)
+{
+	const float scale = float((1 << N) - 1);
+
+	v = (v >= 0) ? v : 0;
+	v = (v <= 1) ? v : 1;
+
+	return int(v * scale + 0.5f);
+}
+
+inline int meshopt_quantizeSnorm(float v, int N)
+{
+	const float scale = float((1 << (N - 1)) - 1);
+
+	float round = (v >= 0 ? 0.5f : -0.5f);
+
+	v = (v >= -1) ? v : -1;
+	v = (v <= +1) ? v : +1;
+
+	return int(v * scale + round);
+}
+
+inline unsigned short meshopt_quantizeHalf(float v)
+{
+	union { float f; unsigned int ui; } u = {v};
+	unsigned int ui = u.ui;
+
+	int s = (ui >> 16) & 0x8000;
+	int em = ui & 0x7fffffff;
+
+	/* bias exponent and round to nearest; 112 is relative exponent bias (127-15) */
+	int h = (em - (112 << 23) + (1 << 12)) >> 13;
+
+	/* underflow: flush to zero; 113 encodes exponent -14 */
+	h = (em < (113 << 23)) ? 0 : h;
+
+	/* overflow: infinity; 143 encodes exponent 16 */
+	h = (em >= (143 << 23)) ? 0x7c00 : h;
+
+	/* NaN; note that we convert all types of NaN to qNaN */
+	h = (em > (255 << 23)) ? 0x7e00 : h;
+
+	return (unsigned short)(s | h);
+}
+
+inline float meshopt_quantizeFloat(float v, int N)
+{
+	union { float f; unsigned int ui; } u = {v};
+	unsigned int ui = u.ui;
+
+	const int mask = (1 << (23 - N)) - 1;
+	const int round = (1 << (23 - N)) >> 1;
+
+	int e = ui & 0x7f800000;
+	unsigned int rui = (ui + round) & ~mask;
+
+	/* round all numbers except inf/nan; this is important to make sure nan doesn't overflow into -0 */
+	ui = e == 0x7f800000 ? ui : rui;
+
+	/* flush denormals to zero */
+	ui = e == 0 ? 0 : ui;
+
+	u.ui = ui;
+	return u.f;
+}
+#endif
+
+/* Internal implementation helpers */
+#ifdef __cplusplus
+class meshopt_Allocator
+{
+public:
+	template <typename T>
+	struct StorageT
+	{
+		static void* (*allocate)(size_t);
+		static void (*deallocate)(void*);
+	};
+
+	typedef StorageT<void> Storage;
+
+	meshopt_Allocator()
+		: blocks()
+		, count(0)
+	{
+	}
+
+	~meshopt_Allocator()
+	{
+		for (size_t i = count; i > 0; --i)
+			Storage::deallocate(blocks[i - 1]);
+	}
+
+	template <typename T> T* allocate(size_t size)
+	{
+		assert(count < sizeof(blocks) / sizeof(blocks[0]));
+		T* result = static_cast<T*>(Storage::allocate(size > size_t(-1) / sizeof(T) ? size_t(-1) : size * sizeof(T)));
+		blocks[count++] = result;
+		return result;
+	}
+
+private:
+	void* blocks[16];
+	size_t count;
+};
+
+// This makes sure that allocate/deallocate are lazily generated in translation units that need them and are deduplicated by the linker
+template <typename T> void* (*meshopt_Allocator::StorageT<T>::allocate)(size_t) = operator new;
+template <typename T> void (*meshopt_Allocator::StorageT<T>::deallocate)(void*) = operator delete;
+#endif
+
+/**
+ * Copyright (c) 2016-2019 Arseny Kapoulkine
+ *
+ * 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.
+ */

+ 230 - 0
3rdparty/meshoptimizer/src/overdrawanalyzer.cpp

@@ -0,0 +1,230 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <float.h>
+#include <string.h>
+
+// This work is based on:
+// Nicolas Capens. Advanced Rasterization. 2004
+namespace meshopt
+{
+
+const int kViewport = 256;
+
+struct OverdrawBuffer
+{
+	float z[kViewport][kViewport][2];
+	unsigned int overdraw[kViewport][kViewport][2];
+};
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+static float computeDepthGradients(float& dzdx, float& dzdy, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3)
+{
+	// z2 = z1 + dzdx * (x2 - x1) + dzdy * (y2 - y1)
+	// z3 = z1 + dzdx * (x3 - x1) + dzdy * (y3 - y1)
+	// (x2-x1 y2-y1)(dzdx) = (z2-z1)
+	// (x3-x1 y3-y1)(dzdy)   (z3-z1)
+	// we'll solve it with Cramer's rule
+	float det = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1);
+	float invdet = (det == 0) ? 0 : 1 / det;
+
+	dzdx = (z2 - z1) * (y3 - y1) - (y2 - y1) * (z3 - z1) * invdet;
+	dzdy = (x2 - x1) * (z3 - z1) - (z2 - z1) * (x3 - x1) * invdet;
+
+	return det;
+}
+
+// half-space fixed point triangle rasterizer
+static void rasterize(OverdrawBuffer* buffer, float v1x, float v1y, float v1z, float v2x, float v2y, float v2z, float v3x, float v3y, float v3z)
+{
+	// compute depth gradients
+	float DZx, DZy;
+	float det = computeDepthGradients(DZx, DZy, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z);
+	int sign = det > 0;
+
+	// flip backfacing triangles to simplify rasterization logic
+	if (sign)
+	{
+		// flipping v2 & v3 preserves depth gradients since they're based on v1
+		float t;
+		t = v2x, v2x = v3x, v3x = t;
+		t = v2y, v2y = v3y, v3y = t;
+		t = v2z, v2z = v3z, v3z = t;
+
+		// flip depth since we rasterize backfacing triangles to second buffer with reverse Z; only v1z is used below
+		v1z = kViewport - v1z;
+		DZx = -DZx;
+		DZy = -DZy;
+	}
+
+	// coordinates, 28.4 fixed point
+	int X1 = int(16.0f * v1x + 0.5f);
+	int X2 = int(16.0f * v2x + 0.5f);
+	int X3 = int(16.0f * v3x + 0.5f);
+
+	int Y1 = int(16.0f * v1y + 0.5f);
+	int Y2 = int(16.0f * v2y + 0.5f);
+	int Y3 = int(16.0f * v3y + 0.5f);
+
+	// bounding rectangle, clipped against viewport
+	// since we rasterize pixels with covered centers, min >0.5 should round up
+	// as for max, due to top-left filling convention we will never rasterize right/bottom edges
+	// so max >= 0.5 should round down
+	int minx = max((min(X1, min(X2, X3)) + 7) >> 4, 0);
+	int maxx = min((max(X1, max(X2, X3)) + 7) >> 4, kViewport);
+	int miny = max((min(Y1, min(Y2, Y3)) + 7) >> 4, 0);
+	int maxy = min((max(Y1, max(Y2, Y3)) + 7) >> 4, kViewport);
+
+	// deltas, 28.4 fixed point
+	int DX12 = X1 - X2;
+	int DX23 = X2 - X3;
+	int DX31 = X3 - X1;
+
+	int DY12 = Y1 - Y2;
+	int DY23 = Y2 - Y3;
+	int DY31 = Y3 - Y1;
+
+	// fill convention correction
+	int TL1 = DY12 < 0 || (DY12 == 0 && DX12 > 0);
+	int TL2 = DY23 < 0 || (DY23 == 0 && DX23 > 0);
+	int TL3 = DY31 < 0 || (DY31 == 0 && DX31 > 0);
+
+	// half edge equations, 24.8 fixed point
+	// note that we offset minx/miny by half pixel since we want to rasterize pixels with covered centers
+	int FX = (minx << 4) + 8;
+	int FY = (miny << 4) + 8;
+	int CY1 = DX12 * (FY - Y1) - DY12 * (FX - X1) + TL1 - 1;
+	int CY2 = DX23 * (FY - Y2) - DY23 * (FX - X2) + TL2 - 1;
+	int CY3 = DX31 * (FY - Y3) - DY31 * (FX - X3) + TL3 - 1;
+	float ZY = v1z + (DZx * float(FX - X1) + DZy * float(FY - Y1)) * (1 / 16.f);
+
+	for (int y = miny; y < maxy; y++)
+	{
+		int CX1 = CY1;
+		int CX2 = CY2;
+		int CX3 = CY3;
+		float ZX = ZY;
+
+		for (int x = minx; x < maxx; x++)
+		{
+			// check if all CXn are non-negative
+			if ((CX1 | CX2 | CX3) >= 0)
+			{
+				if (ZX >= buffer->z[y][x][sign])
+				{
+					buffer->z[y][x][sign] = ZX;
+					buffer->overdraw[y][x][sign]++;
+				}
+			}
+
+			// signed left shift is UB for negative numbers so use unsigned-signed casts
+			CX1 -= int(unsigned(DY12) << 4);
+			CX2 -= int(unsigned(DY23) << 4);
+			CX3 -= int(unsigned(DY31) << 4);
+			ZX += DZx;
+		}
+
+		// signed left shift is UB for negative numbers so use unsigned-signed casts
+		CY1 += int(unsigned(DX12) << 4);
+		CY2 += int(unsigned(DX23) << 4);
+		CY3 += int(unsigned(DX31) << 4);
+		ZY += DZy;
+	}
+}
+
+} // namespace meshopt
+
+meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+	assert(vertex_positions_stride % sizeof(float) == 0);
+
+	meshopt_Allocator allocator;
+
+	size_t vertex_stride_float = vertex_positions_stride / sizeof(float);
+
+	meshopt_OverdrawStatistics result = {};
+
+	float minv[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
+	float maxv[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		const float* v = vertex_positions + i * vertex_stride_float;
+
+		for (int j = 0; j < 3; ++j)
+		{
+			minv[j] = min(minv[j], v[j]);
+			maxv[j] = max(maxv[j], v[j]);
+		}
+	}
+
+	float extent = max(maxv[0] - minv[0], max(maxv[1] - minv[1], maxv[2] - minv[2]));
+	float scale = kViewport / extent;
+
+	float* triangles = allocator.allocate<float>(index_count * 3);
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		const float* v = vertex_positions + index * vertex_stride_float;
+
+		triangles[i * 3 + 0] = (v[0] - minv[0]) * scale;
+		triangles[i * 3 + 1] = (v[1] - minv[1]) * scale;
+		triangles[i * 3 + 2] = (v[2] - minv[2]) * scale;
+	}
+
+	OverdrawBuffer* buffer = allocator.allocate<OverdrawBuffer>(1);
+
+	for (int axis = 0; axis < 3; ++axis)
+	{
+		memset(buffer, 0, sizeof(OverdrawBuffer));
+
+		for (size_t i = 0; i < index_count; i += 3)
+		{
+			const float* vn0 = &triangles[3 * (i + 0)];
+			const float* vn1 = &triangles[3 * (i + 1)];
+			const float* vn2 = &triangles[3 * (i + 2)];
+
+			switch (axis)
+			{
+			case 0:
+				rasterize(buffer, vn0[2], vn0[1], vn0[0], vn1[2], vn1[1], vn1[0], vn2[2], vn2[1], vn2[0]);
+				break;
+			case 1:
+				rasterize(buffer, vn0[0], vn0[2], vn0[1], vn1[0], vn1[2], vn1[1], vn2[0], vn2[2], vn2[1]);
+				break;
+			case 2:
+				rasterize(buffer, vn0[1], vn0[0], vn0[2], vn1[1], vn1[0], vn1[2], vn2[1], vn2[0], vn2[2]);
+				break;
+			}
+		}
+
+		for (int y = 0; y < kViewport; ++y)
+			for (int x = 0; x < kViewport; ++x)
+				for (int s = 0; s < 2; ++s)
+				{
+					unsigned int overdraw = buffer->overdraw[y][x][s];
+
+					result.pixels_covered += overdraw > 0;
+					result.pixels_shaded += overdraw;
+				}
+	}
+
+	result.overdraw = result.pixels_covered ? float(result.pixels_shaded) / float(result.pixels_covered) : 0.f;
+
+	return result;
+}

+ 333 - 0
3rdparty/meshoptimizer/src/overdrawoptimizer.cpp

@@ -0,0 +1,333 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+
+// This work is based on:
+// Pedro Sander, Diego Nehab and Joshua Barczak. Fast Triangle Reordering for Vertex Locality and Reduced Overdraw. 2007
+namespace meshopt
+{
+
+static void calculateSortData(float* sort_data, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_positions_stride, const unsigned int* clusters, size_t cluster_count)
+{
+	size_t vertex_stride_float = vertex_positions_stride / sizeof(float);
+
+	float mesh_centroid[3] = {};
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		const float* p = vertex_positions + vertex_stride_float * indices[i];
+
+		mesh_centroid[0] += p[0];
+		mesh_centroid[1] += p[1];
+		mesh_centroid[2] += p[2];
+	}
+
+	mesh_centroid[0] /= index_count;
+	mesh_centroid[1] /= index_count;
+	mesh_centroid[2] /= index_count;
+
+	for (size_t cluster = 0; cluster < cluster_count; ++cluster)
+	{
+		size_t cluster_begin = clusters[cluster] * 3;
+		size_t cluster_end = (cluster + 1 < cluster_count) ? clusters[cluster + 1] * 3 : index_count;
+		assert(cluster_begin < cluster_end);
+
+		float cluster_area = 0;
+		float cluster_centroid[3] = {};
+		float cluster_normal[3] = {};
+
+		for (size_t i = cluster_begin; i < cluster_end; i += 3)
+		{
+			const float* p0 = vertex_positions + vertex_stride_float * indices[i + 0];
+			const float* p1 = vertex_positions + vertex_stride_float * indices[i + 1];
+			const float* p2 = vertex_positions + vertex_stride_float * indices[i + 2];
+
+			float p10[3] = {p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]};
+			float p20[3] = {p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]};
+
+			float normalx = p10[1] * p20[2] - p10[2] * p20[1];
+			float normaly = p10[2] * p20[0] - p10[0] * p20[2];
+			float normalz = p10[0] * p20[1] - p10[1] * p20[0];
+
+			float area = sqrtf(normalx * normalx + normaly * normaly + normalz * normalz);
+
+			cluster_centroid[0] += (p0[0] + p1[0] + p2[0]) * (area / 3);
+			cluster_centroid[1] += (p0[1] + p1[1] + p2[1]) * (area / 3);
+			cluster_centroid[2] += (p0[2] + p1[2] + p2[2]) * (area / 3);
+			cluster_normal[0] += normalx;
+			cluster_normal[1] += normaly;
+			cluster_normal[2] += normalz;
+			cluster_area += area;
+		}
+
+		float inv_cluster_area = cluster_area == 0 ? 0 : 1 / cluster_area;
+
+		cluster_centroid[0] *= inv_cluster_area;
+		cluster_centroid[1] *= inv_cluster_area;
+		cluster_centroid[2] *= inv_cluster_area;
+
+		float cluster_normal_length = sqrtf(cluster_normal[0] * cluster_normal[0] + cluster_normal[1] * cluster_normal[1] + cluster_normal[2] * cluster_normal[2]);
+		float inv_cluster_normal_length = cluster_normal_length == 0 ? 0 : 1 / cluster_normal_length;
+
+		cluster_normal[0] *= inv_cluster_normal_length;
+		cluster_normal[1] *= inv_cluster_normal_length;
+		cluster_normal[2] *= inv_cluster_normal_length;
+
+		float centroid_vector[3] = {cluster_centroid[0] - mesh_centroid[0], cluster_centroid[1] - mesh_centroid[1], cluster_centroid[2] - mesh_centroid[2]};
+
+		sort_data[cluster] = centroid_vector[0] * cluster_normal[0] + centroid_vector[1] * cluster_normal[1] + centroid_vector[2] * cluster_normal[2];
+	}
+}
+
+static void calculateSortOrderRadix(unsigned int* sort_order, const float* sort_data, unsigned short* sort_keys, size_t cluster_count)
+{
+	// compute sort data bounds and renormalize, using fixed point snorm
+	float sort_data_max = 1e-3f;
+
+	for (size_t i = 0; i < cluster_count; ++i)
+	{
+		float dpa = fabsf(sort_data[i]);
+
+		sort_data_max = (sort_data_max < dpa) ? dpa : sort_data_max;
+	}
+
+	const int sort_bits = 11;
+
+	for (size_t i = 0; i < cluster_count; ++i)
+	{
+		// note that we flip distribution since high dot product should come first
+		float sort_key = 0.5f - 0.5f * (sort_data[i] / sort_data_max);
+
+		sort_keys[i] = meshopt_quantizeUnorm(sort_key, sort_bits) & ((1 << sort_bits) - 1);
+	}
+
+	// fill histogram for counting sort
+	unsigned int histogram[1 << sort_bits];
+	memset(histogram, 0, sizeof(histogram));
+
+	for (size_t i = 0; i < cluster_count; ++i)
+	{
+		histogram[sort_keys[i]]++;
+	}
+
+	// compute offsets based on histogram data
+	size_t histogram_sum = 0;
+
+	for (size_t i = 0; i < 1 << sort_bits; ++i)
+	{
+		size_t count = histogram[i];
+		histogram[i] = unsigned(histogram_sum);
+		histogram_sum += count;
+	}
+
+	assert(histogram_sum == cluster_count);
+
+	// compute sort order based on offsets
+	for (size_t i = 0; i < cluster_count; ++i)
+	{
+		sort_order[histogram[sort_keys[i]]++] = unsigned(i);
+	}
+}
+
+static unsigned int updateCache(unsigned int a, unsigned int b, unsigned int c, unsigned int cache_size, unsigned int* cache_timestamps, unsigned int& timestamp)
+{
+	unsigned int cache_misses = 0;
+
+	// if vertex is not in cache, put it in cache
+	if (timestamp - cache_timestamps[a] > cache_size)
+	{
+		cache_timestamps[a] = timestamp++;
+		cache_misses++;
+	}
+
+	if (timestamp - cache_timestamps[b] > cache_size)
+	{
+		cache_timestamps[b] = timestamp++;
+		cache_misses++;
+	}
+
+	if (timestamp - cache_timestamps[c] > cache_size)
+	{
+		cache_timestamps[c] = timestamp++;
+		cache_misses++;
+	}
+
+	return cache_misses;
+}
+
+static size_t generateHardBoundaries(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int* cache_timestamps)
+{
+	memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
+
+	unsigned int timestamp = cache_size + 1;
+
+	size_t face_count = index_count / 3;
+
+	size_t result = 0;
+
+	for (size_t i = 0; i < face_count; ++i)
+	{
+		unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], timestamp);
+
+		// when all three vertices are not in the cache it's usually relatively safe to assume that this is a new patch in the mesh
+		// that is disjoint from previous vertices; sometimes it might come back to reference existing vertices but that frequently
+		// suggests an inefficiency in the vertex cache optimization algorithm
+		// usually the first triangle has 3 misses unless it's degenerate - thus we make sure the first cluster always starts with 0
+		if (i == 0 || m == 3)
+		{
+			destination[result++] = unsigned(i);
+		}
+	}
+
+	assert(result <= index_count / 3);
+
+	return result;
+}
+
+static size_t generateSoftBoundaries(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, const unsigned int* clusters, size_t cluster_count, unsigned int cache_size, float threshold, unsigned int* cache_timestamps)
+{
+	memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
+
+	unsigned int timestamp = 0;
+
+	size_t result = 0;
+
+	for (size_t it = 0; it < cluster_count; ++it)
+	{
+		size_t start = clusters[it];
+		size_t end = (it + 1 < cluster_count) ? clusters[it + 1] : index_count / 3;
+		assert(start < end);
+
+		// reset cache
+		timestamp += cache_size + 1;
+
+		// measure cluster ACMR
+		unsigned int cluster_misses = 0;
+
+		for (size_t i = start; i < end; ++i)
+		{
+			unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], timestamp);
+
+			cluster_misses += m;
+		}
+
+		float cluster_threshold = threshold * (float(cluster_misses) / float(end - start));
+
+		// first cluster always starts from the hard cluster boundary
+		destination[result++] = unsigned(start);
+
+		// reset cache
+		timestamp += cache_size + 1;
+
+		unsigned int running_misses = 0;
+		unsigned int running_faces = 0;
+
+		for (size_t i = start; i < end; ++i)
+		{
+			unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], timestamp);
+
+			running_misses += m;
+			running_faces += 1;
+
+			if (float(running_misses) / float(running_faces) <= cluster_threshold)
+			{
+				// we have reached the target ACMR with the current triangle so we need to start a new cluster on the next one
+				// note that this may mean that we add 'end` to destination for the last triangle, which will imply that the last
+				// cluster is empty; however, the 'pop_back' after the loop will clean it up
+				destination[result++] = unsigned(i + 1);
+
+				// reset cache
+				timestamp += cache_size + 1;
+
+				running_misses = 0;
+				running_faces = 0;
+			}
+		}
+
+		// each time we reach the target ACMR we flush the cluster
+		// this means that the last cluster is by definition not very good - there are frequent cases where we are left with a few triangles
+		// in the last cluster, producing a very bad ACMR and significantly penalizing the overall results
+		// thus we remove the last cluster boundary, merging the last complete cluster with the last incomplete one
+		// there are sometimes cases when the last cluster is actually good enough - in which case the code above would have added 'end'
+		// to the cluster boundary array which we need to remove anyway - this code will do that automatically
+		if (destination[result - 1] != start)
+		{
+			result--;
+		}
+	}
+
+	assert(result >= cluster_count);
+	assert(result <= index_count / 3);
+
+	return result;
+}
+
+} // namespace meshopt
+
+void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+	assert(vertex_positions_stride % sizeof(float) == 0);
+
+	meshopt_Allocator allocator;
+
+	// guard for empty meshes
+	if (index_count == 0 || vertex_count == 0)
+		return;
+
+	// support in-place optimization
+	if (destination == indices)
+	{
+		unsigned int* indices_copy = allocator.allocate<unsigned int>(index_count);
+		memcpy(indices_copy, indices, index_count * sizeof(unsigned int));
+		indices = indices_copy;
+	}
+
+	unsigned int cache_size = 16;
+
+	unsigned int* cache_timestamps = allocator.allocate<unsigned int>(vertex_count);
+
+	// generate hard boundaries from full-triangle cache misses
+	unsigned int* hard_clusters = allocator.allocate<unsigned int>(index_count / 3);
+	size_t hard_cluster_count = generateHardBoundaries(hard_clusters, indices, index_count, vertex_count, cache_size, cache_timestamps);
+
+	// generate soft boundaries
+	unsigned int* soft_clusters = allocator.allocate<unsigned int>(index_count / 3 + 1);
+	size_t soft_cluster_count = generateSoftBoundaries(soft_clusters, indices, index_count, vertex_count, hard_clusters, hard_cluster_count, cache_size, threshold, cache_timestamps);
+
+	const unsigned int* clusters = soft_clusters;
+	size_t cluster_count = soft_cluster_count;
+
+	// fill sort data
+	float* sort_data = allocator.allocate<float>(cluster_count);
+	calculateSortData(sort_data, indices, index_count, vertex_positions, vertex_positions_stride, clusters, cluster_count);
+
+	// sort clusters using sort data
+	unsigned short* sort_keys = allocator.allocate<unsigned short>(cluster_count);
+	unsigned int* sort_order = allocator.allocate<unsigned int>(cluster_count);
+	calculateSortOrderRadix(sort_order, sort_data, sort_keys, cluster_count);
+
+	// fill output buffer
+	size_t offset = 0;
+
+	for (size_t it = 0; it < cluster_count; ++it)
+	{
+		unsigned int cluster = sort_order[it];
+		assert(cluster < cluster_count);
+
+		size_t cluster_begin = clusters[cluster] * 3;
+		size_t cluster_end = (cluster + 1 < cluster_count) ? clusters[cluster + 1] * 3 : index_count;
+		assert(cluster_begin < cluster_end);
+
+		memcpy(destination + offset, indices + cluster_begin, (cluster_end - cluster_begin) * sizeof(unsigned int));
+		offset += cluster_end - cluster_begin;
+	}
+
+	assert(offset == index_count);
+}

+ 1363 - 0
3rdparty/meshoptimizer/src/simplifier.cpp

@@ -0,0 +1,1363 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <string.h>
+
+#ifndef TRACE
+#define TRACE 0
+#endif
+
+#if TRACE
+#include <stdio.h>
+#endif
+
+// This work is based on:
+// Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
+// Michael Garland. Quadric-based polygonal surface simplification. 1999
+// Peter Lindstrom. Out-of-Core Simplification of Large Polygonal Models. 2000
+// Matthias Teschner, Bruno Heidelberger, Matthias Mueller, Danat Pomeranets, Markus Gross. Optimized Spatial Hashing for Collision Detection of Deformable Objects. 2003
+namespace meshopt
+{
+
+struct EdgeAdjacency
+{
+	unsigned int* counts;
+	unsigned int* offsets;
+	unsigned int* data;
+};
+
+static void buildEdgeAdjacency(EdgeAdjacency& adjacency, const unsigned int* indices, size_t index_count, size_t vertex_count, meshopt_Allocator& allocator)
+{
+	size_t face_count = index_count / 3;
+
+	// allocate arrays
+	adjacency.counts = allocator.allocate<unsigned int>(vertex_count);
+	adjacency.offsets = allocator.allocate<unsigned int>(vertex_count);
+	adjacency.data = allocator.allocate<unsigned int>(index_count);
+
+	// fill edge counts
+	memset(adjacency.counts, 0, vertex_count * sizeof(unsigned int));
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		assert(indices[i] < vertex_count);
+
+		adjacency.counts[indices[i]]++;
+	}
+
+	// fill offset table
+	unsigned int offset = 0;
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		adjacency.offsets[i] = offset;
+		offset += adjacency.counts[i];
+	}
+
+	assert(offset == index_count);
+
+	// fill edge data
+	for (size_t i = 0; i < face_count; ++i)
+	{
+		unsigned int a = indices[i * 3 + 0], b = indices[i * 3 + 1], c = indices[i * 3 + 2];
+
+		adjacency.data[adjacency.offsets[a]++] = b;
+		adjacency.data[adjacency.offsets[b]++] = c;
+		adjacency.data[adjacency.offsets[c]++] = a;
+	}
+
+	// fix offsets that have been disturbed by the previous pass
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		assert(adjacency.offsets[i] >= adjacency.counts[i]);
+
+		adjacency.offsets[i] -= adjacency.counts[i];
+	}
+}
+
+struct PositionHasher
+{
+	const float* vertex_positions;
+	size_t vertex_stride_float;
+
+	size_t hash(unsigned int index) const
+	{
+		// MurmurHash2
+		const unsigned int m = 0x5bd1e995;
+		const int r = 24;
+
+		unsigned int h = 0;
+		const unsigned int* key = reinterpret_cast<const unsigned int*>(vertex_positions + index * vertex_stride_float);
+
+		for (size_t i = 0; i < 3; ++i)
+		{
+			unsigned int k = key[i];
+
+			k *= m;
+			k ^= k >> r;
+			k *= m;
+
+			h *= m;
+			h ^= k;
+		}
+
+		return h;
+	}
+
+	bool equal(unsigned int lhs, unsigned int rhs) const
+	{
+		return memcmp(vertex_positions + lhs * vertex_stride_float, vertex_positions + rhs * vertex_stride_float, sizeof(float) * 3) == 0;
+	}
+};
+
+static size_t hashBuckets2(size_t count)
+{
+	size_t buckets = 1;
+	while (buckets < count)
+		buckets *= 2;
+
+	return buckets;
+}
+
+template <typename T, typename Hash>
+static T* hashLookup2(T* table, size_t buckets, const Hash& hash, const T& key, const T& empty)
+{
+	assert(buckets > 0);
+	assert((buckets & (buckets - 1)) == 0);
+
+	size_t hashmod = buckets - 1;
+	size_t bucket = hash.hash(key) & hashmod;
+
+	for (size_t probe = 0; probe <= hashmod; ++probe)
+	{
+		T& item = table[bucket];
+
+		if (item == empty)
+			return &item;
+
+		if (hash.equal(item, key))
+			return &item;
+
+		// hash collision, quadratic probing
+		bucket = (bucket + probe + 1) & hashmod;
+	}
+
+	assert(false && "Hash table is full"); // unreachable
+	return 0;
+}
+
+static void buildPositionRemap(unsigned int* remap, unsigned int* wedge, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, meshopt_Allocator& allocator)
+{
+	PositionHasher hasher = {vertex_positions_data, vertex_positions_stride / sizeof(float)};
+
+	size_t table_size = hashBuckets2(vertex_count);
+	unsigned int* table = allocator.allocate<unsigned int>(table_size);
+	memset(table, -1, table_size * sizeof(unsigned int));
+
+	// build forward remap: for each vertex, which other (canonical) vertex does it map to?
+	// we use position equivalence for this, and remap vertices to other existing vertices
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		unsigned int index = unsigned(i);
+		unsigned int* entry = hashLookup2(table, table_size, hasher, index, ~0u);
+
+		if (*entry == ~0u)
+			*entry = index;
+
+		remap[index] = *entry;
+	}
+
+	// build wedge table: for each vertex, which other vertex is the next wedge that also maps to the same vertex?
+	// entries in table form a (cyclic) wedge loop per vertex; for manifold vertices, wedge[i] == remap[i] == i
+	for (size_t i = 0; i < vertex_count; ++i)
+		wedge[i] = unsigned(i);
+
+	for (size_t i = 0; i < vertex_count; ++i)
+		if (remap[i] != i)
+		{
+			unsigned int r = remap[i];
+
+			wedge[i] = wedge[r];
+			wedge[r] = unsigned(i);
+		}
+}
+
+enum VertexKind
+{
+	Kind_Manifold, // not on an attribute seam, not on any boundary
+	Kind_Border,   // not on an attribute seam, has exactly two open edges
+	Kind_Seam,     // on an attribute seam with exactly two attribute seam edges
+	Kind_Complex,  // none of the above; these vertices can move as long as all wedges move to the target vertex
+	Kind_Locked,   // none of the above; these vertices can't move
+
+	Kind_Count
+};
+
+// manifold vertices can collapse onto anything
+// border/seam vertices can only be collapsed onto border/seam respectively
+// complex vertices can collapse onto complex/locked
+// a rule of thumb is that collapsing kind A into kind B preserves the kind B in the target vertex
+// for example, while we could collapse Complex into Manifold, this would mean the target vertex isn't Manifold anymore
+const unsigned char kCanCollapse[Kind_Count][Kind_Count] = {
+    {1, 1, 1, 1, 1},
+    {0, 1, 0, 0, 0},
+    {0, 0, 1, 0, 0},
+    {0, 0, 0, 1, 1},
+    {0, 0, 0, 0, 0},
+};
+
+// if a vertex is manifold or seam, adjoining edges are guaranteed to have an opposite edge
+// note that for seam edges, the opposite edge isn't present in the attribute-based topology
+// but is present if you consider a position-only mesh variant
+const unsigned char kHasOpposite[Kind_Count][Kind_Count] = {
+    {1, 1, 1, 0, 1},
+    {1, 0, 1, 0, 0},
+    {1, 1, 1, 0, 1},
+    {0, 0, 0, 0, 0},
+    {1, 0, 1, 0, 0},
+};
+
+static bool hasEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned int b)
+{
+	unsigned int count = adjacency.counts[a];
+	const unsigned int* data = adjacency.data + adjacency.offsets[a];
+
+	for (size_t i = 0; i < count; ++i)
+		if (data[i] == b)
+			return true;
+
+	return false;
+}
+
+static unsigned int findWedgeEdge(const EdgeAdjacency& adjacency, const unsigned int* wedge, unsigned int a, unsigned int b)
+{
+	unsigned int v = a;
+
+	do
+	{
+		if (hasEdge(adjacency, v, b))
+			return v;
+
+		v = wedge[v];
+	} while (v != a);
+
+	return ~0u;
+}
+
+static size_t countOpenEdges(const EdgeAdjacency& adjacency, unsigned int vertex, unsigned int* last = 0)
+{
+	size_t result = 0;
+
+	unsigned int count = adjacency.counts[vertex];
+	const unsigned int* data = adjacency.data + adjacency.offsets[vertex];
+
+	for (size_t i = 0; i < count; ++i)
+		if (!hasEdge(adjacency, data[i], vertex))
+		{
+			result++;
+
+			if (last)
+				*last = data[i];
+		}
+
+	return result;
+}
+
+static void classifyVertices(unsigned char* result, unsigned int* loop, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge)
+{
+	for (size_t i = 0; i < vertex_count; ++i)
+		loop[i] = ~0u;
+
+#if TRACE
+	size_t lockedstats[4] = {};
+#define TRACELOCKED(i) lockedstats[i]++;
+#else
+#define TRACELOCKED(i) (void)0
+#endif
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		if (remap[i] == i)
+		{
+			if (wedge[i] == i)
+			{
+				// no attribute seam, need to check if it's manifold
+				unsigned int v = 0;
+				size_t edges = countOpenEdges(adjacency, unsigned(i), &v);
+
+				// note: we classify any vertices with no open edges as manifold
+				// this is technically incorrect - if 4 triangles share an edge, we'll classify vertices as manifold
+				// it's unclear if this is a problem in practice
+				// also note that we classify vertices as border if they have *one* open edge, not two
+				// this is because we only have half-edges - so a border vertex would have one incoming and one outgoing edge
+				if (edges == 0)
+				{
+					result[i] = Kind_Manifold;
+				}
+				else if (edges == 1)
+				{
+					result[i] = Kind_Border;
+					loop[i] = v;
+				}
+				else
+				{
+					result[i] = Kind_Locked;
+					TRACELOCKED(0);
+				}
+			}
+			else if (wedge[wedge[i]] == i)
+			{
+				// attribute seam; need to distinguish between Seam and Locked
+				unsigned int a = 0;
+				size_t a_count = countOpenEdges(adjacency, unsigned(i), &a);
+				unsigned int b = 0;
+				size_t b_count = countOpenEdges(adjacency, wedge[i], &b);
+
+				// seam should have one open half-edge for each vertex, and the edges need to "connect" - point to the same vertex post-remap
+				if (a_count == 1 && b_count == 1)
+				{
+					unsigned int ao = findWedgeEdge(adjacency, wedge, a, wedge[i]);
+					unsigned int bo = findWedgeEdge(adjacency, wedge, b, unsigned(i));
+
+					if (ao != ~0u && bo != ~0u)
+					{
+						result[i] = Kind_Seam;
+
+						loop[i] = a;
+						loop[wedge[i]] = b;
+					}
+					else
+					{
+						result[i] = Kind_Locked;
+						TRACELOCKED(1);
+					}
+				}
+				else
+				{
+					result[i] = Kind_Locked;
+					TRACELOCKED(2);
+				}
+			}
+			else
+			{
+				// more than one vertex maps to this one; we don't have classification available
+				result[i] = Kind_Locked;
+				TRACELOCKED(3);
+			}
+		}
+		else
+		{
+			assert(remap[i] < i);
+
+			result[i] = result[remap[i]];
+		}
+	}
+
+#if TRACE
+	printf("locked: many open edges %d, disconnected seam %d, many seam edges %d, many wedges %d\n",
+	       int(lockedstats[0]), int(lockedstats[1]), int(lockedstats[2]), int(lockedstats[3]));
+#endif
+}
+
+struct Vector3
+{
+	float x, y, z;
+};
+
+static void rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride)
+{
+	size_t vertex_stride_float = vertex_positions_stride / sizeof(float);
+
+	float minv[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
+	float maxv[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		const float* v = vertex_positions_data + i * vertex_stride_float;
+
+		result[i].x = v[0];
+		result[i].y = v[1];
+		result[i].z = v[2];
+
+		for (int j = 0; j < 3; ++j)
+		{
+			float vj = v[j];
+
+			minv[j] = minv[j] > vj ? vj : minv[j];
+			maxv[j] = maxv[j] < vj ? vj : maxv[j];
+		}
+	}
+
+	float extent = 0.f;
+
+	extent = (maxv[0] - minv[0]) < extent ? extent : (maxv[0] - minv[0]);
+	extent = (maxv[1] - minv[1]) < extent ? extent : (maxv[1] - minv[1]);
+	extent = (maxv[2] - minv[2]) < extent ? extent : (maxv[2] - minv[2]);
+
+	float scale = extent == 0 ? 0.f : 1.f / extent;
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		result[i].x = (result[i].x - minv[0]) * scale;
+		result[i].y = (result[i].y - minv[1]) * scale;
+		result[i].z = (result[i].z - minv[2]) * scale;
+	}
+}
+
+struct Quadric
+{
+	float a00, a11, a22;
+	float a10, a20, a21;
+	float b0, b1, b2, c;
+	float w;
+};
+
+struct Collapse
+{
+	unsigned int v0;
+	unsigned int v1;
+
+	union {
+		unsigned int bidi;
+		float error;
+		unsigned int errorui;
+	};
+};
+
+static float normalize(Vector3& v)
+{
+	float length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
+
+	if (length > 0)
+	{
+		v.x /= length;
+		v.y /= length;
+		v.z /= length;
+	}
+
+	return length;
+}
+
+static void quadricAdd(Quadric& Q, const Quadric& R)
+{
+	Q.a00 += R.a00;
+	Q.a11 += R.a11;
+	Q.a22 += R.a22;
+	Q.a10 += R.a10;
+	Q.a20 += R.a20;
+	Q.a21 += R.a21;
+	Q.b0 += R.b0;
+	Q.b1 += R.b1;
+	Q.b2 += R.b2;
+	Q.c += R.c;
+	Q.w += R.w;
+}
+
+static float quadricError(const Quadric& Q, const Vector3& v)
+{
+	float rx = Q.b0;
+	float ry = Q.b1;
+	float rz = Q.b2;
+
+	rx += Q.a10 * v.y;
+	ry += Q.a21 * v.z;
+	rz += Q.a20 * v.x;
+
+	rx *= 2;
+	ry *= 2;
+	rz *= 2;
+
+	rx += Q.a00 * v.x;
+	ry += Q.a11 * v.y;
+	rz += Q.a22 * v.z;
+
+	float r = Q.c;
+	r += rx * v.x;
+	r += ry * v.y;
+	r += rz * v.z;
+
+	float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
+
+	return fabsf(r) * s;
+}
+
+static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, float w)
+{
+	float aw = a * w;
+	float bw = b * w;
+	float cw = c * w;
+	float dw = d * w;
+
+	Q.a00 = a * aw;
+	Q.a11 = b * bw;
+	Q.a22 = c * cw;
+	Q.a10 = a * bw;
+	Q.a20 = a * cw;
+	Q.a21 = b * cw;
+	Q.b0 = a * dw;
+	Q.b1 = b * dw;
+	Q.b2 = c * dw;
+	Q.c = d * dw;
+	Q.w = w;
+}
+
+static void quadricFromTriangle(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float weight)
+{
+	Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
+	Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
+
+	// normal = cross(p1 - p0, p2 - p0)
+	Vector3 normal = {p10.y * p20.z - p10.z * p20.y, p10.z * p20.x - p10.x * p20.z, p10.x * p20.y - p10.y * p20.x};
+	float area = normalize(normal);
+
+	float distance = normal.x * p0.x + normal.y * p0.y + normal.z * p0.z;
+
+	// we use sqrtf(area) so that the error is scaled linearly; this tends to improve silhouettes
+	quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, sqrtf(area) * weight);
+}
+
+static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float weight)
+{
+	Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
+	float length = normalize(p10);
+
+	// p20p = length of projection of p2-p0 onto normalize(p1 - p0)
+	Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
+	float p20p = p20.x * p10.x + p20.y * p10.y + p20.z * p10.z;
+
+	// normal = altitude of triangle from point p2 onto edge p1-p0
+	Vector3 normal = {p20.x - p10.x * p20p, p20.y - p10.y * p20p, p20.z - p10.z * p20p};
+	normalize(normal);
+
+	float distance = normal.x * p0.x + normal.y * p0.y + normal.z * p0.z;
+
+	// note: the weight is scaled linearly with edge length; this has to match the triangle weight
+	quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight);
+}
+
+static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
+{
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int i0 = indices[i + 0];
+		unsigned int i1 = indices[i + 1];
+		unsigned int i2 = indices[i + 2];
+
+		Quadric Q;
+		quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
+
+		quadricAdd(vertex_quadrics[remap[i0]], Q);
+		quadricAdd(vertex_quadrics[remap[i1]], Q);
+		quadricAdd(vertex_quadrics[remap[i2]], Q);
+	}
+}
+
+static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap, const unsigned char* vertex_kind, const unsigned int* loop)
+{
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		static const int next[3] = {1, 2, 0};
+
+		for (int e = 0; e < 3; ++e)
+		{
+			unsigned int i0 = indices[i + e];
+			unsigned int i1 = indices[i + next[e]];
+
+			unsigned char k0 = vertex_kind[i0];
+			unsigned char k1 = vertex_kind[i1];
+
+			// check that i0 and i1 are border/seam and are on the same edge loop
+			// loop[] tracks half edges so we only need to check i0->i1
+			if (k0 != k1 || (k0 != Kind_Border && k0 != Kind_Seam) || loop[i0] != i1)
+				continue;
+
+			unsigned int i2 = indices[i + next[next[e]]];
+
+			// we try hard to maintain border edge geometry; seam edges can move more freely
+			// due to topological restrictions on collapses, seam quadrics slightly improves collapse structure but aren't critical
+			const float kEdgeWeightSeam = 1.f;
+			const float kEdgeWeightBorder = 10.f;
+
+			float edgeWeight = (k0 == Kind_Seam) ? kEdgeWeightSeam : kEdgeWeightBorder;
+
+			Quadric Q;
+			quadricFromTriangleEdge(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], edgeWeight);
+
+			quadricAdd(vertex_quadrics[remap[i0]], Q);
+			quadricAdd(vertex_quadrics[remap[i1]], Q);
+		}
+	}
+}
+
+static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices, size_t index_count, const unsigned int* remap, const unsigned char* vertex_kind, const unsigned int* loop)
+{
+	size_t collapse_count = 0;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		static const int next[3] = {1, 2, 0};
+
+		for (int e = 0; e < 3; ++e)
+		{
+			unsigned int i0 = indices[i + e];
+			unsigned int i1 = indices[i + next[e]];
+
+			// this can happen either when input has a zero-length edge, or when we perform collapses for complex
+			// topology w/seams and collapse a manifold vertex that connects to both wedges onto one of them
+			// we leave edges like this alone since they may be important for preserving mesh integrity
+			if (remap[i0] == remap[i1])
+				continue;
+
+			unsigned char k0 = vertex_kind[i0];
+			unsigned char k1 = vertex_kind[i1];
+
+			// the edge has to be collapsible in at least one direction
+			if (!(kCanCollapse[k0][k1] | kCanCollapse[k1][k0]))
+				continue;
+
+			// manifold and seam edges should occur twice (i0->i1 and i1->i0) - skip redundant edges
+			if (kHasOpposite[k0][k1] && remap[i1] > remap[i0])
+				continue;
+
+			// two vertices are on a border or a seam, but there's no direct edge between them
+			// this indicates that they belong to two different edge loops and we should not collapse this edge
+			// loop[] tracks half edges so we only need to check i0->i1
+			if (k0 == k1 && (k0 == Kind_Border || k0 == Kind_Seam) && loop[i0] != i1)
+				continue;
+
+			// edge can be collapsed in either direction - we will pick the one with minimum error
+			// note: we evaluate error later during collapse ranking, here we just tag the edge as bidirectional
+			if (kCanCollapse[k0][k1] & kCanCollapse[k1][k0])
+			{
+				Collapse c = {i0, i1, {/* bidi= */ 1}};
+				collapses[collapse_count++] = c;
+			}
+			else
+			{
+				// edge can only be collapsed in one direction
+				unsigned int e0 = kCanCollapse[k0][k1] ? i0 : i1;
+				unsigned int e1 = kCanCollapse[k0][k1] ? i1 : i0;
+
+				Collapse c = {e0, e1, {/* bidi= */ 0}};
+				collapses[collapse_count++] = c;
+			}
+		}
+	}
+
+	return collapse_count;
+}
+
+static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const Vector3* vertex_positions, const Quadric* vertex_quadrics, const unsigned int* remap)
+{
+	for (size_t i = 0; i < collapse_count; ++i)
+	{
+		Collapse& c = collapses[i];
+
+		unsigned int i0 = c.v0;
+		unsigned int i1 = c.v1;
+
+		// most edges are bidirectional which means we need to evaluate errors for two collapses
+		// to keep this code branchless we just use the same edge for unidirectional edges
+		unsigned int j0 = c.bidi ? i1 : i0;
+		unsigned int j1 = c.bidi ? i0 : i1;
+
+		const Quadric& qi = vertex_quadrics[remap[i0]];
+		const Quadric& qj = vertex_quadrics[remap[j0]];
+
+		float ei = quadricError(qi, vertex_positions[i1]);
+		float ej = quadricError(qj, vertex_positions[j1]);
+
+		// pick edge direction with minimal error
+		c.v0 = ei <= ej ? i0 : j0;
+		c.v1 = ei <= ej ? i1 : j1;
+		c.error = ei <= ej ? ei : ej;
+	}
+}
+
+#if TRACE > 1
+static void dumpEdgeCollapses(const Collapse* collapses, size_t collapse_count, const unsigned char* vertex_kind)
+{
+	size_t ckinds[Kind_Count][Kind_Count] = {};
+	float cerrors[Kind_Count][Kind_Count] = {};
+
+	for (int k0 = 0; k0 < Kind_Count; ++k0)
+		for (int k1 = 0; k1 < Kind_Count; ++k1)
+			cerrors[k0][k1] = FLT_MAX;
+
+	for (size_t i = 0; i < collapse_count; ++i)
+	{
+		unsigned int i0 = collapses[i].v0;
+		unsigned int i1 = collapses[i].v1;
+
+		unsigned char k0 = vertex_kind[i0];
+		unsigned char k1 = vertex_kind[i1];
+
+		ckinds[k0][k1]++;
+		cerrors[k0][k1] = (collapses[i].error < cerrors[k0][k1]) ? collapses[i].error : cerrors[k0][k1];
+	}
+
+	for (int k0 = 0; k0 < Kind_Count; ++k0)
+		for (int k1 = 0; k1 < Kind_Count; ++k1)
+			if (ckinds[k0][k1])
+				printf("collapses %d -> %d: %d, min error %e\n", k0, k1, int(ckinds[k0][k1]), cerrors[k0][k1]);
+}
+
+static void dumpLockedCollapses(const unsigned int* indices, size_t index_count, const unsigned char* vertex_kind)
+{
+	size_t locked_collapses[Kind_Count][Kind_Count] = {};
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		static const int next[3] = {1, 2, 0};
+
+		for (int e = 0; e < 3; ++e)
+		{
+			unsigned int i0 = indices[i + e];
+			unsigned int i1 = indices[i + next[e]];
+
+			unsigned char k0 = vertex_kind[i0];
+			unsigned char k1 = vertex_kind[i1];
+
+			locked_collapses[k0][k1] += !kCanCollapse[k0][k1] && !kCanCollapse[k1][k0];
+		}
+	}
+
+	for (int k0 = 0; k0 < Kind_Count; ++k0)
+		for (int k1 = 0; k1 < Kind_Count; ++k1)
+			if (locked_collapses[k0][k1])
+				printf("locked collapses %d -> %d: %d\n", k0, k1, int(locked_collapses[k0][k1]));
+}
+#endif
+
+static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapses, size_t collapse_count)
+{
+	const int sort_bits = 11;
+
+	// fill histogram for counting sort
+	unsigned int histogram[1 << sort_bits];
+	memset(histogram, 0, sizeof(histogram));
+
+	for (size_t i = 0; i < collapse_count; ++i)
+	{
+		// skip sign bit since error is non-negative
+		unsigned int key = (collapses[i].errorui << 1) >> (32 - sort_bits);
+
+		histogram[key]++;
+	}
+
+	// compute offsets based on histogram data
+	size_t histogram_sum = 0;
+
+	for (size_t i = 0; i < 1 << sort_bits; ++i)
+	{
+		size_t count = histogram[i];
+		histogram[i] = unsigned(histogram_sum);
+		histogram_sum += count;
+	}
+
+	assert(histogram_sum == collapse_count);
+
+	// compute sort order based on offsets
+	for (size_t i = 0; i < collapse_count; ++i)
+	{
+		// skip sign bit since error is non-negative
+		unsigned int key = (collapses[i].errorui << 1) >> (32 - sort_bits);
+
+		sort_order[histogram[key]++] = unsigned(i);
+	}
+}
+
+static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, Quadric* vertex_quadrics, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, size_t triangle_collapse_goal, float error_goal, float error_limit)
+{
+	size_t edge_collapses = 0;
+	size_t triangle_collapses = 0;
+
+	for (size_t i = 0; i < collapse_count; ++i)
+	{
+		const Collapse& c = collapses[collapse_order[i]];
+
+		if (c.error > error_limit)
+			break;
+
+		if (c.error > error_goal && triangle_collapses > triangle_collapse_goal / 10)
+			break;
+
+		if (triangle_collapses >= triangle_collapse_goal)
+			break;
+
+		unsigned int i0 = c.v0;
+		unsigned int i1 = c.v1;
+
+		unsigned int r0 = remap[i0];
+		unsigned int r1 = remap[i1];
+
+		// we don't collapse vertices that had source or target vertex involved in a collapse
+		// it's important to not move the vertices twice since it complicates the tracking/remapping logic
+		// it's important to not move other vertices towards a moved vertex to preserve error since we don't re-rank collapses mid-pass
+		if (collapse_locked[r0] | collapse_locked[r1])
+			continue;
+
+		assert(collapse_remap[r0] == r0);
+		assert(collapse_remap[r1] == r1);
+
+		quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]);
+
+		if (vertex_kind[i0] == Kind_Complex)
+		{
+			unsigned int v = i0;
+
+			do
+			{
+				collapse_remap[v] = r1;
+				v = wedge[v];
+			} while (v != i0);
+		}
+		else if (vertex_kind[i0] == Kind_Seam)
+		{
+			// remap v0 to v1 and seam pair of v0 to seam pair of v1
+			unsigned int s0 = wedge[i0];
+			unsigned int s1 = wedge[i1];
+
+			assert(s0 != i0 && s1 != i1);
+			assert(wedge[s0] == i0 && wedge[s1] == i1);
+
+			collapse_remap[i0] = i1;
+			collapse_remap[s0] = s1;
+		}
+		else
+		{
+			assert(wedge[i0] == i0);
+
+			collapse_remap[i0] = i1;
+		}
+
+		collapse_locked[r0] = 1;
+		collapse_locked[r1] = 1;
+
+		// border edges collapse 1 triangle, other edges collapse 2 or more
+		triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2;
+		edge_collapses++;
+	}
+
+	return edge_collapses;
+}
+
+static size_t remapIndexBuffer(unsigned int* indices, size_t index_count, const unsigned int* collapse_remap)
+{
+	size_t write = 0;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int v0 = collapse_remap[indices[i + 0]];
+		unsigned int v1 = collapse_remap[indices[i + 1]];
+		unsigned int v2 = collapse_remap[indices[i + 2]];
+
+		// we never move the vertex twice during a single pass
+		assert(collapse_remap[v0] == v0);
+		assert(collapse_remap[v1] == v1);
+		assert(collapse_remap[v2] == v2);
+
+		if (v0 != v1 && v0 != v2 && v1 != v2)
+		{
+			indices[write + 0] = v0;
+			indices[write + 1] = v1;
+			indices[write + 2] = v2;
+			write += 3;
+		}
+	}
+
+	return write;
+}
+
+static void remapEdgeLoops(unsigned int* loop, size_t vertex_count, const unsigned int* collapse_remap)
+{
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		if (loop[i] != ~0u)
+		{
+			unsigned int l = loop[i];
+			unsigned int r = collapse_remap[l];
+
+			// i == r is a special case when the seam edge is collapsed in a direction opposite to where loop goes
+			loop[i] = (i == r) ? loop[l] : r;
+		}
+	}
+}
+
+struct CellHasher
+{
+	const unsigned int* vertex_ids;
+
+	size_t hash(unsigned int i) const
+	{
+		unsigned int h = vertex_ids[i];
+
+		// MurmurHash2 finalizer
+		h ^= h >> 13;
+		h *= 0x5bd1e995;
+		h ^= h >> 15;
+		return h;
+	}
+
+	bool equal(unsigned int lhs, unsigned int rhs) const
+	{
+		return vertex_ids[lhs] == vertex_ids[rhs];
+	}
+};
+
+struct TriangleHasher
+{
+	unsigned int* indices;
+
+	size_t hash(unsigned int i) const
+	{
+		const unsigned int* tri = indices + i * 3;
+
+		// Optimized Spatial Hashing for Collision Detection of Deformable Objects
+		return (tri[0] * 73856093) ^ (tri[1] * 19349663) ^ (tri[2] * 83492791);
+	}
+
+	bool equal(unsigned int lhs, unsigned int rhs) const
+	{
+		const unsigned int* lt = indices + lhs * 3;
+		const unsigned int* rt = indices + rhs * 3;
+
+		return lt[0] == rt[0] && lt[1] == rt[1] && lt[2] == rt[2];
+	}
+};
+
+static void computeVertexIds(unsigned int* vertex_ids, const Vector3* vertex_positions, size_t vertex_count, int grid_size)
+{
+	assert(grid_size >= 1 && grid_size <= 1024);
+	float cell_scale = float(grid_size - 1);
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		const Vector3& v = vertex_positions[i];
+
+		int xi = int(v.x * cell_scale + 0.5f);
+		int yi = int(v.y * cell_scale + 0.5f);
+		int zi = int(v.z * cell_scale + 0.5f);
+
+		vertex_ids[i] = (xi << 20) | (yi << 10) | zi;
+	}
+}
+
+static size_t countTriangles(const unsigned int* vertex_ids, const unsigned int* indices, size_t index_count)
+{
+	size_t result = 0;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int id0 = vertex_ids[indices[i + 0]];
+		unsigned int id1 = vertex_ids[indices[i + 1]];
+		unsigned int id2 = vertex_ids[indices[i + 2]];
+
+		result += (id0 != id1) & (id0 != id2) & (id1 != id2);
+	}
+
+	return result;
+}
+
+static size_t fillVertexCells(unsigned int* table, size_t table_size, unsigned int* vertex_cells, const unsigned int* vertex_ids, size_t vertex_count)
+{
+	CellHasher hasher = {vertex_ids};
+
+	memset(table, -1, table_size * sizeof(unsigned int));
+
+	size_t result = 0;
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		unsigned int* entry = hashLookup2(table, table_size, hasher, unsigned(i), ~0u);
+
+		if (*entry == ~0u)
+		{
+			*entry = unsigned(i);
+			vertex_cells[i] = unsigned(result++);
+		}
+		else
+		{
+			vertex_cells[i] = vertex_cells[*entry];
+		}
+	}
+
+	return result;
+}
+
+static void fillCellQuadrics(Quadric* cell_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* vertex_cells)
+{
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int i0 = indices[i + 0];
+		unsigned int i1 = indices[i + 1];
+		unsigned int i2 = indices[i + 2];
+
+		unsigned int c0 = vertex_cells[i0];
+		unsigned int c1 = vertex_cells[i1];
+		unsigned int c2 = vertex_cells[i2];
+
+		bool single_cell = (c0 == c1) & (c0 == c2);
+
+		Quadric Q;
+		quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], single_cell ? 3.f : 1.f);
+
+		if (single_cell)
+		{
+			quadricAdd(cell_quadrics[c0], Q);
+		}
+		else
+		{
+			quadricAdd(cell_quadrics[c0], Q);
+			quadricAdd(cell_quadrics[c1], Q);
+			quadricAdd(cell_quadrics[c2], Q);
+		}
+	}
+}
+
+static void fillCellRemap(unsigned int* cell_remap, float* cell_errors, size_t cell_count, const unsigned int* vertex_cells, const Quadric* cell_quadrics, const Vector3* vertex_positions, size_t vertex_count)
+{
+	memset(cell_remap, -1, cell_count * sizeof(unsigned int));
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		unsigned int cell = vertex_cells[i];
+		float error = quadricError(cell_quadrics[cell], vertex_positions[i]);
+
+		if (cell_remap[cell] == ~0u || cell_errors[cell] > error)
+		{
+			cell_remap[cell] = unsigned(i);
+			cell_errors[cell] = error;
+		}
+	}
+}
+
+static size_t filterTriangles(unsigned int* destination, unsigned int* tritable, size_t tritable_size, const unsigned int* indices, size_t index_count, const unsigned int* vertex_cells, const unsigned int* cell_remap)
+{
+	TriangleHasher hasher = {destination};
+
+	memset(tritable, -1, tritable_size * sizeof(unsigned int));
+
+	size_t result = 0;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int c0 = vertex_cells[indices[i + 0]];
+		unsigned int c1 = vertex_cells[indices[i + 1]];
+		unsigned int c2 = vertex_cells[indices[i + 2]];
+
+		if (c0 != c1 && c0 != c2 && c1 != c2)
+		{
+			unsigned int a = cell_remap[c0];
+			unsigned int b = cell_remap[c1];
+			unsigned int c = cell_remap[c2];
+
+			if (b < a && b < c)
+			{
+				unsigned int t = a;
+				a = b, b = c, c = t;
+			}
+			else if (c < a && c < b)
+			{
+				unsigned int t = c;
+				c = b, b = a, a = t;
+			}
+
+			destination[result * 3 + 0] = a;
+			destination[result * 3 + 1] = b;
+			destination[result * 3 + 2] = c;
+
+			unsigned int* entry = hashLookup2(tritable, tritable_size, hasher, unsigned(result), ~0u);
+
+			if (*entry == ~0u)
+				*entry = unsigned(result++);
+		}
+	}
+
+	return result * 3;
+}
+
+} // namespace meshopt
+
+#if TRACE
+unsigned char* meshopt_simplifyDebugKind = 0;
+unsigned int* meshopt_simplifyDebugLoop = 0;
+#endif
+
+size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+	assert(vertex_positions_stride % sizeof(float) == 0);
+	assert(target_index_count <= index_count);
+
+	meshopt_Allocator allocator;
+
+	unsigned int* result = destination;
+
+	// build adjacency information
+	EdgeAdjacency adjacency = {};
+	buildEdgeAdjacency(adjacency, indices, index_count, vertex_count, allocator);
+
+	// build position remap that maps each vertex to the one with identical position
+	unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
+	unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count);
+	buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator);
+
+	// classify vertices; vertex kind determines collapse rules, see kCanCollapse
+	unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
+	unsigned int* loop = allocator.allocate<unsigned int>(vertex_count);
+	classifyVertices(vertex_kind, loop, vertex_count, adjacency, remap, wedge);
+
+#if TRACE
+	size_t unique_positions = 0;
+	for (size_t i = 0; i < vertex_count; ++i)
+		unique_positions += remap[i] == i;
+
+	printf("position remap: %d vertices => %d positions\n", int(vertex_count), int(unique_positions));
+
+	size_t kinds[Kind_Count] = {};
+	for (size_t i = 0; i < vertex_count; ++i)
+		kinds[vertex_kind[i]] += remap[i] == i;
+
+	printf("kinds: manifold %d, border %d, seam %d, complex %d, locked %d\n",
+	       int(kinds[Kind_Manifold]), int(kinds[Kind_Border]), int(kinds[Kind_Seam]), int(kinds[Kind_Complex]), int(kinds[Kind_Locked]));
+#endif
+
+	Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
+	rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride);
+
+	Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
+	memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
+
+	fillFaceQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap);
+	fillEdgeQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap, vertex_kind, loop);
+
+	if (result != indices)
+		memcpy(result, indices, index_count * sizeof(unsigned int));
+
+#if TRACE
+	size_t pass_count = 0;
+	float worst_error = 0;
+#endif
+
+	Collapse* edge_collapses = allocator.allocate<Collapse>(index_count);
+	unsigned int* collapse_order = allocator.allocate<unsigned int>(index_count);
+	unsigned int* collapse_remap = allocator.allocate<unsigned int>(vertex_count);
+	unsigned char* collapse_locked = allocator.allocate<unsigned char>(vertex_count);
+
+	size_t result_count = index_count;
+
+	// target_error input is linear; we need to adjust it to match quadricError units
+	float error_limit = target_error * target_error;
+
+	while (result_count > target_index_count)
+	{
+		size_t edge_collapse_count = pickEdgeCollapses(edge_collapses, result, result_count, remap, vertex_kind, loop);
+
+		// no edges can be collapsed any more due to topology restrictions
+		if (edge_collapse_count == 0)
+			break;
+
+		rankEdgeCollapses(edge_collapses, edge_collapse_count, vertex_positions, vertex_quadrics, remap);
+
+#if TRACE > 1
+		dumpEdgeCollapses(edge_collapses, edge_collapse_count, vertex_kind);
+#endif
+
+		sortEdgeCollapses(collapse_order, edge_collapses, edge_collapse_count);
+
+		// most collapses remove 2 triangles; use this to establish a bound on the pass in terms of error limit
+		// note that edge_collapse_goal is an estimate; triangle_collapse_goal will be used to actually limit collapses
+		size_t triangle_collapse_goal = (result_count - target_index_count) / 3;
+		size_t edge_collapse_goal = triangle_collapse_goal / 2;
+
+		// we limit the error in each pass based on the error of optimal last collapse; since many collapses will be locked
+		// as they will share vertices with other successfull collapses, we need to increase the acceptable error by this factor
+		const float kPassErrorBound = 1.5f;
+
+		float error_goal = edge_collapse_goal < edge_collapse_count ? edge_collapses[collapse_order[edge_collapse_goal]].error * kPassErrorBound : FLT_MAX;
+
+		for (size_t i = 0; i < vertex_count; ++i)
+			collapse_remap[i] = unsigned(i);
+
+		memset(collapse_locked, 0, vertex_count);
+
+		size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, vertex_quadrics, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, triangle_collapse_goal, error_goal, error_limit);
+
+		// no edges can be collapsed any more due to hitting the error limit or triangle collapse limit
+		if (collapses == 0)
+			break;
+
+		remapEdgeLoops(loop, vertex_count, collapse_remap);
+
+		size_t new_count = remapIndexBuffer(result, result_count, collapse_remap);
+		assert(new_count < result_count);
+
+#if TRACE
+		float pass_error = 0.f;
+		for (size_t i = 0; i < edge_collapse_count; ++i)
+		{
+			Collapse& c = edge_collapses[collapse_order[i]];
+
+			if (collapse_remap[c.v0] == c.v1)
+				pass_error = c.error;
+		}
+
+		pass_count++;
+		worst_error = (worst_error < pass_error) ? pass_error : worst_error;
+
+		printf("pass %d: triangles: %d -> %d, collapses: %d/%d (goal: %d), error: %e (limit %e goal %e)\n", int(pass_count), int(result_count / 3), int(new_count / 3), int(collapses), int(edge_collapse_count), int(edge_collapse_goal), pass_error, error_limit, error_goal);
+#endif
+
+		result_count = new_count;
+	}
+
+#if TRACE
+	printf("passes: %d, worst error: %e\n", int(pass_count), worst_error);
+#endif
+
+#if TRACE > 1
+	dumpLockedCollapses(result, result_count, vertex_kind);
+#endif
+
+#if TRACE
+	if (meshopt_simplifyDebugKind)
+		memcpy(meshopt_simplifyDebugKind, vertex_kind, vertex_count);
+
+	if (meshopt_simplifyDebugLoop)
+		memcpy(meshopt_simplifyDebugLoop, loop, vertex_count * sizeof(unsigned int));
+#endif
+
+	return result_count;
+}
+
+size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+	assert(vertex_positions_stride % sizeof(float) == 0);
+	assert(target_index_count <= index_count);
+
+	// we expect to get ~2 triangles/vertex in the output
+	size_t target_cell_count = target_index_count / 6;
+
+	if (target_cell_count == 0)
+		return 0;
+
+	meshopt_Allocator allocator;
+
+	Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
+	rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride);
+
+	// find the optimal grid size using guided binary search
+#if TRACE
+	printf("source: %d vertices, %d triangles\n", int(vertex_count), int(index_count / 3));
+	printf("target: %d cells, %d triangles\n", int(target_cell_count), int(target_index_count / 3));
+#endif
+
+	unsigned int* vertex_ids = allocator.allocate<unsigned int>(vertex_count);
+
+	// invariant: # of triangles in min_grid <= target_count
+	int min_grid = 0;
+	int max_grid = 1025;
+	size_t min_triangles = 0;
+	size_t max_triangles = index_count / 3;
+
+	const int kInterpolationPasses = 5;
+
+	for (int pass = 0; pass < 10 + kInterpolationPasses; ++pass)
+	{
+		assert(min_triangles < target_index_count / 3);
+		assert(max_grid - min_grid > 1);
+
+		int grid_size = 0;
+
+		if (pass == 0)
+		{
+			// instead of starting in the middle, let's guess as to what the answer might be! triangle count usually grows as a square of grid size...
+			grid_size = int(sqrtf(float(target_cell_count)) + 0.5f);
+			grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1 : grid_size;
+		}
+		else if (pass <= kInterpolationPasses)
+		{
+			float k = (float(target_index_count / 3) - float(min_triangles)) / (float(max_triangles) - float(min_triangles));
+			grid_size = int(float(min_grid) * (1 - k) + float(max_grid) * k + 0.5f);
+			grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1 : grid_size;
+		}
+		else
+		{
+			grid_size = (min_grid + max_grid) / 2;
+			assert(grid_size > min_grid && grid_size < max_grid);
+		}
+
+		computeVertexIds(vertex_ids, vertex_positions, vertex_count, grid_size);
+		size_t triangles = countTriangles(vertex_ids, indices, index_count);
+
+#if TRACE
+		printf("pass %d (%s): grid size %d, triangles %d, %s\n",
+		       pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp" : "binary",
+		       grid_size, int(triangles),
+		       (triangles <= target_index_count / 3) ? "under" : "over");
+#endif
+
+		if (triangles <= target_index_count / 3)
+		{
+			min_grid = grid_size;
+			min_triangles = triangles;
+		}
+		else
+		{
+			max_grid = grid_size;
+			max_triangles = triangles;
+		}
+
+		if (triangles == target_index_count / 3 || max_grid - min_grid <= 1)
+			break;
+	}
+
+	if (min_triangles == 0)
+		return 0;
+
+	// build vertex->cell association by mapping all vertices with the same quantized position to the same cell
+	size_t table_size = hashBuckets2(vertex_count);
+	unsigned int* table = allocator.allocate<unsigned int>(table_size);
+
+	unsigned int* vertex_cells = allocator.allocate<unsigned int>(vertex_count);
+
+	computeVertexIds(vertex_ids, vertex_positions, vertex_count, min_grid);
+	size_t cell_count = fillVertexCells(table, table_size, vertex_cells, vertex_ids, vertex_count);
+
+	// build a quadric for each target cell
+	Quadric* cell_quadrics = allocator.allocate<Quadric>(cell_count);
+	memset(cell_quadrics, 0, cell_count * sizeof(Quadric));
+
+	fillCellQuadrics(cell_quadrics, indices, index_count, vertex_positions, vertex_cells);
+
+	// for each target cell, find the vertex with the minimal error
+	unsigned int* cell_remap = allocator.allocate<unsigned int>(cell_count);
+	float* cell_errors = allocator.allocate<float>(cell_count);
+
+	fillCellRemap(cell_remap, cell_errors, cell_count, vertex_cells, cell_quadrics, vertex_positions, vertex_count);
+
+	// collapse triangles!
+	// note that we need to filter out triangles that we've already output because we very frequently generate redundant triangles between cells :(
+	size_t tritable_size = hashBuckets2(min_triangles);
+	unsigned int* tritable = allocator.allocate<unsigned int>(tritable_size);
+
+	size_t write = filterTriangles(destination, tritable, tritable_size, indices, index_count, vertex_cells, cell_remap);
+	assert(write <= target_index_count);
+
+#if TRACE
+	printf("result: %d cells, %d triangles (%d unfiltered)\n", int(cell_count), int(write / 3), int(min_triangles));
+#endif
+
+	return write;
+}

+ 269 - 0
3rdparty/meshoptimizer/src/stripifier.cpp

@@ -0,0 +1,269 @@
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+// This work is based on:
+// Francine Evans, Steven Skiena and Amitabh Varshney. Optimizing Triangle Strips for Fast Rendering. 1996
+namespace meshopt
+{
+
+static unsigned int findStripFirst(const unsigned int buffer[][3], unsigned int buffer_size, const unsigned int* valence)
+{
+	unsigned int index = 0;
+	unsigned int iv = ~0u;
+
+	for (size_t i = 0; i < buffer_size; ++i)
+	{
+		unsigned int va = valence[buffer[i][0]], vb = valence[buffer[i][1]], vc = valence[buffer[i][2]];
+		unsigned int v = (va < vb && va < vc) ? va : (vb < vc) ? vb : vc;
+
+		if (v < iv)
+		{
+			index = unsigned(i);
+			iv = v;
+		}
+	}
+
+	return index;
+}
+
+static int findStripNext(const unsigned int buffer[][3], unsigned int buffer_size, unsigned int e0, unsigned int e1)
+{
+	for (size_t i = 0; i < buffer_size; ++i)
+	{
+		unsigned int a = buffer[i][0], b = buffer[i][1], c = buffer[i][2];
+
+		if (e0 == a && e1 == b)
+			return (int(i) << 2) | 2;
+		else if (e0 == b && e1 == c)
+			return (int(i) << 2) | 0;
+		else if (e0 == c && e1 == a)
+			return (int(i) << 2) | 1;
+	}
+
+	return -1;
+}
+
+} // namespace meshopt
+
+size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count)
+{
+	assert(destination != indices);
+	assert(index_count % 3 == 0);
+
+	using namespace meshopt;
+
+	meshopt_Allocator allocator;
+
+	const size_t buffer_capacity = 8;
+
+	unsigned int buffer[buffer_capacity][3] = {};
+	unsigned int buffer_size = 0;
+
+	size_t index_offset = 0;
+
+	unsigned int strip[2] = {};
+	unsigned int parity = 0;
+
+	size_t strip_size = 0;
+
+	// compute vertex valence; this is used to prioritize starting triangle for strips
+	unsigned int* valence = allocator.allocate<unsigned int>(vertex_count);
+	memset(valence, 0, vertex_count * sizeof(unsigned int));
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		valence[index]++;
+	}
+
+	int next = -1;
+
+	while (buffer_size > 0 || index_offset < index_count)
+	{
+		assert(next < 0 || (size_t(next >> 2) < buffer_size && (next & 3) < 3));
+
+		// fill triangle buffer
+		while (buffer_size < buffer_capacity && index_offset < index_count)
+		{
+			buffer[buffer_size][0] = indices[index_offset + 0];
+			buffer[buffer_size][1] = indices[index_offset + 1];
+			buffer[buffer_size][2] = indices[index_offset + 2];
+
+			buffer_size++;
+			index_offset += 3;
+		}
+
+		assert(buffer_size > 0);
+
+		if (next >= 0)
+		{
+			unsigned int i = next >> 2;
+			unsigned int a = buffer[i][0], b = buffer[i][1], c = buffer[i][2];
+			unsigned int v = buffer[i][next & 3];
+
+			// ordered removal from the buffer
+			memmove(buffer[i], buffer[i + 1], (buffer_size - i - 1) * sizeof(buffer[0]));
+			buffer_size--;
+
+			// update vertex valences for strip start heuristic
+			valence[a]--;
+			valence[b]--;
+			valence[c]--;
+
+			// find next triangle (note that edge order flips on every iteration)
+			// in some cases we need to perform a swap to pick a different outgoing triangle edge
+			// for [a b c], the default strip edge is [b c], but we might want to use [a c]
+			int cont = findStripNext(buffer, buffer_size, parity ? strip[1] : v, parity ? v : strip[1]);
+			int swap = cont < 0 ? findStripNext(buffer, buffer_size, parity ? v : strip[0], parity ? strip[0] : v) : -1;
+
+			if (cont < 0 && swap >= 0)
+			{
+				// [a b c] => [a b a c]
+				destination[strip_size++] = strip[0];
+				destination[strip_size++] = v;
+
+				// next strip has same winding
+				// ? a b => b a v
+				strip[1] = v;
+
+				next = swap;
+			}
+			else
+			{
+				// emit the next vertex in the strip
+				destination[strip_size++] = v;
+
+				// next strip has flipped winding
+				strip[0] = strip[1];
+				strip[1] = v;
+				parity ^= 1;
+
+				next = cont;
+			}
+		}
+		else
+		{
+			// if we didn't find anything, we need to find the next new triangle
+			// we use a heuristic to maximize the strip length
+			unsigned int i = findStripFirst(buffer, buffer_size, &valence[0]);
+			unsigned int a = buffer[i][0], b = buffer[i][1], c = buffer[i][2];
+
+			// ordered removal from the buffer
+			memmove(buffer[i], buffer[i + 1], (buffer_size - i - 1) * sizeof(buffer[0]));
+			buffer_size--;
+
+			// update vertex valences for strip start heuristic
+			valence[a]--;
+			valence[b]--;
+			valence[c]--;
+
+			// we need to pre-rotate the triangle so that we will find a match in the existing buffer on the next iteration
+			int ea = findStripNext(buffer, buffer_size, c, b);
+			int eb = findStripNext(buffer, buffer_size, a, c);
+			int ec = findStripNext(buffer, buffer_size, b, a);
+
+			// in some cases we can have several matching edges; since we can pick any edge, we pick the one with the smallest
+			// triangle index in the buffer. this reduces the effect of stripification on ACMR and additionally - for unclear
+			// reasons - slightly improves the stripification efficiency
+			int mine = INT_MAX;
+			mine = (ea >= 0 && mine > ea) ? ea : mine;
+			mine = (eb >= 0 && mine > eb) ? eb : mine;
+			mine = (ec >= 0 && mine > ec) ? ec : mine;
+
+			if (ea == mine)
+			{
+				// keep abc
+				next = ea;
+			}
+			else if (eb == mine)
+			{
+				// abc -> bca
+				unsigned int t = a;
+				a = b, b = c, c = t;
+
+				next = eb;
+			}
+			else if (ec == mine)
+			{
+				// abc -> cab
+				unsigned int t = c;
+				c = b, b = a, a = t;
+
+				next = ec;
+			}
+
+			// emit the new strip; we use restart indices
+			if (strip_size)
+				destination[strip_size++] = ~0u;
+
+			destination[strip_size++] = a;
+			destination[strip_size++] = b;
+			destination[strip_size++] = c;
+
+			// new strip always starts with the same edge winding
+			strip[0] = b;
+			strip[1] = c;
+			parity = 1;
+		}
+	}
+
+	return strip_size;
+}
+
+size_t meshopt_stripifyBound(size_t index_count)
+{
+	assert(index_count % 3 == 0);
+
+	// worst case is 1 restart index and 3 indices per triangle
+	return (index_count / 3) * 4;
+}
+
+size_t meshopt_unstripify(unsigned int* destination, const unsigned int* indices, size_t index_count)
+{
+	assert(destination != indices);
+
+	size_t offset = 0;
+	size_t start = 0;
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		if (indices[i] == ~0u)
+		{
+			start = i + 1;
+		}
+		else if (i - start >= 2)
+		{
+			unsigned int a = indices[i - 2], b = indices[i - 1], c = indices[i];
+
+			// flip winding for odd triangles
+			if ((i - start) & 1)
+			{
+				unsigned int t = a;
+				a = b, b = t;
+			}
+
+			// although we use restart indices, strip swaps still produce degenerate triangles, so skip them
+			if (a != b && a != c && b != c)
+			{
+				destination[offset + 0] = a;
+				destination[offset + 1] = b;
+				destination[offset + 2] = c;
+				offset += 3;
+			}
+		}
+	}
+
+	return offset;
+}
+
+size_t meshopt_unstripifyBound(size_t index_count)
+{
+	assert(index_count == 0 || index_count >= 3);
+
+	return (index_count == 0) ? 0 : (index_count - 2) * 3;
+}

+ 73 - 0
3rdparty/meshoptimizer/src/vcacheanalyzer.cpp

@@ -0,0 +1,73 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int primgroup_size)
+{
+	assert(index_count % 3 == 0);
+	assert(cache_size >= 3);
+	assert(warp_size == 0 || warp_size >= 3);
+
+	meshopt_Allocator allocator;
+
+	meshopt_VertexCacheStatistics result = {};
+
+	unsigned int warp_offset = 0;
+	unsigned int primgroup_offset = 0;
+
+	unsigned int* cache_timestamps = allocator.allocate<unsigned int>(vertex_count);
+	memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
+
+	unsigned int timestamp = cache_size + 1;
+
+	for (size_t i = 0; i < index_count; i += 3)
+	{
+		unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
+		assert(a < vertex_count && b < vertex_count && c < vertex_count);
+
+		bool ac = (timestamp - cache_timestamps[a]) > cache_size;
+		bool bc = (timestamp - cache_timestamps[b]) > cache_size;
+		bool cc = (timestamp - cache_timestamps[c]) > cache_size;
+
+		// flush cache if triangle doesn't fit into warp or into the primitive buffer
+		if ((primgroup_size && primgroup_offset == primgroup_size) || (warp_size && warp_offset + ac + bc + cc > warp_size))
+		{
+			result.warps_executed += warp_offset > 0;
+
+			warp_offset = 0;
+			primgroup_offset = 0;
+
+			// reset cache
+			timestamp += cache_size + 1;
+		}
+
+		// update cache and add vertices to warp
+		for (int j = 0; j < 3; ++j)
+		{
+			unsigned int index = indices[i + j];
+
+			if (timestamp - cache_timestamps[index] > cache_size)
+			{
+				cache_timestamps[index] = timestamp++;
+				result.vertices_transformed++;
+				warp_offset++;
+			}
+		}
+
+		primgroup_offset++;
+	}
+
+	size_t unique_vertex_count = 0;
+
+	for (size_t i = 0; i < vertex_count; ++i)
+		unique_vertex_count += cache_timestamps[i] > 0;
+
+	result.warps_executed += warp_offset > 0;
+
+	result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
+	result.atvr = unique_vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(unique_vertex_count);
+
+	return result;
+}

+ 453 - 0
3rdparty/meshoptimizer/src/vcacheoptimizer.cpp

@@ -0,0 +1,453 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+// This work is based on:
+// Tom Forsyth. Linear-Speed Vertex Cache Optimisation. 2006
+// Pedro Sander, Diego Nehab and Joshua Barczak. Fast Triangle Reordering for Vertex Locality and Reduced Overdraw. 2007
+namespace meshopt
+{
+
+const size_t kCacheSizeMax = 16;
+const size_t kValenceMax = 8;
+
+static const float kVertexScoreTableCache[1 + kCacheSizeMax] = {
+    0.f,
+    0.792f, 0.767f, 0.764f, 0.956f, 0.827f, 0.751f, 0.820f, 0.864f, 0.738f, 0.788f, 0.642f, 0.646f, 0.165f, 0.654f, 0.545f, 0.284f};
+
+static const float kVertexScoreTableLive[1 + kValenceMax] = {
+    0.f,
+    0.994f, 0.721f, 0.479f, 0.423f, 0.174f, 0.080f, 0.249f, 0.056f};
+
+struct TriangleAdjacency
+{
+	unsigned int* counts;
+	unsigned int* offsets;
+	unsigned int* data;
+};
+
+static void buildTriangleAdjacency(TriangleAdjacency& adjacency, const unsigned int* indices, size_t index_count, size_t vertex_count, meshopt_Allocator& allocator)
+{
+	size_t face_count = index_count / 3;
+
+	// allocate arrays
+	adjacency.counts = allocator.allocate<unsigned int>(vertex_count);
+	adjacency.offsets = allocator.allocate<unsigned int>(vertex_count);
+	adjacency.data = allocator.allocate<unsigned int>(index_count);
+
+	// fill triangle counts
+	memset(adjacency.counts, 0, vertex_count * sizeof(unsigned int));
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		assert(indices[i] < vertex_count);
+
+		adjacency.counts[indices[i]]++;
+	}
+
+	// fill offset table
+	unsigned int offset = 0;
+
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		adjacency.offsets[i] = offset;
+		offset += adjacency.counts[i];
+	}
+
+	assert(offset == index_count);
+
+	// fill triangle data
+	for (size_t i = 0; i < face_count; ++i)
+	{
+		unsigned int a = indices[i * 3 + 0], b = indices[i * 3 + 1], c = indices[i * 3 + 2];
+
+		adjacency.data[adjacency.offsets[a]++] = unsigned(i);
+		adjacency.data[adjacency.offsets[b]++] = unsigned(i);
+		adjacency.data[adjacency.offsets[c]++] = unsigned(i);
+	}
+
+	// fix offsets that have been disturbed by the previous pass
+	for (size_t i = 0; i < vertex_count; ++i)
+	{
+		assert(adjacency.offsets[i] >= adjacency.counts[i]);
+
+		adjacency.offsets[i] -= adjacency.counts[i];
+	}
+}
+
+static unsigned int getNextVertexDeadEnd(const unsigned int* dead_end, unsigned int& dead_end_top, unsigned int& input_cursor, const unsigned int* live_triangles, size_t vertex_count)
+{
+	// check dead-end stack
+	while (dead_end_top)
+	{
+		unsigned int vertex = dead_end[--dead_end_top];
+
+		if (live_triangles[vertex] > 0)
+			return vertex;
+	}
+
+	// input order
+	while (input_cursor < vertex_count)
+	{
+		if (live_triangles[input_cursor] > 0)
+			return input_cursor;
+
+		++input_cursor;
+	}
+
+	return ~0u;
+}
+
+static unsigned int getNextVertexNeighbour(const unsigned int* next_candidates_begin, const unsigned int* next_candidates_end, const unsigned int* live_triangles, const unsigned int* cache_timestamps, unsigned int timestamp, unsigned int cache_size)
+{
+	unsigned int best_candidate = ~0u;
+	int best_priority = -1;
+
+	for (const unsigned int* next_candidate = next_candidates_begin; next_candidate != next_candidates_end; ++next_candidate)
+	{
+		unsigned int vertex = *next_candidate;
+
+		// otherwise we don't need to process it
+		if (live_triangles[vertex] > 0)
+		{
+			int priority = 0;
+
+			// will it be in cache after fanning?
+			if (2 * live_triangles[vertex] + timestamp - cache_timestamps[vertex] <= cache_size)
+			{
+				priority = timestamp - cache_timestamps[vertex]; // position in cache
+			}
+
+			if (priority > best_priority)
+			{
+				best_candidate = vertex;
+				best_priority = priority;
+			}
+		}
+	}
+
+	return best_candidate;
+}
+
+static float vertexScore(int cache_position, unsigned int live_triangles)
+{
+	assert(cache_position >= -1 && cache_position < int(kCacheSizeMax));
+
+	unsigned int live_triangles_clamped = live_triangles < kValenceMax ? live_triangles : kValenceMax;
+
+	return kVertexScoreTableCache[1 + cache_position] + kVertexScoreTableLive[live_triangles_clamped];
+}
+
+static unsigned int getNextTriangleDeadEnd(unsigned int& input_cursor, const unsigned char* emitted_flags, size_t face_count)
+{
+	// input order
+	while (input_cursor < face_count)
+	{
+		if (!emitted_flags[input_cursor])
+			return input_cursor;
+
+		++input_cursor;
+	}
+
+	return ~0u;
+}
+
+} // namespace meshopt
+
+void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+
+	meshopt_Allocator allocator;
+
+	// guard for empty meshes
+	if (index_count == 0 || vertex_count == 0)
+		return;
+
+	// support in-place optimization
+	if (destination == indices)
+	{
+		unsigned int* indices_copy = allocator.allocate<unsigned int>(index_count);
+		memcpy(indices_copy, indices, index_count * sizeof(unsigned int));
+		indices = indices_copy;
+	}
+
+	unsigned int cache_size = 16;
+	assert(cache_size <= kCacheSizeMax);
+
+	size_t face_count = index_count / 3;
+
+	// build adjacency information
+	TriangleAdjacency adjacency = {};
+	buildTriangleAdjacency(adjacency, indices, index_count, vertex_count, allocator);
+
+	// live triangle counts
+	unsigned int* live_triangles = allocator.allocate<unsigned int>(vertex_count);
+	memcpy(live_triangles, adjacency.counts, vertex_count * sizeof(unsigned int));
+
+	// emitted flags
+	unsigned char* emitted_flags = allocator.allocate<unsigned char>(face_count);
+	memset(emitted_flags, 0, face_count);
+
+	// compute initial vertex scores
+	float* vertex_scores = allocator.allocate<float>(vertex_count);
+
+	for (size_t i = 0; i < vertex_count; ++i)
+		vertex_scores[i] = vertexScore(-1, live_triangles[i]);
+
+	// compute triangle scores
+	float* triangle_scores = allocator.allocate<float>(face_count);
+
+	for (size_t i = 0; i < face_count; ++i)
+	{
+		unsigned int a = indices[i * 3 + 0];
+		unsigned int b = indices[i * 3 + 1];
+		unsigned int c = indices[i * 3 + 2];
+
+		triangle_scores[i] = vertex_scores[a] + vertex_scores[b] + vertex_scores[c];
+	}
+
+	unsigned int cache_holder[2 * (kCacheSizeMax + 3)];
+	unsigned int* cache = cache_holder;
+	unsigned int* cache_new = cache_holder + kCacheSizeMax + 3;
+	size_t cache_count = 0;
+
+	unsigned int current_triangle = 0;
+	unsigned int input_cursor = 1;
+
+	unsigned int output_triangle = 0;
+
+	while (current_triangle != ~0u)
+	{
+		assert(output_triangle < face_count);
+
+		unsigned int a = indices[current_triangle * 3 + 0];
+		unsigned int b = indices[current_triangle * 3 + 1];
+		unsigned int c = indices[current_triangle * 3 + 2];
+
+		// output indices
+		destination[output_triangle * 3 + 0] = a;
+		destination[output_triangle * 3 + 1] = b;
+		destination[output_triangle * 3 + 2] = c;
+		output_triangle++;
+
+		// update emitted flags
+		emitted_flags[current_triangle] = true;
+		triangle_scores[current_triangle] = 0;
+
+		// new triangle
+		size_t cache_write = 0;
+		cache_new[cache_write++] = a;
+		cache_new[cache_write++] = b;
+		cache_new[cache_write++] = c;
+
+		// old triangles
+		for (size_t i = 0; i < cache_count; ++i)
+		{
+			unsigned int index = cache[i];
+
+			if (index != a && index != b && index != c)
+			{
+				cache_new[cache_write++] = index;
+			}
+		}
+
+		unsigned int* cache_temp = cache;
+		cache = cache_new, cache_new = cache_temp;
+		cache_count = cache_write > cache_size ? cache_size : cache_write;
+
+		// update live triangle counts
+		live_triangles[a]--;
+		live_triangles[b]--;
+		live_triangles[c]--;
+
+		// remove emitted triangle from adjacency data
+		// this makes sure that we spend less time traversing these lists on subsequent iterations
+		for (size_t k = 0; k < 3; ++k)
+		{
+			unsigned int index = indices[current_triangle * 3 + k];
+
+			unsigned int* neighbours = &adjacency.data[0] + adjacency.offsets[index];
+			size_t neighbours_size = adjacency.counts[index];
+
+			for (size_t i = 0; i < neighbours_size; ++i)
+			{
+				unsigned int tri = neighbours[i];
+
+				if (tri == current_triangle)
+				{
+					neighbours[i] = neighbours[neighbours_size - 1];
+					adjacency.counts[index]--;
+					break;
+				}
+			}
+		}
+
+		unsigned int best_triangle = ~0u;
+		float best_score = 0;
+
+		// update cache positions, vertex scores and triangle scores, and find next best triangle
+		for (size_t i = 0; i < cache_write; ++i)
+		{
+			unsigned int index = cache[i];
+
+			int cache_position = i >= cache_size ? -1 : int(i);
+
+			// update vertex score
+			float score = vertexScore(cache_position, live_triangles[index]);
+			float score_diff = score - vertex_scores[index];
+
+			vertex_scores[index] = score;
+
+			// update scores of vertex triangles
+			const unsigned int* neighbours_begin = &adjacency.data[0] + adjacency.offsets[index];
+			const unsigned int* neighbours_end = neighbours_begin + adjacency.counts[index];
+
+			for (const unsigned int* it = neighbours_begin; it != neighbours_end; ++it)
+			{
+				unsigned int tri = *it;
+				assert(!emitted_flags[tri]);
+
+				float tri_score = triangle_scores[tri] + score_diff;
+				assert(tri_score > 0);
+
+				if (best_score < tri_score)
+				{
+					best_triangle = tri;
+					best_score = tri_score;
+				}
+
+				triangle_scores[tri] = tri_score;
+			}
+		}
+
+		// step through input triangles in order if we hit a dead-end
+		current_triangle = best_triangle;
+
+		if (current_triangle == ~0u)
+		{
+			current_triangle = getNextTriangleDeadEnd(input_cursor, &emitted_flags[0], face_count);
+		}
+	}
+
+	assert(input_cursor == face_count);
+	assert(output_triangle == face_count);
+}
+
+void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
+{
+	using namespace meshopt;
+
+	assert(index_count % 3 == 0);
+	assert(cache_size >= 3);
+
+	meshopt_Allocator allocator;
+
+	// guard for empty meshes
+	if (index_count == 0 || vertex_count == 0)
+		return;
+
+	// support in-place optimization
+	if (destination == indices)
+	{
+		unsigned int* indices_copy = allocator.allocate<unsigned int>(index_count);
+		memcpy(indices_copy, indices, index_count * sizeof(unsigned int));
+		indices = indices_copy;
+	}
+
+	size_t face_count = index_count / 3;
+
+	// build adjacency information
+	TriangleAdjacency adjacency = {};
+	buildTriangleAdjacency(adjacency, indices, index_count, vertex_count, allocator);
+
+	// live triangle counts
+	unsigned int* live_triangles = allocator.allocate<unsigned int>(vertex_count);
+	memcpy(live_triangles, adjacency.counts, vertex_count * sizeof(unsigned int));
+
+	// cache time stamps
+	unsigned int* cache_timestamps = allocator.allocate<unsigned int>(vertex_count);
+	memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
+
+	// dead-end stack
+	unsigned int* dead_end = allocator.allocate<unsigned int>(index_count);
+	unsigned int dead_end_top = 0;
+
+	// emitted flags
+	unsigned char* emitted_flags = allocator.allocate<unsigned char>(face_count);
+	memset(emitted_flags, 0, face_count);
+
+	unsigned int current_vertex = 0;
+
+	unsigned int timestamp = cache_size + 1;
+	unsigned int input_cursor = 1; // vertex to restart from in case of dead-end
+
+	unsigned int output_triangle = 0;
+
+	while (current_vertex != ~0u)
+	{
+		const unsigned int* next_candidates_begin = &dead_end[0] + dead_end_top;
+
+		// emit all vertex neighbours
+		const unsigned int* neighbours_begin = &adjacency.data[0] + adjacency.offsets[current_vertex];
+		const unsigned int* neighbours_end = neighbours_begin + adjacency.counts[current_vertex];
+
+		for (const unsigned int* it = neighbours_begin; it != neighbours_end; ++it)
+		{
+			unsigned int triangle = *it;
+
+			if (!emitted_flags[triangle])
+			{
+				unsigned int a = indices[triangle * 3 + 0], b = indices[triangle * 3 + 1], c = indices[triangle * 3 + 2];
+
+				// output indices
+				destination[output_triangle * 3 + 0] = a;
+				destination[output_triangle * 3 + 1] = b;
+				destination[output_triangle * 3 + 2] = c;
+				output_triangle++;
+
+				// update dead-end stack
+				dead_end[dead_end_top + 0] = a;
+				dead_end[dead_end_top + 1] = b;
+				dead_end[dead_end_top + 2] = c;
+				dead_end_top += 3;
+
+				// update live triangle counts
+				live_triangles[a]--;
+				live_triangles[b]--;
+				live_triangles[c]--;
+
+				// update cache info
+				// if vertex is not in cache, put it in cache
+				if (timestamp - cache_timestamps[a] > cache_size)
+					cache_timestamps[a] = timestamp++;
+
+				if (timestamp - cache_timestamps[b] > cache_size)
+					cache_timestamps[b] = timestamp++;
+
+				if (timestamp - cache_timestamps[c] > cache_size)
+					cache_timestamps[c] = timestamp++;
+
+				// update emitted flags
+				emitted_flags[triangle] = true;
+			}
+		}
+
+		// next candidates are the ones we pushed to dead-end stack just now
+		const unsigned int* next_candidates_end = &dead_end[0] + dead_end_top;
+
+		// get next vertex
+		current_vertex = getNextVertexNeighbour(next_candidates_begin, next_candidates_end, &live_triangles[0], &cache_timestamps[0], timestamp, cache_size);
+
+		if (current_vertex == ~0u)
+		{
+			current_vertex = getNextVertexDeadEnd(&dead_end[0], dead_end_top, input_cursor, &live_triangles[0], vertex_count);
+		}
+	}
+
+	assert(output_triangle == face_count);
+}

+ 954 - 0
3rdparty/meshoptimizer/src/vertexcodec.cpp

@@ -0,0 +1,954 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+#if defined(__ARM_NEON__) || defined(__ARM_NEON)
+#define SIMD_NEON
+#endif
+
+#if defined(__AVX__) || defined(__SSSE3__)
+#define SIMD_SSE
+#endif
+
+#if !defined(SIMD_SSE) && defined(_MSC_VER) && !defined(__clang__) && (defined(_M_IX86) || defined(_M_X64))
+#define SIMD_SSE
+#define SIMD_FALLBACK
+#include <intrin.h> // __cpuid
+#endif
+
+#if !defined(SIMD_NEON) && defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
+#define SIMD_NEON
+#endif
+
+#ifdef SIMD_SSE
+#include <tmmintrin.h>
+#endif
+
+#ifdef SIMD_NEON
+#if defined(_MSC_VER) && defined(_M_ARM64)
+#include <arm64_neon.h>
+#else
+#include <arm_neon.h>
+#endif
+#endif
+
+#ifndef TRACE
+#define TRACE 0
+#endif
+
+#if TRACE
+#include <stdio.h>
+#endif
+
+namespace meshopt
+{
+
+const unsigned char kVertexHeader = 0xa0;
+
+const size_t kVertexBlockSizeBytes = 8192;
+const size_t kVertexBlockMaxSize = 256;
+const size_t kByteGroupSize = 16;
+const size_t kTailMaxSize = 32;
+
+static size_t getVertexBlockSize(size_t vertex_size)
+{
+	// make sure the entire block fits into the scratch buffer
+	size_t result = kVertexBlockSizeBytes / vertex_size;
+
+	// align to byte group size; we encode each byte as a byte group
+	// if vertex block is misaligned, it results in wasted bytes, so just truncate the block size
+	result &= ~(kByteGroupSize - 1);
+
+	return (result < kVertexBlockMaxSize) ? result : kVertexBlockMaxSize;
+}
+
+inline unsigned char zigzag8(unsigned char v)
+{
+	return ((signed char)(v) >> 7) ^ (v << 1);
+}
+
+inline unsigned char unzigzag8(unsigned char v)
+{
+	return -(v & 1) ^ (v >> 1);
+}
+
+#if TRACE
+struct Stats
+{
+	size_t size;
+	size_t header;
+	size_t bitg[4];
+	size_t bitb[4];
+};
+
+Stats* bytestats;
+Stats vertexstats[256];
+#endif
+
+static bool encodeBytesGroupZero(const unsigned char* buffer)
+{
+	for (size_t i = 0; i < kByteGroupSize; ++i)
+		if (buffer[i])
+			return false;
+
+	return true;
+}
+
+static size_t encodeBytesGroupMeasure(const unsigned char* buffer, int bits)
+{
+	assert(bits >= 1 && bits <= 8);
+
+	if (bits == 1)
+		return encodeBytesGroupZero(buffer) ? 0 : size_t(-1);
+
+	if (bits == 8)
+		return kByteGroupSize;
+
+	size_t result = kByteGroupSize * bits / 8;
+
+	unsigned char sentinel = (1 << bits) - 1;
+
+	for (size_t i = 0; i < kByteGroupSize; ++i)
+		result += buffer[i] >= sentinel;
+
+	return result;
+}
+
+static unsigned char* encodeBytesGroup(unsigned char* data, const unsigned char* buffer, int bits)
+{
+	assert(bits >= 1 && bits <= 8);
+
+	if (bits == 1)
+		return data;
+
+	if (bits == 8)
+	{
+		memcpy(data, buffer, kByteGroupSize);
+		return data + kByteGroupSize;
+	}
+
+	size_t byte_size = 8 / bits;
+	assert(kByteGroupSize % byte_size == 0);
+
+	// fixed portion: bits bits for each value
+	// variable portion: full byte for each out-of-range value (using 1...1 as sentinel)
+	unsigned char sentinel = (1 << bits) - 1;
+
+	for (size_t i = 0; i < kByteGroupSize; i += byte_size)
+	{
+		unsigned char byte = 0;
+
+		for (size_t k = 0; k < byte_size; ++k)
+		{
+			unsigned char enc = (buffer[i + k] >= sentinel) ? sentinel : buffer[i + k];
+
+			byte <<= bits;
+			byte |= enc;
+		}
+
+		*data++ = byte;
+	}
+
+	for (size_t i = 0; i < kByteGroupSize; ++i)
+	{
+		if (buffer[i] >= sentinel)
+		{
+			*data++ = buffer[i];
+		}
+	}
+
+	return data;
+}
+
+static unsigned char* encodeBytes(unsigned char* data, unsigned char* data_end, const unsigned char* buffer, size_t buffer_size)
+{
+	assert(buffer_size % kByteGroupSize == 0);
+
+	unsigned char* header = data;
+
+	// round number of groups to 4 to get number of header bytes
+	size_t header_size = (buffer_size / kByteGroupSize + 3) / 4;
+
+	if (size_t(data_end - data) < header_size)
+		return 0;
+
+	data += header_size;
+
+	memset(header, 0, header_size);
+
+	for (size_t i = 0; i < buffer_size; i += kByteGroupSize)
+	{
+		if (size_t(data_end - data) < kTailMaxSize)
+			return 0;
+
+		int best_bits = 8;
+		size_t best_size = encodeBytesGroupMeasure(buffer + i, 8);
+
+		for (int bits = 1; bits < 8; bits *= 2)
+		{
+			size_t size = encodeBytesGroupMeasure(buffer + i, bits);
+
+			if (size < best_size)
+			{
+				best_bits = bits;
+				best_size = size;
+			}
+		}
+
+		int bitslog2 = (best_bits == 1) ? 0 : (best_bits == 2) ? 1 : (best_bits == 4) ? 2 : 3;
+		assert((1 << bitslog2) == best_bits);
+
+		size_t header_offset = i / kByteGroupSize;
+
+		header[header_offset / 4] |= bitslog2 << ((header_offset % 4) * 2);
+
+		unsigned char* next = encodeBytesGroup(data, buffer + i, best_bits);
+
+		assert(data + best_size == next);
+		data = next;
+
+#if TRACE > 1
+		bytestats->bitg[bitslog2]++;
+		bytestats->bitb[bitslog2] += best_size;
+#endif
+	}
+
+#if TRACE > 1
+	bytestats->header += header_size;
+#endif
+
+	return data;
+}
+
+static unsigned char* encodeVertexBlock(unsigned char* data, unsigned char* data_end, const unsigned char* vertex_data, size_t vertex_count, size_t vertex_size, unsigned char last_vertex[256])
+{
+	assert(vertex_count > 0 && vertex_count <= kVertexBlockMaxSize);
+
+	unsigned char buffer[kVertexBlockMaxSize];
+	assert(sizeof(buffer) % kByteGroupSize == 0);
+
+	// we sometimes encode elements we didn't fill when rounding to kByteGroupSize
+	memset(buffer, 0, sizeof(buffer));
+
+	for (size_t k = 0; k < vertex_size; ++k)
+	{
+		size_t vertex_offset = k;
+
+		unsigned char p = last_vertex[k];
+
+		for (size_t i = 0; i < vertex_count; ++i)
+		{
+			buffer[i] = zigzag8(vertex_data[vertex_offset] - p);
+
+			p = vertex_data[vertex_offset];
+
+			vertex_offset += vertex_size;
+		}
+
+#if TRACE
+		const unsigned char* olddata = data;
+		bytestats = &vertexstats[k];
+#endif
+
+		data = encodeBytes(data, data_end, buffer, (vertex_count + kByteGroupSize - 1) & ~(kByteGroupSize - 1));
+		if (!data)
+			return 0;
+
+#if TRACE
+		bytestats = 0;
+		vertexstats[k].size += data - olddata;
+#endif
+	}
+
+	memcpy(last_vertex, &vertex_data[vertex_size * (vertex_count - 1)], vertex_size);
+
+	return data;
+}
+
+#if defined(SIMD_FALLBACK) || (!defined(SIMD_SSE) && !defined(SIMD_NEON))
+static const unsigned char* decodeBytesGroup(const unsigned char* data, unsigned char* buffer, int bitslog2)
+{
+#define READ() byte = *data++
+#define NEXT(bits) enc = byte >> (8 - bits), byte <<= bits, encv = *data_var, *buffer++ = (enc == (1 << bits) - 1) ? encv : enc, data_var += (enc == (1 << bits) - 1)
+
+	unsigned char byte, enc, encv;
+	const unsigned char* data_var;
+
+	switch (bitslog2)
+	{
+	case 0:
+		memset(buffer, 0, kByteGroupSize);
+		return data;
+	case 1:
+		data_var = data + 4;
+
+		// 4 groups with 4 2-bit values in each byte
+		READ(), NEXT(2), NEXT(2), NEXT(2), NEXT(2);
+		READ(), NEXT(2), NEXT(2), NEXT(2), NEXT(2);
+		READ(), NEXT(2), NEXT(2), NEXT(2), NEXT(2);
+		READ(), NEXT(2), NEXT(2), NEXT(2), NEXT(2);
+
+		return data_var;
+	case 2:
+		data_var = data + 8;
+
+		// 8 groups with 2 4-bit values in each byte
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+		READ(), NEXT(4), NEXT(4);
+
+		return data_var;
+	case 3:
+		memcpy(buffer, data, kByteGroupSize);
+		return data + kByteGroupSize;
+	default:
+		assert(!"Unexpected bit length"); // This can never happen since bitslog2 is a 2-bit value
+		return data;
+	}
+
+#undef READ
+#undef NEXT
+}
+
+static const unsigned char* decodeBytes(const unsigned char* data, const unsigned char* data_end, unsigned char* buffer, size_t buffer_size)
+{
+	assert(buffer_size % kByteGroupSize == 0);
+
+	const unsigned char* header = data;
+
+	// round number of groups to 4 to get number of header bytes
+	size_t header_size = (buffer_size / kByteGroupSize + 3) / 4;
+
+	if (size_t(data_end - data) < header_size)
+		return 0;
+
+	data += header_size;
+
+	for (size_t i = 0; i < buffer_size; i += kByteGroupSize)
+	{
+		if (size_t(data_end - data) < kTailMaxSize)
+			return 0;
+
+		size_t header_offset = i / kByteGroupSize;
+
+		int bitslog2 = (header[header_offset / 4] >> ((header_offset % 4) * 2)) & 3;
+
+		data = decodeBytesGroup(data, buffer + i, bitslog2);
+	}
+
+	return data;
+}
+
+static const unsigned char* decodeVertexBlock(const unsigned char* data, const unsigned char* data_end, unsigned char* vertex_data, size_t vertex_count, size_t vertex_size, unsigned char last_vertex[256])
+{
+	assert(vertex_count > 0 && vertex_count <= kVertexBlockMaxSize);
+
+	unsigned char buffer[kVertexBlockMaxSize];
+	unsigned char transposed[kVertexBlockSizeBytes];
+
+	size_t vertex_count_aligned = (vertex_count + kByteGroupSize - 1) & ~(kByteGroupSize - 1);
+
+	for (size_t k = 0; k < vertex_size; ++k)
+	{
+		data = decodeBytes(data, data_end, buffer, vertex_count_aligned);
+		if (!data)
+			return 0;
+
+		size_t vertex_offset = k;
+
+		unsigned char p = last_vertex[k];
+
+		for (size_t i = 0; i < vertex_count; ++i)
+		{
+			unsigned char v = unzigzag8(buffer[i]) + p;
+
+			transposed[vertex_offset] = v;
+			p = v;
+
+			vertex_offset += vertex_size;
+		}
+	}
+
+	memcpy(vertex_data, transposed, vertex_count * vertex_size);
+
+	memcpy(last_vertex, &transposed[vertex_size * (vertex_count - 1)], vertex_size);
+
+	return data;
+}
+#endif
+
+#if defined(SIMD_SSE) || defined(SIMD_NEON)
+static unsigned char kDecodeBytesGroupShuffle[256][8];
+static unsigned char kDecodeBytesGroupCount[256];
+
+static bool decodeBytesGroupBuildTables()
+{
+	for (int mask = 0; mask < 256; ++mask)
+	{
+		unsigned char shuffle[8];
+		unsigned char count = 0;
+
+		for (int i = 0; i < 8; ++i)
+		{
+			int maski = (mask >> i) & 1;
+			shuffle[i] = maski ? count : 0x80;
+			count += (unsigned char)(maski);
+		}
+
+		memcpy(kDecodeBytesGroupShuffle[mask], shuffle, 8);
+		kDecodeBytesGroupCount[mask] = count;
+	}
+
+	return true;
+}
+
+static bool gDecodeBytesGroupInitialized = decodeBytesGroupBuildTables();
+#endif
+
+#ifdef SIMD_SSE
+static __m128i decodeShuffleMask(unsigned char mask0, unsigned char mask1)
+{
+	__m128i sm0 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&kDecodeBytesGroupShuffle[mask0]));
+	__m128i sm1 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&kDecodeBytesGroupShuffle[mask1]));
+	__m128i sm1off = _mm_set1_epi8(kDecodeBytesGroupCount[mask0]);
+
+	__m128i sm1r = _mm_add_epi8(sm1, sm1off);
+
+	return _mm_unpacklo_epi64(sm0, sm1r);
+}
+
+static void transpose8(__m128i& x0, __m128i& x1, __m128i& x2, __m128i& x3)
+{
+	__m128i t0 = _mm_unpacklo_epi8(x0, x1);
+	__m128i t1 = _mm_unpackhi_epi8(x0, x1);
+	__m128i t2 = _mm_unpacklo_epi8(x2, x3);
+	__m128i t3 = _mm_unpackhi_epi8(x2, x3);
+
+	x0 = _mm_unpacklo_epi16(t0, t2);
+	x1 = _mm_unpackhi_epi16(t0, t2);
+	x2 = _mm_unpacklo_epi16(t1, t3);
+	x3 = _mm_unpackhi_epi16(t1, t3);
+}
+
+static __m128i unzigzag8(__m128i v)
+{
+	__m128i xl = _mm_sub_epi8(_mm_setzero_si128(), _mm_and_si128(v, _mm_set1_epi8(1)));
+	__m128i xr = _mm_and_si128(_mm_srli_epi16(v, 1), _mm_set1_epi8(127));
+
+	return _mm_xor_si128(xl, xr);
+}
+
+static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsigned char* buffer, int bitslog2)
+{
+	switch (bitslog2)
+	{
+	case 0:
+	{
+		__m128i result = _mm_setzero_si128();
+
+		_mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result);
+
+		return data;
+	}
+
+	case 1:
+	{
+#ifdef __GNUC__
+		typedef int __attribute__((aligned(1))) unaligned_int;
+#else
+		typedef int unaligned_int;
+#endif
+
+		__m128i sel2 = _mm_cvtsi32_si128(*reinterpret_cast<const unaligned_int*>(data));
+		__m128i rest = _mm_loadu_si128(reinterpret_cast<const __m128i*>(data + 4));
+
+		__m128i sel22 = _mm_unpacklo_epi8(_mm_srli_epi16(sel2, 4), sel2);
+		__m128i sel2222 = _mm_unpacklo_epi8(_mm_srli_epi16(sel22, 2), sel22);
+		__m128i sel = _mm_and_si128(sel2222, _mm_set1_epi8(3));
+
+		__m128i mask = _mm_cmpeq_epi8(sel, _mm_set1_epi8(3));
+		int mask16 = _mm_movemask_epi8(mask);
+		unsigned char mask0 = (unsigned char)(mask16 & 255);
+		unsigned char mask1 = (unsigned char)(mask16 >> 8);
+
+		__m128i shuf = decodeShuffleMask(mask0, mask1);
+
+		__m128i result = _mm_or_si128(_mm_shuffle_epi8(rest, shuf), _mm_andnot_si128(mask, sel));
+
+		_mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result);
+
+		return data + 4 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1];
+	}
+
+	case 2:
+	{
+		__m128i sel4 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(data));
+		__m128i rest = _mm_loadu_si128(reinterpret_cast<const __m128i*>(data + 8));
+
+		__m128i sel44 = _mm_unpacklo_epi8(_mm_srli_epi16(sel4, 4), sel4);
+		__m128i sel = _mm_and_si128(sel44, _mm_set1_epi8(15));
+
+		__m128i mask = _mm_cmpeq_epi8(sel, _mm_set1_epi8(15));
+		int mask16 = _mm_movemask_epi8(mask);
+		unsigned char mask0 = (unsigned char)(mask16 & 255);
+		unsigned char mask1 = (unsigned char)(mask16 >> 8);
+
+		__m128i shuf = decodeShuffleMask(mask0, mask1);
+
+		__m128i result = _mm_or_si128(_mm_shuffle_epi8(rest, shuf), _mm_andnot_si128(mask, sel));
+
+		_mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result);
+
+		return data + 8 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1];
+	}
+
+	case 3:
+	{
+		__m128i rest = _mm_loadu_si128(reinterpret_cast<const __m128i*>(data));
+
+		__m128i result = rest;
+
+		_mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result);
+
+		return data + 16;
+	}
+
+	default:
+		assert(!"Unexpected bit length"); // This can never happen since bitslog2 is a 2-bit value
+		return data;
+	}
+}
+#endif
+
+#ifdef SIMD_NEON
+static uint8x16_t shuffleBytes(unsigned char mask0, unsigned char mask1, uint8x8_t rest0, uint8x8_t rest1)
+{
+	uint8x8_t sm0 = vld1_u8(kDecodeBytesGroupShuffle[mask0]);
+	uint8x8_t sm1 = vld1_u8(kDecodeBytesGroupShuffle[mask1]);
+
+	uint8x8_t r0 = vtbl1_u8(rest0, sm0);
+	uint8x8_t r1 = vtbl1_u8(rest1, sm1);
+
+	return vcombine_u8(r0, r1);
+}
+
+static void neonMoveMask(uint8x16_t mask, unsigned char& mask0, unsigned char& mask1)
+{
+	static const unsigned char byte_mask_data[16] = {1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128};
+
+	uint8x16_t byte_mask = vld1q_u8(byte_mask_data);
+	uint8x16_t masked = vandq_u8(mask, byte_mask);
+
+#ifdef __aarch64__
+	// aarch64 has horizontal sums; MSVC doesn't expose this via arm64_neon.h so this path is exclusive to clang/gcc
+	mask0 = vaddv_u8(vget_low_u8(masked));
+	mask1 = vaddv_u8(vget_high_u8(masked));
+#else
+	// we need horizontal sums of each half of masked, which can be done in 3 steps (yielding sums of sizes 2, 4, 8)
+	uint8x8_t sum1 = vpadd_u8(vget_low_u8(masked), vget_high_u8(masked));
+	uint8x8_t sum2 = vpadd_u8(sum1, sum1);
+	uint8x8_t sum3 = vpadd_u8(sum2, sum2);
+
+	mask0 = vget_lane_u8(sum3, 0);
+	mask1 = vget_lane_u8(sum3, 1);
+#endif
+}
+
+static void transpose8(uint8x16_t& x0, uint8x16_t& x1, uint8x16_t& x2, uint8x16_t& x3)
+{
+	uint8x16x2_t t01 = vzipq_u8(x0, x1);
+	uint8x16x2_t t23 = vzipq_u8(x2, x3);
+
+	uint16x8x2_t x01 = vzipq_u16(vreinterpretq_u16_u8(t01.val[0]), vreinterpretq_u16_u8(t23.val[0]));
+	uint16x8x2_t x23 = vzipq_u16(vreinterpretq_u16_u8(t01.val[1]), vreinterpretq_u16_u8(t23.val[1]));
+
+	x0 = vreinterpretq_u8_u16(x01.val[0]);
+	x1 = vreinterpretq_u8_u16(x01.val[1]);
+	x2 = vreinterpretq_u8_u16(x23.val[0]);
+	x3 = vreinterpretq_u8_u16(x23.val[1]);
+}
+
+static uint8x16_t unzigzag8(uint8x16_t v)
+{
+	uint8x16_t xl = vreinterpretq_u8_s8(vnegq_s8(vreinterpretq_s8_u8(vandq_u8(v, vdupq_n_u8(1)))));
+	uint8x16_t xr = vshrq_n_u8(v, 1);
+
+	return veorq_u8(xl, xr);
+}
+
+static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsigned char* buffer, int bitslog2)
+{
+	switch (bitslog2)
+	{
+	case 0:
+	{
+		uint8x16_t result = vdupq_n_u8(0);
+
+		vst1q_u8(buffer, result);
+
+		return data;
+	}
+
+	case 1:
+	{
+		uint8x8_t sel2 = vld1_u8(data);
+		uint8x8_t sel22 = vzip_u8(vshr_n_u8(sel2, 4), sel2).val[0];
+		uint8x8x2_t sel2222 = vzip_u8(vshr_n_u8(sel22, 2), sel22);
+		uint8x16_t sel = vandq_u8(vcombine_u8(sel2222.val[0], sel2222.val[1]), vdupq_n_u8(3));
+
+		uint8x16_t mask = vceqq_u8(sel, vdupq_n_u8(3));
+		unsigned char mask0, mask1;
+		neonMoveMask(mask, mask0, mask1);
+
+		uint8x8_t rest0 = vld1_u8(data + 4);
+		uint8x8_t rest1 = vld1_u8(data + 4 + kDecodeBytesGroupCount[mask0]);
+
+		uint8x16_t result = vbslq_u8(mask, shuffleBytes(mask0, mask1, rest0, rest1), sel);
+
+		vst1q_u8(buffer, result);
+
+		return data + 4 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1];
+	}
+
+	case 2:
+	{
+		uint8x8_t sel4 = vld1_u8(data);
+		uint8x8x2_t sel44 = vzip_u8(vshr_n_u8(sel4, 4), vand_u8(sel4, vdup_n_u8(15)));
+		uint8x16_t sel = vcombine_u8(sel44.val[0], sel44.val[1]);
+
+		uint8x16_t mask = vceqq_u8(sel, vdupq_n_u8(15));
+		unsigned char mask0, mask1;
+		neonMoveMask(mask, mask0, mask1);
+
+		uint8x8_t rest0 = vld1_u8(data + 8);
+		uint8x8_t rest1 = vld1_u8(data + 8 + kDecodeBytesGroupCount[mask0]);
+
+		uint8x16_t result = vbslq_u8(mask, shuffleBytes(mask0, mask1, rest0, rest1), sel);
+
+		vst1q_u8(buffer, result);
+
+		return data + 8 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1];
+	}
+
+	case 3:
+	{
+		uint8x16_t rest = vld1q_u8(data);
+
+		uint8x16_t result = rest;
+
+		vst1q_u8(buffer, result);
+
+		return data + 16;
+	}
+
+	default:
+		assert(!"Unexpected bit length"); // This can never happen since bitslog2 is a 2-bit value
+		return data;
+	}
+}
+#endif
+
+#if defined(SIMD_SSE) || defined(SIMD_NEON)
+static const unsigned char* decodeBytesSimd(const unsigned char* data, const unsigned char* data_end, unsigned char* buffer, size_t buffer_size)
+{
+	assert(buffer_size % kByteGroupSize == 0);
+	assert(kByteGroupSize == 16);
+
+	const unsigned char* header = data;
+
+	// round number of groups to 4 to get number of header bytes
+	size_t header_size = (buffer_size / kByteGroupSize + 3) / 4;
+
+	if (size_t(data_end - data) < header_size)
+		return 0;
+
+	data += header_size;
+
+	size_t i = 0;
+
+	// fast-path: process 4 groups at a time, do a shared bounds check - each group reads <=32b
+	for (; i + kByteGroupSize * 4 <= buffer_size && size_t(data_end - data) >= kTailMaxSize * 4; i += kByteGroupSize * 4)
+	{
+		size_t header_offset = i / kByteGroupSize;
+		unsigned char header_byte = header[header_offset / 4];
+
+		data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 0, (header_byte >> 0) & 3);
+		data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 1, (header_byte >> 2) & 3);
+		data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 2, (header_byte >> 4) & 3);
+		data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 3, (header_byte >> 6) & 3);
+	}
+
+	// slow-path: process remaining groups
+	for (; i < buffer_size; i += kByteGroupSize)
+	{
+		if (size_t(data_end - data) < kTailMaxSize)
+			return 0;
+
+		size_t header_offset = i / kByteGroupSize;
+
+		int bitslog2 = (header[header_offset / 4] >> ((header_offset % 4) * 2)) & 3;
+
+		data = decodeBytesGroupSimd(data, buffer + i, bitslog2);
+	}
+
+	return data;
+}
+
+static const unsigned char* decodeVertexBlockSimd(const unsigned char* data, const unsigned char* data_end, unsigned char* vertex_data, size_t vertex_count, size_t vertex_size, unsigned char last_vertex[256])
+{
+	assert(vertex_count > 0 && vertex_count <= kVertexBlockMaxSize);
+
+	unsigned char buffer[kVertexBlockMaxSize * 4];
+	unsigned char transposed[kVertexBlockSizeBytes];
+
+	size_t vertex_count_aligned = (vertex_count + kByteGroupSize - 1) & ~(kByteGroupSize - 1);
+
+	for (size_t k = 0; k < vertex_size; k += 4)
+	{
+		for (size_t j = 0; j < 4; ++j)
+		{
+			data = decodeBytesSimd(data, data_end, buffer + j * vertex_count_aligned, vertex_count_aligned);
+			if (!data)
+				return 0;
+		}
+
+#ifdef SIMD_SSE
+#define TEMP __m128i
+#define PREP() __m128i pi = _mm_cvtsi32_si128(*reinterpret_cast<const int*>(last_vertex + k))
+#define LOAD(i) __m128i r##i = _mm_loadu_si128(reinterpret_cast<const __m128i*>(buffer + j + i * vertex_count_aligned))
+#define GRP4(i) t0 = _mm_shuffle_epi32(r##i, 0), t1 = _mm_shuffle_epi32(r##i, 1), t2 = _mm_shuffle_epi32(r##i, 2), t3 = _mm_shuffle_epi32(r##i, 3)
+#define FIXD(i) t##i = pi = _mm_add_epi8(pi, t##i)
+#define SAVE(i) *reinterpret_cast<int*>(savep) = _mm_cvtsi128_si32(t##i), savep += vertex_size
+#endif
+
+#ifdef SIMD_NEON
+#define TEMP uint8x8_t
+#define PREP() uint8x8_t pi = vreinterpret_u8_u32(vld1_lane_u32(reinterpret_cast<uint32_t*>(last_vertex + k), vdup_n_u32(0), 0))
+#define LOAD(i) uint8x16_t r##i = vld1q_u8(buffer + j + i * vertex_count_aligned)
+#define GRP4(i) t0 = vget_low_u8(r##i), t1 = vreinterpret_u8_u32(vdup_lane_u32(vreinterpret_u32_u8(t0), 1)), t2 = vget_high_u8(r##i), t3 = vreinterpret_u8_u32(vdup_lane_u32(vreinterpret_u32_u8(t2), 1))
+#define FIXD(i) t##i = pi = vadd_u8(pi, t##i)
+#define SAVE(i) vst1_lane_u32(reinterpret_cast<uint32_t*>(savep), vreinterpret_u32_u8(t##i), 0), savep += vertex_size
+#endif
+
+		PREP();
+
+		unsigned char* savep = transposed + k;
+
+		for (size_t j = 0; j < vertex_count_aligned; j += 16)
+		{
+			LOAD(0);
+			LOAD(1);
+			LOAD(2);
+			LOAD(3);
+
+			r0 = unzigzag8(r0);
+			r1 = unzigzag8(r1);
+			r2 = unzigzag8(r2);
+			r3 = unzigzag8(r3);
+
+			transpose8(r0, r1, r2, r3);
+
+			TEMP t0, t1, t2, t3;
+
+			GRP4(0);
+			FIXD(0), FIXD(1), FIXD(2), FIXD(3);
+			SAVE(0), SAVE(1), SAVE(2), SAVE(3);
+
+			GRP4(1);
+			FIXD(0), FIXD(1), FIXD(2), FIXD(3);
+			SAVE(0), SAVE(1), SAVE(2), SAVE(3);
+
+			GRP4(2);
+			FIXD(0), FIXD(1), FIXD(2), FIXD(3);
+			SAVE(0), SAVE(1), SAVE(2), SAVE(3);
+
+			GRP4(3);
+			FIXD(0), FIXD(1), FIXD(2), FIXD(3);
+			SAVE(0), SAVE(1), SAVE(2), SAVE(3);
+
+#undef TEMP
+#undef PREP
+#undef LOAD
+#undef GRP4
+#undef FIXD
+#undef SAVE
+		}
+	}
+
+	memcpy(vertex_data, transposed, vertex_count * vertex_size);
+
+	memcpy(last_vertex, &transposed[vertex_size * (vertex_count - 1)], vertex_size);
+
+	return data;
+}
+#endif
+
+} // namespace meshopt
+
+size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, const void* vertices, size_t vertex_count, size_t vertex_size)
+{
+	using namespace meshopt;
+
+	assert(vertex_size > 0 && vertex_size <= 256);
+	assert(vertex_size % 4 == 0);
+
+#if TRACE
+	memset(vertexstats, 0, sizeof(vertexstats));
+#endif
+
+	const unsigned char* vertex_data = static_cast<const unsigned char*>(vertices);
+
+	unsigned char* data = buffer;
+	unsigned char* data_end = buffer + buffer_size;
+
+	if (size_t(data_end - data) < 1 + vertex_size)
+		return 0;
+
+	*data++ = kVertexHeader;
+
+	unsigned char last_vertex[256] = {};
+	if (vertex_count > 0)
+		memcpy(last_vertex, vertex_data, vertex_size);
+
+	size_t vertex_block_size = getVertexBlockSize(vertex_size);
+
+	size_t vertex_offset = 0;
+
+	while (vertex_offset < vertex_count)
+	{
+		size_t block_size = (vertex_offset + vertex_block_size < vertex_count) ? vertex_block_size : vertex_count - vertex_offset;
+
+		data = encodeVertexBlock(data, data_end, vertex_data + vertex_offset * vertex_size, block_size, vertex_size, last_vertex);
+		if (!data)
+			return 0;
+
+		vertex_offset += block_size;
+	}
+
+	size_t tail_size = vertex_size < kTailMaxSize ? kTailMaxSize : vertex_size;
+
+	if (size_t(data_end - data) < tail_size)
+		return 0;
+
+	// write first vertex to the end of the stream and pad it to 32 bytes; this is important to simplify bounds checks in decoder
+	if (vertex_size < kTailMaxSize)
+	{
+		memset(data, 0, kTailMaxSize - vertex_size);
+		data += kTailMaxSize - vertex_size;
+	}
+
+	memcpy(data, vertex_data, vertex_size);
+	data += vertex_size;
+
+	assert(data >= buffer + tail_size);
+	assert(data <= buffer + buffer_size);
+
+#if TRACE
+	size_t total_size = data - buffer;
+
+	for (size_t k = 0; k < vertex_size; ++k)
+	{
+		const Stats& vsk = vertexstats[k];
+
+		printf("%2d: %d bytes\t%.1f%%\t%.1f bpv", int(k), int(vsk.size), double(vsk.size) / double(total_size) * 100, double(vsk.size) / double(vertex_count) * 8);
+
+#if TRACE > 1
+		printf("\t\thdr %d bytes\tbit0 %d (%d bytes)\tbit1 %d (%d bytes)\tbit2 %d (%d bytes)\tbit3 %d (%d bytes)",
+		       int(vsk.header),
+		       int(vsk.bitg[0]), int(vsk.bitb[0]),
+		       int(vsk.bitg[1]), int(vsk.bitb[1]),
+		       int(vsk.bitg[2]), int(vsk.bitb[2]),
+		       int(vsk.bitg[3]), int(vsk.bitb[3]));
+#endif
+
+		printf("\n");
+	}
+#endif
+
+	return data - buffer;
+}
+
+size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size)
+{
+	using namespace meshopt;
+
+	assert(vertex_size > 0 && vertex_size <= 256);
+	assert(vertex_size % 4 == 0);
+
+	size_t vertex_block_size = getVertexBlockSize(vertex_size);
+	size_t vertex_block_count = (vertex_count + vertex_block_size - 1) / vertex_block_size;
+
+	size_t vertex_block_header_size = (vertex_block_size / kByteGroupSize + 3) / 4;
+	size_t vertex_block_data_size = vertex_block_size;
+
+	size_t tail_size = vertex_size < kTailMaxSize ? kTailMaxSize : vertex_size;
+
+	return 1 + vertex_block_count * vertex_size * (vertex_block_header_size + vertex_block_data_size) + tail_size;
+}
+
+int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t vertex_size, const unsigned char* buffer, size_t buffer_size)
+{
+	using namespace meshopt;
+
+	assert(vertex_size > 0 && vertex_size <= 256);
+	assert(vertex_size % 4 == 0);
+
+	const unsigned char* (*decode)(const unsigned char*, const unsigned char*, unsigned char*, size_t, size_t, unsigned char[256]) = 0;
+
+#if defined(SIMD_SSE) && defined(SIMD_FALLBACK)
+	int cpuinfo[4] = {};
+	__cpuid(cpuinfo, 1);
+	decode = (cpuinfo[2] & (1 << 9)) ? decodeVertexBlockSimd : decodeVertexBlock;
+#elif defined(SIMD_SSE) || defined(SIMD_NEON)
+	decode = decodeVertexBlockSimd;
+#else
+	decode = decodeVertexBlock;
+#endif
+
+#if defined(SIMD_SSE) || defined(SIMD_NEON)
+	assert(gDecodeBytesGroupInitialized);
+#endif
+
+	unsigned char* vertex_data = static_cast<unsigned char*>(destination);
+
+	const unsigned char* data = buffer;
+	const unsigned char* data_end = buffer + buffer_size;
+
+	if (size_t(data_end - data) < 1 + vertex_size)
+		return -2;
+
+	if (*data++ != kVertexHeader)
+		return -1;
+
+	unsigned char last_vertex[256];
+	memcpy(last_vertex, data_end - vertex_size, vertex_size);
+
+	size_t vertex_block_size = getVertexBlockSize(vertex_size);
+
+	size_t vertex_offset = 0;
+
+	while (vertex_offset < vertex_count)
+	{
+		size_t block_size = (vertex_offset + vertex_block_size < vertex_count) ? vertex_block_size : vertex_count - vertex_offset;
+
+		data = decode(data, data_end, vertex_data + vertex_offset * vertex_size, block_size, vertex_size, last_vertex);
+		if (!data)
+			return -2;
+
+		vertex_offset += block_size;
+	}
+
+	size_t tail_size = vertex_size < kTailMaxSize ? kTailMaxSize : vertex_size;
+
+	if (size_t(data_end - data) != tail_size)
+		return -3;
+
+	return 0;
+}

+ 58 - 0
3rdparty/meshoptimizer/src/vfetchanalyzer.cpp

@@ -0,0 +1,58 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const unsigned int* indices, size_t index_count, size_t vertex_count, size_t vertex_size)
+{
+	assert(index_count % 3 == 0);
+	assert(vertex_size > 0 && vertex_size <= 256);
+
+	meshopt_Allocator allocator;
+
+	meshopt_VertexFetchStatistics result = {};
+
+	unsigned char* vertex_visited = allocator.allocate<unsigned char>(vertex_count);
+	memset(vertex_visited, 0, vertex_count);
+
+	const size_t kCacheLine = 64;
+	const size_t kCacheSize = 128 * 1024;
+
+	// simple direct mapped cache; on typical mesh data this is close to 4-way cache, and this model is a gross approximation anyway
+	size_t cache[kCacheSize / kCacheLine] = {};
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		vertex_visited[index] = 1;
+
+		size_t start_address = index * vertex_size;
+		size_t end_address = start_address + vertex_size;
+
+		size_t start_tag = start_address / kCacheLine;
+		size_t end_tag = (end_address + kCacheLine - 1) / kCacheLine;
+
+		assert(start_tag < end_tag);
+
+		for (size_t tag = start_tag; tag < end_tag; ++tag)
+		{
+			size_t line = tag % (sizeof(cache) / sizeof(cache[0]));
+
+			// we store +1 since cache is filled with 0 by default
+			result.bytes_fetched += (cache[line] != tag + 1) * kCacheLine;
+			cache[line] = tag + 1;
+		}
+	}
+
+	size_t unique_vertex_count = 0;
+
+	for (size_t i = 0; i < vertex_count; ++i)
+		unique_vertex_count += vertex_visited[i];
+
+	result.overfetch = unique_vertex_count == 0 ? 0 : float(result.bytes_fetched) / float(unique_vertex_count * vertex_size);
+
+	return result;
+}

+ 74 - 0
3rdparty/meshoptimizer/src/vfetchoptimizer.cpp

@@ -0,0 +1,74 @@
+// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
+#include "meshoptimizer.h"
+
+#include <assert.h>
+#include <string.h>
+
+size_t meshopt_optimizeVertexFetchRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count)
+{
+	assert(index_count % 3 == 0);
+
+	memset(destination, -1, vertex_count * sizeof(unsigned int));
+
+	unsigned int next_vertex = 0;
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		if (destination[index] == ~0u)
+		{
+			destination[index] = next_vertex++;
+		}
+	}
+
+	assert(next_vertex <= vertex_count);
+
+	return next_vertex;
+}
+
+size_t meshopt_optimizeVertexFetch(void* destination, unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
+{
+	assert(index_count % 3 == 0);
+	assert(vertex_size > 0 && vertex_size <= 256);
+
+	meshopt_Allocator allocator;
+
+	// support in-place optimization
+	if (destination == vertices)
+	{
+		unsigned char* vertices_copy = allocator.allocate<unsigned char>(vertex_count * vertex_size);
+		memcpy(vertices_copy, vertices, vertex_count * vertex_size);
+		vertices = vertices_copy;
+	}
+
+	// build vertex remap table
+	unsigned int* vertex_remap = allocator.allocate<unsigned int>(vertex_count);
+	memset(vertex_remap, -1, vertex_count * sizeof(unsigned int));
+
+	unsigned int next_vertex = 0;
+
+	for (size_t i = 0; i < index_count; ++i)
+	{
+		unsigned int index = indices[i];
+		assert(index < vertex_count);
+
+		unsigned int& remap = vertex_remap[index];
+
+		if (remap == ~0u) // vertex was not added to destination VB
+		{
+			// add vertex
+			memcpy(static_cast<unsigned char*>(destination) + next_vertex * vertex_size, static_cast<const unsigned char*>(vertices) + index * vertex_size, vertex_size);
+
+			remap = next_vertex++;
+		}
+
+		// modify indices in place
+		indices[i] = remap;
+	}
+
+	assert(next_vertex <= vertex_count);
+
+	return next_vertex;
+}

+ 179 - 0
3rdparty/meshoptimizer/tools/OptMeshLoader.js

@@ -0,0 +1,179 @@
+THREE.OptMeshLoader = (function ()
+{
+	function OptMeshLoader(manager)
+	{
+		this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
+		this.materials = Promise.resolve(null);
+	}
+
+	OptMeshLoader.prototype =
+	{
+		constructor: OptMeshLoader,
+
+		load: function (url, onLoad, onProgress, onError)
+		{
+			var scope = this;
+
+			var loader = new THREE.FileLoader(scope.manager);
+			loader.setResponseType('arraybuffer');
+			loader.setPath(this.path);
+			loader.load(url, function (data)
+			{
+				scope.decoder.ready.then(function ()
+				{
+					scope.materials.then(function (materials)
+					{
+						onLoad(scope.parse(data, materials));
+					});
+				});
+			}, onProgress, onError);
+		},
+
+		setDecoder: function (value)
+		{
+			this.decoder = value;
+			return this;
+
+		},
+
+		setPath: function (value)
+		{
+			this.path = value;
+			return this;
+		},
+
+		setMaterials: function (materials)
+		{
+			this.materials = Promise.resolve(materials);
+			return this;
+		},
+
+		setMaterialLib: function (lib)
+		{
+			var scope = this;
+
+			this.materials = new Promise(function (resolve, reject)
+			{
+				var loader = new THREE.MTLLoader();
+				loader.setPath(scope.path);
+				loader.load(lib, function (materials) { materials.preload(); resolve(materials); }, null, reject);
+			});
+
+			return this;
+		},
+
+		parse: function (data, materials)
+		{
+			console.time('OptMeshLoader');
+
+			var array = new Uint8Array(data);
+			var view = new DataView(data);
+
+			var endian = true;
+			var magic = view.getUint32(0, endian);
+			var objectCount = view.getUint32(4, endian);
+			var vertexCount = view.getUint32(8, endian);
+			var indexCount = view.getUint32(12, endian);
+			var vertexDataSize = view.getUint32(16, endian);
+			var indexDataSize = view.getUint32(20, endian);
+			var posOffsetX = view.getFloat32(24, endian);
+			var posOffsetY = view.getFloat32(28, endian);
+			var posOffsetZ = view.getFloat32(32, endian);
+			var posScale = view.getFloat32(36, endian);
+			var uvOffsetX = view.getFloat32(40, endian);
+			var uvOffsetY = view.getFloat32(44, endian);
+			var uvScaleX = view.getFloat32(48, endian);
+			var uvScaleY = view.getFloat32(52, endian);
+
+			if (magic != 0x4D54504F)
+				throw new Error("Malformed mesh file: unrecognized header");
+
+			var objectOffset = 64;
+			var objectDataOffset = objectOffset + 16 * objectCount;
+
+			var objectDataSize = 0;
+
+			for (var i = 0; i < objectCount; ++i)
+				objectDataSize += view.getUint32(objectOffset + 16 * i + 8, endian);
+
+			var vertexDataOffset = objectDataOffset + objectDataSize;
+			var indexDataOffset = vertexDataOffset + vertexDataSize;
+
+			var endOffset = indexDataOffset + indexDataSize;
+
+			if (endOffset != data.byteLength)
+				throw new Error("Malformed mesh file: unexpected input size");
+
+			var vertexSize = 16;
+			var indexSize = 4;
+
+			var vertexBuffer = new ArrayBuffer(vertexCount * vertexSize);
+			var vertexBufferU8 = new Uint8Array(vertexBuffer);
+			this.decoder.decodeVertexBuffer(vertexBufferU8, vertexCount, vertexSize, array.subarray(vertexDataOffset, vertexDataOffset + vertexDataSize));
+
+			var indexBuffer = new ArrayBuffer(indexCount * indexSize);
+			var indexBufferU8 = new Uint8Array(indexBuffer);
+			this.decoder.decodeIndexBuffer(indexBufferU8, indexCount, indexSize, array.subarray(indexDataOffset, indexDataOffset + indexDataSize));
+
+			var geometry = new THREE.BufferGeometry();
+
+			geometry.addAttribute('position', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Uint16Array(vertexBuffer), 8), 3, 0, false));
+			geometry.addAttribute('normal', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Int8Array(vertexBuffer), 16), 3, 8, true));
+			geometry.addAttribute('uv', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Uint16Array(vertexBuffer), 8), 2, 6, false));
+			geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(indexBuffer), 1, false));
+
+			var objectDataOffsetAcc = objectDataOffset;
+
+			var objectMaterials = [];
+			var objectMaterialsLookup = {};
+
+			for (var i = 0; i < objectCount; i++)
+			{
+				var objectIndexOffset = view.getUint32(objectOffset + 16 * i + 0, endian);
+				var objectIndexCount = view.getUint32(objectOffset + 16 * i + 4, endian);
+				var objectMaterialLength = view.getUint32(objectOffset + 16 * i + 8, endian);
+
+				var objectMaterialName = String.fromCharCode.apply(null, array.subarray(objectDataOffsetAcc, objectDataOffsetAcc + objectMaterialLength));
+				var objectMaterialIndex = objectMaterialsLookup[objectMaterialName];
+
+				if (objectMaterialIndex == undefined)
+				{
+					var objectMaterial = null;
+
+					if (materials !== null)
+						objectMaterial = materials.create(objectMaterialName);
+
+					if (!objectMaterial)
+						objectMaterial = new THREE.MeshPhongMaterial();
+
+					if (objectMaterial.map)
+					{
+						objectMaterial.map.offset.set(uvOffsetX, uvOffsetY);
+						objectMaterial.map.repeat.set(uvScaleX, uvScaleY);
+					}
+
+					objectMaterialIndex = objectMaterials.length;
+					objectMaterialsLookup[objectMaterialName] = objectMaterialIndex;
+					objectMaterials.push(objectMaterial);
+				}
+
+				geometry.addGroup(objectIndexOffset, objectIndexCount, objectMaterialIndex);
+
+				objectDataOffsetAcc += objectMaterialLength;
+			}
+
+			var mesh = new THREE.Mesh(geometry, objectMaterials);
+			mesh.position.set(posOffsetX, posOffsetY, posOffsetZ);
+			mesh.scale.set(posScale, posScale, posScale);
+
+			var container = new THREE.Group();
+			container.add(mesh);
+
+			console.timeEnd('OptMeshLoader');
+
+			return container;
+		}
+	};
+
+	return OptMeshLoader;
+})();

+ 630 - 0
3rdparty/meshoptimizer/tools/lodviewer.cpp

@@ -0,0 +1,630 @@
+#define _CRT_SECURE_NO_WARNINGS
+
+#include "../src/meshoptimizer.h"
+#include "objparser.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <ctime>
+#include <vector>
+
+#include <GLFW/glfw3.h>
+
+#ifdef GLTF
+#define CGLTF_IMPLEMENTATION
+#include "cgltf.h"
+#endif
+
+#ifdef _WIN32
+#pragma comment(lib, "opengl32.lib")
+#endif
+
+extern unsigned char* meshopt_simplifyDebugKind;
+extern unsigned int* meshopt_simplifyDebugLoop;
+
+#ifndef TRACE
+unsigned char* meshopt_simplifyDebugKind;
+unsigned int* meshopt_simplifyDebugLoop;
+#endif
+
+struct Options
+{
+	bool wireframe;
+	enum
+	{
+		Mode_Default,
+		Mode_Texture,
+		Mode_Normals,
+		Mode_UV,
+		Mode_Kind,
+	} mode;
+};
+
+struct Vertex
+{
+	float px, py, pz;
+	float nx, ny, nz;
+	float tx, ty;
+};
+
+struct Mesh
+{
+	std::vector<Vertex> vertices;
+	std::vector<unsigned int> indices;
+
+	// TODO: this is debug only visualization and will go away at some point
+	std::vector<unsigned char> kinds;
+	std::vector<unsigned int> loop;
+};
+
+Mesh parseObj(const char* path)
+{
+	ObjFile file;
+
+	if (!objParseFile(file, path) || !objValidate(file))
+	{
+		printf("Error loading %s\n", path);
+		return Mesh();
+	}
+
+	size_t total_indices = file.f_size / 3;
+
+	std::vector<Vertex> vertices(total_indices);
+
+	for (size_t i = 0; i < total_indices; ++i)
+	{
+		int vi = file.f[i * 3 + 0];
+		int vti = file.f[i * 3 + 1];
+		int vni = file.f[i * 3 + 2];
+
+		Vertex v =
+		    {
+		        file.v[vi * 3 + 0],
+		        file.v[vi * 3 + 1],
+		        file.v[vi * 3 + 2],
+
+		        vni >= 0 ? file.vn[vni * 3 + 0] : 0,
+		        vni >= 0 ? file.vn[vni * 3 + 1] : 0,
+		        vni >= 0 ? file.vn[vni * 3 + 2] : 0,
+
+		        vti >= 0 ? file.vt[vti * 3 + 0] : 0,
+		        vti >= 0 ? file.vt[vti * 3 + 1] : 0,
+		    };
+
+		vertices[i] = v;
+	}
+
+	Mesh result;
+
+	std::vector<unsigned int> remap(total_indices);
+	size_t total_vertices = meshopt_generateVertexRemap(&remap[0], NULL, total_indices, &vertices[0], total_indices, sizeof(Vertex));
+
+	result.indices.resize(total_indices);
+	meshopt_remapIndexBuffer(&result.indices[0], NULL, total_indices, &remap[0]);
+
+	result.vertices.resize(total_vertices);
+	meshopt_remapVertexBuffer(&result.vertices[0], &vertices[0], total_indices, sizeof(Vertex), &remap[0]);
+
+	return result;
+}
+
+#ifdef GLTF
+cgltf_accessor* getAccessor(const cgltf_attribute* attributes, size_t attribute_count, cgltf_attribute_type type, int index = 0)
+{
+	for (size_t i = 0; i < attribute_count; ++i)
+		if (attributes[i].type == type && attributes[i].index == index)
+			return attributes[i].data;
+
+	return 0;
+}
+
+template <typename T>
+const T* getComponentPtr(const cgltf_accessor* a)
+{
+	const char* buffer = (char*)a->buffer_view->buffer->data;
+	size_t offset = a->offset + a->buffer_view->offset;
+
+	return reinterpret_cast<const T*>(&buffer[offset]);
+}
+
+Mesh parseGltf(const char* path)
+{
+	cgltf_options options = {};
+	cgltf_data* data = 0;
+	cgltf_result res = cgltf_parse_file(&options, path, &data);
+
+	if (res != cgltf_result_success)
+	{
+		return Mesh();
+	}
+
+	res = cgltf_load_buffers(&options, data, path);
+	if (res != cgltf_result_success)
+	{
+		cgltf_free(data);
+		return Mesh();
+	}
+
+	res = cgltf_validate(data);
+	if (res != cgltf_result_success)
+	{
+		cgltf_free(data);
+		return Mesh();
+	}
+
+	size_t total_vertices = 0;
+	size_t total_indices = 0;
+
+	for (size_t ni = 0; ni < data->nodes_count; ++ni)
+	{
+		if (!data->nodes[ni].mesh)
+			continue;
+
+		const cgltf_mesh& mesh = *data->nodes[ni].mesh;
+
+		for (size_t pi = 0; pi < mesh.primitives_count; ++pi)
+		{
+			const cgltf_primitive& primitive = mesh.primitives[pi];
+
+			cgltf_accessor* ai = primitive.indices;
+			cgltf_accessor* ap = getAccessor(primitive.attributes, primitive.attributes_count, cgltf_attribute_type_position);
+
+			if (!ai || !ap)
+				continue;
+
+			total_vertices += ap->count;
+			total_indices += ai->count;
+		}
+	}
+
+	Mesh result;
+	result.vertices.resize(total_vertices);
+	result.indices.resize(total_indices);
+
+	size_t vertex_offset = 0;
+	size_t index_offset = 0;
+
+	for (size_t ni = 0; ni < data->nodes_count; ++ni)
+	{
+		if (!data->nodes[ni].mesh)
+			continue;
+
+		const cgltf_mesh& mesh = *data->nodes[ni].mesh;
+
+		float transform[16];
+		cgltf_node_transform_world(&data->nodes[ni], transform);
+
+		for (size_t pi = 0; pi < mesh.primitives_count; ++pi)
+		{
+			const cgltf_primitive& primitive = mesh.primitives[pi];
+
+			cgltf_accessor* ai = primitive.indices;
+			cgltf_accessor* ap = getAccessor(primitive.attributes, primitive.attributes_count, cgltf_attribute_type_position);
+
+			if (!ai || !ap)
+				continue;
+
+			if (ai->component_type == cgltf_component_type_r_32u)
+			{
+				const unsigned int* ptr = getComponentPtr<unsigned int>(ai);
+
+				for (size_t i = 0; i < ai->count; ++i)
+					result.indices[index_offset + i] = unsigned(vertex_offset + ptr[i]);
+			}
+			else
+			{
+				const unsigned short* ptr = getComponentPtr<unsigned short>(ai);
+
+				for (size_t i = 0; i < ai->count; ++i)
+					result.indices[index_offset + i] = unsigned(vertex_offset + ptr[i]);
+			}
+
+			{
+				const float* ptr = getComponentPtr<float>(ap);
+
+				for (size_t i = 0; i < ap->count; ++i)
+				{
+					result.vertices[vertex_offset + i].px = ptr[0] * transform[0] + ptr[1] * transform[4] + ptr[2] * transform[8] + transform[12];
+					result.vertices[vertex_offset + i].py = ptr[0] * transform[1] + ptr[1] * transform[5] + ptr[2] * transform[9] + transform[13];
+					result.vertices[vertex_offset + i].pz = ptr[0] * transform[2] + ptr[1] * transform[6] + ptr[2] * transform[10] + transform[14];
+					ptr += ap->stride / 4;
+				}
+			}
+
+			if (cgltf_accessor* an = getAccessor(primitive.attributes, primitive.attributes_count, cgltf_attribute_type_normal))
+			{
+				const float* ptr = getComponentPtr<float>(an);
+
+				for (size_t i = 0; i < ap->count; ++i)
+				{
+					result.vertices[vertex_offset + i].nx = ptr[0] * transform[0] + ptr[1] * transform[4] + ptr[2] * transform[8];
+					result.vertices[vertex_offset + i].ny = ptr[0] * transform[1] + ptr[1] * transform[5] + ptr[2] * transform[9];
+					result.vertices[vertex_offset + i].nz = ptr[0] * transform[2] + ptr[1] * transform[6] + ptr[2] * transform[10];
+					ptr += an->stride / 4;
+				}
+			}
+
+			if (cgltf_accessor* at = getAccessor(primitive.attributes, primitive.attributes_count, cgltf_attribute_type_texcoord))
+			{
+				const float* ptr = getComponentPtr<float>(at);
+
+				for (size_t i = 0; i < ap->count; ++i)
+				{
+					result.vertices[vertex_offset + i].tx = ptr[0];
+					result.vertices[vertex_offset + i].ty = ptr[1];
+					ptr += at->stride / 4;
+				}
+			}
+
+			vertex_offset += ap->count;
+			index_offset += ai->count;
+		}
+	}
+
+	std::vector<unsigned int> remap(total_indices);
+	size_t unique_vertices = meshopt_generateVertexRemap(&remap[0], &result.indices[0], total_indices, &result.vertices[0], total_vertices, sizeof(Vertex));
+
+	meshopt_remapIndexBuffer(&result.indices[0], &result.indices[0], total_indices, &remap[0]);
+	meshopt_remapVertexBuffer(&result.vertices[0], &result.vertices[0], total_vertices, sizeof(Vertex), &remap[0]);
+
+	result.vertices.resize(unique_vertices);
+
+	cgltf_free(data);
+
+	return result;
+}
+#endif
+
+Mesh loadMesh(const char* path)
+{
+	if (strstr(path, ".obj"))
+		return parseObj(path);
+
+#ifdef GLTF
+	if (strstr(path, ".gltf") || strstr(path, ".glb"))
+		return parseGltf(path);
+#endif
+
+	return Mesh();
+}
+
+bool saveObj(const Mesh& mesh, const char* path)
+{
+	std::vector<Vertex> verts = mesh.vertices;
+	std::vector<unsigned int> tris = mesh.indices;
+	size_t vertcount = meshopt_optimizeVertexFetch(verts.data(), tris.data(), tris.size(), verts.data(), verts.size(), sizeof(Vertex));
+
+	FILE* obj = fopen(path, "w");
+	if (!obj)
+		return false;
+
+	for (size_t i = 0; i < vertcount; ++i)
+	{
+		fprintf(obj, "v %f %f %f\n", verts[i].px, verts[i].py, verts[i].pz);
+		fprintf(obj, "vn %f %f %f\n", verts[i].nx, verts[i].ny, verts[i].nz);
+		fprintf(obj, "vt %f %f %f\n", verts[i].tx, verts[i].ty, 0.f);
+	}
+
+	for (size_t i = 0; i < tris.size(); i += 3)
+	{
+		unsigned int i0 = tris[i + 0] + 1;
+		unsigned int i1 = tris[i + 1] + 1;
+		unsigned int i2 = tris[i + 2] + 1;
+
+		fprintf(obj, "f %d/%d/%d %d/%d/%d %d/%d/%d\n", i0, i0, i0, i1, i1, i1, i2, i2, i2);
+	}
+
+	fclose(obj);
+
+	return true;
+}
+
+Mesh optimize(const Mesh& mesh, int lod)
+{
+	float threshold = powf(0.5f, float(lod));
+	size_t target_index_count = size_t(mesh.indices.size() * threshold);
+	float target_error = 1e-2f;
+
+	Mesh result = mesh;
+	result.kinds.resize(result.vertices.size());
+	result.loop.resize(result.vertices.size());
+	meshopt_simplifyDebugKind = &result.kinds[0];
+	meshopt_simplifyDebugLoop = &result.loop[0];
+	result.indices.resize(meshopt_simplify(&result.indices[0], &result.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_index_count, target_error));
+
+	return result;
+}
+
+void display(int x, int y, int width, int height, const Mesh& mesh, const Options& options)
+{
+	glViewport(x, y, width, height);
+	glEnable(GL_DEPTH_TEST);
+	glDepthFunc(GL_LESS);
+	glDepthMask(GL_TRUE);
+
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	glRotatef(0.f, 0.f, 1.f, 0.f);
+
+	glPolygonMode(GL_FRONT_AND_BACK, options.wireframe ? GL_LINE : GL_FILL);
+
+	float centerx = 0;
+	float centery = 0;
+	float centerz = 0;
+	float centeru = 0;
+	float centerv = 0;
+
+	for (size_t i = 0; i < mesh.vertices.size(); ++i)
+	{
+		const Vertex& v = mesh.vertices[i];
+
+		centerx += v.px;
+		centery += v.py;
+		centerz += v.pz;
+		centeru += v.tx;
+		centerv += v.ty;
+	}
+
+	centerx /= float(mesh.vertices.size());
+	centery /= float(mesh.vertices.size());
+	centerz /= float(mesh.vertices.size());
+	centeru /= float(mesh.vertices.size());
+	centerv /= float(mesh.vertices.size());
+
+	float extent = 0;
+	float extentuv = 0;
+
+	for (size_t i = 0; i < mesh.vertices.size(); ++i)
+	{
+		const Vertex& v = mesh.vertices[i];
+
+		extent = std::max(extent, fabsf(v.px - centerx));
+		extent = std::max(extent, fabsf(v.py - centery));
+		extent = std::max(extent, fabsf(v.pz - centerz));
+		extentuv = std::max(extentuv, fabsf(v.tx - centeru));
+		extentuv = std::max(extentuv, fabsf(v.ty - centerv));
+	}
+
+	extent *= 1.1f;
+	extentuv *= 1.1f;
+
+	float scalex = width > height ? float(height) / float(width) : 1;
+	float scaley = height > width ? float(width) / float(height) : 1;
+
+	glBegin(GL_TRIANGLES);
+
+	for (size_t i = 0; i < mesh.indices.size(); ++i)
+	{
+		const Vertex& v = mesh.vertices[mesh.indices[i]];
+
+		float intensity = -(v.pz - centerz) / extent * 0.5f + 0.5f;
+
+		switch (options.mode)
+		{
+		case Options::Mode_UV:
+			glColor3f(intensity, intensity, intensity);
+			glVertex3f((v.tx - centeru) / extentuv * scalex, (v.ty - centerv) / extentuv * scaley, 0);
+			break;
+
+		case Options::Mode_Texture:
+			glColor3f(v.tx - floorf(v.tx), v.ty - floorf(v.ty), 0.5f);
+			glVertex3f((v.px - centerx) / extent * scalex, (v.py - centery) / extent * scaley, (v.pz - centerz) / extent);
+			break;
+
+		case Options::Mode_Normals:
+			glColor3f(v.nx * 0.5f + 0.5f, v.ny * 0.5f + 0.5f, v.nz * 0.5f + 0.5f);
+			glVertex3f((v.px - centerx) / extent * scalex, (v.py - centery) / extent * scaley, (v.pz - centerz) / extent);
+			break;
+
+		default:
+			glColor3f(intensity, intensity, intensity);
+			glVertex3f((v.px - centerx) / extent * scalex, (v.py - centery) / extent * scaley, (v.pz - centerz) / extent);
+		}
+	}
+
+	glEnd();
+
+	float zbias = 1e-3f;
+
+	if (options.mode == Options::Mode_Kind && !mesh.kinds.empty() && !mesh.loop.empty())
+	{
+		glLineWidth(1);
+
+		glBegin(GL_LINES);
+
+		for (size_t i = 0; i < mesh.indices.size(); ++i)
+		{
+			unsigned int a = mesh.indices[i];
+			unsigned int b = mesh.loop[a];
+
+			if (b != ~0u)
+			{
+				const Vertex& v0 = mesh.vertices[a];
+				const Vertex& v1 = mesh.vertices[b];
+
+				unsigned char kind = mesh.kinds[a];
+
+				glColor3f(kind == 0 || kind == 4, kind == 0 || kind == 2 || kind == 3, kind == 0 || kind == 1 || kind == 3);
+				glVertex3f((v0.px - centerx) / extent * scalex, (v0.py - centery) / extent * scaley, (v0.pz - centerz) / extent - zbias);
+				glVertex3f((v1.px - centerx) / extent * scalex, (v1.py - centery) / extent * scaley, (v1.pz - centerz) / extent - zbias);
+			}
+		}
+
+		glEnd();
+
+		glPointSize(3);
+
+		glBegin(GL_POINTS);
+
+		for (size_t i = 0; i < mesh.indices.size(); ++i)
+		{
+			const Vertex& v = mesh.vertices[mesh.indices[i]];
+			unsigned char kind = mesh.kinds[mesh.indices[i]];
+
+			if (kind != 0)
+			{
+				glColor3f(kind == 0 || kind == 4, kind == 0 || kind == 2 || kind == 3, kind == 0 || kind == 1 || kind == 3);
+				glVertex3f((v.px - centerx) / extent * scalex, (v.py - centery) / extent * scaley, (v.pz - centerz) / extent - zbias * 2);
+			}
+		}
+
+		glEnd();
+	}
+}
+
+void stats(GLFWwindow* window, const char* path, unsigned int triangles, int lod, double time)
+{
+	char title[256];
+	snprintf(title, sizeof(title), "%s: LOD %d - %d triangles (%.1f msec)", path, lod, triangles, time * 1000);
+
+	glfwSetWindowTitle(window, title);
+}
+
+struct File
+{
+	Mesh basemesh;
+	Mesh lodmesh;
+	const char* path;
+};
+
+std::vector<File> files;
+Options options;
+bool redraw;
+
+void keyhandler(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+	if (action == GLFW_PRESS)
+	{
+		if (key == GLFW_KEY_W)
+		{
+			options.wireframe = !options.wireframe;
+			redraw = true;
+		}
+		else if (key == GLFW_KEY_T)
+		{
+			options.mode = options.mode == Options::Mode_Texture ? Options::Mode_Default : Options::Mode_Texture;
+			redraw = true;
+		}
+		else if (key == GLFW_KEY_N)
+		{
+			options.mode = options.mode == Options::Mode_Normals ? Options::Mode_Default : Options::Mode_Normals;
+			redraw = true;
+		}
+		else if (key == GLFW_KEY_U)
+		{
+			options.mode = options.mode == Options::Mode_UV ? Options::Mode_Default : Options::Mode_UV;
+			redraw = true;
+		}
+		else if (key == GLFW_KEY_K)
+		{
+			options.mode = options.mode == Options::Mode_Kind ? Options::Mode_Default : Options::Mode_Kind;
+			redraw = true;
+		}
+		else if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9)
+		{
+			int lod = int(key - GLFW_KEY_0);
+
+			unsigned int triangles = 0;
+
+			clock_t start = clock();
+			for (auto& f : files)
+			{
+				f.lodmesh = optimize(f.basemesh, lod);
+				triangles += unsigned(f.lodmesh.indices.size() / 3);
+			}
+			clock_t end = clock();
+
+			stats(window, files[0].path, triangles, lod, double(end - start) / CLOCKS_PER_SEC);
+			redraw = true;
+		}
+		else if (key == GLFW_KEY_S)
+		{
+			int i = 0;
+
+			for (auto& f : files)
+			{
+				char path[32];
+				sprintf(path, "result%d.obj", i);
+
+				saveObj(f.lodmesh, path);
+
+				printf("Saved LOD of %s to %s\n", f.path, path);
+			}
+		}
+	}
+}
+
+void sizehandler(GLFWwindow* window, int width, int height)
+{
+	redraw = true;
+}
+
+int main(int argc, char** argv)
+{
+	if (argc <= 1)
+	{
+		printf("Usage: %s [.obj files]\n", argv[0]);
+		return 0;
+	}
+
+	unsigned int basetriangles = 0;
+
+	for (int i = 1; i < argc; ++i)
+	{
+		files.emplace_back();
+		File& f = files.back();
+
+		f.path = argv[i];
+		f.basemesh = loadMesh(f.path);
+		f.lodmesh = optimize(f.basemesh, 0);
+
+		basetriangles += unsigned(f.basemesh.indices.size() / 3);
+	}
+
+	glfwInit();
+
+	GLFWwindow* window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
+	glfwMakeContextCurrent(window);
+
+	stats(window, files[0].path, basetriangles, 0, 0);
+
+	glfwSetKeyCallback(window, keyhandler);
+	glfwSetWindowSizeCallback(window, sizehandler);
+
+	redraw = true;
+
+	while (!glfwWindowShouldClose(window))
+	{
+		if (redraw)
+		{
+			redraw = false;
+
+			int width, height;
+			glfwGetFramebufferSize(window, &width, &height);
+
+			glViewport(0, 0, width, height);
+			glClearDepth(1.f);
+			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+			int cols = int(ceil(sqrt(double(files.size()))));
+			int rows = int(ceil(double(files.size()) / cols));
+
+			int tilew = width / cols;
+			int tileh = height / rows;
+
+			for (size_t i = 0; i < files.size(); ++i)
+			{
+				File& f = files[i];
+				int x = int(i) % cols;
+				int y = int(i) / cols;
+
+				display(x * tilew, y * tileh, tilew, tileh, f.lodmesh, options);
+			}
+
+			glfwSwapBuffers(window);
+		}
+
+		glfwWaitEvents();
+	}
+}

+ 255 - 0
3rdparty/meshoptimizer/tools/meshencoder.cpp

@@ -0,0 +1,255 @@
+// Converts .obj files to .optmesh files
+// Usage: meshencoder [.obj] [.optmesh]
+
+// Data layout:
+// Header: 64b
+// Object table: 16b * object_count
+// Object data
+// Vertex data
+// Index data
+
+#include "../src/meshoptimizer.h"
+#include "objparser.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+struct Header
+{
+	char magic[4]; // OPTM
+
+	unsigned int group_count;
+	unsigned int vertex_count;
+	unsigned int index_count;
+	unsigned int vertex_data_size;
+	unsigned int index_data_size;
+
+	float pos_offset[3];
+	float pos_scale;
+	float uv_offset[2];
+	float uv_scale[2];
+
+	unsigned int reserved[2];
+};
+
+struct Object
+{
+	unsigned int index_offset;
+	unsigned int index_count;
+	unsigned int material_length;
+	unsigned int reserved;
+};
+
+struct Vertex
+{
+	unsigned short px, py, pz, pw; // unsigned 16-bit value, use pos_offset/pos_scale to unpack
+	char nx, ny, nz, nw; // normalized signed 8-bit value
+	unsigned short tx, ty; // unsigned 16-bit value, use uv_offset/uv_scale to unpack
+};
+
+float rcpSafe(float v)
+{
+	return v == 0.f ? 0.f : 1.f / v;
+}
+
+int main(int argc, char** argv)
+{
+	if (argc <= 2)
+	{
+		printf("Usage: %s [.obj] [.optmesh]\n", argv[0]);
+		return 1;
+	}
+
+	const char* input = argv[1];
+	const char* output = argv[2];
+
+	ObjFile file;
+
+	if (!objParseFile(file, input))
+	{
+		printf("Error loading %s: file not found\n", input);
+		return 2;
+	}
+
+	if (!objValidate(file))
+	{
+		printf("Error loading %s: invalid file data\n", input);
+		return 3;
+	}
+
+	float pos_offset[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
+	float pos_scale = 0.f;
+
+	for (size_t i = 0; i < file.v_size; i += 3)
+	{
+		pos_offset[0] = std::min(pos_offset[0], file.v[i + 0]);
+		pos_offset[1] = std::min(pos_offset[1], file.v[i + 1]);
+		pos_offset[2] = std::min(pos_offset[2], file.v[i + 2]);
+	}
+
+	for (size_t i = 0; i < file.v_size; i += 3)
+	{
+		pos_scale = std::max(pos_scale, file.v[i + 0] - pos_offset[0]);
+		pos_scale = std::max(pos_scale, file.v[i + 1] - pos_offset[1]);
+		pos_scale = std::max(pos_scale, file.v[i + 2] - pos_offset[2]);
+	}
+
+	float uv_offset[2] = { FLT_MAX, FLT_MAX };
+	float uv_scale[2] = { 0, 0 };
+
+	for (size_t i = 0; i < file.vt_size; i += 3)
+	{
+		uv_offset[0] = std::min(uv_offset[0], file.vt[i + 0]);
+		uv_offset[1] = std::min(uv_offset[1], file.vt[i + 1]);
+	}
+
+	for (size_t i = 0; i < file.vt_size; i += 3)
+	{
+		uv_scale[0] = std::max(uv_scale[0], file.vt[i + 0] - uv_offset[0]);
+		uv_scale[1] = std::max(uv_scale[1], file.vt[i + 1] - uv_offset[1]);
+	}
+
+	float pos_scale_inverse = rcpSafe(pos_scale);
+	float uv_scale_inverse[2] = { rcpSafe(uv_scale[0]), rcpSafe(uv_scale[1]) };
+
+	size_t total_indices = file.f_size / 3;
+
+	std::vector<Vertex> triangles(total_indices);
+
+	int pos_bits = 14;
+	int uv_bits = 12;
+
+	for (size_t i = 0; i < total_indices; ++i)
+	{
+		int vi = file.f[i * 3 + 0];
+		int vti = file.f[i * 3 + 1];
+		int vni = file.f[i * 3 + 2];
+
+		// note: we scale the vertices uniformly; this is not the best option wrt compression quality
+		// however, it means we can scale the mesh uniformly without distorting the normals
+		// this is helpful for backends like ThreeJS that apply mesh scaling to normals
+		float px = (file.v[vi * 3 + 0] - pos_offset[0]) * pos_scale_inverse;
+		float py = (file.v[vi * 3 + 1] - pos_offset[1]) * pos_scale_inverse;
+		float pz = (file.v[vi * 3 + 2] - pos_offset[2]) * pos_scale_inverse;
+
+		// normal is 0 if absent from the mesh
+		float nx = vni >= 0 ? file.vn[vni * 3 + 0] : 0;
+		float ny = vni >= 0 ? file.vn[vni * 3 + 1] : 0;
+		float nz = vni >= 0 ? file.vn[vni * 3 + 2] : 0;
+
+		// scale the normal to make sure the largest component is +-1.0
+		// this reduces the entropy of the normal by ~1.5 bits without losing precision
+		// it's better to use octahedral encoding but that requires special shader support
+		float nm = std::max(fabsf(nx), std::max(fabsf(ny), fabsf(nz)));
+		float ns = nm == 0.f ? 0.f : 1 / nm;
+
+		nx *= ns;
+		ny *= ns;
+		nz *= ns;
+
+		// texture coordinates are 0 if absent, and require a texture matrix to decode
+		float tx = vti >= 0 ? (file.vt[vti * 3 + 0] - uv_offset[0]) * uv_scale_inverse[0] : 0;
+		float ty = vti >= 0 ? (file.vt[vti * 3 + 1] - uv_offset[1]) * uv_scale_inverse[1] : 0;
+
+		Vertex v =
+		    {
+		        (unsigned short)(meshopt_quantizeUnorm(px, pos_bits)),
+		        (unsigned short)(meshopt_quantizeUnorm(py, pos_bits)),
+		        (unsigned short)(meshopt_quantizeUnorm(pz, pos_bits)),
+				0,
+
+		        char(meshopt_quantizeSnorm(nx, 8)),
+		        char(meshopt_quantizeSnorm(ny, 8)),
+		        char(meshopt_quantizeSnorm(nz, 8)),
+				0,
+
+		        (unsigned short)(meshopt_quantizeUnorm(tx, uv_bits)),
+		        (unsigned short)(meshopt_quantizeUnorm(ty, uv_bits)),
+		    };
+
+		triangles[i] = v;
+	}
+
+	std::vector<unsigned int> remap(total_indices);
+
+	size_t total_vertices = meshopt_generateVertexRemap(&remap[0], NULL, total_indices, &triangles[0], total_indices, sizeof(Vertex));
+
+	std::vector<unsigned int> indices(total_indices);
+	meshopt_remapIndexBuffer(&indices[0], NULL, total_indices, &remap[0]);
+
+	std::vector<Vertex> vertices(total_vertices);
+	meshopt_remapVertexBuffer(&vertices[0], &triangles[0], total_indices, sizeof(Vertex), &remap[0]);
+
+	for (size_t i = 0; i < file.g_size; ++i)
+	{
+		ObjGroup& g = file.g[i];
+
+		meshopt_optimizeVertexCache(&indices[g.index_offset], &indices[g.index_offset], g.index_count, vertices.size());
+	}
+
+	meshopt_optimizeVertexFetch(&vertices[0], &indices[0], indices.size(), &vertices[0], vertices.size(), sizeof(Vertex));
+
+	std::vector<unsigned char> vbuf(meshopt_encodeVertexBufferBound(vertices.size(), sizeof(Vertex)));
+	vbuf.resize(meshopt_encodeVertexBuffer(&vbuf[0], vbuf.size(), &vertices[0], vertices.size(), sizeof(Vertex)));
+
+	std::vector<unsigned char> ibuf(meshopt_encodeIndexBufferBound(indices.size(), vertices.size()));
+	ibuf.resize(meshopt_encodeIndexBuffer(&ibuf[0], ibuf.size(), &indices[0], indices.size()));
+
+	FILE* result = fopen(output, "wb");
+	if (!result)
+	{
+		printf("Error saving %s: can't open file for writing\n", output);
+		return 4;
+	}
+
+	Header header = {};
+	memcpy(header.magic, "OPTM", 4);
+
+	header.group_count = unsigned(file.g_size);
+	header.vertex_count = unsigned(vertices.size());
+	header.index_count = unsigned(indices.size());
+	header.vertex_data_size = unsigned(vbuf.size());
+	header.index_data_size = unsigned(ibuf.size());
+
+	header.pos_offset[0] = pos_offset[0];
+	header.pos_offset[1] = pos_offset[1];
+	header.pos_offset[2] = pos_offset[2];
+	header.pos_scale = pos_scale / float((1 << pos_bits) - 1);
+
+	header.uv_offset[0] = uv_offset[0];
+	header.uv_offset[1] = uv_offset[1];
+	header.uv_scale[0] = uv_scale[0] / float((1 << uv_bits) - 1);
+	header.uv_scale[1] = uv_scale[1] / float((1 << uv_bits) - 1);
+
+	fwrite(&header, 1, sizeof(header), result);
+
+	for (size_t i = 0; i < file.g_size; ++i)
+	{
+		ObjGroup& g = file.g[i];
+
+		Object object = {};
+		object.index_offset = unsigned(g.index_offset);
+		object.index_count = unsigned(g.index_count);
+		object.material_length = unsigned(strlen(g.material));
+
+		fwrite(&object, 1, sizeof(object), result);
+	}
+
+	for (size_t i = 0; i < file.g_size; ++i)
+	{
+		ObjGroup& g = file.g[i];
+
+		fwrite(g.material, 1, strlen(g.material), result);
+	}
+
+	fwrite(&vbuf[0], 1, vbuf.size(), result);
+	fwrite(&ibuf[0], 1, ibuf.size(), result);
+	fclose(result);
+
+	return 0;
+}

+ 383 - 0
3rdparty/meshoptimizer/tools/objparser.cpp

@@ -0,0 +1,383 @@
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "objparser.h"
+
+#include <cassert>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+template <typename T>
+static void growArray(T*& data, size_t& capacity)
+{
+	size_t newcapacity = capacity == 0 ? 32 : capacity + capacity / 2;
+	T* newdata = new T[newcapacity];
+
+	if (data)
+	{
+		memcpy(newdata, data, capacity * sizeof(T));
+		delete[] data;
+	}
+
+	data = newdata;
+	capacity = newcapacity;
+}
+
+static int fixupIndex(int index, size_t size)
+{
+	return (index >= 0) ? index - 1 : int(size) + index;
+}
+
+static int parseInt(const char* s, const char** end)
+{
+	// skip whitespace
+	while (*s == ' ' || *s == '\t')
+		s++;
+
+	// read sign bit
+	int sign = (*s == '-');
+	s += (*s == '-' || *s == '+');
+
+	unsigned int result = 0;
+
+	for (;;)
+	{
+		if (unsigned(*s - '0') < 10)
+			result = result * 10 + (*s - '0');
+		else
+			break;
+
+		s++;
+	}
+
+	// return end-of-string
+	*end = s;
+
+	return sign ? -int(result) : int(result);
+}
+
+static float parseFloat(const char* s, const char** end)
+{
+	static const double digits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+	static const double powers[] = {1e0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 1e+21, 1e+22};
+
+	// skip whitespace
+	while (*s == ' ' || *s == '\t')
+		s++;
+
+	// read sign
+	double sign = (*s == '-') ? -1 : 1;
+	s += (*s == '-' || *s == '+');
+
+	// read integer part
+	double result = 0;
+	int power = 0;
+
+	while (unsigned(*s - '0') < 10)
+	{
+		result = result * 10 + digits[*s - '0'];
+		s++;
+	}
+
+	// read fractional part
+	if (*s == '.')
+	{
+		s++;
+
+		while (unsigned(*s - '0') < 10)
+		{
+			result = result * 10 + digits[*s - '0'];
+			s++;
+			power--;
+		}
+	}
+
+	// read exponent part
+	if ((*s | ' ') == 'e')
+	{
+		s++;
+
+		// read exponent sign
+		int expsign = (*s == '-') ? -1 : 1;
+		s += (*s == '-' || *s == '+');
+
+		// read exponent
+		int exppower = 0;
+
+		while (unsigned(*s - '0') < 10)
+		{
+			exppower = exppower * 10 + (*s - '0');
+			s++;
+		}
+
+		// done!
+		power += expsign * exppower;
+	}
+
+	// return end-of-string
+	*end = s;
+
+	// note: this is precise if result < 9e15
+	// for longer inputs we lose a bit of precision here
+	if (unsigned(-power) < sizeof(powers) / sizeof(powers[0]))
+		return float(sign * result / powers[-power]);
+	else if (unsigned(power) < sizeof(powers) / sizeof(powers[0]))
+		return float(sign * result * powers[power]);
+	else
+		return float(sign * result * pow(10.0, power));
+}
+
+static const char* parseFace(const char* s, int& vi, int& vti, int& vni)
+{
+	while (*s == ' ' || *s == '\t')
+		s++;
+
+	vi = parseInt(s, &s);
+
+	if (*s != '/')
+		return s;
+	s++;
+
+	// handle vi//vni indices
+	if (*s != '/')
+		vti = parseInt(s, &s);
+
+	if (*s != '/')
+		return s;
+	s++;
+
+	vni = parseInt(s, &s);
+
+	return s;
+}
+
+ObjFile::ObjFile()
+    : v(0)
+    , v_size(0)
+    , v_cap(0)
+    , vt(0)
+    , vt_size(0)
+    , vt_cap(0)
+    , vn(0)
+    , vn_size(0)
+    , vn_cap(0)
+    , f(0)
+    , f_size(0)
+    , f_cap(0)
+    , g(0)
+    , g_size(0)
+    , g_cap(0)
+{
+}
+
+ObjFile::~ObjFile()
+{
+	delete[] v;
+	delete[] vt;
+	delete[] vn;
+	delete[] f;
+	delete[] g;
+}
+
+void objParseLine(ObjFile& result, const char* line)
+{
+	if (line[0] == 'v' && line[1] == ' ')
+	{
+		const char* s = line + 2;
+
+		float x = parseFloat(s, &s);
+		float y = parseFloat(s, &s);
+		float z = parseFloat(s, &s);
+
+		if (result.v_size + 3 > result.v_cap)
+			growArray(result.v, result.v_cap);
+
+		result.v[result.v_size++] = x;
+		result.v[result.v_size++] = y;
+		result.v[result.v_size++] = z;
+	}
+	else if (line[0] == 'v' && line[1] == 't' && line[2] == ' ')
+	{
+		const char* s = line + 3;
+
+		float u = parseFloat(s, &s);
+		float v = parseFloat(s, &s);
+		float w = parseFloat(s, &s);
+
+		if (result.vt_size + 3 > result.vt_cap)
+			growArray(result.vt, result.vt_cap);
+
+		result.vt[result.vt_size++] = u;
+		result.vt[result.vt_size++] = v;
+		result.vt[result.vt_size++] = w;
+	}
+	else if (line[0] == 'v' && line[1] == 'n' && line[2] == ' ')
+	{
+		const char* s = line + 3;
+
+		float x = parseFloat(s, &s);
+		float y = parseFloat(s, &s);
+		float z = parseFloat(s, &s);
+
+		if (result.vn_size + 3 > result.vn_cap)
+			growArray(result.vn, result.vn_cap);
+
+		result.vn[result.vn_size++] = x;
+		result.vn[result.vn_size++] = y;
+		result.vn[result.vn_size++] = z;
+	}
+	else if (line[0] == 'f' && line[1] == ' ')
+	{
+		const char* s = line + 2;
+
+		if (!result.g)
+		{
+			growArray(result.g, result.g_cap);
+
+			ObjGroup g = {};
+			result.g[result.g_size++] = g;
+		}
+
+		size_t v = result.v_size / 3;
+		size_t vt = result.vt_size / 3;
+		size_t vn = result.vn_size / 3;
+
+		int fv = 0;
+		int f[3][3] = {};
+
+		while (*s)
+		{
+			int vi = 0, vti = 0, vni = 0;
+			s = parseFace(s, vi, vti, vni);
+
+			if (vi == 0)
+				break;
+
+			f[fv][0] = fixupIndex(vi, v);
+			f[fv][1] = fixupIndex(vti, vt);
+			f[fv][2] = fixupIndex(vni, vn);
+
+			if (fv == 2)
+			{
+				if (result.f_size + 9 > result.f_cap)
+					growArray(result.f, result.f_cap);
+
+				memcpy(&result.f[result.f_size], f, 9 * sizeof(int));
+				result.f_size += 9;
+
+				result.g[result.g_size - 1].index_count += 3;
+
+				f[1][0] = f[2][0];
+				f[1][1] = f[2][1];
+				f[1][2] = f[2][2];
+			}
+			else
+			{
+				fv++;
+			}
+		}
+	}
+	else if (strncmp(line, "usemtl", 6) == 0)
+	{
+		const char* s = line + 6;
+
+		// skip whitespace
+		while (*s == ' ' || *s == '\t')
+			s++;
+
+		if (result.g_size + 1 > result.g_cap)
+			growArray(result.g, result.g_cap);
+
+		ObjGroup g = {};
+		g.index_offset = result.f_size / 3;
+
+		strncpy(g.material, s, sizeof(g.material));
+		g.material[sizeof(g.material) - 1] = 0;
+
+		result.g[result.g_size++] = g;
+	}
+}
+
+bool objParseFile(ObjFile& result, const char* path)
+{
+	FILE* file = fopen(path, "rb");
+	if (!file)
+		return false;
+
+	char buffer[65536];
+	size_t size = 0;
+
+	while (!feof(file))
+	{
+		size += fread(buffer + size, 1, sizeof(buffer) - size, file);
+
+		size_t line = 0;
+
+		while (line < size)
+		{
+			// find the end of current line
+			void* eol = memchr(buffer + line, '\n', size - line);
+			if (!eol)
+				break;
+
+			// zero-terminate for objParseLine
+			size_t next = static_cast<char*>(eol) - buffer;
+
+			buffer[next] = 0;
+
+			// process next line
+			objParseLine(result, buffer + line);
+
+			line = next + 1;
+		}
+
+		// move prefix of the last line in the buffer to the beginning of the buffer for next iteration
+		assert(line <= size);
+
+		memmove(buffer, buffer + line, size - line);
+		size -= line;
+	}
+
+	if (size)
+	{
+		// process last line
+		assert(size < sizeof(buffer));
+		buffer[size] = 0;
+
+		objParseLine(result, buffer);
+	}
+
+	fclose(file);
+	return true;
+}
+
+bool objValidate(const ObjFile& result)
+{
+	size_t v = result.v_size / 3;
+	size_t vt = result.vt_size / 3;
+	size_t vn = result.vn_size / 3;
+
+	for (size_t i = 0; i < result.f_size; i += 3)
+	{
+		int vi = result.f[i + 0];
+		int vti = result.f[i + 1];
+		int vni = result.f[i + 2];
+
+		if (vi < 0)
+			return false;
+
+		if (vi >= 0 && size_t(vi) >= v)
+			return false;
+
+		if (vti >= 0 && size_t(vti) >= vt)
+			return false;
+
+		if (vni >= 0 && size_t(vni) >= vn)
+			return false;
+	}
+
+	return true;
+}

+ 42 - 0
3rdparty/meshoptimizer/tools/objparser.h

@@ -0,0 +1,42 @@
+#pragma once
+
+#include <stddef.h>
+
+struct ObjGroup
+{
+	char material[256];
+
+	size_t index_offset;
+	size_t index_count;
+};
+
+class ObjFile
+{
+public:
+	float* v; // positions; stride 3 (xyz)
+	size_t v_size, v_cap;
+
+	float* vt; // texture coordinates; stride 3 (uvw)
+	size_t vt_size, vt_cap;
+
+	float* vn; // vertex normals; stride 3 (xyz)
+	size_t vn_size, vn_cap;
+
+	int* f; // face elements; stride 9 (3 groups of indices into v/vt/vn)
+	size_t f_size, f_cap;
+
+	ObjGroup* g;
+	size_t g_size, g_cap;
+
+	ObjFile();
+	~ObjFile();
+
+private:
+	ObjFile(const ObjFile&);
+	ObjFile& operator=(const ObjFile&);
+};
+
+void objParseLine(ObjFile& result, const char* line);
+bool objParseFile(ObjFile& result, const char* path);
+
+bool objValidate(const ObjFile& result);

+ 495 - 0
3rdparty/meshoptimizer/tools/vcachetester.cpp

@@ -0,0 +1,495 @@
+#ifdef _WIN32
+#include <assert.h>
+#include <d3d11.h>
+#include <d3dcompiler.h>
+#include <stdio.h>
+
+#include <cassert>
+#include <cmath>
+
+#include <algorithm>
+#include <vector>
+
+#include "../src/meshoptimizer.h"
+#include "objparser.h"
+
+#pragma comment(lib, "d3d11.lib")
+#pragma comment(lib, "d3dcompiler.lib")
+#pragma comment(lib, "dxgi.lib")
+
+void stripGen(std::vector<unsigned int>& indices, int x0, int x1, int y0, int y1, int width, bool prefetch)
+{
+	if (prefetch)
+	{
+		for (int x = x0; x < x1; x++)
+		{
+			indices.push_back(x + 0);
+			indices.push_back(x + 0);
+			indices.push_back(x + 1);
+		}
+	}
+
+	for (int y = y0; y < y1; y++)
+	{
+		for (int x = x0; x < x1; x++)
+		{
+			indices.push_back((width + 1) * (y + 0) + (x + 0));
+			indices.push_back((width + 1) * (y + 1) + (x + 0));
+			indices.push_back((width + 1) * (y + 0) + (x + 1));
+
+			indices.push_back((width + 1) * (y + 0) + (x + 1));
+			indices.push_back((width + 1) * (y + 1) + (x + 0));
+			indices.push_back((width + 1) * (y + 1) + (x + 1));
+		}
+	}
+}
+
+void gridGen(std::vector<unsigned int>& indices, int x0, int x1, int y0, int y1, int width, int cacheSize, bool prefetch)
+{
+	if (x1 - x0 + 1 < cacheSize)
+	{
+		bool prefetchStrip = 2 * (x1 - x0) + 1 > cacheSize && prefetch;
+
+		stripGen(indices, x0, x1, y0, y1, width, prefetchStrip);
+	}
+	else
+	{
+		int xm = x0 + cacheSize - 2;
+		gridGen(indices, x0, xm, y0, y1, width, cacheSize, prefetch);
+		gridGen(indices, xm, x1, y0, y1, width, cacheSize, prefetch);
+	}
+}
+
+unsigned int queryVSInvocations(ID3D11Device* device, ID3D11DeviceContext* context, const unsigned int* indices, size_t index_count)
+{
+	if (index_count == 0)
+		return 0;
+
+	ID3D11Buffer* ib = 0;
+
+	{
+		D3D11_BUFFER_DESC bd = {};
+
+		bd.Usage = D3D11_USAGE_DYNAMIC;
+		bd.ByteWidth = index_count * 4;
+		bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
+		bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+		device->CreateBuffer(&bd, 0, &ib);
+
+		D3D11_MAPPED_SUBRESOURCE ms;
+		context->Map(ib, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
+		memcpy(ms.pData, indices, index_count * 4);
+		context->Unmap(ib, 0);
+	}
+
+	context->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+	context->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0);
+
+	D3D11_QUERY_DESC qdesc = {D3D11_QUERY_PIPELINE_STATISTICS};
+	ID3D11Query* query = 0;
+	device->CreateQuery(&qdesc, &query);
+
+	context->Begin(query);
+	context->DrawIndexed(index_count, 0, 0);
+	context->End(query);
+
+	D3D11_QUERY_DATA_PIPELINE_STATISTICS stats = {};
+	while (S_FALSE == context->GetData(query, &stats, sizeof(stats), 0))
+		;
+
+	query->Release();
+	ib->Release();
+
+	assert(stats.IAVertices == index_count);
+
+	return stats.VSInvocations;
+}
+
+void setupShaders(ID3D11Device* device, ID3D11DeviceContext* context)
+{
+	// load and compile the two shaders
+	const char* shaders =
+	    "#define ATTRIBUTES 5\n"
+	    "struct Foo { float4 v[ATTRIBUTES]; };"
+	    "float4 VS(uint index: SV_VertexId, out Foo foo: FOO): SV_Position { uint i = index % 3; [unroll] for (int j = 0; j < ATTRIBUTES; j++) foo.v[j] = j; return float4(i != 0, i != 2, 0, 1); }"
+	    "float4 PS(Foo foo: FOO): SV_Target { float4 result = 0; [unroll] for (int j = 0; j < ATTRIBUTES; j++) result += foo.v[j]; return result; }";
+
+	ID3DBlob* vsblob = 0;
+	ID3DBlob* psblob = 0;
+	D3DCompile(shaders, strlen(shaders), 0, 0, 0, "VS", "vs_5_0", 0, 0, &vsblob, 0);
+	D3DCompile(shaders, strlen(shaders), 0, 0, 0, "PS", "ps_5_0", 0, 0, &psblob, 0);
+
+	ID3D11VertexShader* vs = 0;
+	ID3D11PixelShader* ps = 0;
+	device->CreateVertexShader(vsblob->GetBufferPointer(), vsblob->GetBufferSize(), 0, &vs);
+	device->CreatePixelShader(psblob->GetBufferPointer(), psblob->GetBufferSize(), 0, &ps);
+
+	context->VSSetShader(vs, 0, 0);
+	context->PSSetShader(ps, 0, 0);
+}
+
+template <typename Cache>
+void inspectCache(Cache cache)
+{
+	unsigned int max_cache_size = 200;
+	unsigned int grid_size = 100;
+
+	for (unsigned int cache_size = 3; cache_size <= max_cache_size; cache_size += 1)
+	{
+		std::vector<unsigned int> grid1;
+		gridGen(grid1, 0, grid_size, 0, grid_size, grid_size, cache_size, true);
+
+		std::vector<unsigned int> grid2;
+		gridGen(grid2, 0, grid_size, 0, grid_size, grid_size, cache_size, false);
+
+		std::vector<unsigned int> grid3;
+		gridGen(grid3, 0, grid_size, 0, grid_size, grid_size, grid_size * 4, false); // this generates a simple indexed grid without striping/degenerate triangles
+		meshopt_optimizeVertexCacheFifo(&grid3[0], &grid3[0], grid3.size(), (grid_size + 1) * (grid_size + 1), cache_size);
+
+		std::vector<unsigned int> grid4;
+		gridGen(grid4, 0, grid_size, 0, grid_size, grid_size, grid_size * 4, false); // this generates a simple indexed grid without striping/degenerate triangles
+		meshopt_optimizeVertexCache(&grid4[0], &grid4[0], grid4.size(), (grid_size + 1) * (grid_size + 1));
+
+		unsigned int invocations1 = cache(&grid1[0], grid1.size());
+		unsigned int invocations2 = cache(&grid2[0], grid2.size());
+		unsigned int invocations3 = cache(&grid3[0], grid3.size());
+		unsigned int invocations4 = cache(&grid4[0], grid4.size());
+
+		unsigned int ideal_invocations = (grid_size + 1) * (grid_size + 1);
+
+		printf("%d, %f, %f, %f, %f\n", cache_size,
+		       double(invocations1) / double(ideal_invocations),
+		       double(invocations2) / double(ideal_invocations),
+		       double(invocations3) / double(ideal_invocations),
+		       double(invocations4) / double(ideal_invocations));
+	}
+}
+
+void testCache(IDXGIAdapter* adapter)
+{
+	ID3D11Device* device = 0;
+	ID3D11DeviceContext* context = 0;
+	D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, 0, 0, D3D11_SDK_VERSION, &device, 0, &context);
+
+	setupShaders(device, context);
+
+	inspectCache([&](const unsigned int* indices, size_t index_count) { return queryVSInvocations(device, context, indices, index_count); });
+}
+
+void testCacheSequence(IDXGIAdapter* adapter, int argc, char** argv)
+{
+	ID3D11Device* device = 0;
+	ID3D11DeviceContext* context = 0;
+	D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, 0, 0, D3D11_SDK_VERSION, &device, 0, &context);
+
+	setupShaders(device, context);
+
+	std::vector<unsigned int> ib;
+
+	for (int i = 2; i < argc; ++i)
+	{
+		char* end;
+		int i0 = strtol(argv[i], &end, 10);
+
+		if (end[0] == '-')
+		{
+			int i1 = strtol(end + 1, &end, 10);
+
+			if (end[0] != 0)
+			{
+				printf("Unrecognized index range: %s\n", argv[i]);
+				return;
+			}
+
+			if (i0 < i1)
+			{
+				for (int ii = i0; ii <= i1; ++ii)
+					ib.push_back(ii);
+			}
+			else
+			{
+				for (int ii = i0; ii >= i1; --ii)
+					ib.push_back(ii);
+			}
+		}
+		else if (end[0] == '*')
+		{
+			int i1 = strtol(end + 1, &end, 10);
+
+			if (end[0] != 0 || i1 == 0)
+			{
+				printf("Unrecognized index range: %s\n", argv[i]);
+				return;
+			}
+
+			for (int ii = 0; ii < i1; ++ii)
+				ib.push_back(i0);
+		}
+		else if (end[0] == 'x')
+		{
+			int i1 = strtol(end + 1, &end, 10);
+
+			if (end[0] != 0)
+			{
+				printf("Unrecognized index range: %s\n", argv[i]);
+				return;
+			}
+
+			stripGen(ib, 0, i0, 0, i1, i0, true);
+		}
+		else if (end[0] == 0)
+		{
+			ib.push_back(i0);
+		}
+		else
+		{
+			printf("Unrecognized index range: %s\n", argv[i]);
+			return;
+		}
+	}
+
+	if (ib.size() % 3)
+		ib.resize(ib.size() - ib.size() % 3);
+
+	std::vector<bool> xformed(ib.size());
+
+	for (size_t i = 0; i < ib.size(); i += 3)
+	{
+		unsigned int inv0 = i == 0 ? 0 : queryVSInvocations(device, context, ib.data(), i);
+		unsigned int inv1 = queryVSInvocations(device, context, ib.data(), i + 3);
+
+		assert(inv0 <= inv1);
+		assert(inv0 + 3 >= inv1);
+
+		switch (inv1 - inv0)
+		{
+		case 0:
+			xformed[i + 0] = xformed[i + 1] = xformed[i + 2] = false;
+			break;
+
+		case 3:
+			xformed[i + 0] = xformed[i + 1] = xformed[i + 2] = true;
+			break;
+
+		case 1:
+		case 2:
+		{
+			unsigned int a = ib[i + 0];
+			unsigned int b = ib[i + 1];
+			unsigned int c = ib[i + 2];
+
+			ib[i + 0] = ib[i + 1] = ib[i + 2] = a;
+			unsigned int inva = queryVSInvocations(device, context, ib.data(), i + 3);
+
+			ib[i + 1] = ib[i + 2] = b;
+			unsigned int invb = queryVSInvocations(device, context, ib.data(), i + 3);
+
+			ib[i + 2] = c;
+			unsigned int invc = queryVSInvocations(device, context, ib.data(), i + 3);
+
+			assert(inv0 <= inva && inva <= inv1);
+			assert(inv0 <= invb && invb <= inv1);
+			assert(inv0 <= invc && invc <= inv1);
+
+			if (inv1 - inv0 == 1 && a == c && inva == inv1 && invb == inv0 && invc == inv1)
+			{
+				xformed[i + 0] = false;
+				xformed[i + 1] = false;
+				xformed[i + 2] = true;
+			}
+			else
+			{
+				assert(inva <= invb);
+				assert(invb <= invc);
+
+				xformed[i + 0] = inva == inv0 + 1;
+				xformed[i + 1] = invb == inva + 1;
+				xformed[i + 2] = invc == invb + 1;
+			}
+			break;
+		}
+		}
+	}
+
+	unsigned int xformed_total = 0;
+
+	for (size_t i = 0; i < ib.size(); ++i)
+		xformed_total += xformed[i];
+
+	printf("// Sequence: %d indices", int(ib.size()));
+
+	for (size_t i = 0; i < ib.size(); ++i)
+	{
+		if (i % 12 == 0)
+		{
+			printf("\n// %3d*3:", int(i / 3));
+		}
+
+		if (xformed[i])
+			printf(" %3d*", ib[i]);
+		else
+			printf(" %3d ", ib[i]);
+	}
+
+	printf("\n");
+
+	std::vector<unsigned int> cached;
+
+	for (size_t i = 0; i < ib.size(); ++i)
+	{
+		unsigned int index = ib[i];
+		unsigned int inv0 = queryVSInvocations(device, context, ib.data(), ib.size());
+
+		ib.push_back(index);
+		ib.push_back(index);
+		ib.push_back(index);
+
+		unsigned int inv1 = queryVSInvocations(device, context, ib.data(), ib.size());
+
+		ib.resize(ib.size() - 3);
+
+		if (inv1 == inv0)
+			cached.push_back(index);
+	}
+
+	std::sort(cached.begin(), cached.end());
+	cached.erase(std::unique(cached.begin(), cached.end()), cached.end());
+
+	printf("// Cached  :");
+
+	for (size_t i = 0; i < cached.size(); ++i)
+		printf(" %d", cached[i]);
+
+	printf(" (%d)\n", int(cached.size()));
+
+	unsigned int invocations = queryVSInvocations(device, context, ib.data(), ib.size());
+
+	printf("// Invocations: %d\n", invocations);
+
+	assert(xformed_total == invocations);
+}
+
+void testCacheMeshes(IDXGIAdapter* adapter, int argc, char** argv)
+{
+	ID3D11Device* device = 0;
+	ID3D11DeviceContext* context = 0;
+	D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, 0, 0, D3D11_SDK_VERSION, &device, 0, &context);
+
+	setupShaders(device, context);
+
+	bool stat = false;
+
+	double atvr_sum = 0;
+	double atvr_count = 0;
+
+	unsigned int total_invocations = 0;
+	unsigned int total_vertices = 0;
+
+	for (int i = 1; i < argc; ++i)
+	{
+		const char* path = argv[i];
+
+		if (strcmp(path, "--stat") == 0)
+		{
+			stat = true;
+			continue;
+		}
+
+		ObjFile file;
+
+		if (!objParseFile(file, path))
+		{
+			printf("Error loading %s: file not found\n", path);
+			continue;
+		}
+
+		if (!objValidate(file))
+		{
+			printf("Error loading %s: invalid file data\n", path);
+			continue;
+		}
+
+		std::vector<unsigned int> ib1;
+
+		for (size_t i = 0; i < file.f_size; i += 3)
+			ib1.push_back(file.f[i]);
+
+		unsigned int vertex_count = file.v_size / 3;
+		unsigned int index_count = ib1.size();
+
+		unsigned int invocations1 = queryVSInvocations(device, context, ib1.data(), index_count);
+
+		if (stat)
+		{
+			std::vector<unsigned int> ib2(ib1.size());
+			meshopt_optimizeVertexCache(&ib2[0], &ib1[0], ib1.size(), vertex_count);
+
+			unsigned int invocations = queryVSInvocations(device, context, ib2.data(), index_count);
+
+			atvr_sum += double(invocations) / double(vertex_count);
+			atvr_count += 1;
+
+			total_invocations += invocations;
+			total_vertices += vertex_count;
+		}
+		else
+		{
+			printf("%s: baseline    %f\n", path, double(invocations1) / double(vertex_count));
+
+			std::vector<unsigned int> ib3(ib1.size());
+			meshopt_optimizeVertexCache(&ib3[0], &ib1[0], ib1.size(), vertex_count);
+
+			unsigned int invocations3 = queryVSInvocations(device, context, ib3.data(), index_count);
+
+			printf("%s: forsyth     %f\n", path, double(invocations3) / double(vertex_count));
+
+			for (unsigned int cache_size = 12; cache_size <= 24; ++cache_size)
+			{
+				std::vector<unsigned int> ib2(ib1.size());
+				meshopt_optimizeVertexCacheFifo(&ib2[0], &ib1[0], ib1.size(), vertex_count, cache_size);
+
+				unsigned int invocations2 = queryVSInvocations(device, context, ib2.data(), index_count);
+
+				printf("%s: tipsify(%d) %f\n", path, cache_size, double(invocations2) / double(vertex_count));
+			}
+		}
+	}
+
+	if (stat)
+	{
+		printf("ATVR: average %f cumulative %f; %d vertices\n", atvr_sum / atvr_count, double(total_invocations) / double(total_vertices), total_vertices);
+	}
+}
+
+int main(int argc, char** argv)
+{
+	IDXGIFactory1* factory = 0;
+	CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory);
+
+	IDXGIAdapter* adapter = NULL;
+	for (unsigned int index = 0; SUCCEEDED(factory->EnumAdapters(index, &adapter)); ++index)
+	{
+		DXGI_ADAPTER_DESC ad = {};
+		adapter->GetDesc(&ad);
+
+		if (ad.VendorId == 0x1414 && ad.DeviceId == 0x8c)
+			continue; // Skip Microsoft Basic Render Driver
+
+		printf("// GPU %d: %S (Vendor %04x Device %04x)\n", index, ad.Description, ad.VendorId, ad.DeviceId);
+
+		if (argc == 1)
+		{
+			testCache(adapter);
+		}
+		else if (argc > 1 && strcmp(argv[1], "--") == 0)
+		{
+			testCacheSequence(adapter, argc, argv);
+		}
+		else
+		{
+			testCacheMeshes(adapter, argc, argv);
+		}
+	}
+}
+#endif

+ 587 - 0
3rdparty/meshoptimizer/tools/vcachetuner.cpp

@@ -0,0 +1,587 @@
+#include "../src/meshoptimizer.h"
+#include "objparser.h"
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include <cmath>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+
+const int kCacheSizeMax = 16;
+const int kValenceMax = 8;
+
+namespace meshopt
+{
+extern thread_local float kVertexScoreTableCache[1 + kCacheSizeMax];
+extern thread_local float kVertexScoreTableLive[1 + kValenceMax];
+} // namespace meshopt
+
+struct { int cache, warp, triangle; } profiles[] =
+{
+	{14, 64, 128}, // AMD GCN
+	{32, 32, 32},  // NVidia Pascal
+	// { 16, 32, 32 }, // NVidia Kepler, Maxwell
+	// { 128, 0, 0 }, // Intel
+};
+
+const int Profile_Count = sizeof(profiles) / sizeof(profiles[0]);
+
+struct pcg32_random_t
+{
+	uint64_t state;
+	uint64_t inc;
+};
+
+#define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
+
+uint32_t pcg32_random_r(pcg32_random_t* rng)
+{
+	uint64_t oldstate = rng->state;
+	// Advance internal state
+	rng->state = oldstate * 6364136223846793005ULL + (rng->inc | 1);
+	// Calculate output function (XSH RR), uses old state for max ILP
+	uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
+	uint32_t rot = oldstate >> 59u;
+	return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
+}
+
+pcg32_random_t rngstate = PCG32_INITIALIZER;
+
+float rand01()
+{
+	return pcg32_random_r(&rngstate) / float(1ull << 32);
+}
+
+uint32_t rand32()
+{
+	return pcg32_random_r(&rngstate);
+}
+
+struct State
+{
+	float cache[kCacheSizeMax];
+	float live[kValenceMax];
+};
+
+struct Mesh
+{
+	size_t vertex_count;
+	std::vector<unsigned int> indices;
+
+	float atvr_base[Profile_Count];
+};
+
+Mesh gridmesh(unsigned int N)
+{
+	Mesh result;
+
+	result.vertex_count = (N + 1) * (N + 1);
+	result.indices.reserve(N * N * 6);
+
+	for (unsigned int y = 0; y < N; ++y)
+		for (unsigned int x = 0; x < N; ++x)
+		{
+			result.indices.push_back((y + 0) * (N + 1) + (x + 0));
+			result.indices.push_back((y + 0) * (N + 1) + (x + 1));
+			result.indices.push_back((y + 1) * (N + 1) + (x + 0));
+
+			result.indices.push_back((y + 1) * (N + 1) + (x + 0));
+			result.indices.push_back((y + 0) * (N + 1) + (x + 1));
+			result.indices.push_back((y + 1) * (N + 1) + (x + 1));
+		}
+
+	return result;
+}
+
+Mesh objmesh(const char* path)
+{
+	ObjFile file;
+
+	if (!objParseFile(file, path))
+	{
+		printf("Error loading %s: file not found\n", path);
+		return Mesh();
+	}
+
+	if (!objValidate(file))
+	{
+		printf("Error loading %s: invalid file data\n", path);
+		return Mesh();
+	}
+
+	size_t total_indices = file.f_size / 3;
+
+	struct Vertex
+	{
+		float px, py, pz;
+		float nx, ny, nz;
+		float tx, ty;
+	};
+
+	std::vector<Vertex> vertices(total_indices);
+
+	for (size_t i = 0; i < total_indices; ++i)
+	{
+		int vi = file.f[i * 3 + 0];
+		int vti = file.f[i * 3 + 1];
+		int vni = file.f[i * 3 + 2];
+
+		Vertex v =
+		    {
+		        file.v[vi * 3 + 0],
+		        file.v[vi * 3 + 1],
+		        file.v[vi * 3 + 2],
+
+		        vni >= 0 ? file.vn[vni * 3 + 0] : 0,
+		        vni >= 0 ? file.vn[vni * 3 + 1] : 0,
+		        vni >= 0 ? file.vn[vni * 3 + 2] : 0,
+
+		        vti >= 0 ? file.vt[vti * 3 + 0] : 0,
+		        vti >= 0 ? file.vt[vti * 3 + 1] : 0,
+		    };
+
+		vertices[i] = v;
+	}
+
+	Mesh result;
+
+	std::vector<unsigned int> remap(total_indices);
+
+	size_t total_vertices = meshopt_generateVertexRemap(&remap[0], NULL, total_indices, &vertices[0], total_indices, sizeof(Vertex));
+
+	result.indices.resize(total_indices);
+	meshopt_remapIndexBuffer(&result.indices[0], NULL, total_indices, &remap[0]);
+
+	result.vertex_count = total_vertices;
+
+	return result;
+}
+
+void compute_atvr(const State& state, const Mesh& mesh, float result[Profile_Count])
+{
+	memcpy(meshopt::kVertexScoreTableCache + 1, state.cache, kCacheSizeMax * sizeof(float));
+	memcpy(meshopt::kVertexScoreTableLive + 1, state.live, kValenceMax * sizeof(float));
+
+	std::vector<unsigned int> indices(mesh.indices.size());
+
+	meshopt_optimizeVertexCache(&indices[0], &mesh.indices[0], mesh.indices.size(), mesh.vertex_count);
+
+	for (int profile = 0; profile < Profile_Count; ++profile)
+		result[profile] = meshopt_analyzeVertexCache(&indices[0], indices.size(), mesh.vertex_count, profiles[profile].cache, profiles[profile].warp, profiles[profile].triangle).atvr;
+}
+
+float fitness_score(const State& state, const std::vector<Mesh>& meshes)
+{
+	float result = 0;
+	float count = 0;
+
+	for (auto& mesh : meshes)
+	{
+		float atvr[Profile_Count];
+		compute_atvr(state, mesh, atvr);
+
+		for (int profile = 0; profile < Profile_Count; ++profile)
+		{
+			result += mesh.atvr_base[profile] / atvr[profile];
+			count += 1;
+		}
+	}
+
+	return result / count;
+}
+
+float rndcache()
+{
+	return rand01();
+}
+
+float rndlive()
+{
+	return rand01();
+}
+
+std::vector<State> gen0(size_t count)
+{
+	std::vector<State> result;
+
+	for (size_t i = 0; i < count; ++i)
+	{
+		State state = {};
+
+		for (int j = 0; j < kCacheSizeMax; ++j)
+			state.cache[j] = rndcache();
+
+		for (int j = 0; j < kValenceMax; ++j)
+			state.live[j] = rndlive();
+
+		result.push_back(state);
+	}
+
+	return result;
+}
+
+size_t rndindex(const std::vector<float>& prob)
+{
+	float r = rand01();
+
+	for (size_t i = 0; i < prob.size(); ++i)
+	{
+		r -= prob[i];
+
+		if (r <= 0)
+			return i;
+	}
+
+	return prob.size() - 1;
+}
+
+State mutate(const State& state)
+{
+	State result = state;
+
+	if (rand01() < 0.7f)
+	{
+		size_t idxcache = std::min(int(rand01() * kCacheSizeMax + 0.5f), int(kCacheSizeMax - 1));
+
+		result.cache[idxcache] = rndcache();
+	}
+
+	if (rand01() < 0.7f)
+	{
+		size_t idxlive = std::min(int(rand01() * kValenceMax + 0.5f), int(kValenceMax - 1));
+
+		result.live[idxlive] = rndlive();
+	}
+
+	if (rand01() < 0.2f)
+	{
+		uint32_t mask = rand32();
+
+		for (size_t i = 0; i < kCacheSizeMax; ++i)
+			if (mask & (1 << i))
+				result.cache[i] *= 0.9f + 0.2f * rand01();
+	}
+
+	if (rand01() < 0.2f)
+	{
+		uint32_t mask = rand32();
+
+		for (size_t i = 0; i < kValenceMax; ++i)
+			if (mask & (1 << i))
+				result.live[i] *= 0.9f + 0.2f * rand01();
+	}
+
+	if (rand01() < 0.05f)
+	{
+		uint32_t mask = rand32();
+
+		for (size_t i = 0; i < kCacheSizeMax; ++i)
+			if (mask & (1 << i))
+				result.cache[i] = rndcache();
+	}
+
+	if (rand01() < 0.05f)
+	{
+		uint32_t mask = rand32();
+
+		for (size_t i = 0; i < kValenceMax; ++i)
+			if (mask & (1 << i))
+				result.live[i] = rndlive();
+	}
+
+	return result;
+}
+
+bool accept(float fitnew, float fitold, float temp)
+{
+	if (fitnew >= fitold)
+		return true;
+
+	if (temp == 0)
+		return false;
+
+	float prob = exp2((fitnew - fitold) / temp);
+
+	return rand01() < prob;
+}
+
+std::pair<State, float> genN_SA(std::vector<State>& seed, const std::vector<Mesh>& meshes, size_t steps)
+{
+	std::vector<State> result;
+	result.reserve(seed.size() * (1 + steps));
+
+	// perform several parallel steps of mutation for each temperature
+	for (size_t i = 0; i < seed.size(); ++i)
+	{
+		result.push_back(seed[i]);
+
+		for (size_t s = 0; s < steps; ++s)
+			result.push_back(mutate(seed[i]));
+	}
+
+	// compute fitness for all temperatures & mutations in parallel
+	std::vector<float> resultfit(result.size());
+
+#pragma omp parallel for
+	for (size_t i = 0; i < result.size(); ++i)
+	{
+		resultfit[i] = fitness_score(result[i], meshes);
+	}
+
+	// perform annealing for each temperature
+	std::vector<float> seedfit(seed.size());
+
+	for (size_t i = 0; i < seed.size(); ++i)
+	{
+		size_t offset = i * (1 + steps);
+
+		seedfit[i] = resultfit[offset];
+
+		float temp = (float(i) / float(seed.size() - 1)) / 0.1f;
+
+		for (size_t s = 0; s < steps; ++s)
+		{
+			if (accept(resultfit[offset + s + 1], seedfit[i], temp))
+			{
+				seedfit[i] = resultfit[offset + s + 1];
+				seed[i] = result[offset + s + 1];
+			}
+		}
+	}
+
+	// perform promotion from each temperature to the next one
+	for (size_t i = seed.size() - 1; i > 0; --i)
+	{
+		if (seedfit[i] > seedfit[i - 1])
+		{
+			seedfit[i - 1] = seedfit[i];
+			seed[i - 1] = seed[i];
+		}
+	}
+
+	return std::make_pair(seed[0], seedfit[0]);
+}
+
+std::pair<State, float> genN_GA(std::vector<State>& seed, const std::vector<Mesh>& meshes, float crossover, float mutate)
+{
+	std::vector<State> result;
+	result.reserve(seed.size());
+
+	std::vector<float> seedprob(seed.size());
+
+#pragma omp parallel for
+	for (size_t i = 0; i < seed.size(); ++i)
+	{
+		seedprob[i] = fitness_score(seed[i], meshes);
+	}
+
+	State best = {};
+	float bestfit = 0;
+	float probsum = 0;
+
+	for (size_t i = 0; i < seed.size(); ++i)
+	{
+		float score = seedprob[i];
+		probsum += score;
+
+		if (score > bestfit)
+		{
+			best = seed[i];
+			bestfit = score;
+		}
+	}
+
+	for (auto& prob : seedprob)
+	{
+		prob /= probsum;
+	}
+
+	std::vector<unsigned int> seedidx;
+	seedidx.reserve(seed.size());
+	for (size_t i = 0; i < seed.size(); ++i)
+		seedidx.push_back(i);
+
+	std::sort(seedidx.begin(), seedidx.end(), [&](size_t l, size_t r) { return seedprob[l] < seedprob[r]; });
+
+	while (result.size() < seed.size() / 4)
+	{
+		size_t idx = seedidx.back();
+		seedidx.pop_back();
+
+		result.push_back(seed[idx]);
+	}
+
+	while (result.size() < seed.size())
+	{
+		State s0 = seed[rndindex(seedprob)];
+		State s1 = seed[rndindex(seedprob)];
+
+		State state = s0;
+
+		// crossover
+		if (rand01() < crossover)
+		{
+			size_t idxcache = std::min(int(rand01() * kCacheSizeMax + 0.5f), 15);
+
+			memcpy(state.cache + idxcache, s1.cache + idxcache, (kCacheSizeMax - idxcache) * sizeof(float));
+		}
+
+		if (rand01() < crossover)
+		{
+			size_t idxlive = std::min(int(rand01() * kValenceMax + 0.5f), 7);
+
+			memcpy(state.live + idxlive, s1.live + idxlive, (kValenceMax - idxlive) * sizeof(float));
+		}
+
+		// mutate
+		if (rand01() < mutate)
+		{
+			size_t idxcache = std::min(int(rand01() * kCacheSizeMax + 0.5f), 15);
+
+			state.cache[idxcache] = rndcache();
+		}
+
+		if (rand01() < mutate)
+		{
+			size_t idxlive = std::min(int(rand01() * kValenceMax + 0.5f), 7);
+
+			state.live[idxlive] = rndlive();
+		}
+
+		result.push_back(state);
+	}
+
+	seed.swap(result);
+
+	return std::make_pair(best, bestfit);
+}
+
+bool load_state(const char* path, std::vector<State>& result)
+{
+	FILE* file = fopen(path, "rb");
+	if (!file)
+		return false;
+
+	State state;
+
+	result.clear();
+
+	while (fread(&state, sizeof(State), 1, file) == 1)
+		result.push_back(state);
+
+	fclose(file);
+
+	return true;
+}
+
+bool save_state(const char* path, const std::vector<State>& result)
+{
+	FILE* file = fopen(path, "wb");
+	if (!file)
+		return false;
+
+	for (auto& state : result)
+	{
+		if (fwrite(&state, sizeof(State), 1, file) != 1)
+		{
+			fclose(file);
+			return false;
+		}
+	}
+
+	return fclose(file) == 0;
+}
+
+void dump_state(const State& state)
+{
+	printf("cache:");
+	for (int i = 0; i < kCacheSizeMax; ++i)
+	{
+		printf(" %.3f", state.cache[i]);
+	}
+	printf("\n");
+
+	printf("live:");
+	for (int i = 0; i < kValenceMax; ++i)
+	{
+		printf(" %.3f", state.live[i]);
+	}
+	printf("\n");
+}
+
+int main(int argc, char** argv)
+{
+	bool annealing = false;
+
+	State baseline;
+	memcpy(baseline.cache, meshopt::kVertexScoreTableCache + 1, kCacheSizeMax * sizeof(float));
+	memcpy(baseline.live, meshopt::kVertexScoreTableLive + 1, kValenceMax * sizeof(float));
+
+	std::vector<Mesh> meshes;
+
+	meshes.push_back(gridmesh(50));
+
+	for (int i = 1; i < argc; ++i)
+		meshes.push_back(objmesh(argv[i]));
+
+	size_t total_triangles = 0;
+
+	for (auto& mesh : meshes)
+	{
+		compute_atvr(baseline, mesh, mesh.atvr_base);
+
+		total_triangles += mesh.indices.size() / 3;
+	}
+
+	std::vector<State> pop;
+	size_t gen = 0;
+
+	if (load_state("mutator.state", pop))
+	{
+		printf("Loaded %d state vectors\n", int(pop.size()));
+	}
+	else
+	{
+		pop = gen0(annealing ? 32 : 1000);
+	}
+
+	printf("%d meshes, %.1fM triangles\n", int(meshes.size()), double(total_triangles) / 1e6);
+
+	float atvr_0[Profile_Count];
+	float atvr_N[Profile_Count];
+	compute_atvr(baseline, meshes[0], atvr_0);
+	compute_atvr(baseline, meshes.back(), atvr_N);
+
+	printf("baseline: grid %f %f %s %f %f\n", atvr_0[0], atvr_0[1], argv[argc - 1], atvr_N[0], atvr_N[1]);
+
+	for (;;)
+	{
+		auto best = annealing ? genN_SA(pop, meshes, 31) : genN_GA(pop, meshes, 0.7f, 0.3f);
+		gen++;
+
+		compute_atvr(best.first, meshes[0], atvr_0);
+		compute_atvr(best.first, meshes.back(), atvr_N);
+
+		printf("%d: fitness %f; grid %f %f %s %f %f\n", int(gen), best.second, atvr_0[0], atvr_0[1], argv[argc - 1], atvr_N[0], atvr_N[1]);
+
+		if (gen % 100 == 0)
+		{
+			char buf[128];
+			sprintf(buf, "gcloud logging write vcache-log \"fitness %f; grid %f %f %s %f %f\"", best.second, atvr_0[0], atvr_0[1], argv[argc - 1], atvr_N[0], atvr_N[1]);
+			system(buf);
+		}
+
+		dump_state(best.first);
+
+		if (save_state("mutator.state-temp", pop) && rename("mutator.state-temp", "mutator.state") == 0)
+		{
+		}
+		else
+		{
+			printf("ERROR: Can't save state\n");
+		}
+	}
+}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików