diff --git a/README.md b/README.md index 22d2f34..e1e1ada 100644 --- a/README.md +++ b/README.md @@ -1,348 +1,122 @@ CUDA Rasterizer -=============== +================ **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 4** -* (TODO) YOUR NAME HERE -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) - -### (TODO: Your README) - -*DO NOT* leave the README to the last minute! It is a crucial part of the -project, and we will not be able to grade you without a good README. - - -Instructions (delete me) -======================== - -This is due Sunday, October 11, evening at midnight. - -**Summary:** -In this project, you will use CUDA to implement a simplified -rasterized graphics pipeline, similar to the OpenGL pipeline. You will -implement vertex shading, primitive assembly, rasterization, fragment shading, -and a framebuffer. More information about the rasterized graphics pipeline can -be found in the class slides and in the CIS 560 lecture notes. - -The base code provided includes an OBJ loader and much of the I/O and -bookkeeping code. It also includes some functions that you may find useful, -described below. The core rasterization pipeline is left for you to implement. - -You are not required to use this base code if you don't want -to. You may also change any part of the base code as you please. -**This is YOUR project.** - -**Recommendation:** -Every image you save should automatically get a different -filename. Don't delete all of them! For the benefit of your README, keep a -bunch of them around so you can pick a few to document your progress. - - -### Contents - -* `src/` C++/CUDA source files. -* `util/` C++ utility files. -* `objs/` Example OBJ test files (# verts, # tris in buffers after loading) - * `tri.obj` (3v, 1t): The simplest possible geometric object. - * `cube.obj` (36v, 12t): A small model with low depth-complexity. - * `suzanne.obj` (2904 verts, 968 tris): A medium model with low depth-complexity. - * `suzanne_smooth.obj` (2904 verts, 968 tris): A medium model with low depth-complexity. - This model has normals which must be interpolated. - * `cow.obj` (17412 verts, 5804 tris): A large model with low depth-complexity. - * `cow_smooth.obj` (17412 verts, 5804 tris): A large model with low depth-complexity. - This model has normals which must be interpolated. - * `flower.obj` (1920 verts, 640 tris): A medium model with very high depth-complexity. - * `sponza.obj` (837,489 verts, 279,163 tris): A huge model with very high depth-complexity. -* `renders/` Debug render of an example OBJ. -* `external/` Includes and static libraries for 3rd party libraries. - -### Running the code - -The main function requires a scene description file. Call the program with -one as an argument: `cis565_rasterizer objs/cow.obj`. -(In Visual Studio, `../objs/cow.obj`.) - -If you are using Visual Studio, you can set this in the Debugging > Command -Arguments section in the Project properties. Note that this value is different -for every different configuration type. Make sure you get the path right; read -the console for errors. - -## Requirements +* Shuai Shao (Shrek) +* Tested on: Windows 10, i7-4710HQ @ 2.50GHz 16GB, GeForce GTX 970M (Personal Computer) + +----------------------------------------- + + +## Video Demo +* video demo: +[![youtube_link](img/youtube.png)](https://www.youtube.com/watch?v=w6E4QnAhRAY) + +## Feature Display Images + +#### earth ( bilinear texture filtering; diffuse, specular map) +![earth](img/earth.png) + +|nearest neighbor filtering | bilinear filtering | +|--------------------------| --------------------| +|![nn](img/tex_nearest_neighbor.png) |![bilinear](img/tex_bilinear_filter.png) | + + +#### Rusty car( bilinear texture filtering) +![rusty_car](img/oldcar.png) + + +#### Shading mode +|complete| wireframe | vertex| +|--------------------------| --------------------|------| +|![complete](img/car_shade.png) |![wf](img/car_wireframe.png) | ![v](img/car_vertex.png)| + + +#### Backface Culling +|without | with backface culling | +|--------------------------| --------------------| +|![without](img/cow_wireframe.png) |![with](img/cow_wireframe_backfaceculling.png) | + + +#### Antialiasing +|without | with antialiasing | +|--------------------------| --------------------| +|![without](img/antialiasing_contrast.png) |![with](img/antialiasing_test.png) | + + +#### smooth interpolation +|normal without smooth | normal with smooth | +|--------------------------| --------------------| +|![us](img/cow_normal_unsmooth.png) |![s](img/cow_normal_smooth.png) | + + +#### Scissor Test (easy and boring...) +![scissor_test](img/scissor_test.png) + +#### Huge obj try (improve from 0fps to 3fps...-_-!!!) +![sponza](img/sponza.png) + + +----------------------------------- +## Control + +* `Mouse Left button` : Rotate +* `Mouse Right button` : Translate +* `Mouse Wheel`: Scale +* `b`: enable/disable backface culling +* `s`: switch shading mode : normal / phong shading on default material / phong shading with texture +* `w`: switch rasterization mode : complete / wireframe / vertex + + +## Outline +* [sss](#General-Intro) + + +## PipeLine Description + +* Vertex Shader +takes in VertexIn list, apply the transformation to NDC space and outputs in VertexOut list. Every feature needs to divide w to make perspective correct interpolation (which is critical for texture mapping). + +* Primitive Assembly +takes in VertexOut list, assembles as primitives and output to Primitive list. This step can be merged into Vertex Shader, sharing the same kernel. + * __simple clipping__ + discard the primitives that are totally out of the viewport. Which can improve performance when only a small fraction of the obj is in viewport. + +* Backface culling (optional) +uses thrust stream compaction to remove a primitive if it faces backward. Reduce the number of primitives for rasterization. However, the stream compaction itself costs time. So only when there's a large number of primitives will the impact be seen in FPS (sponza). + +* Rasterization +Use Scanline algorithm for each triangle. Each thread handles one triangle. + * __pixel-walk scanline__: Instead of using a Bounding Box to scan, I calculate the two edge of a triangle that is currently enrolled in the scanning. With the dx and dz, I can move one pixel a time between x_left and x_right and do rasterization immediately. No need for testing if a point is in triangle. So I thought the scanline process can be faster. But turns out it slows down comparing to others result. I think it may because more kernels, functions and register are used (144 per thread...). (x2-x4 slower) + * __supports for wire frame and vertex rasterize__: Different from a geometry shader, this approach changes rasterization method to support wire frame and vertex. This approach is simpler to implement and achieve visually good result. + * __antialiasing__: I implement antialiasing by picking several samples at the edge of the scanline, multiply the final value with a ratio of samples falling in the triangle. This leads to a wireframed image since each triangle are independent so samples out of its triangle cannot get value from other triangles. I fix this using some hacks in fragment shader. + * __depth_test__: When finish rasterization, it needs to be written to fragment shader. This needs to avoid racing condition. I use a int depth buffer and `atomicMin`, and turned the float z value to fixed point value. But there are still rare race issues on large obj(sponza). The possible reason is float limitation. + +* Fragment Shader +Each thread handle one fragment. color by normal, phong shading, or phong with texture + * __texture mapping__: use the uv to pick color value from texture image and use bilinear filtering to eliminate blocky look. Bilinear filtering without mipmapping can be useful when scaling less than two times of original size or larger than half size. + * __scissor test__: This is implemented by discarding fragments out of the clipped rectangle. If a stencil mask is used, this can be useful when rendering a sniper's view. This only has an impact on performance when using an expensive fragment shader. + + +## Performance Analysis + +![s](img/chart.png) + +Vertex shader greatly depends on the number of vertex, while rasterization is related to how big the surfaces to scan are. + +Doing this makes me realize my piece-walk scanline doesn't turn out to fit the GPU well. It needs up to 144 registers per thread which is a huge bottle neck. + +* Backculling +decrease 18% time consuming in rasterization on Lamborghini obj. + +Increase FPS from 0 to 3fps on sponza.... + + +## Reference + +* Transformation: http://www.songho.ca/opengl/gl_transform.html +* pixel-walk Scanline: Stanford CS248 Interactive Computer Graphics +* objs are from www.blend.org, tf3dm.com + -**Ask on the mailing list for any clarifications.** - -In this project, you are given the following code: - -* A library for loading standard Alias/Wavefront `.obj` format mesh - files and converting them to OpenGL-style buffers of index and vertex data. - * This library does NOT read materials, and provides all colors as white by - default. You can use another library if you wish. -* Simple structs for some parts of the pipeline. -* Depth buffer to framebuffer copy. -* CUDA-GL interop. - -You will need to implement the following features/pipeline stages: - -* Vertex shading. -* (Vertex shader) perspective transformation. -* Primitive assembly with support for triangles read from buffers of index and - vertex data. -* Rasterization. -* Fragment shading. -* A depth buffer for storing and depth testing fragments. -* Fragment to depth buffer writing (**with** atomics for race avoidance). -* (Fragment shader) simple lighting scheme, such as Lambert or Blinn-Phong. - -See below for more guidance. - -You are also required to implement at least "3.0" points in extra features. -(the parenthesized numbers must add to 3.0 or more): - -* (1.0) Tile-based pipeline. -* Additional pipeline stages. - * (1.0) Tessellation shader. - * (1.0) Geometry shader, able to output a variable number of primitives per - input primitive, optimized using stream compaction (thrust allowed). - * (0.5 **if not doing geometry shader**) Backface culling, optimized using - stream compaction (thrust allowed). - * (1.0) Transform feedback. - * (0.5) Scissor test. - * (0.5) Blending (when writing into framebuffer). -* (1.0) Instancing: draw one set of vertex data multiple times, each run - through the vertex shader with a different ID. -* (0.5) Correct color interpolation between points on a primitive. -* (1.0) UV texture mapping with bilinear texture filtering and perspective - correct texture coordinates. -* Support for rasterizing additional primitives: - * (0.5) Lines or line strips. - * (0.5) Points. -* (1.0) Anti-aliasing. -* (1.0) Occlusion queries. -* (1.0) Order-independent translucency using a k-buffer. -* (0.5) **Mouse**-based interactive camera support. - -This extra feature list is not comprehensive. If you have a particular idea -you would like to implement, please **contact us first**. - -**IMPORTANT:** -For each extra feature, please provide the following brief analysis: - -* Concise overview write-up of the feature. -* Performance impact of adding the feature (slower or faster). -* If you did something to accelerate the feature, what did you do and why? -* How might this feature be optimized beyond your current implementation? - - -## Base Code Tour - -You will be working primarily in two files: `rasterize.cu`, and -`rasterizeTools.h`. Within these files, areas that you need to complete are -marked with a `TODO` comment. Areas that are useful to and serve as hints for -optional features are marked with `TODO (Optional)`. Functions that are useful -for reference are marked with the comment `CHECKITOUT`. **You should look at -all TODOs and CHECKITOUTs before starting!** There are not many. - -* `src/rasterize.cu` contains the core rasterization pipeline. - * A few pre-made structs are included for you to use, but those marked with - TODO will also be needed for a simple rasterizer. As with any part of the - base code, you may modify or replace these as you see fit. - -* `src/rasterizeTools.h` contains various useful tools - * Includes a number of barycentric coordinate related functions that you may - find useful in implementing scanline based rasterization. - -* `util/utilityCore.hpp` serves as a kitchen-sink of useful functions. - - -## Rasterization Pipeline - -Possible pipelines are described below. Pseudo-type-signatures are given. -Not all of the pseudocode arrays will necessarily actually exist in practice. - -### First-Try Pipeline - -This describes a minimal version of *one possible* graphics pipeline, similar -to modern hardware (DX/OpenGL). Yours need not match precisely. To begin, try -to write a minimal amount of code as described here. Verify some output after -implementing each pipeline step. This will reduce the necessary time spent -debugging. - -Start out by testing a single triangle (`tri.obj`). - -* Clear the depth buffer with some default value. -* Vertex shading: - * `VertexIn[n] vs_input -> VertexOut[n] vs_output` - * A minimal vertex shader will apply no transformations at all - it draws - directly in normalized device coordinates (-1 to 1 in each dimension). -* Primitive assembly. - * `VertexOut[n] vs_output -> Triangle[n/3] primitives` - * Start by supporting ONLY triangles. For a triangle defined by indices - `(a, b, c)` into `VertexOut` array `vo`, simply copy the appropriate values - into a `Triangle` object `(vo[a], vo[b], vo[c])`. -* Rasterization. - * `Triangle[n/3] primitives -> FragmentIn[m] fs_input` - * A scanline implementation is simpler to start with. -* Fragment shading. - * `FragmentIn[m] fs_input -> FragmentOut[m] fs_output` - * A super-simple test fragment shader: output same color for every fragment. - * Also try displaying various debug views (normals, etc.) -* Fragments to depth buffer. - * `FragmentOut[m] -> FragmentOut[width][height]` - * Results in race conditions - don't bother to fix these until it works! - * Can really be done inside the fragment shader, if you call the fragment - shader from the rasterization kernel for every fragment (including those - which get occluded). **OR,** this can be done before fragment shading, which - may be faster but means the fragment shader cannot change the depth. -* A depth buffer for storing and depth testing fragments. - * `FragmentOut[width][height] depthbuffer` - * An array of `fragment` objects. - * At the end of a frame, it should contain the fragments drawn to the screen. -* Fragment to framebuffer writing. - * `FragmentOut[width][height] depthbuffer -> vec3[width][height] framebuffer` - * Simply copies the colors out of the depth buffer into the framebuffer - (to be displayed on the screen). - -### A Useful Pipeline - -* Clear the depth buffer with some default value. -* Vertex shading: - * `VertexIn[n] vs_input -> VertexOut[n] vs_output` - * Apply some vertex transformation (e.g. model-view-projection matrix using - `glm::lookAt ` and `glm::perspective `). -* Primitive assembly. - * `VertexOut[n] vs_output -> Triangle[n/3] primitives` - * As above. - * Other primitive types are optional. -* Rasterization. - * `Triangle[n/3] primitives -> FragmentIn[m] fs_input` - * You may choose to do a tiled rasterization method, which should have lower - global memory bandwidth. - * A scanline optimization: when rasterizing a triangle, only scan over the - box around the triangle (`getAABBForTriangle`). -* Fragment shading. - * `FragmentIn[m] fs_input -> FragmentOut[m] fs_output` - * Add a shading method, such as Lambert or Blinn-Phong. Lights can be defined - by kernel parameters (like GLSL uniforms). -* Fragments to depth buffer. - * `FragmentOut[m] -> FragmentOut[width][height]` - * Can really be done inside the fragment shader, if you call the fragment - shader from the rasterization kernel for every fragment (including those - which get occluded). **OR,** this can be done before fragment shading, which - may be faster but means the fragment shader cannot change the depth. - * This result in an optimization: it allows you to do depth tests before - spending execution time in complex fragment shader code! - * Handle race conditions! Since multiple primitives write fragments to the - same fragment in the depth buffer, races must be avoided by using CUDA - atomics. - * *Approach 1:* Lock the location in the depth buffer during the time that - a thread is comparing old and new fragment depths (and possibly writing - a new fragment). This should work in all cases, but be slower. - * *Approach 2:* Convert your depth value to a fixed-point `int`, and use - `atomicMin` to store it into an `int`-typed depth buffer `intdepth`. After - that, the value which is stored at `intdepth[i]` is (usually) that of the - fragment which should be stored into the `fragment` depth buffer. - * This may result in some rare race conditions (e.g. across blocks). - * The `flower.obj` test file is good for testing race conditions. -* A depth buffer for storing and depth testing fragments. - * `FragmentOut[width][height] depthbuffer` - * An array of `fragment` objects. - * At the end of a frame, it should contain the fragments drawn to the screen. -* Fragment to framebuffer writing. - * `FragmentOut[width][height] depthbuffer -> vec3[width][height] framebuffer` - * Simply copies the colors out of the depth buffer into the framebuffer - (to be displayed on the screen). - -This is a suggested sequence of pipeline steps, but you may choose to alter the -order of this sequence or merge entire kernels as you see fit. For example, if -you decide that doing has benefits, you can choose to merge the vertex shader -and primitive assembly kernels, or merge the perspective transform into another -kernel. There is not necessarily a right sequence of kernels, and you may -choose any sequence that works. Please document in your README what sequence -you choose and why. - - -## Resources - -The following resources may be useful for this project: - -* High-Performance Software Rasterization on GPUs: - * [Paper (HPG 2011)](http://www.tml.tkk.fi/~samuli/publications/laine2011hpg_paper.pdf) - * [Code](http://code.google.com/p/cudaraster/) - * Note that looking over this code for reference with regard to the paper is - fine, but we most likely will not grant any requests to actually - incorporate any of this code into your project. - * [Slides](http://bps11.idav.ucdavis.edu/talks/08-gpuSoftwareRasterLaineAndPantaleoni-BPS2011.pdf) -* The Direct3D 10 System (SIGGRAPH 2006) - for those interested in doing - geometry shaders and transform feedback: - * [Paper](http://dl.acm.org/citation.cfm?id=1141947) - * [Paper, through Penn Libraries proxy](http://proxy.library.upenn.edu:2247/citation.cfm?id=1141947) -* Multi-Fragment Effects on the GPU using the k-Buffer - for those who want to do - order-independent transparency using a k-buffer: - * [Paper](http://www.inf.ufrgs.br/~comba/papers/2007/kbuffer_preprint.pdf) -* FreePipe: A Programmable, Parallel Rendering Architecture for Efficient - Multi-Fragment Effects (I3D 2010): - * [Paper](https://sites.google.com/site/hmcen0921/cudarasterizer) -* Writing A Software Rasterizer In Javascript: - * [Part 1](http://simonstechblog.blogspot.com/2012/04/software-rasterizer-part-1.html) - * [Part 2](http://simonstechblog.blogspot.com/2012/04/software-rasterizer-part-2.html) - - -## Third-Party Code Policy - -* Use of any third-party code must be approved by asking on our Google Group. -* If it is approved, all students are welcome to use it. Generally, we approve - use of third-party code that is not a core part of the project. For example, - for the path tracer, we would approve using a third-party library for loading - models, but would not approve copying and pasting a CUDA function for doing - refraction. -* Third-party code **MUST** be credited in README.md. -* Using third-party code without its approval, including using another - student's code, is an academic integrity violation, and will, at minimum, - result in you receiving an F for the semester. - - -## README - -Replace the contents of this README.md in a clear manner with the following: - -* A brief description of the project and the specific features you implemented. -* At least one screenshot of your project running. -* A 30 second or longer video of your project running. -* A performance analysis (described below). - -### Performance Analysis - -The performance analysis is where you will investigate how to make your CUDA -programs more efficient using the skills you've learned in class. You must have -performed at least one experiment on your code to investigate the positive or -negative effects on performance. - -We encourage you to get creative with your tweaks. Consider places in your code -that could be considered bottlenecks and try to improve them. - -Provide summary of your optimizations (no more than one page), along with -tables and or graphs to visually explain any performance differences. - -* Include a breakdown of time spent in each pipeline stage for a few different - models. It is suggested that you use pie charts or 100% stacked bar charts. -* For optimization steps (like backface culling), include a performance - comparison to show the effectiveness. - - -## Submit - -If you have modified any of the `CMakeLists.txt` files at all (aside from the -list of `SOURCE_FILES`), you must test that your project can build in Moore -100B/C. Beware of any build issues discussed on the Google Group. - -1. Open a GitHub pull request so that we can see that you have finished. - The title should be "Submission: YOUR NAME". - * **ADDITIONALLY:** - In the body of the pull request, include a link to your repository. -2. Send an email to the TA (gmail: kainino1+cis565@) with: - * **Subject**: in the form of `[CIS565] Project N: PENNKEY`. - * Direct link to your pull request on GitHub. - * Estimate the amount of time you spent on the project. - * If there were any outstanding problems, or if you did any extra - work, *briefly* explain. - * Feedback on the project itself, if any. diff --git a/img/0.png b/img/0.png new file mode 100644 index 0000000..8e62104 Binary files /dev/null and b/img/0.png differ diff --git a/img/1.png b/img/1.png new file mode 100644 index 0000000..f9bd582 Binary files /dev/null and b/img/1.png differ diff --git a/img/antialiasing_contrast.png b/img/antialiasing_contrast.png new file mode 100644 index 0000000..da687ea Binary files /dev/null and b/img/antialiasing_contrast.png differ diff --git a/img/antialiasing_test.png b/img/antialiasing_test.png new file mode 100644 index 0000000..6b9ea5f Binary files /dev/null and b/img/antialiasing_test.png differ diff --git a/img/car_normal.png b/img/car_normal.png new file mode 100644 index 0000000..2884993 Binary files /dev/null and b/img/car_normal.png differ diff --git a/img/car_shade.png b/img/car_shade.png new file mode 100644 index 0000000..f65e087 Binary files /dev/null and b/img/car_shade.png differ diff --git a/img/car_vertex.png b/img/car_vertex.png new file mode 100644 index 0000000..3017551 Binary files /dev/null and b/img/car_vertex.png differ diff --git a/img/car_wireframe.png b/img/car_wireframe.png new file mode 100644 index 0000000..822354d Binary files /dev/null and b/img/car_wireframe.png differ diff --git a/img/chart.png b/img/chart.png new file mode 100644 index 0000000..5e4688d Binary files /dev/null and b/img/chart.png differ diff --git a/img/cow_normal_smooth.png b/img/cow_normal_smooth.png new file mode 100644 index 0000000..f0c3cf9 Binary files /dev/null and b/img/cow_normal_smooth.png differ diff --git a/img/cow_normal_unsmooth.png b/img/cow_normal_unsmooth.png new file mode 100644 index 0000000..ca42354 Binary files /dev/null and b/img/cow_normal_unsmooth.png differ diff --git a/img/cow_shade_smooth.png b/img/cow_shade_smooth.png new file mode 100644 index 0000000..78d1798 Binary files /dev/null and b/img/cow_shade_smooth.png differ diff --git a/img/cow_vertex.png b/img/cow_vertex.png new file mode 100644 index 0000000..0c38c37 Binary files /dev/null and b/img/cow_vertex.png differ diff --git a/img/cow_wireframe.png b/img/cow_wireframe.png new file mode 100644 index 0000000..dc13929 Binary files /dev/null and b/img/cow_wireframe.png differ diff --git a/img/cow_wireframe_backfaceculling.png b/img/cow_wireframe_backfaceculling.png new file mode 100644 index 0000000..f5da7ec Binary files /dev/null and b/img/cow_wireframe_backfaceculling.png differ diff --git a/img/earth.png b/img/earth.png new file mode 100644 index 0000000..ecd0781 Binary files /dev/null and b/img/earth.png differ diff --git a/img/oldcar.png b/img/oldcar.png new file mode 100644 index 0000000..f206915 Binary files /dev/null and b/img/oldcar.png differ diff --git a/img/scissor_test.png b/img/scissor_test.png new file mode 100644 index 0000000..5281941 Binary files /dev/null and b/img/scissor_test.png differ diff --git a/img/sponza.png b/img/sponza.png new file mode 100644 index 0000000..50fa62e Binary files /dev/null and b/img/sponza.png differ diff --git a/img/tex_bilinear_filter.png b/img/tex_bilinear_filter.png new file mode 100644 index 0000000..c4aac66 Binary files /dev/null and b/img/tex_bilinear_filter.png differ diff --git a/img/tex_nearest_neighbor.png b/img/tex_nearest_neighbor.png new file mode 100644 index 0000000..5efd012 Binary files /dev/null and b/img/tex_nearest_neighbor.png differ diff --git a/img/youtube.png b/img/youtube.png new file mode 100644 index 0000000..c5f908f Binary files /dev/null and b/img/youtube.png differ diff --git a/objs/bunny.obj b/objs/bunny.obj new file mode 100644 index 0000000..5edcca8 --- /dev/null +++ b/objs/bunny.obj @@ -0,0 +1,9979 @@ +# Blender3D v249 OBJ File: bunny.blend +# www.blender3d.org +mtllib models/bunny.mtl +v 0.246255 0.361040 0.127048 +v -0.536834 0.582859 0.206065 +v -0.025078 0.305633 -0.079512 +v 0.031341 0.178958 0.285107 +v 0.096300 0.842150 -0.332691 +v 0.471036 0.272337 0.229189 +v 0.340769 0.307280 0.236033 +v 0.145667 0.687780 -0.210496 +v -0.063575 0.781513 -0.100317 +v -0.562784 0.153571 -0.053398 +v -0.141978 0.779002 -0.132295 +v -0.352727 0.623906 -0.228883 +v -0.488682 0.728648 -0.359809 +v -0.442182 0.211800 0.426208 +v 0.410170 0.194482 0.292534 +v -0.098216 0.758855 -0.076259 +v 0.329047 -0.562532 0.368181 +v -0.291448 -0.532967 0.372518 +v -0.171734 -0.553764 0.354542 +v -0.057258 0.319632 -0.073363 +v -0.222066 0.635219 0.003449 +v 0.068188 0.646638 -0.137419 +v -0.284372 0.635685 -0.008709 +v -0.247663 -0.528957 0.371202 +v -0.219246 -0.511136 0.354131 +v -0.017130 -0.576757 0.434438 +v 0.244918 -0.515558 0.384920 +v 0.329662 -0.522329 0.366738 +v -0.110525 0.745047 -0.209742 +v -0.288653 -0.487785 0.341874 +v -0.132092 -0.511166 0.330800 +v 0.015637 -0.491810 0.421699 +v 0.061687 -0.501926 0.441943 +v -0.089605 0.747775 -0.077239 +v -0.391809 0.674978 -0.227833 +v 0.777958 -0.239803 0.146825 +v -0.211509 -0.478043 0.321205 +v -0.165547 -0.504176 0.336359 +v -0.156508 -0.470610 0.312368 +v 0.055438 -0.477019 0.428358 +v 0.215183 -0.491793 0.384532 +v 0.284127 -0.492797 0.374704 +v 0.620596 0.193232 0.155457 +v 0.015678 0.868270 -0.171307 +v 0.105022 -0.462513 0.397801 +v 0.210344 -0.477990 0.384360 +v 0.340219 -0.475264 0.400241 +v 0.371364 -0.457411 0.403036 +v -0.074180 0.182321 0.260059 +v -0.479475 0.439925 0.401670 +v 0.628742 -0.510621 0.199048 +v -0.246198 -0.457213 0.296816 +v -0.193432 -0.457589 0.300772 +v -0.108980 -0.478513 0.313152 +v 0.015668 -0.463991 0.402730 +v 0.056699 -0.461419 0.410770 +v 0.146623 -0.463231 0.388343 +v 0.158422 -0.447452 0.404349 +v 0.274021 -0.470225 0.400873 +v 0.301014 -0.441109 0.432407 +v 0.052864 -0.443317 0.375560 +v 0.100336 -0.442977 0.378984 +v 0.202320 -0.440462 0.419391 +v 0.253513 -0.429681 0.441372 +v -0.358399 0.671854 -0.291138 +v 0.604697 -0.488816 0.212672 +v -0.600289 0.307521 -0.084754 +v -0.134680 0.732696 -0.057730 +v -0.364213 0.592134 -0.141676 +v -0.062675 -0.436954 0.292365 +v 0.050863 -0.431949 0.348769 +v 0.136810 -0.397873 0.416608 +v 0.294130 -0.419128 0.440995 +v 0.316642 -0.410169 0.443732 +v 0.361081 -0.426414 0.427240 +v -0.446302 0.358403 0.426187 +v 0.660285 -0.444223 0.228525 +v 0.665330 -0.461531 0.226879 +v 0.495392 0.314243 0.122031 +v -0.484456 0.540586 -0.179872 +v -0.592047 0.254566 -0.092277 +v -0.156842 0.740118 -0.067070 +v -0.126165 0.284495 0.172407 +v -0.186505 -0.396448 0.285378 +v -0.160360 -0.431573 0.299283 +v -0.101084 -0.436159 0.302526 +v 0.081599 -0.426078 0.370925 +v 0.111245 -0.423720 0.394098 +v 0.117865 -0.399234 0.412574 +v 0.175892 -0.405296 0.429091 +v 0.237266 -0.397480 0.448587 +v 0.358510 -0.391649 0.437007 +v 0.659908 0.106716 -0.122527 +v -0.509681 0.342900 0.440998 +v -0.517433 0.402734 0.419407 +v -0.310940 0.561816 0.254400 +v -0.376561 0.554026 0.291114 +v -0.039159 0.309684 0.103510 +v -0.413369 0.664022 -0.182400 +v -0.171898 0.351391 0.113280 +v -0.138434 -0.380512 0.307471 +v -0.025791 -0.398029 0.276447 +v 0.032481 -0.416093 0.317902 +v 0.064468 -0.373786 0.364175 +v 0.277931 -0.396795 0.455916 +v -0.528648 0.313716 0.431058 +v -0.019605 0.838958 -0.142854 +v 0.635511 -0.437660 0.223903 +v 0.713513 -0.420700 0.234426 +v -0.359028 0.584115 0.254315 +v -0.164537 -0.331378 0.304958 +v -0.109442 -0.362193 0.311018 +v -0.510520 0.762293 -0.504227 +v 0.234110 -0.364559 0.449412 +v 0.265372 -0.382901 0.455813 +v 0.332339 -0.371976 0.443740 +v 0.280666 0.289419 0.257001 +v 0.616040 0.210216 0.127489 +v 0.667220 -0.377650 0.221394 +v -0.063501 -0.401195 0.290107 +v 0.195049 -0.340561 0.462594 +v 0.275955 -0.358721 0.454339 +v -0.630430 0.208448 0.310923 +v 0.688112 -0.396581 0.229652 +v 0.736726 -0.368129 0.229427 +v 0.483946 0.302719 0.168568 +v 0.138660 0.334634 -0.077415 +v 0.160481 -0.367223 0.437029 +v 0.312872 -0.343869 0.464148 +v 0.156405 0.284317 0.245387 +v 0.418495 0.290063 0.234530 +v -0.489686 0.609972 0.154852 +v 0.000343 -0.331401 0.284217 +v 0.271809 -0.336220 0.467753 +v -0.100145 0.210551 0.241290 +v 0.118044 0.296139 0.205274 +v 0.026622 0.641846 -0.105297 +v -0.397829 0.603280 0.211842 +v 0.237274 -0.327970 0.466389 +v 0.248398 0.249096 0.293000 +v 0.216065 0.277954 0.266913 +v 0.703487 -0.351164 0.217989 +v 0.765457 -0.324348 0.212977 +v 0.784480 -0.339029 0.211955 +v -0.111499 -0.311410 0.323333 +v -0.064130 -0.334350 0.304944 +v 0.132897 -0.286316 0.446813 +v 0.307002 -0.315155 0.474757 +v 0.140441 0.254102 0.272020 +v 0.476949 0.181467 0.284957 +v -0.045615 0.807717 -0.116449 +v 0.258843 0.052218 0.408002 +v -0.279657 -0.323849 0.188816 +v -0.266715 -0.307540 0.226210 +v -0.232722 -0.336939 0.223854 +v -0.139436 -0.245856 0.327754 +v -0.022368 -0.317409 0.289327 +v 0.166478 -0.294731 0.458685 +v 0.349902 -0.295154 0.465496 +v 0.710508 0.034754 -0.080237 +v 0.686716 -0.326407 0.207917 +v 0.742193 -0.323054 0.211738 +v 0.655887 0.126374 0.172539 +v -0.506050 0.696568 -0.374373 +v -0.339605 0.533993 -0.133752 +v 0.222857 -0.287266 0.471238 +v 0.282894 -0.284744 0.475197 +v 0.074932 0.255796 0.239541 +v 0.323513 0.336101 0.195973 +v -0.185139 -0.265634 0.305862 +v 0.106151 -0.245561 0.450400 +v 0.127935 -0.233056 0.459552 +v 0.177528 -0.252892 0.462401 +v 0.279228 -0.249273 0.475302 +v -0.082736 0.245539 0.216245 +v -0.422901 -0.308478 0.107596 +v 0.710588 -0.304197 0.189897 +v 0.708668 -0.086595 0.188242 +v 0.450173 0.329345 0.138819 +v -0.140858 0.340355 -0.079744 +v 0.443649 0.283034 0.223258 +v -0.532284 0.595962 0.168483 +v -0.042222 -0.060229 -0.341805 +v 0.142608 -0.233276 0.456461 +v 0.333287 -0.262095 0.466209 +v 0.357320 -0.218399 0.470126 +v 0.315188 0.258108 0.278624 +v 0.346890 0.225201 0.296668 +v 0.741223 -0.277416 0.177594 +v 0.803630 -0.298885 0.192323 +v -0.338619 0.287551 -0.178221 +v 0.216422 0.110292 -0.318915 +v -0.071826 -0.256557 0.323319 +v -0.046542 -0.264858 0.310748 +v -0.012097 -0.246640 0.303195 +v 0.230333 -0.245605 0.478430 +v 0.446097 0.246860 0.259928 +v -0.613494 0.048085 0.084723 +v 0.737549 -0.247262 0.144998 +v 0.825729 -0.254188 0.154681 +v -0.169537 -0.226382 0.328797 +v 0.237918 0.349335 0.167797 +v -0.458444 0.267008 0.443462 +v -0.459982 0.498534 0.359454 +v 0.784357 -0.269231 0.178019 +v -0.260212 0.625005 -0.115361 +v 0.541838 0.259317 0.182585 +v 0.172992 0.356873 0.019442 +v -0.170431 -0.069544 -0.309151 +v -0.103052 -0.253718 0.327969 +v -0.012199 -0.190463 0.321369 +v -0.192755 0.687448 -0.029755 +v 0.161697 -0.210318 0.472005 +v 0.216623 -0.220312 0.489234 +v 0.250422 -0.220291 0.491176 +v 0.022547 -0.004374 -0.374378 +v 0.113432 0.214700 0.288036 +v -0.560877 0.141050 0.156814 +v -0.462584 0.693530 -0.245838 +v -0.662614 0.319619 0.101751 +v -0.071714 0.308366 0.125861 +v -0.214602 -0.207792 0.326240 +v -0.050285 -0.175607 0.322284 +v 0.207200 -0.202959 0.489221 +v 0.280576 -0.207195 0.486471 +v 0.322292 -0.213004 0.472492 +v -0.492204 0.514430 0.340734 +v 0.691090 -0.054912 -0.188375 +v 0.654544 0.142927 -0.087098 +v -0.270757 -0.195277 0.328902 +v -0.147045 -0.172202 0.337545 +v -0.404955 0.620849 0.119482 +v 0.180917 -0.178725 0.483390 +v 0.247878 -0.185049 0.496651 +v 0.414501 -0.011418 0.424182 +v -0.454687 -0.003322 -0.238013 +v -0.464361 0.408592 0.416394 +v 0.021844 0.276139 0.170301 +v -0.059872 0.817552 -0.127767 +v -0.473701 0.741752 -0.358425 +v -0.086227 -0.191282 0.329574 +v 0.102402 -0.167294 0.470377 +v 0.166570 -0.143384 0.486493 +v 0.279316 -0.173336 0.491412 +v 0.307739 -0.151099 0.476696 +v 0.336038 -0.178184 0.472777 +v -0.338601 0.600269 -0.280681 +v -0.446112 0.467739 0.379271 +v 0.438354 0.347986 0.041873 +v 0.163323 0.031402 0.425425 +v -0.308865 -0.166700 0.339118 +v -0.250856 -0.163031 0.342854 +v -0.227100 -0.180671 0.340881 +v -0.193661 -0.186652 0.335806 +v -0.170199 -0.154193 0.332918 +v -0.114819 -0.160878 0.338691 +v 0.127901 -0.112748 0.478850 +v 0.134779 -0.176334 0.474437 +v 0.220951 -0.151773 0.489203 +v 0.652122 0.164285 0.097618 +v 0.304287 0.374116 0.029056 +v -0.656085 0.236782 0.096125 +v -0.359041 -0.155937 0.330340 +v -0.173408 -0.118320 0.342326 +v -0.084697 -0.130633 0.341128 +v -0.052086 -0.119489 0.328026 +v -0.027649 -0.141471 0.327485 +v 0.259779 -0.132173 0.485043 +v 0.362205 -0.134594 0.463250 +v 0.150823 0.217203 0.298707 +v -0.500458 0.293039 0.430874 +v 0.014548 0.614614 -0.132459 +v -0.544359 0.220258 -0.113732 +v 0.004972 -0.142508 0.386477 +v 0.292913 -0.103700 0.483969 +v 0.341865 -0.108093 0.474139 +v -0.343975 -0.101803 0.351536 +v -0.318315 -0.136750 0.342275 +v -0.272026 -0.122161 0.359352 +v -0.259647 -0.136471 0.355519 +v -0.219913 -0.129042 0.352146 +v -0.139604 -0.131319 0.334066 +v -0.113222 -0.105842 0.344528 +v -0.581258 0.141704 0.091954 +v -0.586873 0.057017 -0.054958 +v 0.056220 -0.109320 0.465412 +v 0.110425 -0.116597 0.484743 +v 0.156297 -0.089930 0.482182 +v 0.205915 0.227186 0.302343 +v 0.258905 0.172173 0.333871 +v -0.476825 0.310118 0.440378 +v -0.490209 0.377191 0.434129 +v -0.330853 0.614811 0.134675 +v -0.095028 0.332257 0.062713 +v 0.259840 0.067191 0.365764 +v -0.369564 -0.096646 0.350705 +v -0.298262 -0.102712 0.351365 +v -0.176454 -0.092275 0.351099 +v -0.069869 -0.113274 0.338632 +v -0.019463 -0.088132 0.346955 +v -0.608565 0.049936 0.005208 +v 0.089004 -0.107407 0.481678 +v -0.554540 0.130318 -0.082916 +v -0.420771 0.236880 0.436646 +v -0.074906 0.817401 -0.139172 +v -0.427957 0.283287 0.442253 +v 0.731695 -0.005849 -0.028159 +v -0.255810 -0.088687 0.362829 +v -0.209651 -0.079939 0.363025 +v -0.087092 -0.081319 0.345633 +v 0.171631 -0.053888 0.476159 +v 0.241907 -0.094277 0.481484 +v -0.209844 0.234974 0.225319 +v -0.148787 0.241444 0.215955 +v -0.296488 0.614014 0.039336 +v 0.026240 0.305098 -0.089207 +v 0.470479 0.331464 0.087370 +v -0.314629 -0.053701 0.360597 +v -0.288953 -0.061140 0.356434 +v 0.316123 0.371743 -0.018409 +v 0.113524 -0.069489 0.476916 +v 0.195376 -0.102251 0.485557 +v 0.315435 -0.078760 0.479988 +v -0.003630 0.864910 -0.168965 +v -0.485301 0.225248 0.424398 +v 0.459051 -0.033169 0.396634 +v -0.123064 0.224800 0.234107 +v 0.339463 0.371937 0.077742 +v -0.577418 -0.025142 -0.090965 +v -0.223365 -0.053709 0.361384 +v -0.163984 -0.065610 0.344281 +v -0.140207 -0.075040 0.334851 +v -0.050228 -0.080300 0.335108 +v -0.012062 -0.037622 0.351871 +v 0.211393 -0.097826 0.481190 +v 0.214147 -0.038003 0.478302 +v 0.267918 -0.051223 0.475026 +v 0.374433 -0.038875 0.451646 +v 0.682305 0.081004 -0.110544 +v -0.581914 0.204529 -0.068393 +v -0.614598 0.014169 0.051853 +v -0.390964 0.628789 -0.152528 +v -0.248999 -0.033020 0.355193 +v -0.087092 -0.053286 0.342625 +v 0.144096 -0.044276 0.476248 +v 0.513728 0.293190 0.158246 +v -0.090181 0.329354 -0.086948 +v -0.456610 0.619146 0.053102 +v -0.375567 -0.031731 0.350425 +v -0.309617 -0.021849 0.362857 +v -0.052032 -0.056420 0.346475 +v -0.037993 -0.034926 0.351239 +v 0.080135 -0.061834 0.465398 +v 0.168219 -0.018492 0.470557 +v 0.671441 0.140752 0.040928 +v 0.567114 0.253805 0.154964 +v -0.409045 0.623122 -0.110212 +v -0.345794 -0.030887 0.360412 +v 0.584803 0.246489 0.117722 +v 0.127946 -0.023938 0.467677 +v 0.224135 -0.009805 0.468441 +v 0.328347 -0.025607 0.456656 +v -0.402467 -0.018387 0.333392 +v -0.275880 -0.020281 0.360054 +v -0.238653 0.012421 0.348881 +v -0.207733 -0.031317 0.354071 +v -0.173759 -0.032134 0.342032 +v -0.164788 0.006449 0.339229 +v -0.113946 -0.046179 0.341283 +v -0.076065 -0.015981 0.351889 +v 0.279132 -0.010144 0.463488 +v 0.375462 0.012683 0.418611 +v 0.494774 -0.028606 0.389938 +v 0.190527 0.750489 -0.317330 +v -0.449833 0.618055 0.133698 +v -0.367247 0.589004 -0.110867 +v -0.413328 0.010273 0.330794 +v -0.320814 0.013374 0.351343 +v -0.012060 0.000749 0.357716 +v 0.014743 -0.009260 0.359259 +v 0.136417 0.003721 0.449440 +v 0.191666 0.011847 0.453964 +v 0.268168 0.019862 0.447664 +v 0.320836 0.016018 0.438872 +v 0.234338 0.300699 0.244224 +v -0.504007 0.450646 0.392798 +v 0.388103 0.365761 0.052922 +v -0.285880 0.021066 0.346184 +v -0.082632 0.014801 0.345308 +v 0.036558 0.016509 0.353850 +v 0.389512 0.321208 0.208075 +v 0.221734 0.031347 0.436941 +v 0.450092 0.028911 0.383914 +v -0.391963 0.049584 0.325443 +v -0.269585 0.054253 0.339057 +v -0.205823 0.022372 0.351335 +v -0.273333 0.602092 0.071111 +v -0.662078 0.278588 0.145189 +v 0.412787 0.025227 0.397006 +v 0.486750 0.023869 0.379215 +v 0.353787 0.267663 0.269239 +v 0.145418 0.346088 -0.030805 +v 0.079251 0.308299 0.145388 +v -0.414027 0.705838 -0.262682 +v -0.359923 0.036231 0.335158 +v -0.239606 0.054923 0.336670 +v -0.159552 0.052099 0.333339 +v -0.117025 0.079380 0.315249 +v -0.078958 0.055944 0.332862 +v -0.028319 0.026991 0.356019 +v -0.003064 0.035671 0.347117 +v 0.024131 0.044979 0.351613 +v -0.572009 0.165580 0.154881 +v 0.352293 0.046439 0.393700 +v 0.376866 0.068723 0.383235 +v 0.415228 0.065487 0.384047 +v 0.357747 0.372595 0.026334 +v 0.288448 0.221176 0.311180 +v -0.446169 0.714636 -0.272620 +v 0.224348 0.365512 0.014665 +v 0.017320 0.309732 0.083434 +v -0.195547 0.065963 0.332996 +v -0.134251 0.043293 0.327291 +v -0.055464 0.096235 0.316884 +v 0.051655 0.086318 0.344952 +v 0.056737 0.039921 0.357164 +v 0.091652 0.047577 0.354397 +v -0.433980 -0.166420 0.290112 +v -0.449654 0.240516 0.439850 +v -0.404307 0.407659 -0.173855 +v -0.466481 0.136455 -0.180973 +v -0.369232 0.643046 -0.216449 +v -0.508960 0.567150 0.261023 +v -0.460778 0.052270 0.292882 +v -0.424212 0.067722 0.307445 +v -0.310230 0.061971 0.336756 +v -0.211516 0.103046 0.312518 +v -0.011155 0.077581 0.335835 +v 0.164360 0.068626 0.351421 +v 0.331807 0.074235 0.363735 +v -0.234600 0.107518 0.312977 +v 0.078175 0.079284 0.346516 +v 0.322873 0.110219 0.335140 +v 0.448685 0.091593 0.362377 +v 0.023746 0.314111 -0.044958 +v -0.441062 0.111513 0.284737 +v -0.369489 0.095000 0.315983 +v -0.326168 0.104564 0.318568 +v -0.272733 0.094384 0.324671 +v -0.162075 0.101017 0.322904 +v 0.125224 0.101458 0.338699 +v 0.204034 0.088298 0.346611 +v 0.202310 0.109507 0.347759 +v 0.377520 0.110195 0.345543 +v 0.583361 0.213209 0.196355 +v -0.194612 0.121411 0.311161 +v -0.109432 0.126148 0.291981 +v 0.021664 0.100515 0.331580 +v 0.099778 0.108236 0.337533 +v 0.128557 0.138620 0.333009 +v 0.241376 0.114462 0.349976 +v 0.280625 0.102518 0.347264 +v 0.400141 0.098207 0.363468 +v 0.430407 0.130534 0.327624 +v 0.545238 0.280873 0.113486 +v -0.081899 0.121269 0.295953 +v 0.069089 0.151074 0.316658 +v 0.152159 0.103555 0.344161 +v 0.333205 0.152211 0.326254 +v 0.369761 0.128909 0.321939 +v -0.238040 0.664048 -0.019074 +v -0.261657 0.203018 0.257944 +v 0.412620 0.353652 0.106401 +v -0.413467 0.144423 0.284582 +v -0.396553 0.131259 0.289689 +v -0.357467 0.161572 0.285302 +v -0.227137 0.150713 0.292480 +v 0.186421 0.132126 0.344050 +v 0.292117 0.151098 0.336133 +v 0.378377 0.158244 0.308959 +v 0.481670 0.131122 0.312743 +v 0.252484 0.115598 -0.315086 +v -0.269612 0.135264 0.303750 +v -0.179310 0.148359 0.297046 +v -0.142888 0.131573 0.304069 +v -0.041255 0.147495 0.290532 +v -0.027345 0.217576 0.238093 +v 0.164271 0.156215 0.334258 +v -0.013926 -0.010489 -0.339814 +v -0.520079 -0.021354 -0.184694 +v -0.217617 0.192055 0.260684 +v -0.156881 0.676981 -0.032782 +v -0.299460 0.152160 0.289481 +v -0.134555 0.180321 0.268239 +v 0.031059 0.217122 0.250452 +v 0.071540 0.198797 0.288234 +v 0.204837 0.176226 0.329901 +v 0.318024 0.181899 0.324452 +v -0.347939 0.576792 -0.182869 +v -0.311602 0.189924 0.271851 +v -0.230434 -0.003227 -0.308112 +v -0.459097 -0.098407 -0.242040 +v -0.441105 0.406488 -0.168088 +v 0.086268 0.761955 -0.300444 +v -0.274947 0.548398 -0.110098 +v 0.447242 -0.572389 0.339511 +v -0.242416 0.235352 0.247199 +v -0.411657 -0.011763 -0.255357 +v 0.546149 0.228088 0.218184 +v 0.044614 -0.571786 0.450952 +v 0.206582 -0.552271 0.398799 +v 0.412704 -0.557625 0.354519 +v 0.475231 -0.534063 0.335915 +v -0.359182 0.527318 0.294347 +v -0.215438 -0.581190 0.369058 +v -0.152879 -0.579291 0.349928 +v -0.010115 0.313478 -0.012878 +v 0.263014 -0.547387 0.382133 +v -0.033224 0.594065 -0.137234 +v 0.306179 0.132603 -0.296556 +v -0.287666 0.509312 0.226907 +v -0.284286 -0.565324 0.377701 +v -0.229290 -0.559033 0.372366 +v -0.229447 0.406506 0.185355 +v 0.023883 -0.553548 0.451118 +v 0.054936 -0.535998 0.449365 +v 0.104177 -0.553044 0.433539 +v 0.083240 0.740759 -0.220705 +v 0.518158 0.010074 0.372978 +v 0.427800 -0.514986 0.354608 +v 0.497271 -0.540540 0.317969 +v -0.360315 -0.040434 -0.279051 +v 0.483549 0.062041 0.367110 +v -0.083893 -0.005849 -0.325842 +v 0.130545 -0.516441 0.423550 +v -0.292996 0.291855 0.311819 +v -0.261369 0.291637 0.285269 +v 0.506609 -0.505939 0.318550 +v 0.568462 -0.508633 0.231082 +v -0.147285 0.630593 -0.038479 +v 0.372589 -0.500904 0.360079 +v 0.430839 -0.484597 0.347443 +v -0.357216 0.082959 -0.265339 +v -0.060347 0.672742 -0.228365 +v -0.541558 -0.186053 0.074931 +v -0.382637 0.291556 0.415664 +v 0.125256 -0.489324 0.416035 +v 0.469637 -0.499659 0.339603 +v 0.538575 -0.478889 0.292277 +v 0.553044 -0.496677 0.271030 +v -0.172656 0.627350 -0.018459 +v 0.518915 0.119507 0.303285 +v 0.496684 -0.460883 0.316449 +v 0.718211 -0.454118 0.222939 +v 0.761105 -0.452456 0.191159 +v 0.806988 -0.465419 0.121517 +v -0.246867 -0.494927 0.350937 +v -0.020359 0.783677 -0.154093 +v -0.064723 0.602592 -0.073991 +v 0.386654 -0.475037 0.374225 +v 0.447792 -0.457765 0.346291 +v 0.568628 -0.020822 0.348705 +v -0.319014 0.330463 0.317217 +v -0.087164 0.638052 -0.048633 +v -0.098497 0.677816 -0.088027 +v 0.059879 0.892703 -0.211445 +v 0.036711 0.867528 -0.188808 +v -0.168466 0.563141 -0.014044 +v 0.550325 -0.428978 0.297025 +v 0.757715 -0.414645 0.217477 +v 0.797395 -0.453582 0.150984 +v -0.394686 0.200253 0.389865 +v 0.117782 0.660970 -0.187422 +v -0.358906 0.737089 -0.497800 +v -0.136296 0.557459 -0.045090 +v -0.071675 0.707200 -0.117306 +v 0.693545 0.052812 0.152262 +v 0.420909 -0.416916 0.395443 +v 0.474569 -0.428942 0.357494 +v 0.517137 -0.427411 0.320037 +v 0.622938 -0.422847 0.237083 +v 0.839931 -0.410681 0.141482 +v -0.119023 0.550130 -0.074478 +v -0.189531 0.317925 0.179359 +v 0.003273 -0.041343 -0.409610 +v 0.472403 -0.390490 0.386726 +v 0.499217 -0.402880 0.360529 +v 0.593220 -0.413517 0.278641 +v 0.746969 -0.394963 0.229273 +v 0.798594 -0.409388 0.188775 +v -0.012292 0.671886 -0.111535 +v -0.406651 0.504198 0.339921 +v -0.280344 0.557915 0.208181 +v 0.727536 0.005871 0.029752 +v -0.137684 0.616053 -0.025947 +v -0.403336 0.286773 0.433883 +v -0.360791 0.012943 -0.271642 +v 0.096526 0.912211 -0.261859 +v 0.397811 -0.375372 0.428645 +v -0.313396 0.257668 0.314987 +v 0.871278 -0.362586 0.112206 +v 0.715834 0.031739 0.082651 +v 0.017439 0.654183 -0.095680 +v 0.429405 -0.378652 0.404732 +v 0.523219 -0.392570 0.340373 +v 0.569883 -0.380903 0.313394 +v -0.214721 0.352795 0.212097 +v 0.688605 0.009547 0.196084 +v 0.458105 -0.359718 0.398152 +v 0.616096 -0.357003 0.292614 +v 0.644207 -0.372191 0.245519 +v -0.361693 0.282234 0.389588 +v -0.373888 0.458972 0.322594 +v 0.788370 -0.369075 0.209518 +v 0.847075 -0.372447 0.152424 +v -0.213142 0.549196 0.022245 +v -0.417249 0.402130 0.392157 +v 0.475728 -0.342118 0.395266 +v 0.550496 -0.342627 0.344049 +v 0.857151 -0.328226 0.151522 +v -0.288808 0.320196 0.303771 +v 0.515050 0.223471 0.244877 +v -0.302629 0.446395 0.238879 +v 0.344956 -0.339181 0.457305 +v 0.384417 -0.350531 0.434348 +v 0.512197 -0.355612 0.368215 +v 0.610761 -0.324417 0.307319 +v -0.363125 0.320653 0.376006 +v -0.289957 0.214045 0.274453 +v 0.824873 -0.358727 0.186035 +v -0.020987 0.758977 -0.164087 +v -0.090414 0.656481 -0.074399 +v -0.279970 0.430953 0.229210 +v -0.396408 0.472877 0.348186 +v 0.380269 -0.314803 0.449597 +v 0.425572 -0.328327 0.414513 +v 0.580875 -0.320459 0.324963 +v 0.655549 -0.331528 0.253165 +v 0.819797 -0.328240 0.192190 +v 0.871556 -0.310867 0.125123 +v 0.036693 0.827171 -0.207692 +v 0.147823 0.720560 -0.231699 +v 0.672544 0.124770 0.114006 +v 0.100667 0.865648 -0.271530 +v 0.499381 -0.333396 0.382328 +v 0.633775 -0.325855 0.285565 +v -0.341099 0.417822 0.276514 +v 0.848563 -0.305244 0.162365 +v -0.047643 0.652714 -0.068533 +v 0.392479 -0.276314 0.449326 +v 0.409553 -0.300119 0.433916 +v 0.481627 -0.303642 0.388701 +v 0.640075 -0.275459 0.287318 +v 0.679426 -0.298543 0.226371 +v -0.386666 0.378905 0.364314 +v -0.135657 0.655645 -0.055121 +v 0.610803 0.134470 0.228666 +v 0.527078 -0.305210 0.361551 +v 0.541444 -0.262079 0.348531 +v 0.613997 -0.271608 0.306799 +v 0.709515 -0.275078 0.179452 +v 0.827507 -0.295184 0.179301 +v 0.115048 0.690345 -0.182971 +v 0.101441 0.669225 -0.157568 +v 0.691538 0.032757 -0.130252 +v 0.514225 -0.241396 0.379631 +v 0.661386 -0.285371 0.260830 +v 0.381810 0.280013 0.256694 +v 0.864281 -0.274743 0.129299 +v 0.663378 -0.096664 -0.235284 +v 0.621621 0.028384 0.285408 +v -0.033200 0.638833 -0.071367 +v -0.302238 0.467794 0.233911 +v -0.387815 0.252997 0.424407 +v -0.400543 0.222550 0.421017 +v 0.446040 -0.279456 0.419603 +v 0.573986 -0.277058 0.332398 +v 0.650629 -0.002659 -0.207236 +v 0.844484 -0.265556 0.149198 +v -0.332600 0.509843 0.280883 +v 0.364230 0.191467 0.307431 +v 0.398427 -0.232946 0.451909 +v 0.577774 -0.235684 0.326043 +v 0.643301 -0.229948 0.280651 +v 0.679354 -0.239207 0.236705 +v -0.347274 0.435646 0.276290 +v 0.122203 0.808339 -0.277037 +v -0.642333 0.205360 0.079678 +v 0.270861 0.071956 0.352405 +v -0.356772 0.185270 0.289572 +v -0.330603 0.228010 0.306045 +v 0.490276 -0.248801 0.399540 +v 0.536942 -0.236651 0.354904 +v 0.610143 -0.207148 0.314370 +v 0.701918 -0.244980 0.192687 +v -0.274812 0.353451 0.275489 +v -0.127666 0.701450 -0.053047 +v 0.217811 0.070010 0.352725 +v 0.170489 0.719965 -0.250971 +v -0.023157 0.702660 -0.143787 +v 0.541466 0.066744 0.326837 +v -0.375642 0.190795 0.332692 +v 0.568504 0.024971 0.332081 +v 0.432990 -0.226436 0.436678 +v 0.570181 -0.201271 0.343977 +v 0.729083 -0.186988 0.141057 +v -0.501895 0.554093 -0.115515 +v -0.180592 0.587530 -0.000466 +v -0.243333 0.526136 0.098851 +v 0.064436 0.634189 -0.159119 +v 0.452125 -0.211493 0.427770 +v 0.507232 -0.190664 0.402629 +v 0.635077 -0.211389 0.294327 +v -0.614451 0.441842 0.160119 +v -0.251810 0.380042 0.239288 +v -0.097411 0.613039 -0.046795 +v -0.625137 0.409032 0.126310 +v -0.353309 0.361552 0.326204 +v 0.421100 -0.175638 0.451718 +v 0.461455 -0.184090 0.434387 +v 0.702456 -0.153541 0.201377 +v -0.240802 0.475835 0.114608 +v 0.570988 0.172805 0.247562 +v -0.266957 0.484567 0.199309 +v 0.539394 -0.186795 0.373671 +v 0.593345 -0.183081 0.336495 +v 0.664819 -0.185661 0.260011 +v 0.743874 -0.201360 0.093048 +v -0.196208 0.365597 0.164740 +v 0.165883 0.770950 -0.286525 +v -0.086115 0.721858 -0.093312 +v -0.186178 0.649627 -0.012476 +v -0.175342 0.524206 -0.033981 +v 0.694746 -0.018504 -0.165082 +v -0.362517 0.404207 0.308961 +v -0.330932 0.375677 0.298664 +v -0.198078 0.279351 0.197836 +v -0.215011 0.306979 0.227289 +v -0.430997 0.439610 0.388044 +v 0.381496 -0.177474 0.462072 +v 0.459332 -0.146990 0.437100 +v 0.497766 -0.139649 0.413758 +v 0.533073 -0.154906 0.389770 +v 0.589208 -0.152160 0.343392 +v -0.344062 0.466323 0.279163 +v -0.341293 0.624530 -0.268873 +v 0.486930 0.099528 0.339551 +v -0.355671 0.214990 0.335227 +v 0.424597 -0.141300 0.447060 +v 0.568151 -0.116623 0.354778 +v 0.724858 -0.123686 0.155034 +v 0.735777 -0.108772 0.106513 +v -0.216301 0.264225 0.231137 +v -0.011416 0.819840 -0.146737 +v -0.301674 0.384942 0.278691 +v 0.670328 0.028727 -0.168295 +v -0.266901 0.264971 0.284019 +v 0.412248 -0.100044 0.440163 +v 0.081094 0.706819 -0.190396 +v 0.481888 0.242817 0.252217 +v -0.278242 0.235276 0.282039 +v 0.460810 -0.105924 0.422363 +v -0.357214 0.649062 -0.592053 +v 0.095081 0.823164 -0.260931 +v 0.567701 0.093850 0.289857 +v 0.694497 0.086266 0.075294 +v 0.524474 0.038013 0.356379 +v 0.489609 -0.079041 0.403836 +v 0.584807 -0.092560 0.339615 +v 0.610658 -0.104339 0.325874 +v 0.650108 -0.143391 0.281488 +v -0.496857 0.193433 0.391064 +v 0.572857 0.123038 0.275408 +v -0.250425 0.433313 0.192169 +v -0.349549 0.257790 0.361860 +v -0.373626 0.233040 0.396860 +v 0.614096 0.180634 0.187386 +v 0.664493 -0.067256 0.261363 +v -0.339102 0.705768 -0.656972 +v 0.051592 0.797126 -0.224807 +v 0.718019 -0.058255 -0.126204 +v 0.673272 0.070442 0.185010 +v 0.389719 -0.081882 0.456831 +v 0.521444 -0.097229 0.392428 +v 0.647941 0.049799 0.237881 +v -0.239059 0.314443 0.255383 +v -0.035464 0.722029 -0.147815 +v 0.356763 -0.077883 0.470683 +v 0.448067 -0.055709 0.414734 +v 0.624403 -0.072827 0.315247 +v 0.641795 -0.097763 0.288874 +v 0.692945 0.093953 -0.063735 +v 0.528019 0.165956 0.276788 +v 0.054341 0.682889 -0.151212 +v 0.151420 0.845749 -0.316743 +v 0.030966 0.760958 -0.203792 +v -0.204329 0.513805 -0.006834 +v 0.405702 -0.046216 0.443451 +v 0.539086 -0.057332 0.376057 +v 0.607922 -0.052464 0.331659 +v 0.046921 0.668190 -0.122358 +v -0.645593 0.252227 0.177534 +v -0.462791 0.434018 -0.157194 +v -0.644635 0.270995 0.202067 +v -0.493425 0.634271 -0.231832 +v -0.648716 0.288547 0.274737 +v 0.564591 -0.062045 0.351847 +v 0.632874 -0.033787 0.301344 +v 0.437963 -0.010120 0.408898 +v 0.668212 0.007388 0.234707 +v -0.334755 0.295201 0.340131 +v -0.401094 0.332712 0.410994 +v 0.074190 0.881603 -0.233487 +v 0.431729 0.214994 0.279824 +v -0.226826 0.585474 0.027671 +v 0.582044 0.062713 0.303552 +v -0.593908 0.012540 -0.050183 +v -0.319747 0.486291 0.264001 +v -0.305676 0.521568 0.247593 +v 0.604474 -0.004794 0.318407 +v -0.478821 0.557613 -0.258916 +v 0.466323 -0.589216 -0.177278 +v 0.452455 -0.589561 -0.237347 +v 0.723622 -0.033974 0.130480 +v 0.663716 -0.553847 -0.059557 +v 0.502286 -0.574402 -0.111415 +v 0.476717 -0.559815 -0.215572 +v 0.517178 -0.544530 0.280992 +v 0.747290 -0.517502 -0.024846 +v 0.496568 -0.565583 -0.137517 +v 0.446743 -0.560194 -0.289345 +v -0.622183 0.194475 0.286707 +v -0.625582 0.195154 0.012272 +v -0.345060 0.825791 -0.668714 +v 0.169438 0.857053 -0.350460 +v -0.342274 0.579838 -0.316284 +v -0.142410 0.007670 -0.316120 +v 0.713291 -0.523514 -0.069861 +v 0.718153 -0.496848 -0.103118 +v 0.497327 -0.537883 -0.185125 +v 0.168520 0.702845 -0.252012 +v -0.343369 0.589149 -0.380467 +v 0.187868 0.830430 -0.373197 +v 0.695131 -0.087061 -0.182070 +v -0.532330 0.145789 0.203911 +v 0.776114 -0.503996 0.055334 +v 0.810237 -0.464679 -0.040075 +v 0.500133 -0.513602 -0.235858 +v 0.465414 -0.559214 -0.261860 +v -0.070648 0.578188 -0.091823 +v 0.767848 -0.489505 -0.067472 +v 0.599486 0.056545 -0.236705 +v 0.138132 0.674587 -0.223986 +v -0.206279 0.421697 -0.022432 +v 0.184520 0.800455 -0.374403 +v 0.808376 -0.476756 0.013782 +v 0.794695 -0.457303 -0.080094 +v 0.519469 0.038061 -0.298568 +v 0.526028 -0.500854 -0.198704 +v 0.483925 -0.505531 -0.295058 +v 0.061533 0.166586 -0.287449 +v -0.257961 0.556014 0.160171 +v 0.821499 -0.464424 0.084345 +v 0.847663 -0.436998 0.015775 +v 0.739775 -0.460767 -0.129211 +v -0.557820 0.168754 0.194749 +v 0.572435 -0.467653 -0.175577 +v 0.564906 -0.461482 -0.218968 +v 0.546730 -0.466084 -0.254773 +v 0.500758 -0.492230 -0.265781 +v 0.471558 -0.470478 -0.311642 +v 0.122535 0.065140 -0.327737 +v -0.344785 0.779157 -0.618376 +v -0.343099 0.532394 -0.167096 +v 0.736339 -0.060638 0.040745 +v -0.213869 0.486197 -0.000767 +v -0.547261 0.174079 0.351719 +v -0.241305 0.559211 0.083992 +v -0.355810 0.537982 -0.292198 +v -0.234570 0.437483 0.146126 +v -0.334819 0.809590 -0.696813 +v 0.845606 -0.440899 0.065149 +v 0.832936 -0.427993 -0.058433 +v 0.783538 -0.414292 -0.124662 +v -0.346462 0.732253 -0.547634 +v 0.845559 -0.430356 0.108910 +v 0.849437 -0.426374 -0.017957 +v 0.808899 -0.423169 -0.096703 +v -0.108854 -0.604482 -0.380921 +v 0.577764 -0.438908 -0.230404 +v -0.407605 -0.590978 -0.142563 +v 0.868617 -0.387118 0.095984 +v 0.018751 0.288843 -0.135231 +v -0.253062 0.497965 0.152118 +v 0.862131 -0.413942 0.061329 +v 0.878339 -0.373754 0.042932 +v 0.825856 -0.381709 -0.097111 +v 0.548112 -0.427921 -0.292836 +v 0.193397 0.787003 -0.357583 +v -0.490039 -0.222485 0.173555 +v -0.350342 0.647592 -0.520014 +v 0.637424 -0.381325 -0.180489 +v 0.606361 -0.405080 -0.200557 +v 0.577757 -0.416771 -0.252745 +v 0.872742 -0.378528 0.004035 +v 0.854575 -0.382033 -0.050250 +v 0.570987 -0.390050 -0.270916 +v 0.108113 0.009986 -0.411348 +v -0.578757 0.154723 -0.013913 +v 0.886306 -0.325383 0.065420 +v 0.875673 -0.337109 -0.032098 +v 0.853422 -0.342709 -0.071609 +v 0.668651 -0.343757 -0.154748 +v 0.586985 -0.369152 -0.255679 +v 0.002736 0.264698 -0.180648 +v -0.601589 0.089308 0.084595 +v 0.888145 -0.325690 0.014144 +v 0.639508 -0.342992 -0.210161 +v 0.522876 -0.377581 -0.333043 +v -0.339187 0.744377 -0.616707 +v -0.625222 0.185444 0.070915 +v -0.604335 0.170274 0.036296 +v 0.875937 -0.311163 -0.031024 +v 0.589761 -0.336975 -0.271823 +v -0.655401 0.305308 0.171638 +v -0.651541 0.259836 0.288642 +v 0.188061 0.789291 -0.332472 +v -0.537037 -0.173542 0.142641 +v -0.089570 0.564238 -0.110868 +v 0.881293 -0.285221 0.094838 +v 0.878730 -0.277924 -0.005356 +v 0.687419 -0.297402 -0.146416 +v 0.627816 -0.309542 -0.236963 +v -0.338439 0.657890 -0.348558 +v -0.485021 0.592332 -0.219483 +v 0.661468 -0.294037 -0.201916 +v 0.599451 -0.295585 -0.275230 +v -0.551236 0.525272 -0.059738 +v -0.590202 0.114121 0.007156 +v -0.434126 0.868375 -0.645281 +v -0.575964 0.303954 -0.117831 +v 0.887647 -0.284089 0.049253 +v 0.679454 -0.260438 -0.186194 +v 0.630175 -0.264747 -0.247328 +v -0.637863 0.332579 0.274091 +v -0.343897 0.694508 -0.587168 +v -0.431332 0.531860 -0.366405 +v -0.223290 0.429421 -0.070969 +v -0.224569 0.473834 0.072422 +v 0.879224 -0.257025 0.071221 +v -0.333713 0.784727 -0.673153 +v 0.530264 -0.283182 -0.326178 +v -0.468170 0.557156 -0.368025 +v -0.341900 -0.339503 0.113997 +v -0.339662 -0.577805 0.348694 +v 0.864103 -0.230291 0.040232 +v -0.080893 0.286513 -0.173423 +v 0.572522 -0.263653 -0.294681 +v -0.136460 0.315356 -0.160689 +v -0.461908 0.701546 -0.472899 +v 0.182511 0.750693 -0.338062 +v -0.615422 0.265676 -0.055266 +v -0.342762 0.694956 -0.496735 +v 0.715505 -0.026956 -0.116964 +v -0.203986 0.433342 0.041954 +v -0.612774 0.423145 0.214092 +v -0.461945 0.623113 -0.342166 +v 0.654143 -0.211221 -0.216849 +v 0.543575 -0.239749 -0.329282 +v -0.199879 0.500509 -0.047997 +v -0.639839 0.218998 0.267932 +v -0.432698 -0.203165 0.269202 +v -0.340236 0.627625 -0.428341 +v 0.183342 0.731731 -0.284098 +v 0.713778 -0.225394 -0.112800 +v 0.698082 -0.246475 -0.152092 +v 0.615411 -0.214057 -0.260844 +v 0.577007 -0.227087 -0.303319 +v -0.014245 0.612871 -0.102410 +v -0.583607 0.105780 -0.030675 +v -0.268750 0.524076 0.193894 +v 0.722395 -0.090113 -0.111666 +v 0.713001 -0.184050 -0.129339 +v 0.411327 -0.030891 -0.383193 +v -0.390335 -0.030709 -0.264755 +v -0.627860 0.285534 -0.029497 +v 0.736557 -0.195311 -0.064422 +v -0.650041 0.260486 0.021673 +v 0.726713 -0.014212 0.087825 +v 0.167923 0.703596 -0.272903 +v 0.735469 -0.072625 -0.051630 +v 0.742884 -0.168417 -0.021355 +v 0.683173 -0.215784 -0.183376 +v 0.712539 0.052712 -0.040342 +v -0.230726 0.509866 0.052299 +v 0.727287 -0.015270 -0.068029 +v 0.714582 -0.023552 0.154889 +v 0.687871 0.113317 -0.015421 +v -0.575773 0.020616 -0.097147 +v 0.687572 -0.157400 -0.172625 +v 0.635738 -0.181526 -0.234843 +v -0.647008 0.265154 0.236432 +v -0.342428 0.574504 -0.237223 +v 0.729959 -0.132729 -0.084384 +v 0.658504 -0.145174 -0.223392 +v 0.619002 -0.155589 -0.266820 +v -0.630086 0.477831 0.126801 +v -0.459687 0.839697 -0.629659 +v -0.337329 0.664640 -0.430959 +v -0.217117 0.469096 -0.037558 +v 0.691011 -0.037548 0.208391 +v -0.448806 -0.291581 0.097451 +v -0.629140 0.447382 0.083216 +v 0.709148 0.067222 0.004258 +v -0.444198 0.818912 -0.625850 +v -0.478272 0.564975 -0.180705 +v -0.572341 0.084624 -0.076560 +v -0.489899 0.197521 -0.136664 +v 0.743166 -0.155135 0.057368 +v 0.701426 -0.126824 -0.157186 +v 0.645596 -0.122238 -0.252791 +v -0.093845 -0.487870 -0.332763 +v -0.571132 0.454397 -0.065687 +v -0.352776 0.708171 -0.419447 +v -0.335557 0.626002 -0.349952 +v 0.739542 -0.071793 -0.006259 +v 0.726668 -0.100372 -0.082229 +v -0.168072 0.520784 -0.073381 +v -0.360885 0.853207 -0.677800 +v -0.390346 0.865113 -0.656682 +v -0.367580 0.846372 -0.649328 +v -0.363353 0.787466 -0.582752 +v -0.423458 0.864963 -0.622221 +v -0.472336 0.581139 0.253245 +v 0.117626 0.342296 0.076341 +v -0.340804 0.617923 0.089849 +v -0.279751 0.596011 0.163197 +v -0.092422 0.786752 -0.099158 +v -0.461230 0.856572 -0.598443 +v -0.510042 0.611589 0.060923 +v -0.444698 0.603797 0.205393 +v -0.397025 0.830731 -0.594255 +v 0.205010 0.059975 0.384392 +v -0.315399 0.605085 0.173237 +v -0.493470 0.592505 0.218454 +v -0.534610 0.605155 0.106478 +v -0.441876 0.647518 -0.144738 +v 0.143272 0.906960 -0.345991 +v -0.154296 0.302959 0.134693 +v -0.410679 0.613793 -0.074125 +v -0.457124 0.611770 -0.067004 +v -0.401567 0.801827 -0.544154 +v -0.320171 0.585880 0.238381 +v 0.045762 0.319383 0.075642 +v -0.447415 0.843291 -0.572583 +v -0.485599 0.833167 -0.561676 +v 0.419421 0.336928 0.160607 +v -0.583318 0.148498 0.029311 +v -0.033231 0.271942 0.169215 +v -0.210689 0.424532 0.102645 +v -0.148949 0.350688 0.002205 +v -0.372846 0.596877 -0.081357 +v -0.095708 0.300105 0.152640 +v 0.375435 0.362031 0.116655 +v 0.262380 0.369573 0.073111 +v 0.316589 0.365524 0.121191 +v -0.646390 0.228039 0.028400 +v -0.377040 0.614378 0.169681 +v -0.585262 0.482763 -0.006169 +v -0.426958 0.614840 -0.021437 +v 0.199516 0.360898 0.078227 +v -0.162505 0.318507 0.117457 +v -0.421865 0.572197 0.276694 +v 0.128250 0.904208 -0.311068 +v 0.107650 0.927805 -0.290271 +v -0.555252 0.583439 -0.013689 +v -0.600946 0.033250 -0.033707 +v -0.603635 0.447745 0.015911 +v -0.397448 0.619290 0.052268 +v 0.214492 0.322016 0.211768 +v -0.607105 0.420402 -0.019018 +v -0.491710 0.621840 -0.280221 +v -0.651408 0.239946 0.143128 +v 0.045289 0.325045 0.019474 +v -0.385109 0.774956 -0.511773 +v -0.411003 0.782628 -0.480629 +v 0.852160 -0.231079 -0.010188 +v -0.473552 0.853127 -0.614516 +v -0.037931 0.321756 0.009639 +v 0.190468 0.353072 0.129773 +v 0.623616 0.177176 -0.112902 +v -0.533792 0.028847 -0.159241 +v 0.047369 0.890275 -0.269726 +v -0.336059 0.616049 0.020503 +v -0.607907 -0.037322 0.121552 +v 0.864088 -0.261480 -0.033248 +v -0.150099 0.336357 0.077927 +v 0.588714 0.213268 -0.122281 +v -0.605956 0.006657 -0.011158 +v -0.636794 0.228840 0.217599 +v -0.440481 0.807829 -0.509799 +v -0.415049 0.588697 0.248162 +v 0.881144 -0.260863 0.024050 +v -0.120454 0.320683 0.105577 +v 0.608556 0.223407 -0.046037 +v -0.447875 0.508905 -0.247042 +v -0.572345 0.113022 0.142414 +v -0.480156 0.168227 -0.153218 +v -0.585020 0.573325 0.168258 +v 0.839242 -0.216363 0.016201 +v -0.266067 0.610141 0.035629 +v 0.647657 0.169520 -0.051825 +v 0.595376 0.230362 -0.073640 +v -0.507158 0.010248 -0.196502 +v -0.613724 0.493126 0.218752 +v 0.071446 0.917378 -0.240869 +v -0.428278 0.671497 -0.187820 +v -0.428840 0.771514 -0.418133 +v -0.027356 0.314252 0.075452 +v -0.264185 0.587615 0.134556 +v 0.264818 0.333316 0.201833 +v 0.571663 0.260589 -0.029378 +v 0.537616 0.270115 -0.090857 +v -0.612833 0.053314 0.043686 +v -0.473938 0.767405 -0.419294 +v -0.005603 0.247960 0.208386 +v 0.491055 0.307620 -0.079497 +v -0.642051 0.239528 0.321522 +v 0.304452 0.059523 0.378885 +v -0.285919 0.584905 0.205795 +v -0.292291 0.608469 0.102729 +v -0.084164 0.277832 0.186211 +v -0.460725 0.793418 -0.470364 +v 0.795728 -0.207188 0.036492 +v -0.380603 0.611098 -0.018934 +v 0.641377 0.184455 0.014422 +v 0.447509 0.326830 -0.088262 +v -0.527322 0.487985 -0.105808 +v -0.637219 0.491303 0.087412 +v -0.587892 0.585922 0.064719 +v -0.377724 0.734279 -0.396082 +v -0.501816 0.745242 -0.426138 +v -0.445313 0.533168 0.326645 +v 0.864757 -0.240147 0.087301 +v 0.848833 -0.221984 0.080898 +v 0.829551 -0.210539 0.061740 +v 0.754826 -0.205241 0.033805 +v 0.403551 0.348221 -0.077159 +v -0.517549 0.093011 -0.156771 +v -0.486195 0.608821 -0.010809 +v 0.497830 0.269690 0.218293 +v -0.472248 0.551706 0.301264 +v 0.021161 0.885127 -0.225906 +v -0.399481 0.755323 -0.406770 +v 0.448668 0.306559 0.193760 +v 0.820522 -0.213317 0.096285 +v 0.785585 -0.208176 0.071173 +v -0.315467 0.620179 -0.011286 +v 0.533792 0.295320 0.009323 +v 0.472985 0.326784 -0.034943 +v -0.627228 0.480182 0.169586 +v -0.185128 0.389922 0.078401 +v 0.039288 0.895933 -0.205943 +v 0.367141 0.347302 0.171073 +v 0.305276 0.356201 0.157976 +v 0.853809 -0.247328 0.121040 +v -0.572941 0.591836 0.113287 +v 0.609130 0.226991 0.002462 +v 0.522823 0.295620 -0.041731 +v -0.197299 0.388041 0.138245 +v -0.355061 0.691056 -0.349625 +v -0.385695 0.705582 -0.297203 +v -0.404685 0.731046 -0.330091 +v -0.447234 0.754435 -0.360630 +v 0.762426 -0.215170 0.079451 +v 0.006525 0.290270 0.126093 +v -0.170418 0.370289 0.020962 +v 0.572889 0.263615 0.032498 +v 0.417133 0.354571 -0.021168 +v 0.364568 0.366943 -0.027741 +v 0.290041 0.364275 -0.064630 +v 0.311159 0.040918 0.414861 +v -0.243845 0.588855 0.038778 +v -0.423240 0.748544 -0.351938 +v 0.823951 -0.227483 0.123317 +v 0.731972 -0.231852 0.134811 +v 0.473562 0.331679 0.022468 +v -0.652455 0.326954 0.044555 +v -0.593693 0.117244 0.045964 +v 0.051841 -0.035805 0.432309 +v -0.340637 0.598514 0.217878 +v -0.178158 0.265143 0.186155 +v 0.788174 -0.220604 0.116306 +v -0.615716 0.454955 0.202590 +v -0.252873 0.585197 0.071643 +v 0.128086 0.336332 0.124957 +v 0.616993 0.215266 0.081317 +v 0.520360 0.304721 0.064684 +v -0.561311 0.035413 -0.123257 +v -0.081879 0.335597 0.008006 +v -0.111539 0.340664 -0.040149 +v -0.056383 0.835289 -0.172295 +v -0.464529 0.622789 -0.116450 +v -0.187199 0.386274 -0.009283 +v -0.569347 0.590075 0.036049 +v 0.171695 0.327014 0.185259 +v 0.249283 0.365134 -0.034067 +v -0.607248 0.028219 0.120295 +v -0.367756 -0.596849 0.064589 +v -0.362646 -0.591291 0.152225 +v -0.386913 -0.583198 0.247999 +v 0.478742 0.023033 -0.318354 +v -0.106348 0.664865 -0.214073 +v -0.488544 0.362035 -0.160066 +v -0.445040 -0.588163 -0.020197 +v -0.411733 -0.587607 0.029926 +v -0.361251 -0.583148 0.086380 +v -0.387684 -0.568378 0.242467 +v -0.348926 -0.551539 0.336581 +v -0.437165 -0.574262 -0.003529 +v -0.371357 -0.569260 0.169042 +v -0.383563 -0.565032 0.205724 +v -0.365230 -0.545756 0.303620 +v -0.321101 -0.530135 0.352443 +v -0.322827 -0.557725 0.361964 +v -0.087206 -0.055522 -0.329183 +v -0.114590 -0.566640 0.338214 +v -0.439803 -0.566428 -0.050706 +v -0.436579 -0.547545 -0.030350 +v -0.431302 -0.548492 -0.009353 +v -0.409646 -0.557478 0.017194 +v -0.392177 -0.560734 0.044844 +v -0.330900 -0.564255 0.106614 +v -0.111440 -0.518088 0.324265 +v -0.071103 -0.556296 0.386831 +v -0.009152 -0.549296 0.442595 +v 0.098118 0.032790 0.377984 +v -0.388805 0.285735 -0.179573 +v -0.357189 -0.559654 0.075439 +v -0.363800 -0.529317 0.191939 +v -0.578206 0.028099 0.183654 +v -0.094654 -0.539936 0.352470 +v -0.062983 -0.532919 0.393763 +v -0.031372 -0.539212 0.422629 +v -0.419616 -0.521425 -0.023598 +v -0.523436 0.035851 0.245962 +v 0.017626 -0.165844 0.393066 +v -0.094657 -0.514789 0.339389 +v 0.018582 -0.517166 0.442657 +v -0.416015 -0.523343 -0.058670 +v -0.391208 -0.522427 0.011914 +v -0.593698 0.078366 0.129708 +v 0.040913 -0.154154 0.444852 +v -0.328667 -0.507860 0.336290 +v -0.031822 -0.503680 0.407314 +v -0.476937 0.093247 0.270214 +v -0.343896 -0.523298 0.055972 +v -0.330159 -0.498233 0.033724 +v 0.538908 -0.046049 -0.317514 +v -0.496092 -0.120006 0.267481 +v -0.323456 -0.482941 0.310392 +v 0.030537 -0.124379 0.443715 +v -0.064181 -0.496516 0.363734 +v -0.018072 -0.474333 0.386974 +v 0.129161 0.057145 0.354507 +v -0.392708 -0.500387 -0.014537 +v -0.298173 -0.477710 0.020131 +v -0.237796 0.697103 -0.073007 +v -0.271384 -0.458317 0.294682 +v -0.508134 0.244582 0.415733 +v 0.008066 -0.062241 0.388602 +v -0.475012 0.655551 -0.194882 +v -0.081156 -0.477104 0.316913 +v 0.025965 -0.035377 0.398028 +v -0.520147 0.224885 0.397129 +v -0.244779 -0.466377 0.058089 +v -0.040079 -0.437537 0.302920 +v -0.034521 -0.472853 0.362037 +v 0.077142 -0.002160 0.425390 +v -0.441093 -0.026591 0.324452 +v -0.256085 -0.448574 0.031523 +v -0.543682 0.276501 0.403155 +v -0.217187 -0.444772 0.279876 +v -0.042963 -0.455427 0.334744 +v 0.049128 0.003004 0.383093 +v -0.583114 -0.024934 0.177615 +v -0.296774 -0.454977 -0.017730 +v -0.589346 -0.053034 0.158303 +v -0.642020 0.306696 0.317370 +v 0.121729 0.028061 0.410898 +v 0.003157 -0.437135 0.342912 +v -0.578831 0.484186 0.308003 +v -0.470616 -0.041420 0.305315 +v -0.613951 0.530900 0.186454 +v -0.252526 -0.422898 0.026808 +v -0.221330 -0.407533 0.072059 +v -0.579503 0.524935 0.257775 +v -0.419015 -0.081387 0.331261 +v -0.223636 -0.423842 0.249878 +v -0.552633 0.553922 0.246913 +v -0.011391 -0.419510 0.285878 +v -0.607280 0.252338 0.375105 +v -0.496578 0.794641 -0.505282 +v -0.553824 -0.000881 0.218489 +v -0.280318 -0.407449 -0.016777 +v -0.508999 0.539567 0.304135 +v -0.398671 -0.063983 0.344774 +v -0.160755 -0.013316 -0.314228 +v -0.585694 0.380525 0.377335 +v -0.646186 0.266247 0.325801 +v -0.228516 -0.414876 0.054062 +v -0.217277 -0.379743 0.245747 +v -0.617356 0.348331 0.339734 +v -0.000185 -0.396645 0.277373 +v 0.021686 -0.375263 0.301327 +v -0.556665 0.280483 -0.127797 +v -0.534198 0.359066 0.430681 +v -0.234228 -0.383374 0.068508 +v -0.505620 0.802002 -0.556571 +v -0.248741 -0.371725 0.119389 +v -0.249428 -0.346618 0.171624 +v -0.240949 -0.379126 0.176229 +v -0.196788 -0.322710 0.276563 +v -0.555041 -0.130460 0.179645 +v 0.096957 -0.367256 0.407135 +v -0.520341 -0.036294 0.255435 +v -0.557765 -0.078778 0.201737 +v -0.274009 -0.347953 0.139694 +v -0.541920 0.509222 0.315505 +v 0.038481 -0.219464 0.386315 +v 0.026826 -0.316483 0.315926 +v -0.630964 0.286055 0.350656 +v -0.180406 0.739816 -0.083121 +v -0.597936 0.492991 0.266581 +v -0.589549 0.439077 0.332670 +v 0.123198 -0.333926 0.433159 +v -0.557679 0.313955 0.413909 +v -0.347510 0.185264 -0.226550 +v -0.529981 -0.095174 0.240569 +v -0.605278 0.220298 0.363433 +v 0.077673 -0.319487 0.391626 +v 0.154161 -0.325805 0.453745 +v -0.424555 -0.123974 0.315603 +v -0.558468 0.390991 0.400640 +v -0.285246 -0.458600 0.275575 +v 0.379802 0.149817 -0.285224 +v -0.278925 -0.582982 0.373266 +v -0.479676 0.693979 -0.270707 +v -0.557631 0.086914 0.189888 +v -0.602164 0.327118 0.370917 +v -0.510910 0.119833 0.230011 +v -0.601705 0.002702 0.146945 +v -0.610746 0.442984 0.286092 +v 0.087144 -0.020916 0.447711 +v -0.302299 -0.032892 -0.299982 +v 0.009894 -0.272011 0.306226 +v 0.066194 0.855611 -0.307821 +v 0.202117 0.150256 -0.312352 +v 0.040474 -0.082200 0.446669 +v -0.324479 0.614642 -0.047152 +v -0.583534 0.274692 0.393629 +v -0.460486 0.556619 -0.416596 +v 0.074551 -0.146430 0.469643 +v -0.558018 0.450631 0.358443 +v 0.051017 -0.585826 0.438159 +v -0.581179 0.331406 0.395144 +v -0.376929 0.128826 -0.233672 +v 0.065546 -0.200211 0.438081 +v -0.483882 0.631473 -0.180850 +v -0.491803 -0.086207 0.283712 +v -0.561151 0.353346 0.414342 +v -0.531857 -0.132123 0.222063 +v -0.536683 0.074567 0.218901 +v -0.582170 0.068529 0.163642 +v -0.529093 0.448202 0.383095 +v -0.508726 0.006154 0.263860 +v -0.454044 0.011971 0.311611 +v -0.246401 -0.059948 -0.309359 +v -0.484050 -0.167045 0.246987 +v 0.062446 0.123648 -0.313765 +v -0.603252 0.557515 0.169946 +v 0.039568 -0.263088 0.361288 +v 0.080176 -0.266462 0.425158 +v -0.555420 0.263107 0.401280 +v 0.133798 0.803499 -0.350222 +v 0.006398 -0.101072 0.396961 +v -0.138979 -0.057521 -0.311759 +v -0.036582 0.083971 -0.314019 +v 0.001455 0.101915 -0.318805 +v -0.457547 0.259511 -0.169347 +v -0.180885 0.108482 -0.295071 +v 0.006231 -0.209461 0.335918 +v -0.174972 -0.594791 -0.304128 +v -0.169573 -0.551985 -0.301474 +v -0.184269 -0.574153 -0.268283 +v -0.603307 0.194031 -0.032268 +v 0.797819 -0.213183 0.000152 +v -0.423495 -0.567652 -0.099815 +v -0.328875 -0.555937 0.134193 +v -0.496610 0.760633 -0.521675 +v -0.157575 0.753395 -0.163522 +v -0.495515 0.829632 -0.592706 +v -0.125062 -0.553295 -0.364145 +v -0.161801 -0.580841 -0.333018 +v -0.385992 -0.537852 -0.140676 +v -0.412064 -0.527415 -0.088567 +v -0.476050 0.650885 -0.359580 +v -0.350513 -0.546014 0.161320 +v -0.442673 0.576515 -0.505939 +v -0.130158 -0.526869 -0.331106 +v -0.189549 -0.553232 -0.230665 +v -0.615240 0.343011 -0.045038 +v -0.489516 0.594782 -0.113466 +v -0.420860 0.746108 -0.602232 +v -0.367569 -0.524910 0.225673 +v -0.141124 0.298807 -0.186098 +v -0.200340 0.307147 -0.174572 +v -0.141148 -0.508716 -0.305583 +v -0.392794 -0.501815 -0.074754 +v -0.453509 0.604186 -0.389934 +v -0.273171 -0.512793 0.100859 +v -0.320321 -0.527960 0.139037 +v -0.374527 -0.532778 0.262659 +v -0.520307 0.561810 -0.084444 +v -0.159956 -0.522665 -0.270435 +v -0.171508 -0.517621 -0.232432 +v -0.550737 0.084389 -0.123429 +v -0.374371 -0.485880 -0.044920 +v -0.473920 0.577966 -0.234432 +v -0.264377 -0.482780 0.145631 +v -0.344284 -0.504935 0.194438 +v -0.347969 -0.490328 0.255733 +v -0.355024 -0.506915 0.289245 +v -0.322195 -0.494659 -0.131812 +v -0.352063 -0.486659 -0.085653 +v -0.342137 -0.476755 -0.018592 +v -0.629679 0.546417 0.124575 +v -0.290584 -0.482190 0.178157 +v -0.292408 -0.469160 0.208404 +v -0.114842 0.796430 -0.166248 +v -0.616054 0.442037 0.250923 +v -0.645657 0.359710 0.161340 +v -0.642452 0.334050 0.207021 +v -0.059216 -0.531905 -0.387098 +v -0.621638 0.223595 -0.033741 +v -0.304802 -0.464842 -0.088371 +v -0.436878 0.519588 -0.306174 +v -0.243541 -0.487664 0.086368 +v -0.313786 -0.469376 0.251229 +v -0.294849 0.645605 -0.048874 +v -0.529234 0.150512 -0.110685 +v -0.238683 -0.481155 0.103717 +v -0.237943 -0.456468 0.125975 +v -0.496147 0.623646 -0.256487 +v -0.093807 -0.465334 -0.261968 +v -0.508404 0.592546 -0.050620 +v -0.295997 -0.437900 -0.044387 +v -0.245897 -0.437809 0.199972 +v -0.249630 -0.450465 0.249180 +v -0.454669 0.745038 -0.538413 +v -0.263850 -0.463790 -0.149682 +v -0.242770 -0.431302 0.154361 +v -0.510942 0.731502 -0.445558 +v 0.374473 0.292873 -0.188787 +v -0.046800 0.147508 -0.279910 +v -0.030977 -0.446083 -0.284565 +v 0.740330 -0.244011 -0.060352 +v 0.615612 0.154465 -0.160390 +v -0.270114 -0.414480 -0.129957 +v -0.288622 -0.445600 -0.105814 +v -0.222548 -0.451166 0.081152 +v -0.225595 -0.442923 0.101246 +v -0.238517 -0.408909 0.196560 +v -0.396488 0.711207 -0.645159 +v -0.022357 -0.421095 -0.267257 +v 0.189270 0.172012 -0.295928 +v -0.290337 -0.397912 -0.067100 +v -0.047127 0.833832 -0.206770 +v -0.009739 -0.429503 -0.312253 +v -0.033474 -0.424242 -0.229364 +v -0.276383 -0.372317 -0.124006 +v -0.228803 -0.404019 0.107036 +v -0.608397 0.574789 0.110370 +v -0.491173 0.795712 -0.569172 +v -0.505421 0.699908 -0.408754 +v 0.004898 -0.401940 -0.341969 +v -0.264279 -0.388581 0.012773 +v -0.590057 0.363738 -0.081379 +v -0.619736 0.385653 -0.031275 +v -0.641969 0.377385 0.063811 +v -0.206043 0.705092 -0.141087 +v -0.260308 -0.342562 -0.166488 +v -0.293984 -0.365320 -0.003236 +v -0.587590 0.442913 -0.044920 +v -0.649538 0.367075 0.108697 +v -0.632463 0.389034 0.156391 +v 0.498507 0.234898 -0.190648 +v -0.016114 -0.361113 -0.303609 +v -0.032538 -0.390070 -0.234374 +v -0.309665 -0.349809 -0.064355 +v -0.622060 0.415444 0.050996 +v -0.335337 0.766332 -0.707287 +v -0.380345 0.713627 -0.676936 +v 0.034958 0.858431 -0.277765 +v 0.119040 0.887730 -0.350867 +v -0.027737 -0.372175 -0.268846 +v 0.385000 0.019649 -0.349485 +v -0.294559 -0.346854 -0.101282 +v -0.611107 0.422894 0.169032 +v 0.324072 0.097035 -0.305646 +v -0.623413 0.383093 0.220331 +v -0.627597 0.443368 0.115130 +v -0.662020 0.319386 0.131519 +v -0.623012 0.369828 0.290892 +v -0.170469 0.279689 -0.206190 +v 0.393837 0.040282 -0.320738 +v -0.111922 0.049691 -0.309623 +v -0.374738 0.643577 -0.646498 +v -0.493738 0.683896 -0.298041 +v -0.205443 0.726766 -0.115752 +v -0.488872 0.592984 -0.181281 +v -0.397149 0.631327 -0.630317 +v 0.809421 -0.289851 -0.095607 +v -0.010191 -0.331314 -0.339678 +v -0.030312 -0.291567 -0.318006 +v 0.522854 0.084460 -0.273634 +v -0.274379 0.662866 -0.076732 +v -0.386071 0.661932 -0.658922 +v -0.501646 0.665166 -0.330492 +v 0.097150 0.254707 -0.201602 +v 0.497487 0.153479 -0.241306 +v -0.403469 0.655869 -0.632583 +v 0.025901 -0.340070 -0.399143 +v 0.014954 -0.291315 -0.407144 +v -0.003900 -0.320159 -0.369880 +v -0.045700 -0.329509 -0.245026 +v -0.428366 0.219008 -0.170059 +v -0.417448 0.651702 -0.584678 +v -0.022892 -0.265208 -0.367045 +v -0.049417 -0.278504 -0.274351 +v 0.415692 0.083383 -0.306289 +v 0.724442 -0.244567 -0.081019 +v 0.258358 0.179433 -0.287082 +v -0.439928 -0.271689 -0.097721 +v -0.506639 0.789236 -0.517700 +v -0.551763 0.565058 -0.048367 +v -0.594033 0.395332 -0.066521 +v 0.543837 -0.096533 -0.322013 +v -0.468658 -0.237962 -0.113350 +v -0.265406 -0.026526 -0.311482 +v -0.452068 0.580978 -0.447531 +v -0.465152 0.779718 -0.566006 +v -0.006450 -0.259320 -0.396597 +v 0.454086 0.082448 -0.305373 +v -0.532217 -0.211903 -0.019475 +v -0.469466 0.598624 -0.280240 +v -0.635208 0.377471 0.015886 +v 0.272112 0.009496 -0.411059 +v -0.495831 -0.202164 -0.143759 +v -0.518231 -0.214605 -0.060075 +v -0.535918 -0.207449 0.021121 +v -0.456436 0.536443 -0.292858 +v -0.632741 0.542703 0.072205 +v -0.628144 0.520406 0.057595 +v -0.405082 0.809146 -0.662374 +v 0.007818 0.132590 -0.303292 +v 0.494793 0.285227 -0.119812 +v -0.510255 -0.204912 -0.098948 +v -0.540278 -0.182219 -0.072880 +v -0.557009 -0.174437 -0.000909 +v -0.621700 0.552622 0.039855 +v 0.288839 0.224847 -0.263866 +v -0.465418 0.574249 -0.376975 +v -0.010517 -0.212909 -0.424040 +v -0.031483 -0.202260 -0.393894 +v -0.045709 -0.222599 -0.339161 +v -0.525403 -0.176077 -0.120375 +v -0.614553 0.497103 0.034389 +v -0.493527 0.523487 -0.134038 +v -0.448604 0.641341 -0.431590 +v 0.351704 0.204667 -0.273952 +v -0.064669 -0.180855 -0.314227 +v -0.558550 -0.134260 -0.067544 +v -0.557048 -0.169753 -0.043822 +v -0.581689 -0.132848 0.014859 +v -0.580258 -0.142844 0.053912 +v -0.535070 -0.162649 0.176777 +v 0.547019 0.184706 -0.195591 +v -0.480057 0.624151 -0.304700 +v -0.619764 0.566179 0.067032 +v -0.431208 0.691357 -0.544101 +v -0.051752 -0.173424 -0.367579 +v -0.452274 -0.142317 -0.227995 +v -0.512502 -0.141667 -0.160621 +v -0.579988 -0.115698 0.104931 +v -0.562997 -0.134856 0.131309 +v -0.433158 0.630554 -0.512326 +v -0.455127 0.669927 -0.443380 +v 0.447683 0.156968 -0.260696 +v -0.029431 -0.171947 -0.418660 +v -0.343235 0.812327 -0.705355 +v 0.104478 0.206976 -0.262546 +v -0.543183 -0.133392 -0.114534 +v -0.505432 0.462857 -0.136526 +v -0.008954 -0.149679 -0.440993 +v -0.031900 -0.138024 -0.412319 +v -0.052230 -0.145939 -0.361956 +v -0.166617 0.236998 -0.237754 +v -0.516880 -0.099889 -0.178104 +v -0.570064 -0.103977 -0.091272 +v -0.587407 -0.098707 0.033695 +v -0.586390 -0.115505 0.061248 +v -0.570705 -0.090390 0.166299 +v -0.489401 -0.112796 -0.205002 +v -0.547407 -0.107847 -0.134182 +v -0.581447 -0.116434 -0.026856 +v -0.631251 0.472281 0.066244 +v -0.466031 0.497693 -0.162000 +v -0.554128 0.397174 -0.107369 +v -0.477690 0.571292 -0.289308 +v -0.468884 0.585146 -0.284470 +v -0.242787 0.273809 -0.198476 +v -0.026983 -0.087880 -0.395562 +v -0.045549 -0.122729 -0.381498 +v -0.584191 -0.072750 -0.081329 +v 0.155339 0.121285 -0.314097 +v -0.605502 0.518432 0.008285 +v -0.575740 0.529096 -0.024514 +v -0.594755 0.563995 0.011029 +v -0.320778 -0.586651 0.358580 +v -0.602485 -0.073464 -0.009466 +v -0.607768 -0.064501 0.051770 +v -0.599654 -0.075891 0.064171 +v -0.589554 -0.077708 0.133714 +v -0.465743 0.530626 -0.232219 +v -0.066722 -0.101797 -0.333518 +v -0.569292 -0.042530 -0.120563 +v -0.600557 -0.064740 -0.042006 +v -0.634548 0.512162 0.132277 +v -0.663447 0.276237 0.088548 +v -0.011288 -0.088221 -0.427163 +v -0.025221 -0.055896 -0.366002 +v -0.497348 -0.063707 -0.207444 +v -0.526926 -0.060114 -0.168499 +v -0.552368 -0.047389 -0.146998 +v -0.613630 -0.046765 0.025960 +v -0.616627 0.454970 0.047252 +v -0.490992 0.572967 -0.146318 +v -0.230857 0.695257 -0.117136 +v -0.584073 0.334588 -0.105360 +v -0.415699 0.606921 -0.592382 +v -0.592295 -0.021055 -0.048436 +v -0.610505 -0.018384 0.015203 +v -0.615766 -0.026157 0.087627 +v -0.546968 0.477530 -0.077966 +v -0.445827 0.494658 -0.200366 +v -0.496415 0.718944 -0.458269 +v 0.129577 -0.003521 -0.433669 +v -0.430216 0.605533 -0.548281 +v -0.642962 0.310233 0.001094 +v -0.480110 -0.031783 -0.226927 +v -0.549071 -0.009238 -0.152352 +v 0.176245 0.003768 -0.428344 +v -0.012954 0.205468 -0.248942 +v -0.091825 0.217269 -0.242226 +v 0.156058 0.086445 -0.328720 +v 0.346867 -0.060710 -0.419954 +v 0.216237 -0.013393 -0.438672 +v 0.438359 0.257500 -0.204652 +v 0.571385 0.082595 -0.248179 +v 0.701164 -0.307349 -0.115901 +v 0.567588 0.037277 -0.265469 +v 0.080481 0.085676 -0.324425 +v 0.617841 -0.105714 -0.276800 +v 0.093500 0.926807 -0.292982 +v 0.344512 0.236863 -0.253323 +v 0.843409 -0.264456 -0.063970 +v 0.226749 0.186785 -0.286628 +v 0.738051 -0.295867 -0.102662 +v 0.179448 0.040141 -0.367809 +v -0.324228 0.233409 -0.204041 +v 0.409697 0.246570 -0.230289 +v 0.432714 0.007624 -0.334867 +v -0.028572 -0.468065 -0.340035 +v 0.102695 0.915079 -0.320988 +v 0.150008 0.158130 -0.292107 +v -0.431708 -0.556070 -0.082774 +v 0.459405 0.120616 -0.267788 +v -0.055878 0.241887 -0.209770 +v -0.218711 0.236678 -0.234520 +v 0.213479 0.232565 -0.244088 +v 0.125842 0.917605 -0.338454 +v -0.025682 -0.561771 -0.391734 +v 0.148154 0.897563 -0.365690 +v -0.198237 0.174117 -0.265317 +v 0.149367 -0.034395 -0.457088 +v -0.350816 0.600388 -0.060765 +v -0.271040 0.163005 -0.267223 +v 0.169389 0.878077 -0.370920 +v 0.014668 -0.595197 -0.381633 +v 0.213960 0.080065 -0.325689 +v -0.289607 0.632016 -0.084471 +v 0.471123 -0.023449 -0.339398 +v 0.415088 0.300834 -0.158857 +v 0.063052 0.041954 -0.333564 +v 0.108935 0.038419 -0.339739 +v -0.306624 0.571576 -0.097076 +v 0.315998 0.334333 -0.135168 +v 0.194987 0.057057 -0.334006 +v 0.158637 0.870355 -0.381107 +v -0.330783 0.588366 -0.080497 +v -0.015349 0.229232 -0.227251 +v 0.585658 0.179965 -0.172356 +v -0.036784 -0.591040 -0.397085 +v 0.143446 0.849315 -0.371760 +v 0.396566 0.212742 -0.254352 +v -0.339579 0.560651 -0.106793 +v 0.647197 0.067801 -0.188981 +v 0.765484 -0.224174 -0.030490 +v 0.275699 0.256211 -0.226601 +v 0.447829 -0.041016 -0.361767 +v 0.350190 0.035145 -0.338499 +v -0.151911 -0.479520 -0.208213 +v 0.196795 0.195205 -0.272894 +v 0.156813 0.213522 -0.255365 +v 0.748702 -0.198614 0.010900 +v 0.533549 0.151017 -0.226292 +v -0.144238 0.197093 -0.252376 +v 0.857804 -0.300571 -0.064218 +v -0.316748 -0.576798 -0.185445 +v 0.248279 0.154055 -0.305734 +v 0.550564 -0.328698 -0.313416 +v 0.351387 0.076961 -0.302805 +v -0.101900 0.304397 -0.163753 +v 0.539773 0.215480 -0.172689 +v -0.332622 -0.603153 -0.183712 +v -0.314310 0.532240 -0.109381 +v 0.385423 0.066615 -0.311591 +v 0.611171 0.085183 -0.218368 +v 0.405536 0.105382 -0.289655 +v 0.511237 -0.002168 -0.312602 +v 0.595911 -0.017308 -0.272538 +v 0.343080 0.056948 -0.313464 +v -0.128815 -0.480938 -0.269921 +v 0.634431 0.039733 -0.210585 +v 0.374493 0.270035 -0.219873 +v 0.817709 -0.221882 -0.022485 +v 0.536561 0.245917 -0.140826 +v -0.101145 -0.517489 -0.359435 +v -0.001767 0.169531 -0.270515 +v -0.322179 0.491755 -0.128402 +v 0.470526 0.097990 -0.283827 +v 0.355804 -0.025334 -0.406927 +v 0.209596 0.281857 -0.204140 +v 0.089882 0.023466 -0.366295 +v 0.110823 0.124770 -0.310525 +v 0.273626 0.069832 -0.319073 +v 0.190178 0.310648 -0.168407 +v -0.401005 0.858456 -0.678656 +v 0.044355 0.209226 -0.246269 +v -0.317955 -0.513733 -0.156965 +v 0.811598 -0.352032 -0.119349 +v -0.088961 -0.571082 -0.387637 +v -0.281794 0.471766 -0.118523 +v 0.647316 0.095129 -0.170117 +v -0.078494 0.261848 -0.196900 +v 0.186788 -0.087918 -0.471621 +v -0.320916 0.261984 -0.184287 +v -0.118071 0.273456 -0.206199 +v 0.563579 0.142640 -0.216729 +v 0.261624 0.217236 -0.262190 +v 0.666839 -0.040622 -0.215992 +v 0.262998 -0.019714 -0.433600 +v 0.780365 -0.326035 -0.125145 +v 0.838947 -0.313054 -0.083592 +v 0.484972 0.209382 -0.221533 +v 0.128699 0.237652 -0.235151 +v -0.428238 -0.227054 0.248456 +v 0.507097 -0.076095 -0.339750 +v 0.633945 -0.067767 -0.261586 +v 0.464366 0.272395 -0.167300 +v 0.026098 -0.527945 -0.382544 +v 0.198272 0.025619 -0.398593 +v -0.287749 -0.603416 -0.202159 +v -0.065529 -0.494706 -0.361724 +v -0.122160 0.240598 -0.227236 +v 0.444227 0.198079 -0.245465 +v 0.706710 -0.334181 -0.125079 +v -0.226515 -0.582797 -0.214303 +v 0.353804 0.002940 -0.387328 +v 0.083290 -0.012982 -0.436864 +v 0.159527 0.279768 -0.187616 +v 0.768416 -0.257577 -0.073543 +v 0.249487 0.041870 -0.364527 +v -0.251631 0.425134 -0.107076 +v -0.192544 0.363380 -0.073586 +v 0.325009 0.262249 -0.229810 +v 0.256507 0.286898 -0.194320 +v 0.032024 0.016425 -0.342117 +v -0.142612 -0.579236 -0.363032 +v -0.263525 0.398337 -0.130416 +v -0.225037 0.391510 -0.101368 +v 0.306397 0.027271 -0.374566 +v 0.202194 0.339966 -0.109926 +v 0.345469 0.358096 -0.081207 +v 0.627786 -0.019414 -0.247041 +v -0.397520 0.866733 -0.672406 +v -0.056797 0.173001 -0.271280 +v 0.324988 0.300574 -0.184787 +v 0.046655 -0.008228 -0.410814 +v -0.209464 0.355909 -0.103725 +v 0.272541 0.340136 -0.122985 +v 0.305318 -0.043579 -0.426780 +v 0.354910 0.177524 -0.286038 +v 0.568269 -0.030582 -0.294198 +v -0.255544 0.301590 -0.163966 +v -0.197079 0.264288 -0.218625 +v 0.084195 0.268764 -0.185983 +v -0.370117 0.857759 -0.688082 +v -0.236685 -0.565952 -0.208130 +v -0.240886 0.350828 -0.131682 +v -0.172987 0.346994 -0.074676 +v 0.249886 0.349790 -0.101183 +v 0.352487 0.330040 -0.142569 +v 0.397050 0.329860 -0.122346 +v 0.810921 -0.245067 -0.059204 +v -0.349854 0.838940 -0.694431 +v 0.562405 -0.298243 -0.297476 +v 0.624359 0.108145 -0.192745 +v 0.590109 0.136870 -0.201080 +v -0.209487 0.205896 -0.250162 +v -0.047860 0.287895 -0.149584 +v -0.227572 0.329493 -0.138679 +v -0.072660 0.312626 -0.122038 +v 0.844910 -0.242641 -0.041304 +v 0.117953 0.309062 -0.126995 +v 0.110653 0.169824 -0.286360 +v -0.260524 -0.544343 -0.195942 +v -0.061548 -0.467015 -0.313511 +v 0.417348 -0.003013 -0.354772 +v 0.289157 0.050194 -0.334052 +v -0.184237 0.330240 -0.139339 +v -0.136998 0.326605 -0.132237 +v 0.070352 0.289209 -0.151686 +v 0.159053 0.315101 -0.142503 +v 0.236535 0.321920 -0.159991 +v 0.294443 -0.594336 -0.323147 +v 0.131895 -0.591446 -0.351214 +v 0.066362 -0.594204 -0.370084 +v 0.400449 -0.582536 -0.307853 +v 0.318606 -0.580863 -0.329276 +v -0.231038 0.024020 -0.311447 +v -0.267776 0.038869 -0.304749 +v 0.004387 0.755827 -0.272200 +v 0.413956 -0.548381 -0.315459 +v 0.324276 -0.555411 -0.332198 +v 0.211879 -0.577710 -0.342267 +v 0.147555 -0.565159 -0.354414 +v -0.196370 -0.580989 -0.223508 +v -0.175544 0.143227 -0.278462 +v -0.220600 0.156937 -0.275541 +v -0.377309 -0.577460 -0.162569 +v 0.045799 0.740317 -0.278724 +v 0.234439 -0.558110 -0.344624 +v 0.030816 -0.567745 -0.382023 +v 0.570435 -0.568573 -0.093243 +v 0.200888 -0.527256 -0.349608 +v 0.112319 -0.544617 -0.366149 +v -0.371204 0.461298 -0.167344 +v -0.190444 -0.535149 -0.209194 +v -0.404349 -0.567378 -0.140053 +v 0.653626 -0.540060 -0.099080 +v 0.633856 -0.529585 -0.118571 +v 0.332178 -0.526792 -0.331152 +v 0.466964 0.060923 -0.311768 +v -0.324751 0.132690 -0.260918 +v -0.343386 -0.540695 -0.164536 +v 0.534927 -0.547317 -0.130747 +v 0.278074 -0.508206 -0.341740 +v 0.199269 -0.507765 -0.351896 +v 0.106733 -0.509781 -0.367147 +v 0.016190 -0.495415 -0.372593 +v 0.318422 0.152278 -0.292533 +v -0.301967 0.014749 -0.296656 +v -0.380867 -0.518743 -0.118034 +v -0.329242 -0.000425 -0.280652 +v 0.593880 -0.515663 -0.137240 +v -0.055052 -0.578729 0.400404 +v 0.452885 -0.498799 -0.321167 +v 0.386734 -0.500540 -0.339757 +v 0.324200 -0.484088 -0.358385 +v 0.197851 -0.490668 -0.374906 +v 0.122873 -0.491717 -0.369273 +v 0.570260 -0.495177 -0.152359 +v 0.362043 -0.491625 -0.342283 +v 0.270728 -0.488373 -0.363578 +v 0.263324 -0.463963 -0.389785 +v -0.035001 -0.494751 -0.371290 +v -0.055839 0.626991 -0.200744 +v -0.227155 -0.511059 -0.190682 +v 0.649266 -0.468623 -0.151553 +v 0.530113 -0.515710 -0.160665 +v 0.525981 -0.458460 -0.287223 +v 0.419998 -0.486364 -0.337561 +v 0.414118 -0.455852 -0.356010 +v 0.317666 -0.460876 -0.380755 +v 0.192410 -0.471587 -0.389312 +v 0.142819 -0.423505 -0.412930 +v 0.068349 -0.475585 -0.370009 +v 0.677292 -0.485570 -0.135770 +v 0.616631 -0.454978 -0.154400 +v -0.373164 0.050790 -0.258697 +v 0.293225 -0.438319 -0.394070 +v 0.198560 -0.443697 -0.401209 +v 0.108514 -0.460050 -0.387915 +v 0.019863 -0.465230 -0.351990 +v -0.567113 0.165680 0.304388 +v -0.232812 -0.459449 -0.169806 +v -0.544708 0.334393 -0.137292 +v 0.666994 -0.425189 -0.157406 +v -0.476074 0.052249 -0.209772 +v 0.483202 -0.428663 -0.339449 +v 0.339793 -0.432389 -0.381689 +v 0.025074 -0.427428 -0.359342 +v -0.075270 -0.448157 -0.219146 +v -0.147833 0.679863 -0.193871 +v -0.375579 0.824416 -0.695543 +v -0.061154 0.802124 -0.223621 +v 0.717089 -0.440533 -0.150339 +v -0.223067 0.612464 -0.142423 +v 0.534999 -0.401858 -0.307406 +v 0.381855 -0.449570 -0.368001 +v 0.059925 -0.406035 -0.391852 +v -0.048398 -0.425379 -0.199382 +v -0.095781 -0.446808 -0.206757 +v -0.127149 -0.449304 -0.203357 +v -0.183495 -0.467247 -0.191355 +v 0.725089 -0.409225 -0.153823 +v 0.612413 -0.431949 -0.162878 +v 0.437141 -0.430463 -0.354474 +v 0.348699 -0.392054 -0.396107 +v 0.301782 -0.387127 -0.403839 +v 0.286286 -0.413476 -0.395634 +v 0.243876 -0.423465 -0.405075 +v 0.186111 -0.388163 -0.427035 +v 0.087336 -0.359908 -0.429693 +v -0.330486 0.396464 -0.162744 +v -0.152740 -0.385587 -0.204517 +v -0.330448 0.741222 -0.682416 +v 0.756104 -0.412719 -0.141796 +v -0.093673 0.172922 -0.272929 +v 0.480082 -0.398058 -0.361578 +v 0.334332 -0.358330 -0.399533 +v 0.174321 -0.406126 -0.424529 +v -0.069626 -0.418840 -0.193969 +v -0.184355 -0.429112 -0.188795 +v -0.399096 0.207205 -0.185603 +v -0.430125 0.573953 -0.537288 +v 0.221453 -0.594249 -0.332740 +v 0.448779 -0.386599 -0.373341 +v 0.387468 -0.395279 -0.388171 +v 0.268530 -0.347231 -0.424105 +v 0.228031 -0.385266 -0.418898 +v -0.236701 -0.417448 -0.164543 +v -0.245907 -0.341718 -0.180062 +v -0.445629 0.035472 -0.234841 +v 0.723670 -0.383975 -0.150858 +v 0.664991 -0.392807 -0.152318 +v 0.668743 -0.364073 -0.143080 +v 0.188342 -0.347054 -0.434867 +v -0.072268 -0.389306 -0.195946 +v -0.103007 -0.397120 -0.199549 +v 0.103082 -0.579260 0.431727 +v 0.780422 -0.361197 -0.136707 +v 0.741697 -0.349367 -0.138265 +v 0.431460 -0.343957 -0.376953 +v 0.383481 -0.366290 -0.390448 +v 0.219004 -0.339587 -0.437454 +v 0.157175 -0.348192 -0.443181 +v 0.135688 -0.310795 -0.459154 +v -0.186146 -0.343746 -0.211854 +v -0.285364 0.305872 -0.162381 +v -0.512018 0.263386 -0.147240 +v -0.512991 0.313910 -0.151671 +v 0.503757 -0.357233 -0.350637 +v 0.356628 -0.321172 -0.401854 +v 0.313459 -0.337587 -0.415306 +v 0.112238 -0.329403 -0.449789 +v -0.044562 -0.370192 -0.211543 +v -0.060725 -0.327490 -0.221027 +v -0.058613 -0.371902 -0.200971 +v -0.105879 -0.359122 -0.205553 +v -0.169727 -0.314916 -0.224400 +v -0.288603 0.397719 -0.146766 +v -0.168182 0.632448 -0.177227 +v -0.505738 -0.245587 0.027612 +v 0.043057 0.076460 -0.328860 +v -0.000872 0.051069 -0.326297 +v -0.220410 0.557610 -0.126915 +v -0.050127 0.017431 -0.324760 +v 0.475561 -0.321508 -0.363420 +v -0.108290 0.091243 -0.296909 +v -0.209172 -0.379345 -0.192704 +v -0.259573 0.507710 -0.101589 +v -0.174949 0.042953 -0.307791 +v -0.228753 0.065302 -0.306690 +v 0.512815 -0.314230 -0.340975 +v 0.377770 -0.310341 -0.401909 +v 0.271696 -0.296559 -0.435405 +v 0.195093 -0.302138 -0.449000 +v -0.204158 -0.294214 -0.220795 +v -0.242895 0.119326 -0.283208 +v -0.272296 0.079513 -0.289467 +v -0.310063 0.048167 -0.282725 +v -0.298110 0.101194 -0.275753 +v 0.009222 0.791060 -0.275884 +v 0.508677 -0.271330 -0.353471 +v 0.425548 -0.296200 -0.389052 +v 0.395070 -0.266341 -0.399507 +v 0.102964 -0.279547 -0.467069 +v -0.370240 0.403055 -0.171395 +v -0.477936 0.482305 -0.148585 +v -0.133266 -0.325782 -0.218633 +v -0.281122 -0.322940 -0.148037 +v -0.340904 -0.313702 -0.135698 +v -0.092568 0.702750 -0.226766 +v 0.082168 0.708794 -0.266585 +v 0.343238 -0.287992 -0.416126 +v 0.221107 -0.246999 -0.449830 +v 0.174971 -0.262164 -0.455666 +v -0.073500 -0.273981 -0.244844 +v -0.259588 -0.295768 -0.183750 +v -0.358166 -0.286432 -0.159889 +v -0.358852 0.335269 -0.175990 +v 0.010950 -0.580315 0.443023 +v 0.476544 -0.272081 -0.374057 +v 0.403109 -0.242816 -0.406027 +v 0.334622 -0.259676 -0.417801 +v 0.236273 -0.275963 -0.439198 +v 0.061244 -0.270708 -0.455853 +v -0.176074 0.604540 -0.163465 +v -0.236378 -0.273649 -0.211699 +v -0.300695 -0.277496 -0.190939 +v -0.289566 0.489031 -0.112898 +v -0.526154 0.369830 -0.134893 +v -0.285086 0.342938 -0.152510 +v 0.457938 -0.240770 -0.384542 +v 0.345338 -0.234237 -0.425749 +v 0.287940 -0.237811 -0.435121 +v 0.147998 -0.249227 -0.469670 +v -0.393551 0.246813 -0.177797 +v -0.100838 -0.300532 -0.228787 +v 0.298884 0.188180 -0.288438 +v -0.479151 -0.260449 0.090684 +v 0.180337 -0.215441 -0.467109 +v 0.100596 -0.236018 -0.474934 +v 0.049997 -0.214371 -0.471222 +v 0.019156 -0.230381 -0.445011 +v -0.404997 0.450782 -0.168542 +v -0.072273 -0.231479 -0.270614 +v -0.135225 -0.244415 -0.258236 +v -0.247960 -0.239166 -0.239145 +v -0.389431 -0.265766 -0.158590 +v 0.177912 0.847427 -0.385884 +v -0.472369 0.325854 -0.170737 +v -0.593242 0.182676 0.329999 +v 0.367860 -0.199140 -0.424478 +v -0.362138 0.662347 -0.660910 +v -0.163183 -0.208433 -0.269240 +v -0.177269 -0.247702 -0.249783 +v -0.199217 -0.216725 -0.251565 +v -0.297869 -0.246775 -0.234660 +v -0.440359 -0.226774 -0.165210 +v 0.535086 -0.201210 -0.339881 +v 0.437554 -0.204592 -0.387973 +v 0.328571 -0.204516 -0.436020 +v 0.257829 -0.202942 -0.449367 +v 0.206522 -0.194159 -0.462734 +v 0.078104 -0.171204 -0.480938 +v -0.059805 -0.221143 -0.298727 +v -0.104577 -0.213757 -0.265518 +v -0.363568 -0.210992 -0.243849 +v -0.364450 -0.240282 -0.213113 +v 0.041814 0.674297 -0.235537 +v 0.501402 -0.215229 -0.359497 +v 0.435681 -0.176286 -0.386565 +v 0.396098 -0.193550 -0.404334 +v 0.133042 -0.165748 -0.475402 +v 0.120169 -0.199267 -0.479140 +v -0.230679 -0.211436 -0.252926 +v -0.299538 -0.201977 -0.265719 +v -0.415727 -0.218927 -0.199840 +v -0.479604 0.229258 -0.156073 +v -0.099519 0.132990 -0.290253 +v 0.387319 -0.143263 -0.410591 +v 0.226924 -0.159510 -0.465265 +v 0.019537 -0.180242 -0.458297 +v -0.111253 0.629733 -0.196301 +v -0.375742 -0.183555 -0.257996 +v -0.421419 -0.185522 -0.228888 +v -0.462557 -0.194072 -0.184033 +v -0.353932 0.776383 -0.704617 +v 0.587206 -0.184887 -0.298276 +v 0.473407 -0.151977 -0.367935 +v 0.194365 -0.148768 -0.469547 +v 0.048356 -0.176470 -0.474361 +v -0.100821 -0.178254 -0.276939 +v -0.161954 -0.165514 -0.280761 +v -0.229898 -0.185105 -0.272364 +v -0.425594 0.357328 -0.178125 +v 0.561834 -0.154302 -0.314820 +v 0.356373 -0.147796 -0.427641 +v 0.329860 -0.161883 -0.434593 +v 0.121774 -0.130500 -0.482351 +v 0.095336 -0.108717 -0.480603 +v -0.517036 0.418530 -0.131978 +v -0.029445 0.721310 -0.252907 +v -0.077141 -0.169672 -0.284236 +v -0.209090 -0.151292 -0.286252 +v -0.270301 -0.161263 -0.288050 +v 0.517417 -0.139751 -0.344997 +v 0.402898 -0.107588 -0.398211 +v 0.298907 -0.095227 -0.438881 +v 0.278271 -0.152741 -0.448316 +v 0.276086 -0.112682 -0.454302 +v 0.236256 -0.114210 -0.465168 +v -0.051666 0.115677 -0.296971 +v -0.111713 -0.126792 -0.296206 +v -0.323197 -0.144489 -0.284251 +v -0.137361 0.097515 -0.298825 +v 0.168317 -0.115022 -0.475392 +v 0.048542 -0.125286 -0.473787 +v 0.008025 -0.136446 -0.456702 +v -0.074345 -0.140195 -0.313755 +v -0.168285 -0.122176 -0.295231 +v -0.226122 -0.119061 -0.304154 +v -0.274869 -0.122879 -0.304033 +v -0.600539 0.171393 0.094666 +v -0.440004 0.168636 0.363119 +v -0.053241 0.756484 -0.244985 +v -0.388033 -0.320450 0.125273 +v 0.587663 -0.122465 -0.290900 +v 0.442600 -0.077352 -0.380016 +v -0.418199 0.060634 -0.238974 +v -0.358005 -0.125109 -0.279584 +v -0.398791 -0.140792 -0.261777 +v -0.177164 0.691920 -0.172276 +v 0.397633 -0.062048 -0.399097 +v 0.353692 -0.089455 -0.418789 +v 0.246001 -0.071976 -0.455105 +v 0.010716 -0.097027 -0.454113 +v -0.085177 -0.088994 -0.316257 +v -0.107554 -0.089828 -0.309671 +v -0.296412 -0.079572 -0.301479 +v -0.345461 -0.078210 -0.282188 +v -0.433596 0.304729 -0.176440 +v 0.428373 0.048254 -0.318925 +v 0.068728 0.807030 -0.310267 +v 0.132115 -0.069267 -0.473666 +v 0.047500 -0.047475 -0.450768 +v -0.235599 -0.097935 -0.306505 +v -0.414453 -0.085591 -0.262480 +v -0.428815 0.133329 -0.205462 +v 0.581810 -0.079315 -0.294577 +v -0.275424 0.214614 -0.236955 +v 0.199376 -0.051455 -0.456017 +v -0.531706 0.178354 -0.099325 +v 0.092635 -0.043775 -0.460413 +v 0.069353 -0.076279 -0.468986 +v 0.022258 -0.053259 -0.441318 +v -0.209491 -0.034838 -0.308667 +v -0.078392 -0.594395 -0.398948 +v -0.051287 -0.606090 -0.387714 +v 0.020717 -0.607285 -0.353707 +v 0.113182 -0.606039 -0.336750 +v 0.226871 -0.603865 -0.316500 +v 0.345201 -0.599226 -0.299045 +v 0.419861 -0.593355 -0.276624 +v -0.144303 -0.600264 -0.363102 +v -0.052054 -0.606368 -0.357690 +v 0.343171 -0.600497 -0.278138 +v -0.162301 -0.605519 -0.309640 +v 0.043643 -0.605846 -0.322673 +v 0.164771 -0.603201 -0.301038 +v 0.259951 -0.601616 -0.283806 +v 0.297681 -0.597559 -0.256574 +v 0.007196 -0.603055 -0.304033 +v 0.146646 -0.598540 -0.280733 +v 0.376244 -0.600083 -0.244736 +v 0.130542 -0.583374 -0.270419 +v 0.256883 -0.583124 -0.249793 +v 0.302901 -0.578040 -0.238335 +v -0.071634 -0.603803 -0.295578 +v 0.019603 -0.582969 -0.284547 +v 0.363098 -0.585703 -0.216982 +v 0.385094 -0.594729 -0.203124 +v 0.420911 -0.597321 -0.235453 +v -0.089348 -0.585352 -0.240573 +v 0.255638 -0.558068 -0.232086 +v -0.114462 -0.605973 -0.326620 +v -0.130558 -0.602095 -0.210471 +v -0.035541 -0.586232 -0.282537 +v 0.079494 -0.561511 -0.262703 +v 0.169225 -0.559253 -0.246959 +v 0.324880 -0.565104 -0.220072 +v 0.439062 -0.597993 -0.120162 +v -0.198363 -0.600792 -0.244678 +v -0.194859 -0.605928 -0.218541 +v -0.053716 -0.566385 -0.252077 +v 0.001842 -0.558112 -0.262600 +v 0.195292 -0.551866 -0.220504 +v 0.344910 -0.560504 -0.192144 +v 0.354504 -0.595564 -0.120612 +v 0.400019 -0.598801 -0.150067 +v 0.484505 -0.586480 -0.128302 +v 0.087469 -0.554530 -0.232522 +v 0.268967 -0.550388 -0.194309 +v 0.318506 -0.551911 -0.171323 +v 0.355565 -0.574821 -0.158110 +v 0.480038 -0.593716 -0.109480 +v -0.170227 -0.606151 -0.215771 +v -0.027191 -0.555757 -0.231003 +v -0.234641 -0.604864 -0.211321 +v 0.042788 -0.556298 -0.201428 +v 0.320092 -0.560070 -0.128459 +v 0.375843 -0.599829 -0.073333 +v 0.571223 -0.584155 -0.054865 +v -0.279295 -0.606856 -0.181742 +v 0.085122 -0.557103 -0.135930 +v 0.443992 -0.598208 -0.067547 +v 0.493605 -0.595915 -0.034051 +v -0.116346 -0.580415 -0.163893 +v 0.137840 -0.555675 -0.133526 +v 0.303619 -0.588673 -0.067249 +v 0.420500 -0.585117 -0.051617 +v 0.433585 -0.579758 -0.053867 +v 0.517888 -0.595448 -0.050610 +v 0.604049 -0.583995 -0.020249 +v -0.356802 -0.604386 -0.170561 +v -0.362312 -0.606530 -0.141749 +v -0.100309 -0.556969 -0.163575 +v 0.186048 -0.553278 -0.165344 +v 0.320035 -0.600153 -0.040741 +v 0.374650 -0.581851 -0.045220 +v 0.578947 -0.592354 0.007854 +v -0.246944 -0.607176 -0.108613 +v -0.132353 -0.603601 -0.109296 +v 0.249252 -0.552694 -0.118289 +v 0.342551 -0.590814 -0.025003 +v 0.489336 -0.582784 -0.002646 +v 0.636417 -0.576889 0.007660 +v -0.390426 -0.603754 -0.152184 +v 0.272243 -0.567914 -0.042774 +v 0.311849 -0.600902 0.027127 +v 0.329529 -0.602184 0.001171 +v 0.531665 -0.596686 0.019630 +v 0.562843 -0.591692 0.069672 +v -0.389973 -0.290696 0.182433 +v -0.183445 -0.606103 -0.099439 +v -0.051277 -0.560201 -0.095747 +v -0.040385 -0.558921 -0.094706 +v 0.063430 -0.559495 -0.045395 +v 0.519665 -0.593988 0.086896 +v 0.707548 -0.542385 -0.001174 +v -0.305684 -0.607533 -0.092662 +v -0.092787 -0.605825 -0.044771 +v 0.176117 -0.557270 -0.028203 +v 0.266460 -0.555642 -0.066529 +v 0.277273 -0.587531 -0.007888 +v 0.266268 -0.580225 0.038950 +v 0.502886 -0.576322 0.049302 +v -0.429261 -0.598698 -0.098333 +v -0.410305 -0.604979 -0.092472 +v -0.367899 -0.607097 -0.062273 +v -0.190239 -0.607137 -0.054849 +v 0.243403 -0.560428 0.039973 +v 0.615116 -0.577682 0.072174 +v 0.652853 -0.567056 0.057663 +v -0.176402 -0.605119 -0.026195 +v -0.106036 -0.602782 -0.004989 +v 0.185293 -0.558629 0.065211 +v 0.495355 -0.584084 0.091199 +v 0.729122 -0.529845 0.069587 +v -0.444383 -0.579596 -0.074963 +v -0.434624 -0.597626 -0.048469 +v 0.002448 -0.561526 -0.011119 +v 0.114793 -0.559291 0.011662 +v 0.361401 -0.593726 0.090851 +v 0.516252 -0.583249 0.162881 +v 0.692971 -0.536305 0.117024 +v -0.233152 -0.605698 -0.010166 +v -0.190686 -0.586661 -0.009692 +v 0.266254 -0.572156 0.079325 +v 0.289528 -0.594122 0.065851 +v 0.309245 -0.595793 0.098002 +v 0.413149 -0.598360 0.123741 +v 0.423584 -0.597900 0.125436 +v 0.455258 -0.595692 0.129914 +v 0.579042 -0.579667 0.108227 +v -0.111863 -0.578893 0.017404 +v -0.022714 -0.602201 0.056569 +v 0.481169 -0.590428 0.189692 +v 0.530247 -0.561110 0.203800 +v 0.616198 -0.559116 0.138791 +v 0.770514 -0.496419 0.116099 +v -0.301903 -0.276082 0.260007 +v -0.392951 -0.603691 -0.003229 +v -0.066566 -0.603868 0.033890 +v -0.017675 -0.599285 0.073036 +v 0.297381 -0.579047 0.121301 +v 0.731727 -0.495901 0.164670 +v -0.408408 0.160062 0.299551 +v -0.296448 -0.605929 0.049908 +v -0.251748 -0.606302 0.049375 +v -0.076759 -0.583240 0.064534 +v -0.008258 -0.588188 0.083005 +v 0.014552 -0.564729 0.066558 +v 0.269383 -0.560677 0.113775 +v 0.630834 -0.532416 0.179208 +v -0.416497 -0.597368 0.007489 +v -0.259833 -0.609056 0.067985 +v 0.325174 -0.570977 0.157057 +v 0.346963 -0.590108 0.152664 +v 0.364190 -0.594668 0.150078 +v 0.669188 -0.531826 0.159270 +v 0.253915 -0.554885 0.160817 +v 0.312579 -0.555071 0.168492 +v 0.370374 -0.573246 0.194326 +v 0.412327 -0.593798 0.225814 +v 0.503273 -0.571622 0.240515 +v 0.569841 -0.550555 0.181853 +v -0.597378 0.175986 0.280948 +v 0.101652 -0.560117 0.111937 +v 0.381231 -0.571679 0.217730 +v 0.703323 -0.487798 0.199914 +v -0.563056 0.196646 0.374639 +v -0.457600 0.147408 0.301677 +v -0.232076 -0.299763 0.252085 +v -0.337417 -0.601977 0.078510 +v -0.086294 -0.589113 0.139825 +v 0.131055 -0.555720 0.203288 +v -0.528588 0.154567 0.288607 +v -0.617869 0.196565 0.237958 +v -0.416198 -0.254872 0.220783 +v -0.504141 0.156728 0.334684 +v -0.477884 0.137335 0.280792 +v -0.277049 -0.600875 0.176248 +v -0.102439 -0.587865 0.153311 +v -0.072476 -0.600358 0.136953 +v 0.022376 -0.563505 0.109319 +v 0.349421 -0.552113 0.204990 +v 0.434847 -0.593631 0.279353 +v 0.471639 -0.585749 0.275927 +v -0.356293 -0.281677 0.227785 +v 0.676405 -0.492760 0.209428 +v -0.522586 -0.225131 0.069458 +v -0.261497 -0.268928 0.278861 +v -0.450745 0.542561 -0.377980 +v -0.309643 -0.204640 0.321475 +v -0.314850 -0.331753 -0.114249 +v -0.347561 -0.596188 0.144561 +v -0.138598 -0.605472 0.178905 +v 0.370165 -0.565761 0.248513 +v 0.365645 -0.593275 0.272156 +v -0.617682 0.207655 0.337221 +v -0.375097 -0.197852 0.301185 +v -0.366085 -0.324923 -0.088240 +v 0.332854 -0.547085 0.242217 +v 0.482860 -0.571824 0.302776 +v -0.389707 -0.309227 -0.107989 +v -0.364441 -0.335641 -0.048152 +v -0.291839 -0.372151 -0.041320 +v -0.463271 -0.217785 0.223805 +v -0.339833 -0.598724 0.228337 +v -0.188351 -0.597714 0.214636 +v 0.072214 -0.558146 0.188189 +v 0.444751 -0.585804 0.322315 +v -0.410515 0.178346 0.362705 +v -0.437759 0.543976 -0.436890 +v -0.415031 -0.311408 -0.054737 +v -0.568282 -0.158234 0.074125 +v -0.631531 0.216734 0.156560 +v -0.607920 0.193762 0.148241 +v -0.432671 0.190381 0.403950 +v -0.268412 -0.239332 0.297787 +v -0.491732 0.129433 0.256887 +v -0.332061 -0.352081 -0.009579 +v -0.378499 -0.591905 0.203670 +v -0.298537 -0.597960 0.272162 +v -0.238120 -0.597453 0.255856 +v -0.067989 -0.594941 0.255287 +v -0.029490 -0.560236 0.233406 +v 0.230744 -0.548506 0.276527 +v 0.402599 -0.590381 0.335710 +v -0.468625 0.203731 0.417269 +v -0.524334 0.193641 0.375939 +v -0.460718 -0.246295 0.182149 +v -0.509669 -0.178762 0.201985 +v -0.372614 -0.594366 0.246948 +v -0.056207 -0.598714 0.278645 +v 0.329676 -0.594007 0.344126 +v 0.393831 -0.580025 0.356027 +v -0.325336 -0.230610 0.296042 +v -0.609438 0.202931 0.193965 +v -0.405078 -0.331251 0.015082 +v -0.546752 0.222742 0.394690 +v -0.138775 -0.597478 0.241505 +v 0.167459 -0.546863 0.297945 +v 0.252095 -0.593302 0.365619 +v -0.365255 -0.347314 0.040121 +v -0.305457 -0.364141 0.043800 +v 0.047157 -0.550460 0.294237 +v 0.098758 -0.548932 0.303533 +v 0.115643 -0.594027 0.346352 +v 0.313264 -0.583821 0.369751 +v -0.571939 0.177916 0.213674 +v -0.576090 0.171016 0.251852 +v -0.464947 -0.275348 -0.043542 +v -0.430773 -0.314641 -0.002500 +v -0.331137 -0.353811 0.074899 +v -0.188766 -0.595884 0.306902 +v -0.127246 -0.595473 0.314430 +v 0.017126 -0.595575 0.344240 +v 0.248521 -0.579856 0.388235 +v -0.519048 0.149512 0.250703 +v -0.316765 -0.310503 0.197396 +v -0.231409 -0.261537 0.283488 +v -0.220909 -0.232824 0.304315 +v -0.447544 -0.298157 0.061564 +v -0.404755 -0.330009 0.063045 +v -0.113075 -0.587754 0.334430 +v 0.199051 -0.592072 0.384529 +v -0.380450 -0.240128 0.265033 +v -0.405669 0.557072 -0.491009 +v -0.436864 -0.271925 0.159102 +v -0.470793 -0.276585 0.011945 +v -0.371109 -0.582699 0.307255 +v -0.088629 -0.582909 0.357446 +v 0.185577 -0.582379 0.403847 +v -0.571402 0.228525 0.390899 +v -0.353307 -0.314253 0.165981 +v -0.385976 -0.332138 0.090517 +v -0.301319 -0.342304 0.135565 +v -0.361765 -0.592230 0.303524 +v -0.253901 -0.596555 0.337329 +v 0.100042 -0.593556 0.402152 +v 0.165953 -0.565748 0.412262 +v -0.471296 0.173273 0.376576 +v -0.491327 -0.243891 -0.039890 +v -0.447656 -0.298330 0.030395 +v -0.499863 -0.232204 0.122726 +v -0.332277 -0.595251 0.329453 +v -0.263680 -0.592082 0.358250 +v -0.177186 -0.590086 0.344686 +v -0.057967 -0.590467 0.379083 +v -0.006219 -0.591322 0.414999 +v 0.127293 -0.589691 0.410843 +v -0.372479 0.617089 -0.589155 +v -0.384321 0.544999 -0.406289 +v -0.340603 0.696677 -0.674355 +v -0.352392 0.582418 -0.412713 +v -0.157200 0.535185 -0.111929 +v -0.376612 0.514008 -0.280243 +v -0.386779 0.593727 -0.581466 +v 0.175529 0.724673 -0.307956 +v -0.347088 0.697598 -0.684478 +v -0.423775 0.470765 -0.175086 +v -0.334947 0.461607 -0.153230 +v 0.165833 0.779908 -0.358945 +v -0.356954 0.715548 -0.691532 +v -0.001831 0.633659 -0.200490 +v 0.095644 0.654616 -0.202191 +v -0.386650 0.581522 -0.543159 +v -0.218607 0.524930 -0.109110 +v -0.034139 0.603891 -0.167298 +v -0.394120 0.608612 -0.606438 +v 0.171291 0.822775 -0.382959 +v -0.440479 0.554400 -0.483154 +v -0.361951 0.545625 -0.349493 +v -0.350209 0.492010 -0.165403 +v -0.250076 0.467100 -0.095236 +v -0.112337 0.578368 -0.156699 +v -0.367612 0.578906 -0.452351 +v -0.363646 0.641285 -0.633059 +v -0.381424 0.479680 -0.184262 +v -0.397157 0.518365 -0.323828 +v -0.366959 0.598851 -0.495144 +v 0.037701 0.626613 -0.169005 +v 0.123125 0.689079 -0.254461 +v -0.428520 0.498306 -0.239580 +v -0.163061 0.569226 -0.147355 +v -0.348611 0.527322 -0.221482 +v -0.357197 0.500732 -0.204453 +v -0.401788 0.496938 -0.240337 +v -0.222357 0.491501 -0.075342 +v -0.004999 0.678692 -0.238356 +v -0.377750 0.493757 -0.216349 +v -0.281435 0.435285 -0.131170 +v -0.408312 0.530178 -0.377894 +v -0.329297 0.758056 -0.698889 +v 0.141402 0.736561 -0.309468 +v -0.413773 0.570029 -0.535881 +v -0.270041 -0.369058 0.079414 +vn -0.858211 0.127628 -0.497116 +vn -0.904294 -0.055727 -0.423200 +vn -0.861141 -0.145329 -0.487106 +vn -0.972228 -0.228370 -0.050813 +vn -0.937437 -0.244697 -0.247505 +vn -0.959105 0.235664 -0.156682 +vn -0.054415 0.980041 0.191076 +vn -0.086520 0.922636 0.375774 +vn -0.199408 0.876736 0.437635 +vn 0.162999 0.868831 0.467452 +vn 0.318461 0.865871 0.385723 +vn 0.515519 0.718375 0.467055 +vn 0.165777 0.852870 0.495041 +vn -0.229957 0.757225 0.611286 +vn -0.612171 0.505661 0.607868 +vn -0.202673 0.696585 0.688223 +vn -0.597674 0.697378 0.395520 +vn -0.173528 0.982360 0.069399 +vn -0.090365 0.977203 0.191961 +vn -0.087985 0.993286 0.075014 +vn 0.549089 0.810297 0.204657 +vn 0.674734 0.608081 0.418256 +vn 0.747917 0.643727 0.161840 +vn -0.819788 -0.571886 0.028748 +vn -0.797876 -0.600269 0.054903 +vn -0.882595 -0.460707 -0.093600 +vn 0.427747 -0.873074 -0.233955 +vn -0.007813 -0.913236 -0.407300 +vn 0.605426 -0.768944 -0.205237 +vn -0.915342 -0.398724 0.055879 +vn -0.995605 -0.066225 0.065798 +vn -0.989105 -0.127628 -0.073092 +vn 0.724601 0.621326 0.298105 +vn 0.661824 0.598804 0.451003 +vn 0.831690 0.292062 0.472182 +vn -0.531388 0.846583 0.029786 +vn -0.616260 0.760888 -0.203009 +vn -0.422498 0.853572 0.304727 +vn -0.204260 0.951720 0.229072 +vn -0.765374 -0.632496 -0.118809 +vn -0.864254 -0.452956 -0.218787 +vn 0.253029 0.901975 0.349803 +vn -0.102237 0.919187 0.380261 +vn 0.277444 0.867061 0.413709 +vn 0.795007 0.544450 0.267403 +vn 0.761956 0.542894 0.353069 +vn 0.825465 0.477371 0.301096 +vn 0.757805 0.553362 0.345622 +vn 0.674367 0.693808 0.252602 +vn 0.845424 0.498520 0.191595 +vn -0.376598 0.300394 -0.876278 +vn -0.760155 -0.152257 -0.631611 +vn -0.352245 -0.603442 -0.715354 +vn 0.521989 0.815271 0.250587 +vn 0.249489 0.915372 0.315928 +vn 0.661031 0.715476 0.226020 +vn 0.519150 0.813623 0.261605 +vn 0.301004 0.766564 0.567217 +vn 0.231697 0.821314 0.521256 +vn 0.531419 0.704398 0.470473 +vn -0.150761 0.889004 0.432356 +vn -0.501785 0.502396 -0.704093 +vn -0.134159 0.161138 -0.977752 +vn -0.118412 0.226997 -0.966643 +vn -0.311502 0.905850 0.286996 +vn -0.312540 0.894406 0.319834 +vn -0.325419 0.799280 0.505203 +vn -0.930845 0.365368 -0.001495 +vn -0.972777 0.208533 0.100894 +vn -0.918485 0.387066 -0.080721 +vn -0.179846 0.928556 -0.324625 +vn -0.212073 0.966582 -0.143895 +vn -0.133305 0.981414 -0.138005 +vn -0.792047 -0.506546 -0.340617 +vn -0.808191 0.338420 -0.481918 +vn -0.762688 -0.150182 -0.629048 +vn -0.878964 -0.476058 -0.027528 +vn -0.996338 0.032746 -0.078829 +vn -0.988311 -0.098483 0.116184 +vn -0.880306 -0.412091 0.234931 +vn -0.977599 -0.158300 0.138524 +vn -0.204413 0.978179 -0.036378 +vn -0.140599 0.989288 -0.038850 +vn -0.266030 0.921598 -0.282601 +vn -0.191931 0.621296 -0.759697 +vn -0.350749 0.868374 -0.350536 +vn -0.237434 0.966094 -0.101199 +vn -0.222602 0.973998 -0.041688 +vn -0.085116 0.995636 -0.037690 +vn -0.356243 0.338420 -0.870907 +vn -0.377606 -0.035554 -0.925260 +vn -0.212806 0.100955 -0.971862 +vn -0.984191 0.166570 -0.060030 +vn -0.952818 0.302744 -0.020234 +vn -0.083682 0.938566 -0.334788 +vn -0.684225 0.643727 0.342631 +vn -0.481796 0.747307 0.457534 +vn -0.504654 0.807886 0.304270 +vn 0.091403 0.643178 0.760216 +vn 0.251442 0.582995 0.772546 +vn 0.077822 0.822932 0.562761 +vn -0.268654 0.962035 0.047578 +vn -0.180151 0.970000 0.163182 +vn -0.986450 0.151921 -0.061708 +vn -0.968596 0.165136 -0.185797 +vn -0.037416 0.999268 -0.006165 +vn -0.195746 0.900052 0.389294 +vn -0.301279 0.929655 0.211890 +vn -0.308512 0.924894 0.222205 +vn -0.368328 0.861660 0.349010 +vn -0.034333 0.966826 -0.253090 +vn 0.006012 0.993866 -0.110202 +vn -0.814539 -0.560656 0.148778 +vn -0.844142 -0.534928 0.034700 +vn 0.588977 0.708243 0.389172 +vn 0.880184 0.460829 0.113468 +vn -0.876247 0.266823 -0.401196 +vn -0.867000 0.397290 -0.300699 +vn -0.794702 0.295083 -0.530381 +vn 0.094241 0.945708 -0.311014 +vn 0.139988 0.591113 -0.794336 +vn 0.252083 0.527055 -0.811548 +vn 0.272805 0.755028 -0.596210 +vn 0.389416 0.844508 0.367595 +vn -0.109409 0.907773 0.404889 +vn -0.258797 0.866115 0.427564 +vn -0.636921 0.696524 0.330393 +vn -0.327830 0.929563 0.168493 +vn 0.006317 0.939299 0.342967 +vn -0.113346 0.921110 0.372387 +vn -0.027528 0.840327 0.541368 +vn -0.974731 -0.033601 -0.220771 +vn -0.999939 0.009247 0.005768 +vn -0.965819 0.163457 -0.201147 +vn -0.515030 0.780480 0.354289 +vn -0.665548 -0.745720 -0.029603 +vn -0.675283 -0.734916 0.062105 +vn -0.792261 -0.563799 -0.233283 +vn -0.147771 0.833064 0.533006 +vn -0.063509 0.768883 0.636219 +vn 0.607318 0.400067 0.686331 +vn 0.240181 0.498245 0.833064 +vn 0.582965 0.596973 0.551103 +vn -0.886471 -0.413221 0.208197 +vn -0.980773 -0.114536 0.157842 +vn -0.950194 -0.311228 0.014771 +vn -0.381359 -0.299539 0.874508 +vn -0.159185 0.030152 0.986755 +vn -0.413648 0.191137 0.890133 +vn 0.054353 0.298715 0.952788 +vn -0.276162 0.441511 0.853664 +vn -0.420057 0.825983 -0.375835 +vn -0.219459 0.933256 0.284341 +vn 0.197119 0.918638 0.342326 +vn -0.323374 0.757714 0.566790 +vn -0.302438 0.828211 0.471725 +vn 0.036225 0.508896 0.860042 +vn -0.131260 0.700430 0.701529 +vn 0.362316 0.928220 0.084262 +vn -0.813440 -0.577899 0.065615 +vn -0.481185 -0.262185 0.836451 +vn -0.202124 0.580554 0.788690 +vn -0.228797 0.691977 0.684652 +vn -0.434095 0.559313 0.706168 +vn 0.234993 0.947844 0.215186 +vn 0.343699 0.776025 0.528764 +vn -0.455733 0.785852 0.417982 +vn -0.520402 0.479659 0.706442 +vn -0.558855 0.281625 0.779962 +vn -0.400952 0.485458 0.776879 +vn -0.930448 0.308267 -0.198035 +vn 0.102115 -0.537034 -0.837336 +vn -0.027375 -0.437269 -0.898892 +vn 0.107212 -0.547502 -0.829890 +vn 0.146641 0.098819 -0.984222 +vn -0.115726 0.069308 -0.990844 +vn -0.033570 0.112094 -0.993103 +vn -0.231025 0.866085 0.443281 +vn 0.003143 0.973937 0.226783 +vn 0.227729 0.797998 0.557939 +vn -0.052919 0.008789 0.998535 +vn 0.033509 0.515915 0.855953 +vn 0.923429 0.216498 -0.316782 +vn 0.815851 0.304880 -0.491287 +vn 0.845912 0.312784 -0.431898 +vn -0.923887 -0.350902 -0.152532 +vn -0.973510 -0.222327 0.053102 +vn -0.201483 0.969359 -0.140355 +vn -0.222724 0.974792 -0.012665 +vn -0.981567 0.020295 -0.189886 +vn -0.994354 -0.067110 -0.081973 +vn 0.836238 0.501480 0.221747 +vn 0.135533 0.990539 -0.020142 +vn 0.060305 0.993194 0.099521 +vn 0.044435 0.633412 0.772485 +vn -0.623402 0.567003 0.538377 +vn -0.947478 0.283639 0.147649 +vn -0.854732 -0.009461 0.518967 +vn 0.158879 0.976836 -0.143132 +vn -0.407666 -0.382916 0.828944 +vn -0.143376 -0.091006 0.985443 +vn 0.312601 0.259713 0.913663 +vn 0.250923 0.390240 0.885830 +vn 0.033967 0.272042 -0.961669 +vn 0.047609 0.476943 -0.877621 +vn 0.148930 0.198218 -0.968749 +vn 0.528733 -0.787896 0.315592 +vn 0.467879 -0.883419 -0.025117 +vn 0.550890 -0.734855 0.395520 +vn -0.933470 0.062777 -0.353038 +vn -0.914365 0.270333 -0.301370 +vn -0.860805 0.369060 -0.350352 +vn 0.097781 0.049287 -0.993957 +vn 0.052095 -0.275216 -0.959960 +vn -0.030854 -0.143315 -0.989166 +vn -0.551164 0.252480 -0.795251 +vn -0.390667 -0.131046 -0.911130 +vn -0.081606 -0.285409 0.954894 +vn -0.136570 0.803827 0.578936 +vn 0.050417 0.718314 0.693869 +vn -0.792352 0.216834 -0.570177 +vn -0.875576 0.113834 -0.469405 +vn -0.955687 -0.126530 -0.265725 +vn 0.293863 0.107028 -0.949828 +vn 0.246529 -0.284921 -0.926298 +vn 0.540574 0.146306 -0.828455 +vn 0.245338 0.146855 0.958220 +vn 0.234077 0.517960 0.822718 +vn -0.215155 -0.642293 0.735618 +vn 0.050569 -0.575793 0.816004 +vn 0.391064 -0.110599 -0.913663 +vn 0.922452 0.285379 -0.260018 +vn 0.805383 -0.200537 -0.557787 +vn -0.948973 0.032533 -0.313608 +vn -0.287698 -0.243202 -0.926298 +vn -0.212256 -0.408185 -0.887845 +vn -0.067476 -0.537095 -0.840785 +vn 0.917844 0.296457 -0.263924 +vn 0.877590 0.434919 -0.201605 +vn 0.937529 0.330760 -0.107730 +vn 0.557176 -0.356761 -0.749809 +vn 0.670217 -0.425398 -0.608112 +vn 0.612568 -0.592059 -0.523576 +vn -0.191229 -0.374371 -0.907315 +vn 0.442671 -0.848354 -0.290323 +vn 0.820093 -0.548326 -0.163610 +vn 0.897855 -0.410749 -0.158422 +vn 0.196692 0.308329 0.930692 +vn 0.184454 0.473464 0.861263 +vn 0.070315 0.498520 0.863979 +vn 0.449355 -0.545671 -0.707297 +vn 0.876522 0.479659 -0.039979 +vn 0.929991 0.367077 0.017792 +vn 0.749504 -0.236061 -0.618458 +vn 0.685385 0.279702 -0.672262 +vn 0.857692 0.153142 -0.490768 +vn 0.683004 0.373699 -0.627522 +vn -0.262520 0.959655 0.100558 +vn 0.014191 0.979034 0.203192 +vn -0.213691 0.151494 0.965056 +vn -0.362590 0.320231 0.875179 +vn -0.537095 0.196509 0.820307 +vn 0.247047 -0.290597 0.924375 +vn 0.180578 -0.199408 0.963103 +vn 0.204413 -0.420911 0.883755 +vn 0.063051 -0.173650 0.982757 +vn 0.390118 0.492416 0.778008 +vn 0.567003 -0.822504 0.044038 +vn 0.458846 -0.886227 -0.063387 +vn 0.534013 -0.829768 -0.162053 +vn 0.807092 -0.065706 -0.586749 +vn 0.867763 -0.291299 -0.402631 +vn 0.963683 0.046876 -0.262886 +vn 0.973357 0.030763 -0.227180 +vn 0.993591 0.066805 -0.090976 +vn -0.768334 0.495743 -0.404798 +vn -0.595569 0.787622 0.157872 +vn -0.892758 0.424451 -0.150853 +vn -0.926145 0.225532 -0.302286 +vn -0.855647 -0.171239 -0.488357 +vn -0.859890 0.281655 -0.425672 +vn -0.702353 -0.711112 -0.031007 +vn -0.697470 -0.683370 -0.215583 +vn -0.694510 -0.685690 -0.217750 +vn -0.159703 0.209449 0.964660 +vn -0.205176 0.310862 0.928007 +vn -0.188055 -0.153722 0.970031 +vn 0.111515 -0.241432 0.963958 +vn 0.061922 0.145512 0.987396 +vn 0.099063 0.236000 0.966674 +vn 0.040193 0.404553 0.913602 +vn 0.254585 0.414258 0.873806 +vn 0.372387 0.466994 0.801996 +vn 0.276498 0.583422 0.763634 +vn 0.316813 -0.342784 0.884365 +vn 0.107547 -0.139103 0.984405 +vn 0.114109 -0.433058 0.894101 +vn 0.527757 0.365459 0.766717 +vn 0.439253 0.183477 0.879391 +vn 0.930967 0.346660 -0.114475 +vn 0.984375 0.176000 -0.003082 +vn -0.975188 0.221320 -0.002777 +vn -0.971648 0.218604 0.089877 +vn -0.918516 0.382366 0.100345 +vn -0.820215 -0.036836 -0.570818 +vn -0.776971 0.032411 -0.628651 +vn -0.000977 0.913541 -0.406690 +vn 0.040132 0.852657 0.520890 +vn -0.219428 0.368328 0.903409 +vn 0.819239 -0.541429 -0.188788 +vn 0.757469 -0.594348 -0.270058 +vn 0.956786 -0.267220 -0.114414 +vn 0.069277 -0.444472 0.893094 +vn -0.082614 -0.729789 0.678610 +vn 0.004395 -0.395947 0.918241 +vn 0.080813 0.582934 0.808466 +vn 0.068941 0.733726 0.675893 +vn 0.082858 0.594195 0.800012 +vn 0.954466 -0.258583 -0.148625 +vn 0.737144 -0.675588 -0.012970 +vn 0.814325 -0.434156 0.385113 +vn -0.982391 0.155278 0.103580 +vn -0.019990 -0.518296 -0.854946 +vn -0.074099 -0.606952 -0.791253 +vn 0.268258 -0.842036 -0.467940 +vn 0.973479 0.222755 0.051576 +vn 0.977538 0.200720 -0.064211 +vn 0.996338 0.083621 -0.016480 +vn -0.219977 0.929929 -0.294595 +vn -0.920408 -0.386456 -0.058840 +vn 0.279183 0.917966 -0.281716 +vn 0.022797 -0.997436 0.067446 +vn 0.026154 -0.996673 0.076937 +vn 0.019959 -0.998047 0.058748 +vn 0.320597 -0.402631 0.857356 +vn 0.193457 -0.405255 0.893490 +vn 0.179662 -0.695944 0.695212 +vn 0.177526 0.090060 0.979980 +vn 0.990631 -0.070559 -0.116733 +vn 0.943083 0.208319 -0.259194 +vn 0.918302 0.371014 -0.137944 +vn 0.781915 -0.465560 -0.414533 +vn 0.772637 -0.576342 -0.266121 +vn 0.522477 -0.650716 -0.550920 +vn 0.941801 -0.336131 -0.000977 +vn -0.313517 0.129765 0.940642 +vn -0.439711 0.009980 0.898068 +vn -0.329447 0.167852 0.929106 +vn 0.217353 0.584216 0.781945 +vn 0.368511 0.604877 0.705893 +vn 0.061831 0.621998 0.780541 +vn 0.132084 0.185247 0.973754 +vn 0.224189 0.378735 0.897916 +vn 0.245033 -0.157231 0.956664 +vn 0.162084 -0.227668 0.960143 +vn 0.653310 0.265358 0.709006 +vn 0.332774 0.568102 0.752647 +vn 0.973846 -0.004456 -0.227058 +vn 0.972686 0.039766 -0.228614 +vn 0.887478 -0.091647 -0.451582 +vn 0.268380 0.918821 0.289285 +vn 0.334056 0.936247 -0.108615 +vn 0.460555 0.887082 -0.030915 +vn 0.453841 0.879849 -0.140782 +vn -0.241646 -0.337230 0.909848 +vn -0.246284 -0.192938 0.949767 +vn -0.459883 -0.323374 0.826960 +vn -0.465316 -0.035920 0.884396 +vn -0.275033 0.248024 0.928861 +vn 0.899838 -0.052217 -0.432997 +vn 0.912717 0.238563 -0.331645 +vn -0.049989 -0.169591 0.984222 +vn -0.072787 -0.384075 0.920408 +vn -0.069063 -0.347758 0.935026 +vn -0.065035 0.509659 0.857875 +vn -0.077792 0.754509 0.651631 +vn 0.035035 0.617695 0.785607 +vn 0.205908 -0.099734 0.973449 +vn 0.218879 -0.075991 0.972777 +vn 0.150578 0.015595 0.988464 +vn 0.515915 0.275246 0.811182 +vn 0.530137 0.286874 0.797876 +vn 0.342967 0.578967 0.739677 +vn -0.117008 -0.242470 0.963042 +vn -0.243690 -0.107028 0.963897 +vn 0.735160 -0.173406 0.655293 +vn 0.761956 -0.265999 0.590442 +vn 0.699759 -0.080020 0.709861 +vn -0.698843 -0.687887 0.195898 +vn -0.760735 -0.508713 0.403027 +vn 0.864284 0.393414 0.313395 +vn 0.847621 0.527024 0.061220 +vn 0.827845 0.485733 0.280465 +vn -0.519456 -0.175695 -0.836207 +vn -0.443098 -0.183782 -0.877407 +vn -0.544847 -0.359691 -0.757439 +vn -0.057100 -0.248390 0.966948 +vn -0.207038 0.115452 0.971465 +vn -0.053255 0.303598 0.951292 +vn 0.127598 -0.129673 0.983306 +vn 0.365795 -0.481094 0.796686 +vn 0.491592 -0.318094 0.810633 +vn -0.336375 -0.426557 -0.839564 +vn -0.505844 -0.352702 -0.787194 +vn -0.339183 -0.593707 -0.729667 +vn -0.171636 0.045198 0.984100 +vn 0.875515 -0.437086 -0.205847 +vn 0.760582 0.585009 0.281472 +vn 0.734001 0.501083 0.458327 +vn 0.821253 0.426313 0.379101 +vn -0.118015 0.305307 0.944884 +vn -0.064638 0.437330 0.896939 +vn 0.111911 -0.065279 0.991546 +vn -0.030366 -0.294595 0.955107 +vn -0.149205 -0.057192 0.987121 +vn 0.114383 -0.144536 0.982849 +vn 0.439985 0.268624 -0.856838 +vn 0.664602 0.085147 -0.742302 +vn -0.977966 -0.152348 0.142674 +vn -0.980102 -0.070101 0.185583 +vn -0.973357 0.174657 -0.148350 +vn -0.311594 0.703482 0.638722 +vn 0.336009 -0.667806 -0.664144 +vn 0.217444 -0.797449 -0.562822 +vn 0.473342 -0.785485 -0.398663 +vn -0.291879 -0.806085 -0.514756 +vn -0.305521 -0.876614 -0.371715 +vn -0.317087 -0.905698 -0.281320 +vn -0.188116 -0.308298 0.932493 +vn -0.179479 -0.196356 0.963958 +vn 0.015351 -0.121250 0.992492 +vn -0.004700 0.127049 0.991882 +vn -0.151708 0.690237 0.707480 +vn -0.018616 0.509018 0.860530 +vn 0.297586 0.137761 0.944700 +vn -0.736595 -0.292673 -0.609699 +vn -0.725791 -0.137730 -0.673971 +vn -0.911985 -0.053560 -0.406690 +vn -0.120823 -0.122501 0.985076 +vn 0.135258 0.284951 0.948912 +vn 0.273659 -0.030519 0.961333 +vn 0.186102 -0.215064 0.958678 +vn 0.007874 0.108615 0.994049 +vn -0.878872 -0.349895 -0.324229 +vn -0.958129 -0.130558 -0.254799 +vn -0.737754 -0.623524 -0.258553 +vn -0.073855 0.457198 0.886258 +vn 0.510330 0.118625 0.851741 +vn 0.314859 -0.010895 0.949065 +vn 0.037263 0.446638 0.893918 +vn -0.469466 0.136296 -0.872341 +vn -0.746818 0.303629 -0.591632 +vn -0.585681 0.548265 -0.596912 +vn -0.055116 -0.028901 0.998047 +vn 0.435652 -0.511887 0.740349 +vn -0.456832 -0.339091 0.822352 +vn -0.733848 -0.184301 0.653798 +vn -0.498398 -0.111148 0.859767 +vn 0.269814 0.953429 0.134648 +vn 0.367077 0.858516 0.357982 +vn -0.272011 0.324534 -0.905881 +vn -0.363933 0.420026 -0.831324 +vn -0.356304 0.353252 -0.864986 +vn -0.165288 -0.527390 0.833369 +vn -0.067873 -0.469771 0.880154 +vn 0.172246 0.166936 0.970794 +vn -0.002289 0.437727 0.899075 +vn 0.198828 -0.044343 0.979003 +vn 0.276803 0.219550 0.935484 +vn 0.156011 0.204505 0.966338 +vn 0.999451 0.001526 -0.033021 +vn 0.910154 0.285257 -0.300302 +vn 0.776116 -0.312143 -0.547868 +vn -0.037324 0.666097 0.744896 +vn -0.121555 -0.519883 0.845515 +vn -0.026399 0.889462 0.456221 +vn -0.645985 -0.619190 -0.446394 +vn -0.687277 -0.487655 -0.538347 +vn -0.040345 0.064760 -0.997070 +vn 0.114475 0.190466 -0.974975 +vn -0.129704 -0.153783 0.979522 +vn -0.014771 0.503647 0.863765 +vn 0.261849 0.070742 0.962493 +vn 0.127812 0.098300 0.986908 +vn -0.001740 0.107486 0.994201 +vn 0.987213 -0.094638 0.128208 +vn 0.991272 0.129643 0.023560 +vn 0.952635 0.139836 0.269997 +vn 0.115421 0.357189 0.926847 +vn -0.245430 0.344676 0.906034 +vn 0.075442 0.776147 0.625965 +vn -0.002533 0.721122 0.692770 +vn 0.121677 0.085208 -0.988891 +vn 0.286782 -0.900998 -0.325449 +vn -0.095157 -0.936277 -0.338115 +vn -0.070406 -0.589007 0.805017 +vn 0.044710 -0.314066 0.948332 +vn -0.076632 -0.030061 0.996582 +vn 0.026276 0.284433 0.958312 +vn 0.312021 0.155431 0.937254 +vn 0.081362 0.201605 0.976074 +vn -0.148320 0.181127 0.972198 +vn 0.290750 0.217902 0.931639 +vn 0.220527 0.236305 0.946287 +vn 0.382855 0.290872 0.876797 +vn 0.084353 0.666524 0.740654 +vn 0.375317 -0.918577 0.123722 +vn 0.349467 -0.936308 -0.033692 +vn -0.180120 0.934629 0.306558 +vn -0.361766 0.175298 -0.915616 +vn -0.007752 -0.327128 0.944945 +vn 0.108158 0.162267 0.980773 +vn -0.206214 -0.559038 0.803064 +vn 0.221625 0.465438 0.856838 +vn 0.150365 0.347972 0.925352 +vn -0.133641 0.498215 0.856655 +vn -0.046602 0.584185 0.810236 +vn 0.293100 0.249306 0.922971 +vn 0.419233 0.270425 0.866634 +vn 0.450636 0.360546 0.816614 +vn 0.119968 0.429334 0.895108 +vn 0.380535 0.645741 0.661946 +vn 0.677145 -0.691000 -0.252907 +vn 0.847499 -0.483505 -0.218879 +vn 0.812098 -0.578173 -0.078555 +vn 0.353801 0.424604 0.833369 +vn -0.580676 0.762505 -0.285195 +vn -0.497543 0.714347 -0.492019 +vn -0.696768 0.578661 -0.423780 +vn 0.776452 0.491073 0.394848 +vn 0.855586 0.357311 0.374493 +vn -0.168462 -0.291818 0.941496 +vn -0.380718 -0.205756 0.901486 +vn -0.378887 -0.361705 0.851802 +vn -0.450880 0.102756 0.886624 +vn -0.467544 -0.461257 0.754051 +vn 0.112674 -0.246681 0.962493 +vn -0.050081 0.193335 0.979827 +vn -0.001434 0.337992 0.941130 +vn -0.044069 0.483230 0.874355 +vn 0.122868 0.639760 0.758660 +vn -0.103519 -0.108676 0.988647 +vn 0.096805 -0.201117 0.974761 +vn -0.110660 -0.298624 0.947905 +vn 0.342479 0.565447 0.750267 +vn 0.317820 0.450056 0.834498 +vn 0.177679 0.443525 0.878445 +vn 0.881802 0.440565 0.168096 +vn 0.835597 0.538255 0.109745 +vn -0.019959 -0.342784 0.939177 +vn 0.075259 0.441664 0.894009 +vn 0.282571 0.012207 0.959136 +vn 0.050539 0.480941 0.875271 +vn -0.112278 0.922239 0.369945 +vn 0.079409 0.745048 0.662252 +vn -0.422559 0.640889 0.640828 +vn 0.178106 -0.036714 0.983306 +vn 0.037690 0.174993 0.983825 +vn 0.137974 0.124821 0.982513 +vn 0.143040 0.361156 0.921445 +vn 0.158391 0.368389 0.916044 +vn 0.024659 0.337443 0.941008 +vn 0.998352 -0.030763 0.048158 +vn 0.955779 0.239845 0.169988 +vn 0.999329 -0.019135 0.030580 +vn 0.249733 0.485977 0.837489 +vn 0.917020 0.008942 0.398694 +vn 0.184790 -0.953948 -0.236244 +vn 0.065432 -0.973449 -0.219245 +vn 0.522050 -0.818415 -0.239967 +vn -0.083743 0.412275 0.907163 +vn 0.344523 -0.082858 0.935087 +vn -0.216346 0.915189 0.339946 +vn -0.157079 0.872799 0.462081 +vn 0.262703 -0.178106 -0.948271 +vn 0.665059 -0.495407 -0.558763 +vn -0.924589 -0.340129 0.171453 +vn -0.989715 0.141270 -0.021516 +vn -0.792383 -0.609851 -0.011750 +vn 0.110080 0.207831 0.971923 +vn 0.036042 0.346751 0.937254 +vn 0.099979 -0.580462 0.808100 +vn 0.237953 -0.428297 0.871731 +vn 0.075350 -0.279824 0.957060 +vn -0.183447 -0.282113 0.941649 +vn 0.266213 0.205237 0.941771 +vn 0.214911 0.275124 0.937071 +vn 0.306558 0.167364 0.936979 +vn -0.154759 0.573077 0.804712 +vn -0.653218 0.167577 0.738365 +vn -0.797784 0.441084 0.411023 +vn 0.081515 -0.390515 0.916959 +vn 0.119083 -0.606861 0.785791 +vn -0.162633 0.390698 0.906034 +vn 0.015046 0.561357 0.827418 +vn 0.346812 -0.717582 -0.603931 +vn 0.675893 -0.680135 -0.283761 +vn -0.263131 0.171148 0.949431 +vn 0.303323 -0.181433 0.935423 +vn 0.369182 -0.135228 0.919462 +vn 0.249245 0.129551 0.959716 +vn 0.331614 0.089358 0.939146 +vn -0.996429 0.054292 0.064547 +vn -0.971038 0.018036 -0.238166 +vn -0.997711 -0.004975 -0.067110 +vn 0.400250 -0.573626 0.714652 +vn -0.238105 0.721458 0.650197 +vn 0.162603 0.521622 0.837519 +vn 0.380779 0.127995 0.915738 +vn 0.373028 0.594378 0.712394 +vn 0.531022 0.295572 0.794092 +vn 0.797143 0.557024 -0.232856 +vn 0.669942 0.248329 -0.699637 +vn -0.134892 0.293344 -0.946410 +vn 0.087436 0.086581 0.992370 +vn 0.195929 -0.799219 -0.568163 +vn 0.441603 -0.793908 -0.417890 +vn 0.436872 0.256386 0.862178 +vn -0.850032 0.351085 -0.392621 +vn -0.711905 0.513901 -0.478591 +vn 0.008057 0.453719 0.891079 +vn 0.483718 0.814722 0.319651 +vn 0.692129 -0.135075 -0.709006 +vn 0.550829 -0.020966 -0.834346 +vn 0.547655 -0.024751 -0.836329 +vn -0.104495 -0.192022 0.975799 +vn 0.067141 -0.089572 0.993683 +vn 0.174139 0.161748 0.971313 +vn 0.151585 0.337230 0.929106 +vn -0.065065 0.721061 0.689779 +vn -0.171850 -0.590838 -0.788263 +vn -0.033143 -0.779382 -0.625629 +vn 0.266640 -0.859188 -0.436628 +vn 0.132847 -0.766686 -0.628101 +vn 0.296213 -0.913846 -0.277688 +vn 0.549089 0.290201 0.783715 +vn 0.354289 0.264290 0.896969 +vn -0.104373 -0.030244 0.994049 +vn 0.064821 0.607044 0.791986 +vn 0.025544 0.626789 0.778741 +vn 0.992523 -0.004639 0.121830 +vn 0.949675 0.070132 0.305185 +vn 0.657826 -0.749260 -0.076266 +vn 0.145116 0.231269 0.961974 +vn -0.140782 -0.192816 0.971068 +vn -0.044343 -0.041139 0.998138 +vn 0.244087 0.376415 0.893674 +vn 0.722892 -0.660390 -0.203162 +vn 0.279946 -0.021821 0.959746 +vn 0.057405 0.017457 0.998169 +vn 0.140843 0.430830 0.891354 +vn -0.967467 -0.217048 0.129826 +vn -0.156194 -0.146519 0.976775 +vn 0.148137 0.004852 0.988922 +vn 0.065493 0.186010 0.980346 +vn -0.968017 0.186377 0.167760 +vn 0.977813 -0.209326 -0.004303 +vn -0.006043 0.585894 0.810358 +vn 0.250649 0.319895 0.913663 +vn 0.164830 -0.147771 0.975158 +vn 0.044771 -0.163610 0.985473 +vn -0.070772 -0.069704 0.995025 +vn 0.991729 0.067385 0.109073 +vn -0.680624 0.731803 -0.033998 +vn -0.443037 0.893338 -0.075076 +vn 0.016633 0.101382 0.994690 +vn -0.138615 0.107395 0.984497 +vn -0.167913 -0.011628 0.985717 +vn 0.107639 0.302591 0.946989 +vn 0.112217 0.134434 0.984527 +vn 0.057924 -0.065310 0.996155 +vn -0.160039 -0.034059 0.986511 +vn -0.178594 -0.004181 0.983886 +vn 0.048769 0.375103 0.925687 +vn 0.945738 0.267434 -0.184484 +vn 0.938688 0.343272 0.031343 +vn 0.974578 -0.223212 -0.017975 +vn 0.391247 -0.780725 -0.487167 +vn 0.360942 -0.667104 -0.651662 +vn 0.407147 -0.913236 -0.013367 +vn 0.502182 -0.745537 0.438124 +vn 0.140599 -0.108097 0.984130 +vn -0.214576 0.165532 0.962554 +vn 0.172826 0.408399 0.896268 +vn 0.086550 0.482711 0.871456 +vn 0.074099 0.578631 0.812189 +vn -0.011200 0.643757 0.765130 +vn -0.105167 0.798364 0.592883 +vn -0.377667 0.920133 0.103366 +vn -0.444319 0.891598 -0.087161 +vn -0.607501 0.784387 0.125065 +vn 0.598773 -0.024873 0.800501 +vn 0.278970 0.474410 0.834895 +vn 0.100070 0.643483 0.758873 +vn -0.031312 0.571368 0.820063 +vn 0.021302 0.709891 0.703940 +vn -0.100833 0.680380 0.725852 +vn -0.285684 0.348888 0.892544 +vn 0.928587 0.085665 -0.361034 +vn 0.926695 -0.135594 -0.350414 +vn 0.532853 0.180059 0.826807 +vn 0.280251 -0.117283 0.952696 +vn 0.260903 -0.145329 0.954344 +vn 0.113865 0.018860 0.993286 +vn 0.018403 -0.121250 0.992431 +vn -0.181371 0.000458 0.983398 +vn -0.184637 0.412824 0.891873 +vn -0.130467 0.493545 0.859859 +vn 0.345531 -0.116001 0.931181 +vn 0.913053 0.389538 0.120518 +vn 0.941008 0.308664 0.138493 +vn 0.394818 -0.898007 -0.194006 +vn 0.694449 -0.679952 -0.235328 +vn -0.311563 0.549669 0.775079 +vn -0.000641 0.494583 0.869106 +vn 0.329875 -0.085391 0.940123 +vn 0.332987 -0.194708 0.922575 +vn 0.175909 -0.140965 0.974242 +vn -0.166875 0.560228 0.811335 +vn 0.193121 0.302988 0.933195 +vn 0.280068 0.286996 0.916044 +vn 0.016053 0.021271 0.999634 +vn 0.761681 -0.203284 0.615192 +vn 0.362560 -0.147465 0.920194 +vn 0.018189 -0.214484 0.976531 +vn -0.211097 -0.295907 0.931578 +vn -0.193976 0.474593 0.858547 +vn 0.554430 0.112949 0.824519 +vn 0.550005 0.143040 0.822779 +vn 0.744987 0.638600 0.192694 +vn 0.434462 0.879177 0.195471 +vn 0.347758 -0.151219 0.925291 +vn 0.197882 -0.150731 0.968535 +vn -0.086520 0.637715 0.765374 +vn -0.045503 0.774346 0.631092 +vn -0.051698 -0.165410 0.984863 +vn -0.102817 0.513169 0.852077 +vn -0.064974 0.392834 0.917295 +vn 0.124882 0.077486 0.989135 +vn 0.257027 -0.190741 0.947386 +vn -0.020661 0.075533 0.996918 +vn -0.039308 0.211097 0.976653 +vn -0.519242 -0.804071 -0.289499 +vn -0.954741 -0.129215 -0.267861 +vn -0.985260 0.168004 -0.032044 +vn -0.559038 -0.219428 0.799554 +vn -0.071230 0.352947 0.932890 +vn 0.304331 0.403943 0.862636 +vn 0.055635 0.644734 0.762352 +vn 0.625385 -0.649739 -0.432081 +vn -0.043825 -0.242256 0.969207 +vn -0.417127 -0.271889 0.867183 +vn -0.579730 -0.115207 0.806574 +vn -0.503830 0.090030 0.859096 +vn -0.014771 0.209174 0.977752 +vn 0.991852 0.112247 0.060183 +vn 0.974944 0.186651 0.120975 +vn 0.604511 -0.407300 0.684561 +vn 0.117283 0.100833 0.987945 +vn 0.312510 0.406507 0.858516 +vn 0.208930 0.599414 0.772668 +vn -0.865413 -0.199133 0.459731 +vn -0.879513 0.045198 0.473647 +vn 0.781274 0.159612 -0.603412 +vn 0.826136 0.417402 -0.378430 +vn 0.257271 0.965575 0.037812 +vn -0.348582 -0.163884 0.922819 +vn -0.406873 0.177343 0.896084 +vn 0.835292 0.420667 -0.353954 +vn 0.806665 0.499466 -0.315897 +vn 0.212378 0.805841 0.552690 +vn 0.177648 0.608020 0.773766 +vn 0.870022 0.415754 0.264901 +vn 0.980468 0.070223 0.183660 +vn 0.727836 -0.635029 -0.258736 +vn 0.835566 -0.504074 -0.218390 +vn -0.332438 0.825709 0.455702 +vn -0.509995 0.704154 0.494003 +vn -0.319193 0.733604 0.599933 +vn -0.667776 -0.244942 0.702872 +vn -0.177984 0.206305 0.962127 +vn -0.250740 0.583575 0.772362 +vn -0.208747 0.413923 0.886044 +vn -0.137944 0.716086 -0.684225 +vn -0.105075 0.624226 -0.774132 +vn -0.158452 0.631489 -0.758995 +vn 0.077212 0.025147 0.996673 +vn -0.064089 -0.060640 -0.996094 +vn 0.951476 -0.298227 -0.075716 +vn -0.774194 -0.028932 0.632252 +vn -0.801721 -0.156468 0.576830 +vn -0.825037 -0.263009 0.500076 +vn -0.937223 -0.028047 0.347575 +vn -0.995727 -0.084933 0.036073 +vn -0.893002 -0.302835 0.332835 +vn 0.724021 -0.278024 0.631214 +vn -0.399213 0.312113 0.862056 +vn -0.190130 0.450117 0.872463 +vn -0.244545 0.663259 0.707266 +vn -0.148015 0.749901 0.644734 +vn -0.238716 -0.073305 -0.968291 +vn -0.290750 -0.352397 -0.889523 +vn -0.045320 0.792108 0.608661 +vn 0.145024 0.906156 0.397259 +vn 0.379131 0.925230 0.013733 +vn -0.391552 0.358074 0.847591 +vn -0.043489 0.618366 0.784661 +vn -0.366832 0.776818 0.511795 +vn -0.596362 0.469741 0.650868 +vn 0.589129 0.121097 0.798883 +vn -0.116459 0.334269 0.935240 +vn 0.207007 -0.880184 -0.427045 +vn 0.476791 -0.864284 -0.160100 +vn 0.624744 0.144658 0.767296 +vn 0.313761 0.475082 0.822077 +vn 0.021516 0.811182 0.584368 +vn -0.291269 0.395489 0.871029 +vn 0.105075 0.346690 0.932066 +vn 0.010987 0.820063 0.572131 +vn -0.072176 0.224311 0.971831 +vn -0.165288 0.642994 0.747795 +vn -0.099094 0.626270 0.773247 +vn -0.946684 0.094028 -0.308054 +vn 0.185614 0.901212 0.391552 +vn 0.765313 0.275124 0.581866 +vn 0.805872 0.381939 0.452376 +vn 0.344676 0.930967 0.120273 +vn -0.318705 0.388653 0.864467 +vn 0.364391 -0.088687 0.927000 +vn 0.353618 0.911893 0.208228 +vn -0.955290 0.218757 -0.198798 +vn -0.983428 -0.177282 0.037599 +vn -0.962554 -0.232398 -0.139470 +vn -0.275521 0.569903 0.774102 +vn 0.612140 0.295663 -0.733360 +vn 0.532640 0.186621 0.825465 +vn 0.435469 0.277932 0.856197 +vn -0.505600 0.317209 0.802301 +vn -0.740471 -0.151097 0.654836 +vn -0.092471 -0.356822 -0.929563 +vn -0.591693 -0.303018 -0.747032 +vn -0.504654 -0.433790 -0.746391 +vn 0.287667 0.706839 0.646199 +vn 0.321940 0.693655 0.644307 +vn 0.272164 0.616291 0.738975 +vn 0.027833 0.264870 0.963866 +vn 0.351085 -0.051149 0.934935 +vn 0.263894 0.074618 0.961638 +vn 0.110202 0.762169 0.637898 +vn -0.974670 0.190466 -0.116977 +vn -0.891507 0.417768 0.175085 +vn -0.724357 0.679922 -0.113956 +vn 0.391400 0.856960 -0.335185 +vn -0.456374 0.866543 0.202002 +vn -0.488815 0.861904 -0.134617 +vn 0.528184 -0.841121 0.116214 +vn -0.041536 0.289560 0.956236 +vn -0.272164 0.238075 -0.932310 +vn -0.590960 0.419782 -0.688833 +vn -0.181097 0.317789 -0.930692 +vn 0.280038 0.016144 0.959838 +vn 0.354167 -0.036897 0.934416 +vn 0.268746 0.508194 0.818201 +vn -0.214576 0.185980 0.958800 +vn -0.475997 -0.387097 0.789636 +vn -0.046785 0.997833 -0.045869 +vn 0.178472 0.963225 0.200812 +vn -0.245979 -0.621052 -0.744133 +vn -0.546739 0.042940 0.836177 +vn -0.391430 -0.268410 0.880154 +vn -0.284127 0.034700 0.958129 +vn -0.239723 -0.081606 0.967376 +vn 0.474899 0.389416 0.789178 +vn -0.010956 0.145390 0.989288 +vn -0.413068 0.325114 0.850673 +vn -0.147526 0.571764 0.807031 +vn -0.263070 0.563158 0.783319 +vn 0.697043 -0.160100 -0.698904 +vn 0.655782 -0.177404 -0.733787 +vn 0.567614 0.012238 -0.823176 +vn 0.274972 -0.081759 0.957945 +vn -0.590320 0.806726 0.026643 +vn -0.112857 -0.266488 0.957183 +vn 0.092868 -0.091861 0.991424 +vn -0.384838 -0.385113 0.838771 +vn -0.681753 -0.193091 0.705618 +vn -0.474380 -0.307260 0.824946 +vn -0.014954 -0.244179 0.969604 +vn -0.234046 0.439528 0.867183 +vn -0.419385 0.517777 0.745659 +vn 0.337230 0.874813 0.347728 +vn -0.005158 -0.990814 0.134983 +vn -0.062075 -0.872127 0.485275 +vn 0.004181 -0.991333 0.131260 +vn -0.151677 0.281259 0.947539 +vn -0.269295 0.656850 0.704276 +vn -0.040651 0.006195 0.999146 +vn -0.464370 -0.233375 0.854305 +vn -0.237037 -0.412427 0.879574 +vn -0.190802 -0.169866 0.966796 +vn -0.111637 -0.243995 0.963317 +vn 0.101749 -0.076449 0.991852 +vn -0.067263 0.205145 0.976409 +vn -0.237068 0.663625 0.709464 +vn -0.815455 0.108890 -0.568468 +vn -0.778069 0.304483 -0.549394 +vn 0.327921 0.931669 0.156255 +vn -0.200354 0.490341 0.848170 +vn -0.256752 0.757439 0.600238 +vn 0.555681 -0.733360 -0.391552 +vn 0.926603 -0.154729 -0.342662 +vn -0.079989 -0.246406 0.965850 +vn -0.058168 0.097324 0.993530 +vn -0.257210 -0.533555 0.805689 +vn -0.289834 -0.232093 0.928495 +vn -0.142460 -0.048952 0.988586 +vn -0.098422 0.154546 0.983062 +vn -0.156896 0.350963 0.923124 +vn 0.370647 0.466506 0.803095 +vn -0.212226 -0.314554 0.925199 +vn -0.266121 -0.223182 0.937712 +vn -0.199255 -0.090579 0.975738 +vn -0.065340 0.345195 0.936247 +vn -0.020325 0.156529 0.987457 +vn 0.962096 0.179113 -0.205481 +vn -0.084140 0.038667 0.995697 +vn -0.082247 -0.310923 -0.946837 +vn -0.306436 0.947935 0.086459 +vn -0.274178 -0.027619 0.961272 +vn 0.074129 0.108768 0.991272 +vn -0.105319 0.907559 0.406446 +vn -0.294778 0.829493 0.474349 +vn -0.028657 0.707358 0.706259 +vn -0.927580 0.312754 0.204291 +vn 0.343760 -0.125736 0.930570 +vn 0.242958 0.032044 0.969481 +vn 0.479202 0.000458 0.877682 +vn 0.788415 -0.161626 0.593493 +vn -0.469069 0.802759 0.368145 +vn 0.589526 0.470260 0.656697 +vn 0.465102 0.453322 0.760338 +vn 0.460921 0.343516 0.818232 +vn 0.435957 -0.201575 0.877071 +vn 0.537522 -0.471877 0.698813 +vn 0.449538 0.326426 0.831446 +vn 0.379009 -0.214850 0.900082 +vn 0.453413 -0.222053 0.863186 +vn 0.087130 -0.896207 0.434980 +vn 0.249916 -0.460952 0.851497 +vn 0.214209 -0.605029 0.766808 +vn 0.515854 0.403119 0.755882 +vn 0.433485 0.274087 0.858455 +vn 0.532487 0.322642 0.782495 +vn 0.575365 0.075900 0.814325 +vn 0.417127 -0.232398 0.878597 +vn 0.438765 -0.171209 0.882107 +vn 0.345744 -0.127018 0.929655 +vn 0.680837 -0.172979 0.711692 +vn 0.852535 -0.128849 0.506516 +vn 0.803827 -0.238319 0.545000 +vn 0.945097 0.075259 -0.317911 +vn -0.259957 0.038423 0.964843 +vn 0.282022 -0.295144 0.912870 +vn 0.757012 0.131870 0.639943 +vn 0.631977 -0.379406 0.675710 +vn -0.180731 -0.492111 -0.851527 +vn -0.001556 -0.630390 -0.776238 +vn 0.440046 -0.438978 0.783349 +vn 0.462081 -0.602313 0.650868 +vn 0.449171 -0.339305 0.826472 +vn 0.652455 -0.646046 -0.396069 +vn 0.665365 -0.679403 -0.309275 +vn 0.741203 -0.452956 -0.495346 +vn 0.693258 -0.110141 -0.712210 +vn 0.674032 -0.178472 -0.716788 +vn 0.761376 -0.257576 -0.594897 +vn 0.449843 0.491165 0.745872 +vn 0.142582 0.828242 0.541856 +vn 0.469405 -0.125004 0.874050 +vn 0.484603 -0.197180 0.852199 +vn 0.513565 -0.232002 0.826075 +vn 0.901059 0.354106 0.250343 +vn -0.655202 0.454634 -0.603290 +vn 0.454207 0.367199 0.811670 +vn 0.458693 -0.216803 0.861721 +vn 0.437178 -0.171911 0.882748 +vn 0.783349 -0.017945 0.621296 +vn 0.076785 -0.326762 0.941954 +vn -0.185614 -0.607562 0.772240 +vn 0.060793 -0.840846 0.537797 +vn 0.642048 0.296060 0.707144 +vn 0.710257 0.517045 -0.477615 +vn 0.792016 0.496414 -0.355296 +vn 0.795923 0.423322 -0.432722 +vn 0.706015 0.212409 0.675558 +vn -0.957213 0.288705 -0.019715 +vn -0.927702 0.085971 0.363231 +vn -0.996368 0.051180 0.067904 +vn 0.343913 0.537889 0.769646 +vn 0.640828 0.397717 0.656606 +vn 0.534898 0.392224 0.748314 +vn 0.550920 0.466201 0.692160 +vn 0.225135 0.006775 0.974273 +vn 0.182989 0.699698 0.690573 +vn 0.347880 -0.674215 0.651418 +vn 0.025391 -0.733604 -0.679098 +vn 0.758873 -0.413404 0.503159 +vn 0.607685 -0.613269 0.504532 +vn -0.703757 -0.709677 -0.032777 +vn 0.638600 -0.136631 0.757286 +vn 0.801660 0.256630 0.539842 +vn 0.655782 0.116153 0.745933 +vn 0.794336 -0.359172 0.489883 +vn 0.487838 -0.510300 0.708213 +vn 0.562792 -0.693167 0.450270 +vn 0.217292 0.635395 0.740959 +vn 0.841426 0.040315 0.538804 +vn 0.938231 0.000458 0.345958 +vn 0.478957 -0.734123 0.481246 +vn 0.529130 -0.793817 0.299661 +vn 0.814478 -0.249001 0.524033 +vn 0.780389 0.326609 0.533189 +vn 0.836421 -0.067110 0.543931 +vn 0.795984 -0.256203 0.548387 +vn 0.812342 -0.096133 0.575152 +vn 0.686300 -0.025330 0.726829 +vn 0.710044 -0.166417 0.684164 +vn 0.817347 0.247200 0.520371 +vn 0.837275 0.330454 0.435621 +vn 0.760369 0.338115 0.554521 +vn -0.100040 0.121891 -0.987457 +vn -0.075625 0.274483 -0.958586 +vn 0.593341 -0.733757 0.330912 +vn 0.408032 -0.848750 0.336253 +vn 0.781121 -0.483627 0.394879 +vn 0.839442 0.042695 0.541734 +vn 0.932249 -0.320444 -0.167821 +vn 0.631764 0.446913 0.633320 +vn 0.799646 -0.043916 0.598804 +vn 0.731346 -0.021760 0.681631 +vn 0.706839 -0.061464 0.704672 +vn 0.643452 0.081576 0.761101 +vn 0.627064 0.035707 0.778130 +vn 0.568499 0.108707 0.815455 +vn 0.340190 0.639454 0.689444 +vn 0.681356 0.362377 0.635914 +vn 0.593097 -0.226447 0.772607 +vn 0.592151 0.008759 0.805750 +vn 0.551164 -0.045412 0.833125 +vn 0.776360 -0.043428 0.628742 +vn 0.817835 0.036409 0.574236 +vn 0.753502 -0.026704 0.656880 +vn 0.721671 0.096500 0.685446 +vn -0.006561 0.419965 -0.907498 +vn 0.006867 0.387188 -0.921964 +vn 0.016755 0.268532 -0.963103 +vn 0.408612 0.130558 0.903287 +vn 0.680074 0.321879 0.658681 +vn 0.885983 0.360668 0.291421 +vn 0.771325 0.292856 0.565020 +vn 0.475875 0.209357 0.854213 +vn 0.439253 -0.041658 0.897366 +vn 0.548173 -0.570574 0.611469 +vn 0.394177 0.515183 0.761010 +vn 0.582385 0.474807 0.659780 +vn 0.561663 0.273995 0.780633 +vn 0.483810 -0.554826 0.676778 +vn 0.878689 -0.013703 0.477157 +vn 0.761956 0.068972 0.643910 +vn 0.002991 0.232215 -0.972625 +vn -0.132298 0.414136 -0.900510 +vn 0.824366 -0.032228 0.565081 +vn 0.481155 -0.354259 0.801843 +vn 0.565661 -0.353404 0.745048 +vn 0.544206 -0.331858 0.770470 +vn 0.464492 -0.153111 0.872219 +vn 0.665822 -0.379986 0.642048 +vn 0.599780 -0.029206 0.799585 +vn 0.582659 -0.096072 0.807001 +vn 0.399884 0.094760 0.911649 +vn 0.457076 -0.034974 0.888730 +vn 0.715171 -0.368145 0.594073 +vn 0.519181 -0.607257 -0.601367 +vn 0.605945 -0.535936 0.587848 +vn 0.656056 -0.303903 0.690786 +vn 0.499496 0.350169 0.792352 +vn 0.464034 0.505173 0.727622 +vn 0.611408 0.365032 0.702048 +vn 0.668874 -0.134373 0.731101 +vn 0.605213 -0.420637 0.675802 +vn 0.593036 -0.027039 0.804682 +vn -0.000488 0.311777 -0.950133 +vn 0.578387 0.023133 0.815424 +vn -0.211798 -0.090121 0.973144 +vn 0.201819 0.068209 0.977020 +vn -0.836634 -0.321909 -0.443159 +vn 0.309366 -0.009247 0.950865 +vn 0.737754 -0.559587 0.377514 +vn 0.623798 -0.399060 0.671987 +vn 0.448073 -0.889065 0.093661 +vn 0.587878 0.385357 0.711234 +vn 0.792291 0.145024 0.592639 +vn -0.484848 -0.547929 -0.681661 +vn 0.144810 -0.724845 -0.673482 +vn 0.500290 -0.330607 0.800226 +vn 0.643666 0.035371 0.764458 +vn 0.728721 0.017518 0.684530 +vn 0.470748 -0.501602 0.725791 +vn 0.407514 0.498611 0.765038 +vn 0.572588 0.267830 0.774834 +vn 0.703848 -0.033052 0.709525 +vn 0.739708 -0.185308 0.646870 +vn 0.632496 0.338054 0.696860 +vn 0.603626 -0.609302 0.514115 +vn 0.624958 0.359844 0.692740 +vn 0.246620 0.778802 0.576739 +vn 0.656026 0.196509 0.728660 +vn 0.555040 -0.419813 0.718101 +vn 0.645344 -0.234199 0.727073 +vn 0.607532 0.364238 0.705802 +vn 0.444868 0.503800 0.740440 +vn 0.569414 0.399884 0.718223 +vn 0.551134 0.222175 0.804254 +vn 0.784448 -0.025666 0.619648 +vn 0.541032 0.474319 -0.694449 +vn 0.055177 -0.721488 -0.690176 +vn 0.703604 0.041871 0.709311 +vn -0.041444 -0.583300 0.811151 +vn 0.302347 0.182318 0.935575 +vn 0.431349 -0.875698 0.216865 +vn 0.273293 0.688406 0.671834 +vn 0.845454 0.391461 0.363170 +vn 0.575915 -0.802423 -0.156133 +vn 0.538713 0.118839 0.834040 +vn 0.617359 -0.064943 0.783959 +vn 0.254524 -0.093356 0.962523 +vn 0.667745 0.412244 0.619770 +vn 0.784661 0.006043 0.619831 +vn 0.104740 -0.889859 0.444014 +vn 0.006256 -0.923734 0.382916 +vn 0.017182 -0.991333 0.130161 +vn 0.594623 -0.439070 0.673482 +vn -0.454329 0.184362 -0.871517 +vn -0.316080 0.196173 -0.928190 +vn 0.740928 0.171392 0.649312 +vn 0.847774 0.127354 0.514817 +vn 0.176794 -0.478103 0.860286 +vn 0.271645 0.208075 0.939604 +vn 0.650777 -0.572619 0.498520 +vn 0.701987 0.407239 0.584185 +vn 0.570788 0.485031 0.662526 +vn 0.716849 -0.010804 0.697134 +vn 0.596545 -0.038789 0.801630 +vn 0.505142 -0.238990 0.829249 +vn 0.590686 -0.166967 0.789422 +vn 0.700766 -0.260567 0.664083 +vn 0.604663 -0.267464 0.750175 +vn 0.806116 0.114994 0.580432 +vn 0.902921 0.075350 0.423109 +vn -0.292306 -0.940977 -0.170476 +vn -0.456893 -0.862209 -0.218635 +vn 0.505692 0.107150 0.856014 +vn 0.737571 -0.042024 0.673940 +vn 0.903470 0.092105 0.418592 +vn 0.517777 -0.410749 0.750420 +vn 0.551592 -0.166295 0.817347 +vn 0.523087 0.027192 0.851833 +vn 0.610248 0.294839 0.735252 +vn 0.096591 -0.544176 -0.833369 +vn 0.603168 -0.141148 0.784997 +vn 0.510605 -0.091800 0.854885 +vn 0.338633 -0.773522 -0.535691 +vn 0.416608 -0.681539 -0.601550 +vn 0.470656 -0.795526 -0.381542 +vn -0.495285 0.398816 0.771752 +vn 0.834559 0.333689 0.438307 +vn 0.967956 -0.077212 0.238807 +vn 0.886349 -0.268471 0.377178 +vn 0.618336 0.298441 0.727042 +vn 0.859828 0.509018 0.039796 +vn 0.581286 -0.142003 0.801202 +vn 0.573260 0.140049 0.807306 +vn -0.762383 0.421155 -0.491256 +vn -0.716727 -0.198401 -0.668508 +vn -0.421216 0.334239 -0.843104 +vn 0.821284 0.097140 0.562120 +vn 0.793023 0.308603 0.525224 +vn 0.415540 0.082919 0.905759 +vn 0.516617 -0.241005 0.821558 +vn 0.512589 0.165227 0.842555 +vn 0.611438 -0.064913 0.788598 +vn 0.656240 -0.269997 0.704550 +vn 0.647298 -0.331400 0.686392 +vn 0.567827 0.062655 0.820734 +vn 0.531327 0.051851 0.845546 +vn 0.934233 0.199835 0.295389 +vn -0.805536 -0.576861 0.135228 +vn 0.799097 0.330515 0.502152 +vn 0.409650 0.448805 0.794153 +vn 0.588610 -0.181860 0.787683 +vn -0.973601 -0.187994 0.129307 +vn -0.974914 -0.134373 -0.177252 +vn 0.602741 -0.005005 0.797876 +vn 0.636860 -0.143315 0.757500 +vn 0.763207 0.155309 0.627186 +vn 0.260048 0.014649 0.965453 +vn 0.538835 -0.515702 0.666066 +vn 0.675985 -0.214850 -0.704856 +vn 0.767510 -0.111484 -0.631214 +vn 0.689169 -0.321116 -0.649525 +vn -0.500259 0.757927 -0.418561 +vn -0.620869 0.702597 -0.347606 +vn -0.334025 -0.266305 -0.904141 +vn 0.872066 0.140294 0.468795 +vn -0.467391 0.142644 -0.872433 +vn -0.591540 0.277596 -0.756951 +vn -0.439314 0.241737 -0.865169 +vn 0.277627 -0.928129 -0.247871 +vn 0.217658 -0.936521 -0.274819 +vn 0.761498 0.193548 0.618549 +vn 0.898129 -0.437391 0.044710 +vn 0.956633 -0.291208 0.001953 +vn 0.602008 -0.035096 0.797693 +vn -0.411389 -0.088534 -0.907132 +vn -0.612751 -0.480270 0.627552 +vn -0.789911 0.068728 0.609302 +vn -0.648244 -0.431654 0.627216 +vn -0.994629 -0.060427 0.083712 +vn 0.820276 0.214209 0.530320 +vn 0.184088 -0.010346 0.982849 +vn -0.136814 -0.680685 -0.719657 +vn -0.221076 -0.580767 -0.783441 +vn -0.231574 0.258431 -0.937834 +vn -0.676351 0.368480 -0.637745 +vn -0.359600 -0.923185 -0.135472 +vn 0.539384 0.684866 -0.489883 +vn 0.196448 -0.627400 0.753471 +vn 0.136448 0.101993 0.985351 +vn -0.139561 0.015198 0.990081 +vn 0.417554 -0.690481 0.590594 +vn 0.820887 -0.523453 -0.228248 +vn 0.791894 -0.542039 -0.281167 +vn 0.776025 -0.567125 -0.275857 +vn -0.873653 -0.486526 0.001068 +vn 0.086978 0.703360 -0.705466 +vn 0.675161 0.733451 0.078677 +vn 0.420545 -0.110935 0.900449 +vn 0.124760 0.822535 0.554826 +vn 0.924314 -0.199805 0.325114 +vn 0.796442 -0.529008 0.292886 +vn 0.921659 -0.323985 0.213385 +vn 0.624378 0.723441 -0.294534 +vn 0.497879 0.693991 -0.520035 +vn 0.182287 0.895505 -0.405927 +vn 0.788385 -0.612568 0.056307 +vn 0.735466 0.674673 -0.062227 +vn 0.906278 0.394391 0.151830 +vn -0.050783 -0.356853 -0.932768 +vn 0.287362 0.257668 -0.922483 +vn 0.539048 0.570666 -0.619465 +vn 0.311350 -0.023927 0.949980 +vn 0.078341 -0.948607 -0.306497 +vn -0.826930 0.491562 0.272958 +vn -0.519150 0.798425 0.304941 +vn -0.047090 0.940794 0.335612 +vn 0.601337 -0.168523 0.780999 +vn 0.516617 0.129093 0.846400 +vn -0.492355 0.097415 -0.864895 +vn -0.601550 0.273385 -0.750572 +vn -0.545885 0.110111 -0.830561 +vn -0.795373 -0.588366 0.145543 +vn 0.599292 -0.260231 0.757012 +vn 0.978118 0.142521 0.151372 +vn 0.874660 0.425275 0.232521 +vn 0.919492 0.302957 0.250465 +vn 0.564226 -0.639515 -0.522111 +vn 0.713889 -0.666280 0.215430 +vn 0.274392 -0.957823 0.085055 +vn 0.466323 -0.871883 0.149510 +vn -0.210273 0.266701 -0.940550 +vn 0.438002 0.703055 0.560198 +vn 0.245338 0.716178 0.653310 +vn 0.389111 -0.149327 0.908994 +vn 0.336375 -0.487747 -0.805536 +vn -0.919828 0.042604 0.389966 +vn -0.960875 0.113742 0.252480 +vn -0.945952 -0.181127 0.268960 +vn -0.315714 0.741539 -0.591937 +vn 0.942930 0.032624 0.331309 +vn 0.874020 0.235176 0.425123 +vn 0.034120 -0.716208 0.697012 +vn 0.841151 0.276620 0.464644 +vn 0.647664 -0.617267 0.446608 +vn 0.355937 0.343364 0.869137 +vn 0.302591 0.598376 0.741844 +vn -0.137181 -0.038331 -0.989776 +vn -0.081301 -0.025330 -0.996338 +vn -0.105625 0.003967 -0.994385 +vn 0.321818 -0.042268 0.945830 +vn 0.011628 -0.999359 -0.033448 +vn 0.019288 -0.999695 -0.014649 +vn 0.028413 -0.999329 -0.022919 +vn 0.972076 0.064119 0.225715 +vn -0.135594 0.590564 -0.795465 +vn 0.377361 -0.882321 -0.281167 +vn 0.291665 -0.016724 0.956359 +vn 0.567400 0.224921 0.792108 +vn 0.814722 -0.101505 -0.570849 +vn 0.540757 -0.234870 0.807703 +vn -0.489822 0.807520 -0.328532 +vn -0.562700 0.783074 -0.264840 +vn -0.682150 0.470412 -0.559771 +vn 0.894162 -0.056093 -0.444197 +vn -0.072787 -0.013398 -0.997253 +vn 0.318155 0.251076 0.914182 +vn 0.959593 0.212622 -0.184118 +vn 0.400922 -0.360973 -0.841975 +vn 0.601459 0.210150 0.770745 +vn 0.991211 -0.132023 0.004151 +vn 0.037629 0.716025 0.697012 +vn -0.631764 -0.775140 0.000122 +vn -0.018708 0.155583 -0.987640 +vn 0.432997 0.704947 0.561724 +vn -0.710318 0.618610 0.335734 +vn -0.747887 0.591876 0.300485 +vn -0.926389 0.305399 0.220222 +vn 0.826197 -0.133763 0.547197 +vn -0.165166 0.111332 -0.979949 +vn 0.155156 0.936674 -0.313852 +vn -0.716147 -0.681722 0.149480 +vn 0.801996 0.572680 -0.169652 +vn -0.034852 -0.056642 -0.997772 +vn -0.028291 -0.081393 -0.996277 +vn -0.005493 -0.017273 -0.999817 +vn -0.832362 0.405621 0.377606 +vn -0.971648 0.120365 0.203375 +vn -0.922727 0.261391 0.283181 +vn 0.928465 -0.361126 -0.086550 +vn -0.901669 -0.399548 0.165288 +vn -0.981658 0.135411 0.133976 +vn 0.940703 -0.320994 -0.109592 +vn 0.960814 -0.236335 -0.144658 +vn 0.999359 -0.035066 -0.000275 +vn 0.994110 0.106967 -0.016144 +vn 0.956755 0.272805 0.100925 +vn -0.899014 -0.435835 -0.042207 +vn -0.522721 0.056520 0.850612 +vn -0.770135 0.205756 0.603748 +vn -0.623035 -0.297983 0.723167 +vn -0.744743 -0.582232 0.326029 +vn -0.975677 -0.136113 0.171789 +vn -0.383282 -0.595691 0.705832 +vn 0.031220 -0.999420 0.012940 +vn 0.503769 -0.860408 -0.076632 +vn -0.873897 0.323801 0.362529 +vn -0.893857 -0.021943 0.447737 +vn -0.964904 0.055757 0.256600 +vn -0.911618 0.358562 0.200781 +vn -0.500626 0.562181 -0.658223 +vn -0.881649 0.434034 0.185064 +vn 0.991791 0.123661 0.031526 +vn -0.998108 0.051515 -0.033143 +vn 0.647755 0.189062 -0.737968 +vn -0.930052 -0.260079 -0.259438 +vn 0.673910 -0.231513 -0.701559 +vn 0.224464 -0.744224 0.629017 +vn 0.328471 -0.702109 0.631764 +vn 0.274789 -0.892544 0.357494 +vn 0.010254 -0.995239 0.096835 +vn 0.015503 -0.999756 -0.014771 +vn 0.515885 0.071810 -0.853633 +vn 0.634022 0.168950 -0.754601 +vn 0.894040 0.272286 0.355724 +vn 0.924772 -0.199042 -0.324290 +vn -0.950835 -0.083254 -0.298288 +vn -0.936918 0.248085 0.246132 +vn -0.886715 0.270394 0.374950 +vn -0.776543 0.553514 -0.300912 +vn 0.973052 0.207617 0.100162 +vn 0.741050 -0.564409 -0.363628 +vn -0.856288 0.332133 -0.395459 +vn -0.863643 -0.305979 -0.400555 +vn 0.580889 -0.533341 -0.614887 +vn 0.379833 -0.853725 -0.356151 +vn 0.108341 0.807062 -0.580401 +vn 0.194037 0.827662 -0.526566 +vn 0.200262 0.835536 -0.511551 +vn 0.800104 -0.249855 -0.545305 +vn 0.797296 -0.018342 -0.603259 +vn 0.719687 -0.161321 -0.675253 +vn 0.800775 -0.435408 -0.411237 +vn 0.719535 -0.276681 -0.636921 +vn 0.378338 -0.303598 -0.874447 +vn 0.334727 -0.618488 -0.710898 +vn -0.913572 0.222449 -0.340342 +vn 0.753380 0.051393 -0.655538 +vn 0.717887 -0.042146 -0.694845 +vn 0.750481 -0.080905 -0.655873 +vn -0.015839 0.323222 -0.946165 +vn -0.895138 -0.312235 0.318125 +vn -0.742088 -0.522568 -0.419782 +vn -0.810541 0.585589 0.009033 +vn -0.840449 -0.533586 0.094272 +vn 0.856533 0.135380 -0.497971 +vn 0.738731 0.292886 -0.606983 +vn 0.109592 0.214972 -0.970428 +vn -0.009369 0.617969 -0.786126 +vn -0.073061 0.266793 -0.960967 +vn -0.328440 -0.618763 -0.713584 +vn -0.375072 -0.574664 -0.727317 +vn 0.595569 0.086886 -0.798578 +vn 0.680166 -0.018403 -0.732780 +vn 0.784906 0.264290 -0.560381 +vn 0.701773 0.188482 -0.686972 +vn 0.767479 0.261605 -0.585223 +vn -0.672445 -0.711783 0.202795 +vn -0.897549 -0.053652 -0.437574 +vn -0.843379 -0.300302 -0.445509 +vn 0.792413 -0.133824 -0.595111 +vn -0.941282 -0.049501 -0.333872 +vn 0.748772 -0.211402 -0.628163 +vn 0.810450 -0.225593 -0.540574 +vn 0.687551 -0.143193 -0.711844 +vn 0.650197 -0.114383 -0.751091 +vn 0.628346 -0.025269 -0.777520 +vn -0.894589 0.012513 -0.446638 +vn 0.179785 0.933287 -0.310800 +vn 0.172185 0.971313 -0.163884 +vn 0.271859 0.940794 -0.202338 +vn -0.023621 0.828669 -0.559191 +vn 0.017365 0.827723 -0.560839 +vn -0.001770 0.727989 -0.685568 +vn -0.303781 -0.533341 -0.789422 +vn -0.176824 -0.249977 -0.951933 +vn -0.181799 0.820185 0.542405 +vn 0.600513 -0.706778 0.373913 +vn 0.717887 -0.607288 0.340281 +vn -0.986999 -0.123783 0.102298 +vn -0.998596 0.051454 0.011567 +vn 0.650166 0.408582 -0.640522 +vn 0.826472 -0.306223 -0.472335 +vn 0.804468 -0.493332 -0.330790 +vn -0.976775 -0.134648 0.166570 +vn 0.564531 -0.792840 -0.229438 +vn -0.496475 -0.414441 0.762688 +vn -0.343547 -0.511002 0.787927 +vn -0.458724 0.722861 -0.516709 +vn -0.280343 0.659474 -0.697470 +vn -0.263588 0.889431 -0.373363 +vn -0.547380 0.721580 -0.423872 +vn 0.824946 0.004761 -0.565172 +vn 0.847407 -0.132572 -0.514084 +vn -0.695700 0.262490 -0.668630 +vn -0.545854 0.365642 -0.753838 +vn 0.900601 -0.206030 -0.382611 +vn 0.768822 -0.344615 -0.538621 +vn 0.720878 -0.648061 -0.245582 +vn 0.661824 -0.620991 -0.419904 +vn 0.539872 -0.795984 -0.273659 +vn -0.587451 0.709922 0.388409 +vn -0.890988 0.417035 0.179357 +vn 0.827754 -0.311594 -0.466567 +vn 0.429060 -0.528001 0.732871 +vn 0.529099 -0.826228 0.193243 +vn 0.394024 -0.906308 0.152562 +vn -0.390332 0.781732 0.486282 +vn -0.496963 0.717124 0.488601 +vn -0.959105 0.112827 -0.259529 +vn -0.240272 -0.886013 -0.396496 +vn 0.128361 -0.726096 -0.675466 +vn 0.129521 -0.932340 -0.337535 +vn 0.611896 0.062532 -0.788446 +vn 0.388165 0.027772 -0.921140 +vn -0.242714 -0.383007 -0.891263 +vn -0.605518 -0.356090 -0.711692 +vn -0.502274 0.864345 -0.024110 +vn -0.396832 0.856685 0.329508 +vn -0.733238 0.628834 0.258614 +vn -0.927549 -0.147221 -0.343425 +vn 0.183844 -0.789239 0.585894 +vn -0.859554 0.184179 -0.476669 +vn -0.788934 0.507736 -0.346019 +vn -0.683493 0.398724 -0.611408 +vn -0.214240 0.698111 -0.683157 +vn -0.124821 0.470687 -0.873409 +vn -0.328715 0.496780 -0.803186 +vn 0.666646 0.440443 -0.601276 +vn 0.608448 0.335246 -0.719291 +vn -0.747917 -0.618183 0.241737 +vn 0.924863 0.185400 0.332011 +vn -0.426740 -0.331889 0.841243 +vn -0.658711 -0.185492 0.729148 +vn -0.080691 0.282907 -0.955718 +vn -0.385479 -0.743248 -0.546739 +vn 0.223457 -0.468825 0.854549 +vn 0.618336 -0.031526 -0.785272 +vn 0.000244 -0.395367 -0.918485 +vn 0.003479 -0.372936 -0.927824 +vn 0.542039 -0.751732 0.375561 +vn -0.120212 0.641285 -0.757805 +vn 0.919126 0.330485 0.214301 +vn -0.806391 0.547746 -0.222907 +vn -0.667562 0.690115 0.279397 +vn 0.917600 -0.148289 -0.368755 +vn 0.853542 0.464583 0.235817 +vn -0.097995 0.904141 -0.415784 +vn 0.075503 0.892270 -0.445112 +vn 0.004364 0.848750 -0.528764 +vn 0.767418 -0.285379 -0.574114 +vn 0.307962 0.485763 -0.817988 +vn 0.601367 0.058168 -0.796838 +vn 0.184454 0.440626 -0.878506 +vn 0.641865 -0.112094 -0.758538 +vn -0.857570 0.388714 0.336833 +vn 0.795404 0.578997 -0.178991 +vn 0.477798 -0.240211 -0.844966 +vn -0.007447 -0.990295 0.138585 +vn 0.004395 -0.991668 0.128666 +vn -0.078738 -0.830164 0.551897 +vn -0.155614 -0.638508 0.753685 +vn 0.028596 -0.985443 0.167455 +vn -0.670064 -0.431867 -0.603687 +vn -0.603320 -0.559954 -0.567797 +vn -0.319529 -0.656758 -0.683004 +vn -0.965178 0.213630 -0.150884 +vn -0.909146 -0.394910 -0.132115 +vn -0.863948 -0.400128 -0.305704 +vn -0.198492 -0.521378 -0.829890 +vn 0.906247 0.324229 0.271218 +vn 0.171300 -0.501053 -0.848262 +vn 0.950682 0.131016 0.281045 +vn -0.225898 -0.614765 0.755638 +vn -0.349528 -0.786065 0.509781 +vn -0.283151 -0.794549 0.537095 +vn -0.517472 0.621448 0.588214 +vn 0.257881 0.431532 -0.864437 +vn 0.119724 0.507187 -0.853450 +vn 0.217078 0.626759 -0.748344 +vn 0.631397 0.103244 -0.768548 +vn 0.960265 0.153264 0.233161 +vn 0.677419 -0.723624 0.131932 +vn -0.347179 -0.223487 -0.910764 +vn -0.710379 -0.251747 -0.657216 +vn 0.918516 0.278390 0.280709 +vn 0.825404 0.465835 0.318827 +vn -0.757317 -0.575549 0.308451 +vn -0.857143 -0.396710 0.328440 +vn -0.775384 -0.588092 0.229896 +vn -0.168126 -0.219214 -0.961058 +vn -0.506638 -0.243873 -0.826930 +vn 0.631550 -0.687216 0.358928 +vn 0.069887 -0.973388 -0.218177 +vn -0.100558 -0.988067 -0.116398 +vn -0.047670 -0.914731 -0.401227 +vn 0.600513 -0.308847 -0.737510 +vn 0.812189 0.548570 0.198401 +vn -0.701804 0.018464 -0.712088 +vn 0.544267 0.748100 0.379589 +vn 0.658193 0.747673 0.087863 +vn 0.639668 0.656636 0.399457 +vn 0.631306 0.764336 -0.131199 +vn -0.500778 -0.813898 -0.294504 +vn -0.498672 0.800958 0.331278 +vn 0.496170 0.828791 -0.258583 +vn 0.725944 0.684530 -0.066225 +vn 0.558306 0.798730 0.224189 +vn 0.336406 0.793268 0.507462 +vn -0.079806 0.989227 0.122654 +vn -0.078951 0.955779 0.283273 +vn -0.540086 0.841456 -0.014374 +vn 0.143040 0.936552 0.319895 +vn -0.004913 0.956786 0.290719 +vn 0.370891 0.915098 -0.158147 +vn 0.283608 0.958068 0.040468 +vn 0.204413 0.935026 0.289651 +vn -0.091311 0.909360 0.405805 +vn -0.218055 0.789300 0.573962 +vn -0.036988 0.999268 0.008606 +vn -0.130558 0.986267 0.100925 +vn 0.057833 0.967345 -0.246742 +vn 0.248390 0.917875 0.309427 +vn -0.621967 0.428144 -0.655568 +vn 0.604419 0.796442 -0.017731 +vn 0.022340 0.413739 -0.910092 +vn 0.110477 0.993469 0.028016 +vn 0.236824 0.971129 -0.028230 +vn -0.829005 0.426038 -0.362194 +vn -0.410932 0.894528 -0.175756 +vn 0.160375 0.981262 0.106632 +vn 0.039796 0.980651 0.191626 +vn 0.016205 0.907071 0.420576 +vn 0.344188 0.878536 -0.331156 +vn 0.348094 0.924070 -0.157720 +vn 0.196692 0.951537 -0.236305 +vn -0.015778 0.998657 -0.049226 +vn -0.681234 0.543535 -0.490341 +vn 0.167425 0.977477 -0.128452 +vn 0.026887 0.997040 -0.071993 +vn -0.140263 0.987579 -0.070559 +vn 0.261940 0.964995 0.010559 +vn 0.432539 0.901334 0.021485 +vn 0.170415 0.957335 0.233283 +vn 0.607288 0.726768 0.320902 +vn 0.043519 0.879971 0.473006 +vn -0.922666 -0.343822 0.174505 +vn -0.788903 0.516495 0.332865 +vn -0.522324 -0.564714 0.638936 +vn -0.882107 -0.177007 0.436445 +vn -0.706778 0.627003 -0.327555 +vn -0.911435 0.149174 -0.383404 +vn 0.540513 0.766137 0.347606 +vn 0.699881 0.580187 0.416517 +vn -0.025941 0.901456 0.432051 +vn -0.397259 0.910215 0.116703 +vn 0.174383 0.762139 -0.623463 +vn 0.006684 0.998535 0.053377 +vn 0.214454 0.955596 -0.201941 +vn 0.012757 0.942381 0.334269 +vn -0.709983 0.613575 0.345531 +vn 0.081606 0.901547 -0.424848 +vn -0.367046 -0.185827 -0.911435 +vn -0.986877 0.118046 0.109928 +vn 0.007630 0.818567 0.574328 +vn -0.483016 0.831629 -0.273965 +vn -0.859401 0.316538 0.401502 +vn -0.914670 0.385479 0.121464 +vn -0.987915 0.146306 0.051027 +vn -0.120701 0.961150 -0.248207 +vn 0.225715 0.969695 -0.093356 +vn -0.851283 0.509995 -0.123264 +vn 0.649007 0.593951 0.475356 +vn -0.523087 0.495712 -0.693258 +vn -0.550920 0.225349 -0.803522 +vn -0.779015 0.299753 -0.550676 +vn 0.813288 0.581713 -0.011353 +vn -0.849940 0.254250 0.461440 +vn -0.901120 0.305155 0.307932 +vn 0.762261 0.621082 0.182165 +vn -0.989288 -0.142247 -0.032655 +vn 0.772027 0.633564 0.050172 +vn -0.066958 -0.170324 -0.983093 +vn 0.007080 -0.371441 -0.928404 +vn -0.692679 0.721183 -0.008148 +vn 0.763482 0.568255 -0.306803 +vn 0.539323 0.602222 0.588580 +vn 0.568438 0.737815 0.363933 +vn -0.626026 0.524430 0.577074 +vn -0.540391 0.778283 0.319681 +vn 0.088198 0.324595 -0.941710 +vn 0.018983 0.565264 -0.824671 +vn 0.216376 0.330546 -0.918638 +vn 0.748650 0.662496 -0.023865 +vn 0.698935 0.697317 0.158696 +vn 0.624165 0.726585 0.287057 +vn 0.766472 0.619831 -0.168157 +vn 0.674551 0.738212 0.000336 +vn 0.591296 0.783441 0.191107 +vn 0.688101 0.627430 -0.364391 +vn 0.715079 0.650624 -0.255593 +vn -0.895871 0.236793 -0.375927 +vn -0.076876 0.920927 -0.382000 +vn -0.511032 0.258248 -0.819819 +vn 0.641835 0.756737 -0.123936 +vn 0.515488 0.796686 0.315470 +vn 0.740684 0.549821 -0.385998 +vn -0.798883 -0.560991 0.216895 +vn 0.387188 0.844997 0.368786 +vn 0.030763 0.875973 0.481338 +vn 0.577532 0.814508 -0.054415 +vn 0.557634 0.828944 0.042848 +vn 0.466628 0.863277 0.192236 +vn 0.342479 0.778130 0.526475 +vn 0.574511 0.761071 -0.301096 +vn 0.561846 0.810663 -0.164617 +vn 0.425031 0.899075 0.104801 +vn 0.400098 0.870235 0.287362 +vn 0.492996 0.822596 -0.283242 +vn 0.038972 0.209387 -0.977050 +vn -0.745750 0.391247 -0.539171 +vn -0.776574 -0.240761 -0.582171 +vn -0.450056 -0.429121 -0.783105 +vn -0.881588 -0.469008 0.053041 +vn -0.425581 0.652272 0.627186 +vn -0.839747 -0.357677 0.408460 +vn -0.979858 -0.006745 -0.199500 +vn -0.323862 -0.826319 0.460707 +vn -0.311319 -0.873226 0.374859 +vn -0.343669 0.799615 0.492416 +vn -0.491440 0.729118 0.476241 +vn -0.716208 0.478256 0.508225 +vn -0.390240 0.756676 0.524522 +vn -0.284616 0.648244 0.706198 +vn -0.415754 0.031739 0.908902 +vn -0.590075 -0.058657 -0.805200 +vn -0.351299 -0.104099 -0.930418 +vn -0.583697 0.241737 -0.775140 +vn -0.473952 0.678732 0.560961 +vn -0.792383 -0.390423 0.468703 +vn -0.686697 -0.332743 0.646290 +vn -0.778466 0.280648 0.561388 +vn -0.186560 -0.751701 -0.632527 +vn -0.810205 -0.326304 0.486892 +vn -0.801843 -0.333079 0.496078 +vn -0.879818 0.098422 0.464919 +vn -0.708457 0.465529 0.530412 +vn 0.145878 0.406812 -0.901761 +vn 0.021088 -0.999573 -0.019105 +vn 0.558000 -0.822993 -0.106204 +vn 0.053407 -0.998352 -0.019654 +vn -0.769585 0.481002 -0.419935 +vn -0.624073 0.461409 0.630543 +vn -0.559862 0.243660 0.791925 +vn -0.672262 -0.284921 0.683248 +vn -0.675588 0.455306 0.579882 +vn -0.417280 0.218299 -0.882138 +vn -0.697409 0.248360 0.672231 +vn -0.689474 0.703269 -0.173254 +vn -0.618336 -0.368358 0.694205 +vn -0.989624 0.074313 0.122745 +vn -0.910581 0.372570 0.178899 +vn -0.646779 0.338878 0.683218 +vn -0.712088 0.290384 0.639180 +vn -0.779015 -0.067385 0.623341 +vn -0.258003 0.068850 -0.963652 +vn -0.285836 0.175298 -0.942076 +vn -0.378765 0.103824 -0.919645 +vn -0.360118 0.019990 -0.932676 +vn -0.347056 0.142064 -0.927000 +vn -0.359447 0.109409 -0.926695 +vn -0.779290 -0.009278 -0.626545 +vn -0.694540 -0.266305 -0.668294 +vn -0.703421 -0.596179 0.386944 +vn -0.316355 -0.850978 0.419172 +vn -0.773034 0.240120 0.587146 +vn -0.971496 0.096957 0.216193 +vn -0.483444 0.718253 0.500351 +vn -0.260109 -0.833613 0.487228 +vn -0.623524 -0.357067 0.695456 +vn -0.821253 0.562334 -0.096347 +vn -0.576891 0.517899 0.631611 +vn -0.475539 0.651204 0.591388 +vn 0.535600 0.703787 -0.466659 +vn -0.220191 -0.187017 0.957335 +vn -0.458266 -0.269753 0.846858 +vn -0.448653 -0.098575 0.888241 +vn -0.967315 0.141148 -0.210517 +vn -0.166265 -0.092654 0.981689 +vn -0.652608 0.141484 0.744346 +vn -0.730216 0.104343 0.675161 +vn -0.930052 -0.236213 -0.281350 +vn -0.630543 -0.342235 0.696616 +vn -0.632221 -0.480209 0.607990 +vn -0.837275 0.411969 -0.359416 +vn -0.983490 -0.029237 -0.178442 +vn 0.201270 -0.598193 -0.775628 +vn 0.228919 -0.644734 -0.729301 +vn -0.641407 -0.162908 0.749687 +vn -0.373302 -0.330119 0.866970 +vn -0.755394 0.277749 0.593463 +vn -0.610553 -0.011078 0.791864 +vn -0.370403 0.191839 -0.908811 +vn -0.452498 0.344249 -0.822626 +vn -0.341136 0.349895 -0.872433 +vn -0.758385 -0.022767 0.651387 +vn -0.666860 -0.143956 0.731101 +vn -0.115696 -0.350383 0.929411 +vn -0.546770 -0.351543 -0.759880 +vn -0.053865 -0.538652 0.840785 +vn -0.035615 0.196905 -0.979766 +vn -0.056124 0.233406 -0.970733 +vn -0.928373 0.370952 0.022492 +vn -0.787133 0.602588 -0.131291 +vn -0.476150 0.149022 -0.866604 +vn -0.635182 0.271554 -0.723014 +vn -0.462600 0.212775 -0.860622 +vn -0.766106 0.393139 0.508377 +vn 0.253945 0.289834 -0.922758 +vn 0.434187 0.319041 -0.842402 +vn 0.405927 0.296426 -0.864467 +vn -0.725639 -0.675161 -0.132542 +vn -0.803461 0.074282 0.590655 +vn -0.633503 0.145238 -0.759941 +vn -0.902890 0.168004 0.395642 +vn -0.792810 0.409803 0.451064 +vn -0.743675 0.644490 0.177618 +vn -0.750237 0.143803 0.645314 +vn -0.308664 -0.269845 -0.912076 +vn -0.566118 0.386944 -0.727836 +vn -0.309183 0.150792 -0.938963 +vn -0.933256 -0.340190 0.115299 +vn -0.665029 0.134983 0.734489 +vn -0.422071 -0.903775 0.070864 +vn -0.880367 -0.226051 0.416883 +vn -0.850063 -0.081057 0.520371 +vn -0.841853 0.134312 0.522691 +vn -0.715964 0.372845 0.590197 +vn -0.655263 0.446303 -0.609424 +vn -0.756554 -0.224189 0.614246 +vn -0.842860 -0.179418 0.507279 +vn -0.813318 0.268715 0.516007 +vn -0.465011 -0.782739 -0.413556 +vn -0.587298 -0.019501 0.809107 +vn -0.696280 0.377911 0.610187 +vn -0.768670 0.025086 0.639149 +vn -0.528520 -0.005249 -0.848872 +vn -0.343883 -0.028169 -0.938566 +vn -0.131535 -0.206336 -0.969573 +vn -0.697562 0.165105 0.697195 +vn -0.127689 -0.867458 0.480789 +vn -0.119114 0.138981 -0.983093 +vn 0.455245 0.776452 -0.435682 +vn -0.632588 0.623890 0.458846 +vn -0.854854 -0.173711 0.488876 +vn -0.757805 -0.389447 0.523453 +vn -0.715506 0.223243 0.661946 +vn -0.367779 0.898618 -0.239143 +vn -0.686575 0.480453 0.545640 +vn -0.655354 0.539232 0.528825 +vn -0.614643 0.472732 0.631428 +vn -0.778832 -0.152654 0.608325 +vn -0.783441 0.073153 0.617115 +vn -0.740837 -0.461348 0.488113 +vn 0.163915 0.236732 -0.957610 +vn 0.183966 0.408094 -0.894192 +vn 0.169439 0.306742 -0.936583 +vn -0.270852 -0.054384 -0.961058 +vn -0.593707 0.107181 -0.797479 +vn -0.555895 -0.090670 -0.826258 +vn -0.722465 -0.575121 0.383709 +vn 0.107425 -0.103824 -0.988769 +vn 0.201788 -0.597003 -0.776421 +vn 0.005921 0.253456 -0.967315 +vn -0.802149 0.096133 0.589282 +vn -0.068331 0.122868 -0.990051 +vn -0.606922 0.777947 0.162511 +vn -0.691885 -0.040559 -0.720847 +vn -0.564928 -0.148625 -0.811609 +vn -0.604144 -0.295663 -0.739982 +vn -0.411573 0.070620 -0.908628 +vn -0.464583 -0.860530 0.208838 +vn 0.008881 -0.999481 0.030396 +vn -0.387524 0.432325 -0.814173 +vn -0.371441 -0.615894 0.694723 +vn -0.026765 0.373241 -0.927335 +vn -0.624043 -0.443861 0.643055 +vn -0.565081 0.007324 -0.824976 +vn 0.325297 -0.418317 -0.848018 +vn -0.352763 -0.077731 -0.932463 +vn 0.345897 0.467910 -0.813257 +vn 0.346141 0.430555 -0.833522 +vn 0.322062 0.325785 -0.888852 +vn -0.000153 0.832850 -0.553484 +vn -0.018555 0.592975 -0.804987 +vn -0.034791 0.629322 -0.776330 +vn -0.424207 0.071474 -0.902707 +vn 0.100620 0.833522 -0.543199 +vn -0.047212 0.387402 -0.920682 +vn -0.194128 0.630512 -0.751457 +vn 0.109226 0.858455 -0.501083 +vn 0.163915 0.688131 -0.706778 +vn 0.104434 0.610675 -0.784936 +vn -0.043672 0.729240 -0.682852 +vn 0.143956 0.734367 -0.663289 +vn 0.300363 0.698233 -0.649770 +vn 0.365856 0.471419 -0.802393 +vn 0.586108 0.289254 -0.756798 +vn -0.816553 -0.340587 -0.466018 +vn -0.407392 0.611042 -0.678671 +vn -0.621967 -0.309854 -0.719108 +vn -0.672597 -0.503098 -0.542619 +vn -0.645222 -0.301462 -0.701987 +vn -0.418928 -0.350352 -0.837672 +vn -0.968047 0.024354 -0.249458 +vn -0.886380 -0.080630 -0.455824 +vn -0.462447 -0.641530 -0.611988 +vn -0.932127 -0.213630 -0.292367 +vn -0.525346 -0.606250 -0.597003 +vn -0.634693 -0.583911 -0.506149 +vn -0.983001 0.059572 -0.173467 +vn -0.960936 0.011017 -0.276467 +vn -0.759545 -0.514725 -0.397656 +vn -0.643880 0.735740 -0.209906 +vn -0.527024 -0.666982 -0.526597 +vn -0.934538 -0.277627 -0.222510 +vn -0.958098 -0.193732 -0.210822 +vn -0.624775 -0.663900 -0.410871 +vn -0.856929 -0.434126 -0.277749 +vn -0.035249 0.776238 -0.629414 +vn 0.284341 0.588855 -0.756554 +vn 0.247200 0.482528 -0.840236 +vn -0.608722 0.709220 -0.355541 +vn -0.607379 0.630482 -0.483261 +vn -0.288797 -0.941435 -0.173894 +vn -0.964843 0.238777 -0.109561 +vn -0.024537 0.606403 -0.794763 +vn 0.045259 0.555132 -0.830500 +vn -0.054079 0.751122 -0.657888 +vn -0.300088 -0.951842 0.062563 +vn -0.402600 -0.870540 0.282937 +vn -0.247230 -0.919065 0.306864 +vn -0.638173 -0.768456 0.046632 +vn -0.541337 -0.832087 0.120487 +vn -0.475326 -0.843440 -0.250282 +vn -0.109653 0.712638 -0.692862 +vn -0.107822 0.365032 -0.924711 +vn -0.700858 -0.326426 -0.634205 +vn -0.728111 -0.294076 -0.619129 +vn -0.810450 -0.130192 -0.571123 +vn -0.849391 0.118107 -0.514328 +vn -0.950224 -0.296579 -0.095218 +vn 0.609210 0.470321 -0.638447 +vn 0.545366 0.383343 -0.745354 +vn -0.783837 -0.362926 -0.503800 +vn -0.870663 -0.289956 -0.397290 +vn -0.395428 0.778405 -0.487533 +vn -0.687674 0.569140 -0.450697 +vn -0.854396 0.319987 -0.409375 +vn -0.698599 -0.628040 -0.342692 +vn 0.171056 0.495682 -0.851466 +vn -0.056459 0.406262 -0.911985 +vn 0.118900 0.485824 -0.865902 +vn 0.094638 0.371044 -0.923765 +vn -0.843562 -0.291177 -0.451186 +vn -0.929350 -0.096774 -0.356273 +vn -0.890500 0.170965 -0.421552 +vn -0.995300 0.059511 0.076144 +vn -0.850063 -0.272774 -0.450514 +vn -0.930509 0.017304 -0.365795 +vn -0.902799 -0.353771 -0.244423 +vn -0.863948 -0.201788 -0.461348 +vn -0.910733 -0.274697 -0.308329 +vn -0.946654 -0.305765 -0.101718 +vn 0.132267 0.445601 -0.885372 +vn -0.856838 -0.143468 -0.495163 +vn -0.905148 -0.273568 -0.325327 +vn -0.847560 0.219031 -0.483322 +vn -0.767052 -0.534623 -0.354595 +vn -0.670064 0.233345 -0.704642 +vn -0.669851 0.499649 -0.549150 +vn -0.519059 0.534227 -0.667196 +vn -0.920591 -0.130222 -0.368145 +vn -0.776910 -0.447096 0.443220 +vn -0.615650 0.171453 -0.769097 +vn -0.699026 0.402875 -0.590747 +vn -0.702994 -0.614093 -0.358654 +vn 0.042695 0.129826 -0.990600 +vn -0.296548 -0.642262 -0.706748 +vn -0.275704 -0.902646 0.330363 +vn -0.202063 -0.978759 0.033876 +vn -0.061220 -0.995819 0.067721 +vn -0.968505 -0.231208 -0.092257 +vn 0.316904 0.793603 -0.519333 +vn 0.173376 0.798761 -0.576098 +vn -0.856685 0.365612 -0.363842 +vn -0.480880 0.822016 -0.304910 +vn -0.875088 -0.265969 -0.404309 +vn -0.321146 0.667074 -0.672170 +vn -0.749107 -0.641804 -0.163884 +vn -0.983306 0.168950 -0.067354 +vn -0.901761 -0.352489 -0.250069 +vn -0.958983 0.273629 -0.073611 +vn -0.610645 0.234779 -0.756279 +vn -0.596606 -0.111454 -0.794733 +vn -0.638813 0.185492 -0.746635 +vn -0.920713 0.296182 -0.253975 +vn 0.212500 -0.516984 -0.829157 +vn -0.809168 -0.530259 -0.253059 +vn -0.678152 0.582812 -0.447645 +vn -0.839778 0.487899 -0.238044 +vn -0.940214 0.199042 -0.276315 +vn -0.946654 -0.147771 -0.286325 +vn -0.247749 -0.514206 -0.821070 +vn -0.973846 -0.226997 0.008820 +vn 0.495987 0.361400 -0.789514 +vn 0.609272 0.195288 -0.768517 +vn -0.161992 0.329112 -0.930265 +vn -0.703391 -0.710654 0.014222 +vn -0.816523 0.488937 -0.306864 +vn -0.943907 -0.114078 -0.309793 +vn 0.526139 0.614215 -0.588122 +vn 0.455672 0.509018 -0.730216 +vn 0.433119 0.513382 -0.740806 +vn 0.020264 -0.995727 0.089908 +vn -0.663686 -0.582904 -0.468703 +vn -0.595752 -0.523545 -0.609027 +vn -0.514847 -0.705161 -0.487442 +vn -0.594623 -0.785821 0.169836 +vn -0.986847 -0.084536 -0.137669 +vn -0.910062 0.296091 -0.289987 +vn -0.837581 0.430189 -0.336680 +vn 0.198950 0.247932 -0.948119 +vn 0.013489 0.720817 -0.692984 +vn -0.063173 0.714103 -0.697165 +vn 0.458174 0.496841 -0.736991 +vn 0.371258 0.520890 -0.768639 +vn -0.949950 -0.311106 -0.027375 +vn -0.604480 -0.365276 -0.707877 +vn -0.713828 -0.273629 -0.644612 +vn -0.565600 -0.146580 -0.811518 +vn -0.381268 -0.817103 0.432356 +vn -0.168676 0.863796 -0.474746 +vn -0.625690 0.693716 -0.356700 +vn 0.268349 0.852565 -0.448408 +vn -0.526749 -0.786859 -0.321451 +vn -0.552690 -0.768853 -0.321512 +vn -0.643178 -0.697043 -0.316874 +vn -0.965056 -0.144841 -0.218299 +vn -0.751915 -0.086154 -0.653584 +vn -0.741050 -0.075533 -0.667135 +vn -0.597400 0.062685 -0.799463 +vn -0.681845 0.177587 -0.709586 +vn -0.071627 0.519639 -0.851344 +vn -0.992645 -0.110965 -0.047945 +vn -0.855129 -0.195227 -0.480209 +vn -0.719260 0.235206 -0.653676 +vn -0.975982 -0.084292 -0.200720 +vn -0.179418 0.584674 -0.791131 +vn -0.854213 -0.160772 -0.494400 +vn -0.011048 0.921537 -0.388104 +vn 0.230323 0.845302 -0.482040 +vn 0.212775 -0.588519 -0.779962 +vn 0.215094 -0.036927 -0.975890 +vn 0.476760 0.183874 -0.859554 +vn 0.464064 0.433546 -0.772423 +vn 0.477859 0.457472 -0.749870 +vn 0.214972 -0.121677 -0.968993 +vn -0.799890 0.072298 -0.595721 +vn 0.362163 0.649159 -0.668874 +vn -0.686544 -0.455367 -0.566820 +vn 0.355785 0.404798 -0.842341 +vn 0.451216 0.250465 -0.856502 +vn 0.022828 0.707297 -0.706504 +vn 0.003876 -0.999939 0.010193 +vn 0.154027 0.347819 -0.924802 +vn -0.975951 0.014008 -0.217505 +vn -0.072237 0.561022 -0.824610 +vn -0.171270 0.542467 -0.822413 +vn -0.818140 -0.287790 -0.497787 +vn -0.783349 -0.114200 -0.610950 +vn 0.023103 -0.999451 -0.023164 +vn -0.063997 0.635273 -0.769585 +vn -0.087527 0.673238 -0.734214 +vn -0.095065 0.788446 -0.607654 +vn 0.190954 0.276742 -0.941771 +vn -0.868160 -0.239906 -0.434370 +vn -0.683676 -0.325968 -0.652913 +vn -0.629383 -0.696066 -0.345439 +vn -0.795312 -0.291391 -0.531510 +vn 0.003265 0.512986 -0.858364 +vn -0.814295 -0.087802 -0.573717 +vn -0.844172 0.357067 -0.399823 +vn -0.814081 -0.428632 -0.391797 +vn -0.836848 -0.394299 -0.379681 +vn -0.902280 -0.048891 -0.428327 +vn -0.826319 0.155583 -0.541246 +vn -0.770928 0.261177 -0.580859 +vn -0.567858 0.278573 -0.774529 +vn -0.736595 0.666799 -0.112980 +vn -0.095218 0.716178 -0.691366 +vn -0.504715 -0.679739 -0.532151 +vn -0.577410 -0.689322 -0.437422 +vn -0.798395 0.252693 -0.546495 +vn -0.712943 -0.111393 -0.692282 +vn -0.910825 0.140385 -0.388165 +vn -0.726707 0.450026 -0.518967 +vn -0.409436 0.849452 -0.332835 +vn -0.617298 0.342174 -0.708365 +vn -0.631245 -0.685385 -0.362926 +vn -0.601672 -0.510666 -0.614154 +vn -0.673818 -0.680135 -0.288705 +vn -0.861721 -0.357799 -0.359630 +vn -0.926176 0.061831 -0.371899 +vn -0.788476 0.173681 -0.589984 +vn -0.916593 -0.103793 -0.386059 +vn -0.948088 0.005890 -0.317911 +vn -0.266915 0.743004 -0.613727 +vn 0.128025 -0.989746 0.062838 +vn -0.577899 0.157689 -0.800684 +vn -0.731681 0.548601 -0.404492 +vn -0.580432 0.778527 -0.238685 +vn -0.726341 -0.242347 -0.643178 +vn -0.862911 0.042726 -0.503494 +vn -0.667714 -0.020295 -0.744102 +vn -0.751427 0.189825 -0.631886 +vn 0.457350 0.249214 -0.853633 +vn 0.507279 0.273110 -0.817316 +vn -0.720481 0.487503 -0.493179 +vn -0.828883 -0.471786 -0.300516 +vn 0.574114 0.491226 -0.655019 +vn -0.754997 0.615192 -0.226844 +vn -0.694449 -0.674734 -0.249794 +vn 0.556597 0.090609 -0.825800 +vn 0.320261 0.407758 -0.855068 +vn 0.405194 0.156133 -0.900784 +vn 0.580401 0.581164 -0.570391 +vn -0.212775 0.796777 -0.565539 +vn -0.001526 0.798090 -0.602496 +vn 0.471419 0.637196 -0.609668 +vn 0.047639 0.416242 -0.907987 +vn 0.400159 0.757805 -0.515305 +vn 0.441481 0.607318 -0.660482 +vn 0.672597 0.228889 -0.703696 +vn -0.028565 -0.847926 0.529313 +vn -0.147618 -0.688894 0.709616 +vn 0.129826 -0.672292 0.728782 +vn -0.245705 -0.968993 -0.025513 +vn -0.366222 -0.915922 -0.163976 +vn 0.250099 0.480850 -0.840358 +vn 0.156407 0.704917 -0.691794 +vn 0.152074 0.567553 -0.809137 +vn -0.112674 0.879665 -0.462020 +vn 0.310068 0.642048 -0.701132 +vn 0.352092 0.690451 -0.631855 +vn 0.293313 0.526963 -0.797632 +vn 0.019013 -0.997040 0.074435 +vn 0.099948 0.664235 -0.740776 +vn 0.471084 0.497208 -0.728568 +vn -0.012421 0.414136 -0.910092 +vn -0.432386 -0.799463 -0.416944 +vn -0.122013 0.849605 -0.513077 +vn 0.301309 0.698477 -0.649068 +vn -0.185308 0.627277 -0.756401 +vn -0.588763 -0.797540 0.131382 +vn -0.007996 -0.999542 0.028779 +vn 0.226508 0.309061 -0.923643 +vn -0.415754 0.235176 -0.878506 +vn 0.115604 0.167364 -0.979064 +vn -0.028687 0.859828 -0.509751 +vn -0.274941 0.816950 -0.506882 +vn 0.288278 -0.571947 -0.767937 +vn 0.295389 0.340312 -0.892697 +vn 0.577227 0.271737 -0.770012 +vn 0.440565 0.198218 -0.875546 +vn -0.030427 0.352214 -0.935392 +vn 0.050600 0.433912 -0.899503 +vn -0.025086 0.374523 -0.926847 +vn -0.572131 -0.810327 -0.126621 +vn -0.127903 0.396893 -0.908872 +vn 0.590655 0.292184 -0.752129 +vn 0.099429 0.722343 -0.684317 +vn 0.119236 0.410077 -0.904202 +vn -0.073489 0.628773 -0.774071 +vn -0.195044 0.668661 -0.717490 +vn -0.229987 0.507706 -0.830226 +vn -0.301035 0.568651 -0.765496 +vn 0.148625 -0.157567 -0.976257 +vn 0.282418 0.261391 -0.922971 +vn 0.458663 0.356334 -0.813990 +vn 0.175481 0.618946 -0.765557 +vn 0.328990 0.258614 -0.908200 +vn 0.448775 0.674612 -0.586047 +vn -0.130039 0.521561 -0.843226 +vn -0.090457 0.769524 -0.632160 +vn -0.033967 0.434675 -0.899930 +vn -0.097201 0.638722 -0.763268 +vn -0.000122 0.660726 -0.750603 +vn 0.184515 0.889920 -0.417066 +vn 0.058443 0.487259 -0.871273 +vn 0.104678 0.761437 -0.639699 +vn 0.018616 0.456618 -0.889431 +vn 0.149052 0.871090 -0.467910 +vn -0.456984 -0.658162 0.598285 +vn 0.038667 0.134129 -0.990204 +vn 0.148320 0.546617 -0.824122 +vn 0.230079 -0.562059 0.794427 +vn 0.223395 0.612293 -0.758385 +vn 0.295938 0.788934 -0.538469 +vn 0.349620 0.101596 -0.931333 +vn -0.744987 -0.629994 -0.219275 +vn 0.180212 0.200262 -0.963012 +vn 0.074282 0.601947 -0.795038 +vn -0.026093 0.483871 -0.874722 +vn 0.510880 0.096194 -0.854213 +vn -0.557207 -0.351268 -0.752373 +vn -0.538224 -0.105564 -0.836146 +vn -0.463729 0.354137 -0.812098 +vn -0.248909 -0.106052 -0.962676 +vn -0.386944 -0.277200 -0.879421 +vn -0.305124 0.017273 -0.952116 +vn -0.396161 0.137791 -0.907743 +vn 0.434095 -0.234352 -0.869808 +vn -0.118137 0.307505 -0.944182 +vn -0.210364 0.380566 -0.900479 +vn 0.193182 -0.030488 -0.980682 +vn 0.019013 0.284249 -0.958525 +vn 0.286019 -0.324931 -0.901425 +vn -0.124943 -0.456069 -0.881100 +vn 0.484848 -0.012421 -0.874477 +vn -0.387310 -0.243049 -0.889309 +vn -0.417005 -0.243843 -0.875546 +vn -0.391247 0.155431 -0.907041 +vn -0.479751 -0.665487 -0.571734 +vn -0.320017 -0.603717 -0.730125 +vn -0.378582 -0.701254 -0.604053 +vn -0.440260 -0.149083 -0.885372 +vn -0.518204 -0.490860 -0.700339 +vn 0.121097 -0.295663 -0.947569 +vn -0.252083 0.232612 -0.939299 +vn -0.197394 0.110050 -0.974120 +vn -0.439009 0.148534 -0.886105 +vn 0.082797 -0.075655 -0.993683 +vn -0.096438 -0.496597 -0.862575 +vn -0.027345 -0.998383 -0.049440 +vn -0.222144 0.143620 -0.964354 +vn -0.254128 0.005615 -0.967132 +vn -0.311258 0.272408 -0.910428 +vn -0.121281 0.012085 -0.992523 +vn -0.463515 0.009247 -0.886013 +vn -0.139988 -0.319651 -0.937132 +vn -0.480361 -0.476852 -0.736076 +vn 0.114475 -0.223609 -0.967925 +vn -0.262734 -0.119327 -0.957457 +vn 0.043641 -0.416211 -0.908200 +vn -0.062227 0.350017 -0.934660 +vn 0.065401 -0.281045 -0.957427 +vn -0.324900 -0.372387 -0.869320 +vn 0.061251 -0.321482 -0.944914 +vn -0.330058 -0.735435 -0.591723 +vn -0.351970 -0.262856 -0.898312 +vn -0.248299 -0.298074 -0.921659 +vn -0.420270 -0.315683 -0.850703 +vn -0.119449 -0.321299 -0.939390 +vn -0.218024 -0.921628 -0.320994 +vn -0.248909 -0.195013 -0.948668 +vn 0.013428 -0.164678 -0.986236 +vn -0.181799 -0.297067 -0.937376 +vn 0.251869 -0.295602 -0.921476 +vn 0.274178 0.250618 -0.928434 +vn -0.341929 -0.414747 -0.843226 +vn 0.633808 -0.137883 -0.761071 +vn 0.469771 0.056581 -0.880947 +vn -0.106449 0.238716 -0.965209 +vn 0.425367 -0.461440 -0.778527 +vn -0.172857 -0.368938 -0.913205 +vn 0.433515 0.052309 -0.899594 +vn 0.399976 -0.322550 -0.857875 +vn 0.451033 -0.081790 -0.888730 +vn 0.454207 -0.114566 -0.883480 +vn 0.404309 0.004669 -0.914579 +vn 0.399396 0.108066 -0.910367 +vn 0.360210 -0.406384 -0.839686 +vn 0.308634 -0.077151 -0.948027 +vn 0.250282 -0.273751 -0.928648 +vn -0.219337 0.287606 -0.932279 +vn 0.300485 -0.350658 -0.886959 +vn 0.414167 0.021149 -0.909940 +vn -0.642781 -0.747154 0.168950 +vn 0.291208 -0.272286 -0.917051 +vn 0.419813 0.074709 -0.904508 +vn -0.545122 -0.838038 0.022584 +vn -0.513138 -0.858119 0.015961 +vn 0.291696 -0.411389 -0.863491 +vn 0.240120 -0.230720 -0.942900 +vn 0.505020 -0.107059 -0.856410 +vn 0.224799 -0.168798 -0.959655 +vn 0.272652 -0.158513 -0.948943 +vn 0.482162 0.040925 -0.875088 +vn 0.094150 -0.253670 -0.962676 +vn 0.120670 -0.445204 -0.887234 +vn 0.213752 -0.412275 -0.885617 +vn 0.214515 -0.081088 -0.973327 +vn 0.295358 -0.392071 -0.871212 +vn 0.311533 -0.418012 -0.853328 +vn 0.102512 -0.229347 -0.967925 +vn 0.274209 -0.172124 -0.946104 +vn 0.164159 -0.080294 -0.983154 +vn 0.238502 -0.128941 -0.962523 +vn 0.372692 -0.201209 -0.905850 +vn 0.462508 -0.127964 -0.877316 +vn 0.319559 0.085269 -0.943693 +vn 0.284036 0.125340 -0.950560 +vn 0.167943 -0.322153 -0.931669 +vn 0.042177 -0.195410 -0.979797 +vn 0.360759 0.080386 -0.929167 +vn -0.030335 -0.218207 -0.975402 +vn 0.233741 -0.110080 -0.966033 +vn 0.255928 0.030976 -0.966186 +vn 0.327433 -0.574358 -0.750237 +vn 0.319468 -0.495773 -0.807520 +vn 0.293924 -0.231666 -0.927305 +vn 0.428907 0.073977 -0.900296 +vn 0.198950 -0.269478 -0.942198 +vn 0.213141 -0.178716 -0.960509 +vn 0.214850 -0.194037 -0.957152 +vn 0.249001 -0.285684 -0.925382 +vn 0.110111 -0.457228 -0.882473 +vn 0.379070 -0.058992 -0.923460 +vn 0.119419 -0.731773 -0.670980 +vn 0.211737 -0.279092 -0.936613 +vn 0.220771 -0.053743 -0.973815 +vn 0.127506 -0.138432 -0.982116 +vn 0.113407 -0.511307 -0.851863 +vn 0.227149 -0.144108 -0.963134 +vn 0.409009 0.036103 -0.911802 +vn 0.237739 -0.050966 -0.969970 +vn 0.164403 -0.086123 -0.982604 +vn 0.177252 -0.256172 -0.950224 +vn 0.225257 0.010559 -0.974212 +vn 0.130161 -0.302072 -0.944334 +vn 0.206061 -0.103092 -0.973083 +vn 0.231880 -0.155950 -0.960143 +vn 0.096744 -0.517777 -0.850002 +vn 0.014008 -0.483718 -0.875088 +vn 0.114353 -0.289438 -0.950316 +vn 0.224494 -0.152593 -0.962432 +vn -0.061342 -0.817682 0.572344 +vn 0.033540 -0.711966 -0.701407 +vn 0.053438 -0.467849 -0.882168 +vn 0.184271 -0.154912 -0.970580 +vn 0.214881 -0.220466 -0.951415 +vn 0.034486 -0.385510 -0.922025 +vn 0.137364 -0.290475 -0.946959 +vn 0.117313 -0.077334 -0.990051 +vn 0.258797 -0.178167 -0.949339 +vn 0.250282 -0.125248 -0.960021 +vn 0.003418 -0.125645 -0.992065 +vn 0.138005 -0.004700 -0.990417 +vn -0.073061 -0.432966 -0.898434 +vn 0.079684 -0.315287 -0.945616 +vn 0.215094 -0.183050 -0.959258 +vn 0.511246 -0.859188 0.019807 +vn -0.114811 -0.595965 0.794733 +vn -0.560411 -0.093142 -0.822932 +vn 0.111850 0.017670 -0.993561 +vn -0.003967 -0.485336 -0.874294 +vn 0.135502 -0.243324 -0.960418 +vn 0.431959 -0.891018 0.139378 +vn 0.096316 -0.040498 -0.994507 +vn -0.033387 -0.100040 -0.994415 +vn -0.471633 -0.695395 -0.542161 +vn -0.241096 -0.438093 -0.865963 +vn -0.160527 -0.376751 -0.912259 +vn 0.353160 -0.832392 0.427015 +vn -0.120334 -0.172857 -0.977538 +vn 0.260842 -0.875362 0.407056 +vn 0.110324 -0.991821 0.063906 +vn 0.072604 -0.949675 0.304605 +vn -0.342692 -0.392102 -0.853694 +vn -0.145726 -0.257546 -0.955199 +vn -0.098300 -0.010956 -0.995086 +vn -0.480789 -0.176061 -0.858943 +vn -0.912931 -0.386608 -0.130467 +vn -0.849178 -0.182531 -0.495529 +vn -0.057833 -0.028993 -0.997894 +vn -0.226569 -0.036622 -0.973296 +vn -0.423627 -0.320841 -0.847072 +vn -0.422010 -0.864711 0.272256 +vn -0.347789 -0.198798 -0.916227 +vn -0.289834 -0.065249 -0.954833 +vn -0.288491 0.099704 -0.952269 +vn -0.211615 -0.590075 0.779077 +vn -0.241066 -0.856746 0.455885 +vn 0.020447 -0.999207 0.033784 +vn 0.079318 -0.994781 0.063814 +vn -0.369579 -0.929167 0.000336 +vn -0.543748 -0.768303 -0.337626 +vn 0.097964 -0.988311 0.116703 +vn 0.001953 -0.983490 -0.180792 +vn 0.193579 -0.489731 0.850093 +vn 0.138340 -0.989837 -0.032350 +vn -0.230415 -0.973052 0.003754 +vn 0.045137 -0.963988 0.262032 +vn -0.160863 -0.935972 0.313120 +vn -0.364025 -0.925047 -0.108341 +vn -0.209082 -0.910672 -0.356273 +vn -0.157262 -0.922544 -0.352367 +vn 0.460402 -0.880001 0.116459 +vn -0.665059 -0.705863 0.243721 +vn -0.521897 -0.734764 0.433210 +vn -0.449995 -0.845058 0.288675 +vn -0.269936 -0.942228 0.198309 +vn -0.439802 -0.892026 0.104099 +vn 0.405957 -0.872219 0.272713 +vn -0.018921 -0.998688 0.047487 +vn -0.013764 -0.999878 -0.006806 +vn -0.124210 -0.621204 0.773705 +vn -0.219062 -0.962889 -0.157567 +vn -0.729637 -0.676840 -0.097446 +vn 0.082247 -0.954527 0.286508 +vn 0.077975 -0.949553 0.303720 +vn 0.284249 -0.953246 0.102237 +vn -0.031220 -0.999023 0.030976 +vn -0.425581 -0.876095 0.226508 +vn -0.445326 -0.886044 0.128636 +vn 0.182409 -0.982665 -0.032777 +vn 0.002991 -0.999268 -0.037385 +vn 0.031098 -0.999237 -0.022614 +vn -0.788995 -0.588549 -0.176214 +vn -0.233314 -0.944670 0.230476 +vn -0.515854 -0.836146 0.186224 +vn -0.462539 -0.881039 -0.098880 +vn -0.412671 -0.907926 0.072878 +vn 0.331034 -0.873226 0.357555 +vn 0.042665 -0.998413 0.036134 +vn 0.398480 -0.916776 -0.026093 +vn -0.625416 -0.778954 -0.045198 +vn 0.262001 -0.951353 -0.162053 +vn 0.173589 -0.978332 0.112644 +vn -0.478591 -0.755028 0.448134 +vn 0.359569 -0.905606 0.224769 +vn -0.654378 -0.736686 -0.170446 +vn -0.819788 -0.562700 0.106113 +vn -0.697043 -0.715720 0.043062 +vn -0.642933 -0.724509 -0.248360 +vn -0.372143 -0.921476 -0.111209 +vn 0.068911 -0.997528 -0.013611 +vn 0.181982 -0.980804 -0.069735 +vn -0.473678 -0.880642 -0.007355 +vn -0.052919 -0.992401 0.110813 +vn -0.487228 -0.800012 0.350047 +vn -0.127110 -0.833125 0.538224 +vn -0.386059 -0.831416 0.399548 +vn -0.689993 -0.561174 0.457106 +vn -0.311899 -0.941160 0.130009 +vn 0.020722 -0.996124 0.085208 +vn 0.292306 -0.941496 0.167577 +vn 0.005737 -0.997162 0.074862 +vn -0.284036 -0.955504 0.079440 +vn -0.274087 -0.749809 0.602191 +vn -0.301523 -0.649342 0.698141 +vn -0.376446 -0.901059 0.215247 +vn -0.508927 -0.681143 0.526292 +vn -0.136784 -0.937315 0.320414 +vn 0.296945 -0.899411 0.320719 +vn 0.033204 -0.997162 0.067110 +vn -0.673330 -0.608417 0.419996 +vn -0.520554 -0.816675 -0.248970 +vn -0.705985 -0.627583 0.328104 +vn -0.587237 -0.803705 -0.095767 +vn -0.687857 -0.725791 0.006623 +vn -0.647206 -0.758843 0.072359 +vn -0.089084 -0.859066 0.504013 +vn -0.332377 -0.842311 0.424238 +vn -0.648427 -0.618580 0.443678 +vn -0.579730 -0.749565 0.319376 +vn -0.584643 -0.732505 0.348704 +vn 0.164190 -0.919004 0.358348 +vn -0.338206 -0.908567 -0.245155 +vn -0.456618 -0.888119 -0.051943 +vn -0.592639 -0.667257 0.451094 +vn -0.614734 -0.612903 0.496384 +vn -0.444899 -0.864528 -0.233650 +vn -0.187292 -0.981964 -0.024781 +vn -0.474624 -0.872799 0.113712 +vn -0.427869 -0.898373 -0.098880 +vn -0.317759 -0.947996 0.016205 +vn -0.359416 -0.904904 0.227882 +vn -0.462020 -0.752678 0.468978 +vn -0.038636 -0.999023 0.021271 +vn -0.379101 -0.857265 0.348338 +vn -0.475234 -0.669912 0.570360 +vn -0.494369 -0.534288 0.685629 +vn -0.156499 -0.982574 0.100131 +vn -0.431501 -0.799280 0.418226 +vn 0.130345 -0.991211 -0.021882 +vn -0.030061 -0.997345 -0.066317 +vn -0.012177 -0.999603 -0.025178 +vn -0.271218 -0.940916 0.202643 +vn -0.343608 -0.669820 0.658193 +vn -0.367382 -0.909024 0.196570 +vn -0.237892 -0.971252 0.004273 +vn -0.263924 -0.912931 0.311228 +vn -0.295022 -0.864437 0.406995 +vn -0.319224 -0.792596 0.519456 +vn -0.024781 -0.999146 0.032868 +vn -0.089969 -0.994140 0.059877 +vn -0.232063 -0.756340 0.611591 +vn -0.201483 -0.622150 0.756493 +vn -0.338084 -0.927274 -0.160741 +vn -0.374920 -0.910337 -0.175176 +vn -0.022706 -0.999512 -0.021302 +vn 0.048341 -0.998718 0.014130 +vn 0.148595 -0.988678 0.020447 +vn -0.212317 -0.977050 0.016114 +vn 0.042360 -0.999023 -0.010010 +vn -0.039369 -0.997345 0.060976 +vn -0.111850 -0.992187 0.054903 +vn -0.022156 -0.996490 0.080630 +vn -0.090884 -0.639943 0.763024 +vn 0.470809 -0.872127 0.133000 +vn 0.237800 -0.882473 0.405744 +vn 0.021485 -0.881680 0.471328 +vn 0.236854 -0.755943 0.610248 +vn 0.000641 -0.999603 0.027100 +vn -0.275826 -0.916807 0.288675 +vn 0.229926 -0.893979 0.384594 +vn 0.470565 -0.882321 -0.006287 +vn 0.543229 -0.728874 0.416608 +vn 0.679708 -0.707358 0.193915 +vn -0.206915 -0.565691 0.798212 +vn 0.278695 -0.735405 0.617634 +vn 0.370312 -0.798700 0.474227 +vn 0.398877 -0.881527 0.252541 +vn -0.000305 -0.861080 0.508408 +vn -0.426740 -0.701712 0.570482 +vn -0.021119 -0.995819 0.088717 +vn 0.015503 -0.999603 0.023347 +vn -0.028718 -0.648305 0.760826 +vn 0.078219 -0.993805 0.078555 +vn 0.050813 -0.998413 -0.023743 +vn 0.069765 -0.902799 0.424299 +vn -0.249367 -0.875118 0.414624 +vn -0.379711 -0.912687 0.150914 +usemtl (null) +s 1 +f 1069//1 1647//2 1578//3 +f 1058//4 909//5 939//6 +f 421//7 1176//8 238//9 +f 1055//10 1101//11 1042//12 +f 238//9 1059//13 1126//14 +f 1254//15 30//16 1261//17 +f 1071//18 1//19 1065//20 +f 1037//21 1130//22 1120//23 +f 1570//24 2381//25 1585//26 +f 2434//27 2502//28 2473//29 +f 1632//30 1654//31 1646//32 +f 1144//33 1166//34 669//35 +f 1202//36 1440//37 305//38 +f 1090//39 1//19 1071//18 +f 1555//40 1570//24 1584//41 +f 1184//42 1174//43 404//44 +f 65//45 432//46 12//47 +f 1032//48 1085//49 574//50 +f 1789//51 2207//52 2223//53 +f 1154//54 1118//55 1184//42 +f 1141//56 1086//57 1154//54 +f 99//58 1117//59 342//60 +f 404//44 1174//43 419//61 +f 489//62 2000//63 1998//64 +f 1118//55 1174//43 1184//42 +f 1196//65 403//66 136//67 +f 1495//68 717//69 1490//70 +f 1804//71 402//72 1207//73 +f 2272//74 1398//75 891//76 +f 1100//77 1002//78 804//79 +f 1596//80 1595//81 2381//25 +f 208//82 420//83 1207//73 +f 402//72 208//82 1207//73 +f 1455//84 1935//85 1925//86 +f 1176//8 1059//13 238//9 +f 1150//87 1040//88 348//89 +f 1957//90 1537//91 2051//92 +f 1124//93 1189//94 939//6 +f 1804//71 1207//73 1823//95 +f 1381//96 1300//97 1109//98 +f 383//99 384//100 1182//101 +f 1085//49 1086//57 1141//56 +f 1040//88 1046//102 132//103 +f 220//104 1495//68 1188//105 +f 420//83 261//106 1207//73 +f 261//106 420//83 1065//20 +f 1055//10 1133//107 1101//11 +f 1054//108 421//7 403//66 +f 182//109 1109//98 2//110 +f 1181//111 1207//73 320//112 +f 545//113 1570//24 1561//114 +f 35//115 342//60 432//46 +f 1024//116 574//50 1141//56 +f 432//46 342//60 12//47 +f 1489//117 1081//118 1547//119 +f 1181//111 320//112 1805//120 +f 1516//121 1683//122 1507//123 +f 357//124 1117//59 1047//125 +f 1561//114 1570//24 1555//40 +f 1090//39 1196//65 1206//126 +f 1047//125 1203//127 1051//128 +f 1165//129 202//130 1121//131 +f 1099//132 341//133 301//134 +f 1174//43 240//135 419//61 +f 922//136 921//137 833//138 +f 1121//131 1080//139 385//140 +f 815//141 21//142 1183//143 +f 35//115 99//58 342//60 +f 1083//144 398//145 262//146 +f 106//147 94//148 1317//149 +f 94//148 292//150 1317//149 +f 292//150 95//151 1317//149 +f 940//152 1039//153 1033//154 +f 1300//97 1306//155 433//156 +f 21//142 212//157 471//158 +f 1120//23 1131//159 1037//21 +f 833//138 921//137 688//160 +f 1117//59 357//124 342//60 +f 106//147 271//161 94//148 +f 386//162 227//163 1375//164 +f 1130//22 1044//165 1053//166 +f 419//61 240//135 219//167 +f 1255//168 1244//169 32//170 +f 1557//171 1081//118 1489//117 +f 2062//172 2120//173 2109//174 +f 2034//175 2110//176 430//177 +f 23//178 315//179 1111//180 +f 291//181 94//148 271//161 +f 291//181 292//150 94//148 +f 50//182 386//162 95//151 +f 964//183 734//184 665//185 +f 1616//186 1585//26 1611//187 +f 445//188 1084//189 402//72 +f 574//50 1085//49 1141//56 +f 1654//31 341//133 1653//190 +f 220//104 1188//105 1640//191 +f 342//60 69//192 12//47 +f 417//193 261//106 328//194 +f 292//150 50//182 95//151 +f 204//195 227//163 386//162 +f 50//182 204//195 386//162 +f 1276//196 1471//197 1311//198 +f 1206//126 1196//65 136//67 +f 1033//154 1055//10 1042//12 +f 1037//21 1044//165 1130//22 +f 1180//199 320//112 417//193 +f 1121//131 202//130 1080//139 +f 325//200 203//201 271//161 +f 291//181 76//202 292//150 +f 292//150 237//203 50//182 +f 2159//204 1696//205 1767//206 +f 583//207 929//208 850//209 +f 1584//41 1585//26 1616//186 +f 1495//68 1490//70 1188//105 +f 1557//171 1489//117 1660//210 +f 1078//211 1069//1 1494//212 +f 1972//213 1992//214 1971//215 +f 183//216 1226//217 2000//63 +f 325//200 429//218 203//201 +f 292//150 76//202 237//203 +f 1152//219 227//163 1143//220 +f 1488//221 1412//222 1489//117 +f 1638//223 1646//32 1653//190 +f 1947//224 1869//225 2468//226 +f 203//201 306//227 291//181 +f 306//227 76//202 291//181 +f 237//203 248//228 50//182 +f 204//195 1143//220 227//163 +f 2395//229 14//230 429//218 +f 1502//231 881//232 2500//233 +f 1//19 1090//39 202//130 +f 1652//234 1653//190 1099//132 +f 2117//235 1863//236 2496//237 +f 50//182 248//228 204//195 +f 160//238 792//239 994//240 +f 884//241 888//242 857//243 +f 544//244 2117//235 2496//237 +f 1090//39 1206//126 202//130 +f 2463//245 879//246 2492//247 +f 429//218 306//227 203//201 +f 498//248 188//249 418//250 +f 865//251 884//241 857//243 +f 994//240 998//252 1014//253 +f 884//241 897//254 888//242 +f 1795//255 948//256 1802//257 +f 208//82 1035//258 1071//18 +f 1065//20 1//19 1066//259 +f 377//260 435//261 1377//262 +f 304//263 429//218 14//230 +f 304//263 306//227 429//218 +f 73//264 60//265 74//266 +f 248//228 592//267 204//195 +f 846//268 2264//269 829//270 +f 897//254 912//271 906//272 +f 1004//273 991//274 992//275 +f 1422//276 1421//277 1233//278 +f 980//279 10//280 303//281 +f 1058//4 922//136 909//5 +f 2436//282 2449//283 2418//284 +f 394//285 435//261 377//260 +f 435//261 475//286 446//287 +f 475//286 474//288 446//287 +f 336//289 337//290 361//291 +f 338//292 235//293 372//294 +f 624//295 148//296 129//297 +f 812//298 306//227 596//299 +f 1726//300 992//275 1019//301 +f 945//302 1514//303 1511//304 +f 1069//1 1627//305 1628//306 +f 1812//307 1823//95 1181//111 +f 1165//129 1121//131 169//308 +f 447//309 475//286 435//261 +f 2487//310 2458//311 901//312 +f 42//313 59//314 46//315 +f 401//316 7//317 187//318 +f 1010//319 970//320 797//321 +f 1513//322 220//104 1640//191 +f 2474//323 2491//324 2462//325 +f 594//326 307//327 1014//253 +f 398//145 1513//322 1640//191 +f 307//327 594//326 1026//328 +f 545//113 2381//25 1570//24 +f 403//66 421//7 238//9 +f 445//188 402//72 127//329 +f 1611//187 1631//330 1616//186 +f 1805//120 1180//199 1148//331 +f 394//285 447//309 435//261 +f 2341//332 2413//333 2376//334 +f 75//335 74//266 60//265 +f 541//336 47//337 42//313 +f 47//337 59//314 42//313 +f 541//336 42//313 28//338 +f 917//339 931//340 1103//341 +f 897//254 906//272 883//342 +f 2484//343 2068//344 779//345 +f 888//242 883//342 857//243 +f 261//106 1065//20 328//194 +f 363//346 1307//347 349//348 +f 377//260 363//346 394//285 +f 444//349 747//350 464//351 +f 323//352 338//292 362//353 +f 92//354 116//355 74//266 +f 592//267 634//356 97//357 +f 982//358 1027//359 1004//273 +f 1020//360 982//358 1004//273 +f 1084//189 1054//108 1035//258 +f 208//82 402//72 1084//189 +f 421//7 1119//361 1176//8 +f 1207//73 1181//111 1823//95 +f 1179//362 1187//363 1160//364 +f 263//365 296//366 1343//367 +f 1298//368 296//366 1307//347 +f 1307//347 296//366 349//348 +f 405//369 363//346 349//348 +f 405//369 394//285 363//346 +f 405//369 447//309 394//285 +f 362//353 372//294 384//100 +f 338//292 372//294 362//353 +f 983//370 1004//273 987//371 +f 122//372 134//373 139//374 +f 415//375 440//376 414//377 +f 75//335 92//354 74//266 +f 226//378 186//379 246//380 +f 796//381 787//382 700//383 +f 1119//361 1059//13 1176//8 +f 122//372 114//384 91//385 +f 624//295 129//297 116//355 +f 641//386 558//387 631//388 +f 1311//198 1318//389 1487//390 +f 100//391 1162//392 1170//393 +f 1653//190 341//133 1099//132 +f 1316//394 1983//395 273//396 +f 263//365 277//397 296//366 +f 296//366 358//398 349//348 +f 436//399 447//309 405//369 +f 109//400 554//401 570//402 +f 504//403 1385//404 2501//405 +f 115//406 122//372 91//385 +f 2068//344 2460//407 779//345 +f 43//408 777//409 163//410 +f 378//411 405//369 349//348 +f 358//398 378//411 349//348 +f 448//412 447//309 436//399 +f 448//412 476//413 447//309 +f 78//414 77//415 108//416 +f 75//335 60//265 47//337 +f 1764//417 2481//418 1795//255 +f 717//69 714//419 1512//420 +f 1490//70 717//69 1501//421 +f 238//9 1126//14 168//422 +f 1878//423 1866//424 826//425 +f 2025//426 2360//427 2367//428 +f 251//429 278//430 263//365 +f 278//430 277//397 263//365 +f 277//397 318//431 296//366 +f 296//366 318//431 358//398 +f 318//431 350//432 358//398 +f 378//411 436//399 405//369 +f 384//100 372//294 1182//101 +f 454//433 440//376 415//375 +f 987//371 1004//273 992//275 +f 493//434 476//413 448//412 +f 323//352 788//435 338//292 +f 403//66 238//9 136//67 +f 1565//436 1503//437 1474//438 +f 297//439 277//397 278//430 +f 297//439 318//431 277//397 +f 358//398 350//432 378//411 +f 378//411 388//440 436//399 +f 476//413 493//434 500//441 +f 73//264 105//442 60//265 +f 323//352 337//290 312//443 +f 953//444 1573//445 2358//446 +f 142//447 161//448 119//449 +f 454//433 443//450 440//376 +f 1862//451 1871//452 1405//453 +f 297//439 319//454 318//431 +f 560//455 47//337 541//336 +f 170//456 1323//457 111//458 +f 357//124 1047//125 1050//459 +f 1119//361 98//460 1059//13 +f 1838//461 1877//462 1900//463 +f 2359//464 230//465 251//429 +f 350//432 364//466 378//411 +f 449//467 448//412 436//399 +f 449//467 493//434 448//412 +f 185//468 186//379 226//378 +f 443//450 469//469 479//470 +f 874//471 165//472 2480//473 +f 463//474 444//349 464//351 +f 64//475 105//442 91//385 +f 1182//101 440//376 1129//476 +f 1958//477 1651//478 2502//28 +f 1238//479 2034//175 191//480 +f 251//429 279//481 278//430 +f 278//430 279//481 297//439 +f 364//466 388//440 378//411 +f 483//482 493//434 449//467 +f 134//373 148//296 139//374 +f 244//483 268//484 259//485 +f 910//486 942//487 930//488 +f 105//442 115//406 91//385 +f 24//489 30//16 18//490 +f 1132//491 487//492 1059//13 +f 1869//225 1947//224 2021//493 +f 2497//494 2494//495 2463//245 +f 2359//464 2385//496 230//465 +f 230//465 280//497 251//429 +f 251//429 280//497 279//481 +f 279//481 308//498 297//439 +f 297//439 308//498 319//454 +f 319//454 364//466 318//431 +f 364//466 350//432 318//431 +f 388//440 395//499 436//399 +f 436//399 395//499 449//467 +f 493//434 472//500 500//441 +f 122//372 129//297 134//373 +f 125//501 142//447 124//502 +f 373//503 400//504 393//505 +f 24//489 557//506 30//16 +f 2264//269 2278//507 2251//508 +f 1261//17 30//16 1269//509 +f 1730//510 1862//451 1877//462 +f 252//511 280//497 230//465 +f 343//512 364//466 319//454 +f 364//466 343//512 388//440 +f 63//513 64//475 91//385 +f 399//514 393//505 416//515 +f 416//515 444//349 463//474 +f 162//516 189//517 142//447 +f 768//518 373//503 326//519 +f 189//517 661//520 177//521 +f 189//517 199//522 661//520 +f 847//523 887//524 864//525 +f 533//526 747//350 444//349 +f 1744//527 1022//528 1418//529 +f 1170//393 524//530 729//531 +f 121//532 1342//533 128//534 +f 1236//535 1244//169 26//536 +f 280//497 281//537 279//481 +f 281//537 308//498 279//481 +f 343//512 319//454 308//498 +f 343//512 365//538 388//440 +f 388//440 365//538 395//499 +f 365//538 406//539 395//499 +f 406//539 449//467 395//499 +f 483//482 477//540 493//434 +f 477//540 491//541 472//500 +f 493//434 477//540 472//500 +f 78//414 109//400 77//415 +f 166//542 174//543 196//544 +f 481//545 150//546 814//547 +f 63//513 59//314 64//475 +f 326//519 373//503 393//505 +f 643//548 260//549 43//408 +f 230//465 253//550 252//511 +f 449//467 441//551 483//482 +f 441//551 477//540 483//482 +f 415//375 416//515 463//474 +f 226//378 246//380 245//552 +f 464//351 470//553 454//433 +f 323//352 362//353 337//290 +f 52//554 37//555 1283//556 +f 253//550 281//537 252//511 +f 281//537 280//497 252//511 +f 309//557 308//498 281//537 +f 330//558 343//512 308//498 +f 366//559 365//538 343//512 +f 441//551 449//467 406//539 +f 464//351 814//547 15//560 +f 883//342 906//272 887//524 +f 337//290 362//353 371//561 +f 479//470 498//248 290//562 +f 247//563 746//564 1003//565 +f 25//566 37//555 557//506 +f 640//567 930//488 669//35 +f 2486//568 2499//569 2459//570 +f 309//557 330//558 308//498 +f 343//512 330//558 366//559 +f 441//551 437//571 477//540 +f 290//562 498//248 418//250 +f 124//502 119//449 108//416 +f 77//415 124//502 108//416 +f 589//572 125//501 109//400 +f 570//402 589//572 109//400 +f 125//501 162//516 142//447 +f 1045//573 433//156 1034//574 +f 1207//73 261//106 320//112 +f 2004//575 2474//323 2495//576 +f 1215//577 1228//578 2285//579 +f 365//538 396//580 406//539 +f 396//580 422//581 406//539 +f 422//581 437//571 441//551 +f 406//539 422//581 441//551 +f 59//314 47//337 60//265 +f 51//582 78//414 66//583 +f 361//291 371//561 383//99 +f 196//544 215//584 214//585 +f 463//474 454//433 415//375 +f 27//586 41//587 535//588 +f 53//589 1283//556 37//555 +f 84//590 1299//591 1283//556 +f 1805//120 320//112 1180//199 +f 254//592 253//550 222//593 +f 254//592 281//537 253//550 +f 309//557 366//559 330//558 +f 396//580 365//538 366//559 +f 456//594 477//540 437//571 +f 484//595 491//541 477//540 +f 2480//473 2485//596 2493//597 +f 418//250 188//249 187//318 +f 53//589 85//598 1283//556 +f 85//598 84//590 1283//556 +f 420//83 1071//18 1065//20 +f 264//599 281//537 254//592 +f 298//600 309//557 281//537 +f 368//601 366//559 367//602 +f 368//601 396//580 366//559 +f 1639//603 1564//604 1139//605 +f 560//455 48//606 47//337 +f 82//607 471//158 212//157 +f 25//566 38//608 37//555 +f 202//130 1206//126 1080//139 +f 264//599 298//600 281//537 +f 298//600 331//609 309//557 +f 309//557 331//609 366//559 +f 331//609 367//602 366//559 +f 396//580 368//601 422//581 +f 422//581 456//594 437//571 +f 491//541 1192//610 313//611 +f 1699//612 2064//613 1710//614 +f 462//615 443//450 479//470 +f 371//561 362//353 384//100 +f 2502//28 2476//616 2464//617 +f 371//561 384//100 383//99 +f 21//142 732//618 212//157 +f 1571//619 1629//620 1627//305 +f 38//608 39//621 53//589 +f 37//555 38//608 53//589 +f 39//621 85//598 53//589 +f 1173//622 1184//42 404//44 +f 1006//623 2142//624 1674//625 +f 201//626 255//627 254//592 +f 255//627 264//599 254//592 +f 368//601 407//628 422//581 +f 450//629 456//594 422//581 +f 450//629 484//595 456//594 +f 456//594 484//595 477//540 +f 314//630 1192//610 491//541 +f 2027//631 2501//405 2489//632 +f 2475//633 2471//634 2488//635 +f 551//636 492//637 732//618 +f 464//351 481//545 814//547 +f 1081//118 1494//212 1547//119 +f 201//626 231//638 255//627 +f 407//628 450//629 422//581 +f 484//595 494//639 491//541 +f 494//639 327//640 491//541 +f 327//640 314//630 491//541 +f 876//641 797//321 995//642 +f 847//523 856//643 829//270 +f 125//501 143//644 162//516 +f 134//373 129//297 148//296 +f 1564//604 1571//619 1627//305 +f 417//193 320//112 261//106 +f 328//194 1065//20 1066//259 +f 170//456 156//645 201//626 +f 156//645 231//638 201//626 +f 231//638 282//646 255//627 +f 282//646 264//599 255//627 +f 450//629 485//647 484//595 +f 484//595 485//647 494//639 +f 2463//245 2486//568 2479//648 +f 159//649 185//468 167//650 +f 492//637 68//651 212//157 +f 732//618 492//637 212//157 +f 68//651 82//607 212//157 +f 1311//198 1471//197 1296//652 +f 101//653 156//645 111//458 +f 332//654 264//599 282//646 +f 332//654 298//600 264//599 +f 332//654 331//609 298//600 +f 331//609 332//654 367//602 +f 407//628 423//655 450//629 +f 450//629 423//655 485//647 +f 804//79 1002//78 1443//656 +f 2484//343 779//345 946//657 +f 689//658 443//450 462//615 +f 440//376 689//658 1129//476 +f 166//542 167//650 174//543 +f 38//608 31//659 39//621 +f 112//660 145//661 101//653 +f 101//653 145//661 156//645 +f 156//645 256//662 231//638 +f 332//654 423//655 368//601 +f 367//602 332//654 368//601 +f 368//601 423//655 407//628 +f 946//657 779//345 920//663 +f 1432//664 1261//17 1449//665 +f 461//666 478//667 453//668 +f 464//351 15//560 470//553 +f 31//659 54//669 39//621 +f 39//621 54//669 85//598 +f 86//670 101//653 85//598 +f 145//661 210//671 156//645 +f 282//646 283//672 332//654 +f 283//672 369//673 332//654 +f 369//673 423//655 332//654 +f 423//655 408//674 485//647 +f 854//675 876//641 965//676 +f 78//414 108//416 66//583 +f 440//376 443//450 689//658 +f 374//677 2465//678 961//679 +f 929//208 519//680 979//681 +f 54//669 86//670 85//598 +f 156//645 241//682 256//662 +f 256//662 282//646 231//638 +f 256//662 283//672 282//646 +f 389//683 423//655 369//673 +f 389//683 408//674 423//655 +f 408//674 457//684 485//647 +f 457//684 49//685 485//647 +f 485//647 49//685 494//639 +f 494//639 135//686 327//640 +f 175//687 83//688 314//630 +f 1167//689 1140//690 1483//691 +f 196//544 174//543 215//584 +f 697//692 16//693 68//651 +f 1038//694 82//607 16//693 +f 140//695 117//696 141//697 +f 1654//31 1653//190 1646//32 +f 1234//698 54//669 31//659 +f 86//670 112//660 101//653 +f 210//671 241//682 156//645 +f 923//699 917//339 911//700 +f 697//692 34//701 16//693 +f 145//661 193//702 210//671 +f 256//662 265//703 283//672 +f 265//703 310//704 283//672 +f 283//672 310//704 369//673 +f 310//704 344//705 369//673 +f 344//705 370//706 369//673 +f 370//706 389//683 369//673 +f 409//707 408//674 389//683 +f 409//707 466//708 408//674 +f 466//708 457//684 408//674 +f 466//708 49//685 457//684 +f 49//685 135//686 494//639 +f 174//543 225//709 215//584 +f 1014//253 766//710 602//711 +f 826//425 2220//712 2215//713 +f 1078//211 1494//212 1081//118 +f 1273//714 70//715 86//670 +f 120//716 112//660 86//670 +f 146//717 145//661 112//660 +f 146//717 193//702 145//661 +f 265//703 256//662 241//682 +f 223//718 265//703 241//682 +f 486//719 49//685 466//708 +f 175//687 327//640 135//686 +f 105//442 122//372 115//406 +f 480//720 15//560 681//721 +f 225//709 234//722 215//584 +f 731//723 34//701 697//692 +f 86//670 54//669 1273//714 +f 70//715 120//716 86//670 +f 193//702 241//682 210//671 +f 299//724 310//704 265//703 +f 310//704 333//725 344//705 +f 344//705 351//726 370//706 +f 424//727 466//708 409//707 +f 135//686 49//685 175//687 +f 214//585 215//584 234//722 +f 48//606 75//335 47//337 +f 34//701 9//728 1038//694 +f 16//693 34//701 1038//694 +f 203//201 291//181 271//161 +f 9//728 558//387 754//729 +f 1195//730 397//731 1120//23 +f 120//716 146//717 112//660 +f 146//717 194//732 193//702 +f 266//733 265//703 223//718 +f 266//733 299//724 265//703 +f 299//724 333//725 310//704 +f 333//725 351//726 344//705 +f 382//734 383//99 392//735 +f 399//514 416//515 415//375 +f 266//733 333//725 299//724 +f 351//726 352//736 370//706 +f 424//727 486//719 466//708 +f 487//492 175//687 49//685 +f 7//317 117//696 187//318 +f 1182//101 414//377 440//376 +f 41//587 42//313 46//315 +f 290//562 289//737 497//738 +f 2502//28 2464//617 2473//29 +f 372//294 399//514 414//377 +f 1570//24 1585//26 1584//41 +f 1066//259 1//19 1165//129 +f 1//19 202//130 1165//129 +f 120//716 70//715 102//739 +f 157//740 146//717 120//716 +f 194//732 223//718 193//702 +f 223//718 241//682 193//702 +f 352//736 379//741 370//706 +f 370//706 379//741 389//683 +f 410//742 409//707 389//683 +f 2478//743 1409//744 1958//477 +f 806//745 945//302 1002//78 +f 157//740 194//732 146//717 +f 267//746 266//733 223//718 +f 267//746 333//725 266//733 +f 379//741 410//742 389//683 +f 410//742 438//747 409//707 +f 438//747 424//727 409//707 +f 190//748 205//749 143//644 +f 337//290 371//561 361//291 +f 2215//713 830//750 826//425 +f 1631//330 1646//32 1638//223 +f 102//739 157//740 120//716 +f 157//740 195//751 194//732 +f 195//751 223//718 194//732 +f 195//751 211//752 223//718 +f 223//718 211//752 267//746 +f 267//746 300//753 333//725 +f 300//753 334//754 351//726 +f 333//725 300//753 351//726 +f 351//726 334//754 352//736 +f 410//742 411//755 438//747 +f 438//747 486//719 424//727 +f 487//492 49//685 486//719 +f 875//756 594//326 989//757 +f 108//416 581//758 66//583 +f 225//709 245//552 244//483 +f 312//443 336//289 335//759 +f 151//760 754//729 107//761 +f 274//762 1386//763 300//753 +f 352//736 334//754 379//741 +f 923//699 1729//764 1096//765 +f 244//483 245//552 268//484 +f 463//474 464//351 454//433 +f 414//377 399//514 415//375 +f 15//560 480//720 470//553 +f 1647//2 1069//1 1078//211 +f 909//5 922//136 833//138 +f 387//766 417//193 328//194 +f 133//767 157//740 102//739 +f 1314//768 133//767 102//739 +f 133//767 195//751 157//740 +f 1148//331 1179//362 1160//364 +f 1046//102 1167//689 182//109 +f 379//741 411//755 410//742 +f 792//239 339//769 229//770 +f 391//771 7//317 668//772 +f 185//468 226//378 174//543 +f 461//666 290//562 497//738 +f 2027//631 504//403 2501//405 +f 1196//65 1054//108 403//66 +f 728//773 1019//301 752//774 +f 2459//570 2483//775 2461//776 +f 1291//777 1264//778 55//779 +f 133//767 1356//780 195//751 +f 195//751 1356//780 211//752 +f 412//781 438//747 411//755 +f 4//782 486//719 438//747 +f 458//783 4//782 438//747 +f 4//782 487//492 486//719 +f 1720//784 1572//785 1771//786 +f 245//552 275//787 268//484 +f 1869//225 2021//493 2059//788 +f 235//293 399//514 372//294 +f 64//475 60//265 105//442 +f 836//789 2492//247 879//246 +f 1315//790 133//767 1314//768 +f 1331//791 1382//792 1356//780 +f 1310//793 926//794 1128//795 +f 7//317 1121//131 117//696 +f 119//449 161//448 611//796 +f 380//797 379//741 334//754 +f 379//741 380//797 411//755 +f 467//798 4//782 458//783 +f 495//799 487//492 4//782 +f 495//799 1126//14 487//492 +f 416//515 400//504 533//526 +f 479//470 469//469 498//248 +f 74//266 116//355 73//264 +f 478//667 461//666 497//738 +f 393//505 400//504 416//515 +f 61//800 1291//777 55//779 +f 505//801 1999//802 2474//323 +f 1999//802 2491//324 2474//323 +f 199//522 189//517 36//803 +f 1164//804 1165//129 169//308 +f 1179//362 387//766 249//805 +f 390//806 411//755 380//797 +f 411//755 390//806 412//781 +f 458//783 438//747 412//781 +f 495//799 168//422 1126//14 +f 480//720 469//469 470//553 +f 116//355 122//372 105//442 +f 418//250 187//318 140//695 +f 185//468 174//543 167//650 +f 166//542 148//296 167//650 +f 470//553 469//469 443//450 +f 40//807 55//779 32//170 +f 61//800 71//808 1291//777 +f 71//808 103//809 1291//777 +f 1184//42 1173//622 1154//54 +f 634//356 514//810 97//357 +f 425//811 458//783 412//781 +f 917//339 923//699 931//340 +f 2472//812 2489//632 853//813 +f 754//729 641//386 567//814 +f 44//815 567//814 1163//816 +f 454//433 470//553 443//450 +f 40//807 32//170 1249//817 +f 33//818 40//807 1249//817 +f 56//819 55//779 40//807 +f 56//819 61//800 55//779 +f 451//820 1265//821 439//822 +f 1180//199 417//193 1179//362 +f 1099//132 301//134 1077//823 +f 1189//94 1058//4 939//6 +f 1059//13 221//824 1132//491 +f 598//825 1074//826 1075//827 +f 412//781 426//828 425//811 +f 650//829 186//379 185//468 +f 234//722 244//483 259//485 +f 226//378 245//552 225//709 +f 1033//154 1042//12 1030//830 +f 2492//247 836//789 247//563 +f 7//317 169//308 1121//131 +f 1462//831 1322//832 1482//833 +f 425//811 467//798 458//783 +f 496//834 4//782 467//798 +f 1751//835 2468//226 2480//473 +f 290//562 418//250 140//695 +f 326//519 789//836 762//837 +f 142//447 177//521 161//448 +f 165//472 1751//835 2480//473 +f 87//838 103//809 71//808 +f 103//809 87//838 104//839 +f 1180//199 1179//362 1148//331 +f 417//193 387//766 1179//362 +f 2081//840 2060//841 2031//842 +f 1154//54 1173//622 1141//56 +f 181//843 131//844 197//845 +f 442//846 425//811 426//828 +f 614//847 144//848 143//644 +f 876//641 1010//319 797//321 +f 40//807 45//849 56//819 +f 56//819 45//849 61//800 +f 87//838 71//808 61//800 +f 1563//850 1437//851 1590//852 +f 1121//131 385//140 117//696 +f 1148//331 1160//364 1137//853 +f 1449//665 1459//854 1439//855 +f 1028//856 2462//325 929//208 +f 442//846 459//857 425//811 +f 459//857 467//798 425//811 +f 168//422 495//799 4//782 +f 496//834 168//422 4//782 +f 1763//858 1403//859 1444//860 +f 140//695 187//318 117//696 +f 244//483 234//722 225//709 +f 246//380 740//861 269//862 +f 372//294 414//377 1182//101 +f 40//807 547//863 45//849 +f 45//849 62//864 61//800 +f 62//864 87//838 61//800 +f 87//838 88//865 104//839 +f 1084//189 517//866 1054//108 +f 387//766 328//194 1064//867 +f 2467//868 2497//494 2485//596 +f 286//869 1363//870 302//871 +f 205//749 189//517 162//516 +f 290//562 140//695 289//737 +f 214//585 234//722 224//872 +f 393//505 399//514 809//873 +f 315//179 1131//159 397//731 +f 302//871 321//874 353//875 +f 1164//804 169//308 391//771 +f 427//876 459//857 442//846 +f 217//877 496//834 467//798 +f 217//877 168//422 496//834 +f 978//878 969//879 2074//880 +f 361//291 383//99 382//734 +f 269//862 276//881 245//552 +f 1440//37 11//882 305//38 +f 62//864 88//865 87//838 +f 328//194 1066//259 1064//867 +f 1066//259 1165//129 1164//804 +f 242//883 287//884 302//871 +f 1363//870 242//883 302//871 +f 287//884 321//874 302//871 +f 1179//362 249//805 1187//363 +f 983//370 1020//360 1004//273 +f 464//351 747//350 481//545 +f 788//435 323//352 276//881 +f 269//862 245//552 246//380 +f 88//865 89//885 1325//886 +f 171//887 172//888 242//883 +f 360//889 353//875 321//874 +f 360//889 1354//890 353//875 +f 1057//891 1064//867 1164//804 +f 2184//892 2188//893 2183//894 +f 460//895 459//857 451//820 +f 460//895 467//798 459//857 +f 149//896 168//422 217//877 +f 149//896 136//67 168//422 +f 116//355 129//297 122//372 +f 109//400 124//502 77//415 +f 159//649 167//650 148//296 +f 28//338 42//313 41//587 +f 57//897 88//865 62//864 +f 45//849 57//897 62//864 +f 1336//898 1325//886 89//885 +f 89//885 72//899 1336//898 +f 147//900 172//888 171//887 +f 172//888 258//901 242//883 +f 258//901 257//902 242//883 +f 257//902 287//884 242//883 +f 257//902 321//874 287//884 +f 345//903 360//889 321//874 +f 360//889 381//904 1354//890 +f 1069//1 938//905 1655//906 +f 387//766 473//907 249//805 +f 270//908 217//877 467//798 +f 130//909 136//67 149//896 +f 851//910 847//523 829//270 +f 983//370 987//371 975//911 +f 189//517 177//521 142//447 +f 88//865 72//899 89//885 +f 184//912 258//901 172//888 +f 257//902 288//913 321//874 +f 1265//821 451//820 459//857 +f 270//908 149//896 217//877 +f 226//378 225//709 174//543 +f 27//586 28//338 41//587 +f 109//400 125//501 124//502 +f 547//863 57//897 45//849 +f 57//897 58//914 88//865 +f 88//865 58//914 72//899 +f 2476//616 2484//343 2458//311 +f 147//900 184//912 172//888 +f 184//912 213//915 258//901 +f 258//901 243//916 257//902 +f 243//916 288//913 257//902 +f 345//903 321//874 288//913 +f 391//771 169//308 7//317 +f 468//917 460//895 451//820 +f 468//917 488//918 460//895 +f 270//908 467//798 460//895 +f 488//918 270//908 460//895 +f 1206//126 136//67 130//909 +f 481//545 793//919 150//546 +f 143//644 205//749 162//516 +f 142//447 119//449 124//502 +f 58//914 90//920 72//899 +f 90//920 128//534 72//899 +f 147//900 173//921 184//912 +f 173//921 213//915 184//912 +f 213//915 233//922 258//901 +f 258//901 233//922 243//916 +f 354//923 360//889 345//903 +f 354//923 381//904 360//889 +f 1026//328 991//274 307//327 +f 268//484 312//443 259//485 +f 1206//126 130//909 1080//139 +f 116//355 105//442 73//264 +f 139//374 148//296 166//542 +f 275//787 312//443 268//484 +f 188//249 401//316 187//318 +f 2479//648 2459//570 2461//776 +f 58//914 63//513 90//920 +f 1064//867 1066//259 1164//804 +f 1064//867 473//907 387//766 +f 288//913 311//924 345//903 +f 311//924 354//923 345//903 +f 996//925 994//240 307//327 +f 452//926 468//917 439//822 +f 452//926 478//667 468//917 +f 478//667 488//918 468//917 +f 141//697 130//909 149//896 +f 1564//604 1639//603 1563//850 +f 547//863 41//587 57//897 +f 2081//840 2107//927 2060//841 +f 382//734 381//904 354//923 +f 497//738 270//908 488//918 +f 289//737 149//896 270//908 +f 289//737 141//697 149//896 +f 114//384 122//372 139//374 +f 59//314 60//265 64//475 +f 275//787 323//352 312//443 +f 401//316 668//772 7//317 +f 41//587 46//315 57//897 +f 57//897 46//315 58//914 +f 1459//854 1345//928 1269//509 +f 1342//533 121//532 158//929 +f 166//542 173//921 158//929 +f 213//915 224//872 233//922 +f 233//922 259//485 243//916 +f 243//916 322//930 288//913 +f 322//930 311//924 288//913 +f 453//668 478//667 452//926 +f 497//738 289//737 270//908 +f 912//271 911//700 906//272 +f 276//881 323//352 275//787 +f 276//881 275//787 245//552 +f 46//315 63//513 58//914 +f 90//920 121//532 128//534 +f 173//921 214//585 213//915 +f 213//915 214//585 224//872 +f 259//485 322//930 243//916 +f 336//289 311//924 322//930 +f 336//289 354//923 311//924 +f 361//291 382//734 354//923 +f 1043//931 439//822 1290//932 +f 497//738 488//918 478//667 +f 385//140 130//909 141//697 +f 385//140 1080//139 130//909 +f 144//848 190//748 143//644 +f 535//588 41//587 547//863 +f 121//532 166//542 158//929 +f 335//759 336//289 322//930 +f 354//923 336//289 361//291 +f 2004//575 2481//418 1764//417 +f 698//933 439//822 1043//931 +f 289//737 140//695 141//697 +f 923//699 1096//765 931//340 +f 650//829 185//468 159//649 +f 46//315 59//314 63//513 +f 63//513 91//385 90//920 +f 90//920 114//384 121//532 +f 121//532 139//374 166//542 +f 173//921 196//544 214//585 +f 259//485 335//759 322//930 +f 2478//743 2502//28 2434//27 +f 312//443 337//290 336//289 +f 90//920 91//385 114//384 +f 114//384 139//374 121//532 +f 166//542 196//544 173//921 +f 224//872 234//722 233//922 +f 234//722 259//485 233//922 +f 259//485 312//443 335//759 +f 1124//93 916//934 1189//94 +f 542//935 541//336 530//936 +f 462//615 479//470 290//562 +f 269//862 783//937 276//881 +f 813//938 567//814 641//386 +f 276//881 783//937 788//435 +f 82//607 1038//694 1333//939 +f 816//940 701//941 703//942 +f 672//943 137//944 603//945 +f 625//946 635//947 624//295 +f 2457//948 2439//949 1973//950 +f 767//951 533//526 529//952 +f 2468//226 1869//225 2480//473 +f 662//953 190//748 639//954 +f 711//955 720//956 719//957 +f 630//958 639//954 614//847 +f 161//448 654//959 638//960 +f 781//961 991//274 982//358 +f 1227//962 31//659 516//963 +f 648//964 639//954 630//958 +f 630//958 614//847 590//965 +f 2098//966 544//244 1899//967 +f 578//968 579//969 586//970 +f 697//692 492//637 551//636 +f 529//952 533//526 400//504 +f 869//971 859//972 870//973 +f 1732//974 924//975 914//976 +f 1004//273 1027//359 991//274 +f 801//977 591//978 603//945 +f 636//979 676//980 651//981 +f 876//641 949//982 965//676 +f 2207//52 1789//51 1859//983 +f 76//202 739//984 237//203 +f 188//249 681//721 15//560 +f 578//968 604//985 599//986 +f 797//321 616//987 995//642 +f 510//988 2035//989 1365//990 +f 76//202 812//298 617//991 +f 617//991 739//984 76//202 +f 1468//992 93//993 1765//994 +f 596//299 546//995 812//298 +f 1457//996 1305//997 1477//998 +f 760//999 197//845 150//546 +f 671//1000 773//1001 765//1002 +f 586//970 609//1003 604//985 +f 591//978 700//383 632//1004 +f 476//413 2312//1005 474//288 +f 2084//1006 2027//631 2489//632 +f 582//1007 590//965 571//1008 +f 1555//40 2449//283 1996//1009 +f 674//1010 546//995 596//299 +f 812//298 655//1011 617//991 +f 161//448 177//521 661//520 +f 599//986 604//985 636//979 +f 700//383 787//382 576//1012 +f 776//1013 675//1014 572//1015 +f 776//1013 674//1010 675//1014 +f 617//991 634//356 739//984 +f 591//978 632//1004 649//1016 +f 612//1017 546//995 674//1010 +f 617//991 655//1011 634//356 +f 728//773 752//774 706//1018 +f 571//1008 2311//1019 2305//1020 +f 775//1021 674//1010 776//1013 +f 775//1021 612//1017 674//1010 +f 612//1017 628//1022 546//995 +f 546//995 628//1022 812//298 +f 812//298 628//1022 655//1011 +f 620//1023 630//958 615//1024 +f 620//1023 648//964 630//958 +f 667//1025 653//1026 646//1027 +f 810//1028 782//1029 785//1030 +f 150//546 197//845 814//547 +f 534//1031 1517//1032 2000//63 +f 702//1033 572//1015 2378//1034 +f 748//1035 776//1013 572//1015 +f 655//1011 613//1036 634//356 +f 911//700 917//339 905//1037 +f 648//964 679//1038 662//953 +f 727//1039 771//1040 713//1041 +f 750//1042 807//1043 799//1044 +f 639//954 190//748 144//848 +f 662//953 679//1038 200//1045 +f 702//1033 748//1035 572//1015 +f 775//1021 776//1013 748//1035 +f 628//1022 718//1046 655//1011 +f 626//1047 658//1048 645//1049 +f 791//1050 778//1051 790//1052 +f 612//1017 811//1053 628//1022 +f 613//1036 514//810 634//356 +f 1380//1054 1756//1055 1673//1056 +f 570//402 590//965 614//847 +f 720//956 741//1057 719//957 +f 1074//826 795//1058 835//1059 +f 614//847 639//954 144//848 +f 612//1017 775//1021 811//1053 +f 718//1046 735//1060 655//1011 +f 655//1011 735//1060 613//1036 +f 798//1061 338//292 788//435 +f 636//979 652//1062 676//980 +f 571//1008 590//965 555//1063 +f 528//1064 730//1065 687//1066 +f 690//1067 702//1033 2312//1005 +f 476//413 690//1067 2312//1005 +f 811//1053 718//1046 628//1022 +f 721//1068 778//1051 727//1039 +f 748//1035 702//1033 690//1067 +f 735//1060 686//1069 613//1036 +f 1517//1032 2002//1070 2127//1071 +f 654//959 685//1072 667//1025 +f 569//1073 588//1074 606//1075 +f 513//1076 531//1077 538//1078 +f 538//1078 549//1079 548//1080 +f 549//1079 553//1081 548//1080 +f 550//1082 588//1074 549//1079 +f 1903//1083 869//971 870//973 +f 691//1084 775//1021 748//1035 +f 691//1084 600//1085 775//1021 +f 600//1085 811//1053 775//1021 +f 811//1053 563//1086 718//1046 +f 563//1086 736//1087 718//1046 +f 718//1046 736//1087 735//1060 +f 736//1087 647//1088 735//1060 +f 735//1060 647//1088 686//1069 +f 686//1069 745//1089 613//1036 +f 745//1089 514//810 613//1036 +f 569//1073 606//1075 605//1090 +f 654//959 667//1025 638//960 +f 851//910 857//243 847//523 +f 588//1074 569//1073 549//1079 +f 690//1067 691//1084 748//1035 +f 680//1091 514//810 745//1089 +f 2127//1071 2002//1070 2094//1092 +f 747//350 701//941 481//545 +f 400//504 373//503 529//952 +f 600//1085 536//1093 811//1053 +f 536//1093 563//1086 811//1053 +f 1306//155 227//163 1152//219 +f 522//1094 24//489 18//490 +f 523//1095 24//489 522//1094 +f 865//251 857//243 851//910 +f 2031//842 2060//841 1540//1096 +f 767//951 701//941 747//350 +f 618//1097 652//1062 609//1003 +f 652//1062 636//979 609//1003 +f 573//1098 22//1099 710//1100 +f 642//1101 699//1102 730//1065 +f 1522//1103 1518//1104 2476//616 +f 500//441 629//1105 691//1084 +f 690//1067 500//441 691//1084 +f 691//1084 629//1105 600//1085 +f 780//1106 644//1107 641//386 +f 579//969 578//968 561//1108 +f 131//844 668//772 197//845 +f 197//845 668//772 814//547 +f 789//836 809//873 798//1061 +f 622//1109 760//999 150//546 +f 621//1110 563//1086 536//1093 +f 673//1111 745//1089 686//1069 +f 673//1111 818//1112 745//1089 +f 818//1112 680//1091 745//1089 +f 680//1091 96//1113 514//810 +f 2495//576 2462//325 1028//856 +f 1028//856 583//207 575//1114 +f 663//1115 794//1116 664//1117 +f 629//1105 761//1118 600//1085 +f 761//1118 757//1119 600//1085 +f 600//1085 757//1119 536//1093 +f 621//1110 696//1120 563//1086 +f 755//1121 736//1087 563//1086 +f 696//1120 755//1121 563//1086 +f 633//1122 736//1087 755//1121 +f 633//1122 647//1088 736//1087 +f 623//1123 686//1069 647//1088 +f 633//1122 623//1123 647//1088 +f 686//1069 623//1123 673//1111 +f 819//1124 680//1091 818//1112 +f 680//1091 819//1124 96//1113 +f 1729//764 1677//1125 1096//765 +f 2482//1126 1899//967 2471//634 +f 537//1127 536//1093 757//1119 +f 536//1093 537//1127 621//1110 +f 673//1111 819//1124 818//1112 +f 2428//1128 222//593 230//465 +f 25//566 24//489 523//1095 +f 25//566 557//506 24//489 +f 38//608 25//566 19//1129 +f 710//1100 22//1099 272//1130 +f 663//1115 759//1131 794//1116 +f 1120//23 878//1132 1195//730 +f 537//1127 696//1120 621//1110 +f 696//1120 633//1122 755//1121 +f 822//1133 2215//713 2220//712 +f 97//357 96//1113 1053//166 +f 750//1042 784//1134 743//1135 +f 887//524 905//1037 864//525 +f 768//518 784//1134 373//503 +f 512//1136 513//1076 548//1080 +f 573//1098 664//1117 22//1099 +f 696//1120 715//1137 633//1122 +f 673//1111 521//1138 819//1124 +f 2454//1139 2453//1140 2445//1141 +f 883//342 887//524 847//523 +f 306//227 812//298 76//202 +f 642//1101 528//1064 759//1131 +f 798//1061 809//873 235//293 +f 994//240 792//239 998//252 +f 587//1142 626//1047 586//970 +f 1900//463 1918//1143 1937//1144 +f 645//1049 652//1062 618//1097 +f 537//1127 786//1145 696//1120 +f 521//1138 593//1146 819//1124 +f 515//1147 19//1129 523//1095 +f 741//1057 749//1148 719//957 +f 789//836 326//519 809//873 +f 539//1149 581//758 550//1082 +f 657//1150 777//409 723//1151 +f 684//1152 713//1041 660//1153 +f 692//1154 712//1155 720//956 +f 652//1062 666//1156 692//1154 +f 507//1157 761//1118 629//1105 +f 472//500 507//1157 629//1105 +f 507//1157 757//1119 761//1118 +f 623//1123 633//1122 673//1111 +f 724//1158 521//1138 673//1111 +f 515//1147 516//963 19//1129 +f 304//263 675//1014 674//1010 +f 178//1159 778//1051 721//1068 +f 947//1160 1447//1161 2358//446 +f 626//1047 645//1049 618//1097 +f 586//970 626//1047 618//1097 +f 784//1134 768//518 742//1162 +f 753//1163 537//1127 757//1119 +f 537//1127 753//1163 786//1145 +f 724//1158 981//1164 521//1138 +f 521//1138 981//1164 593//1146 +f 979//681 559//1165 850//209 +f 637//1166 660//1153 677//1167 +f 787//382 631//388 576//1012 +f 141//697 117//696 385//140 +f 809//873 399//514 235//293 +f 641//386 754//729 558//387 +f 542//935 553//1081 561//1108 +f 742//1162 768//518 762//837 +f 444//349 416//515 533//526 +f 528//1064 687//1066 796//381 +f 813//938 598//825 566//1168 +f 1490//70 1501//421 1557//171 +f 753//1163 757//1119 507//1157 +f 786//1145 715//1137 696//1120 +f 633//1122 724//1158 673//1111 +f 2090//1169 2062//172 2109//174 +f 646//1027 653//1026 660//1153 +f 660//1153 694//1170 683//1171 +f 677//1167 660//1153 683//1171 +f 1872//1172 839//1173 838//1174 +f 1224//1175 18//490 30//16 +f 326//519 393//505 809//873 +f 799//1044 529//952 373//503 +f 313//611 507//1157 472//500 +f 715//1137 774//1176 633//1122 +f 974//1177 699//1102 841//1178 +f 703//942 820//1179 816//940 +f 692//1154 711//955 676//980 +f 1014//253 355//1180 766//710 +f 875//756 752//774 1019//301 +f 627//1181 646//1027 660//1153 +f 711//955 692//1154 720//956 +f 652//1062 692//1154 676//980 +f 799//1044 373//503 784//1134 +f 813//938 566//1168 567//814 +f 2462//325 2482//1126 2475//633 +f 764//1182 644//1107 780//1106 +f 1479//1183 1924//1184 1916//1185 +f 753//1163 738//1186 786//1145 +f 738//1186 607//1187 786//1145 +f 786//1145 607//1187 715//1137 +f 715//1137 524//530 774//1176 +f 633//1122 774//1176 724//1158 +f 559//1165 979//681 672//943 +f 758//1188 798//1061 783//937 +f 683//1171 694//1170 705//1189 +f 820//1179 703//942 562//1190 +f 764//1182 687//1066 644//1107 +f 744//1191 743//1135 725//1192 +f 313//611 753//1163 507//1157 +f 607//1187 524//530 715//1137 +f 664//1117 801//977 22//1099 +f 646//1027 627//1181 610//1193 +f 800//1194 820//1179 562//1190 +f 750//1042 769//1195 807//1043 +f 767//951 747//350 533//526 +f 578//968 586//970 604//985 +f 862//1196 593//1146 981//1164 +f 688//160 2382//1197 1083//144 +f 306//227 304//263 674//1010 +f 738//1186 584//1198 607//1187 +f 168//422 136//67 238//9 +f 773//1001 552//1199 765//1002 +f 2473//29 2464//617 2458//311 +f 773//1001 793//919 552//1199 +f 626//1047 619//1200 658//1048 +f 1007//1201 1139//605 1013//1202 +f 562//1190 529//952 799//1044 +f 744//1191 750//1042 743//1135 +f 659//1203 683//1171 693//1204 +f 677//1167 683//1171 659//1203 +f 313//611 737//1205 753//1163 +f 753//1163 737//1205 738//1186 +f 607//1187 729//531 524//530 +f 27//586 518//1206 28//338 +f 553//1081 569//1073 580//1207 +f 657//1150 163//410 777//409 +f 580//1207 569//1073 605//1090 +f 789//836 798//1061 758//1188 +f 769//1195 562//1190 807//1043 +f 820//1179 671//1000 816//940 +f 638//960 646//1027 611//796 +f 1074//826 598//825 644//1107 +f 750//1042 799//1044 784//1134 +f 1931//1208 907//1209 898//1210 +f 2483//775 2487//310 2461//776 +f 737//1205 584//1198 738//1186 +f 1439//855 1438//1211 1431//1212 +f 2098//966 1213//1213 544//244 +f 48//606 578//968 75//335 +f 796//381 631//388 787//382 +f 815//141 732//618 21//142 +f 581//758 588//1074 550//1082 +f 625//946 636//979 651//981 +f 778//1051 1011//1214 810//1028 +f 693//1204 705//1189 725//1192 +f 693//1204 683//1171 705//1189 +f 236//1215 1921//1216 1966//1217 +f 584//1198 729//531 607//1187 +f 2237//1218 1866//424 2227//1219 +f 530//936 541//336 28//338 +f 237//203 739//984 248//228 +f 512//1136 530//936 28//338 +f 727//1039 778//1051 771//1040 +f 684//1152 727//1039 713//1041 +f 2237//1218 2220//712 826//425 +f 542//935 561//1108 560//455 +f 528//1064 796//381 700//383 +f 808//1220 785//1030 671//1000 +f 739//984 592//267 248//228 +f 895//1221 905//1037 896//1222 +f 740//861 246//380 186//379 +f 272//1130 137//944 979//681 +f 770//1223 769//1195 744//1191 +f 712//1155 742//1162 720//956 +f 1213//1213 2026//1224 544//244 +f 1888//1225 1235//1226 2438//1227 +f 555//1063 554//401 2311//1019 +f 737//1205 313//611 1192//610 +f 1585//26 1612//1228 1611//187 +f 695//1229 721//1068 685//1072 +f 518//1206 17//1230 28//338 +f 769//1195 770//1223 562//1190 +f 719//957 749//1148 740//861 +f 648//964 669//35 679//1038 +f 773//1001 657//1150 723//1151 +f 606//1075 637//1166 619//1200 +f 2072//1231 2062//172 2042//1232 +f 606//1075 619//1200 626//1047 +f 549//1079 569//1073 553//1081 +f 161//448 638//960 611//796 +f 910//486 917//339 942//487 +f 917//339 1103//341 942//487 +f 991//274 1026//328 992//275 +f 979//681 137//944 672//943 +f 785//1030 163//410 657//1150 +f 710//1100 2488//635 2472//812 +f 611//796 581//758 119//449 +f 808//1220 671//1000 820//1179 +f 1820//1233 1900//463 1870//1234 +f 759//1131 700//383 591//978 +f 637//1166 677//1167 619//1200 +f 2494//495 2490//1235 2463//245 +f 671//1000 765//1002 816//940 +f 687//1066 764//1182 780//1106 +f 1019//301 992//275 1026//328 +f 1726//300 1719//1236 987//371 +f 713//1041 771//1040 694//1170 +f 51//582 2355//1237 78//414 +f 510//988 526//1238 525//1239 +f 525//1239 526//1238 1249//817 +f 526//1238 33//818 1249//817 +f 2311//1019 554//401 2335//1240 +f 827//1241 848//1242 840//1243 +f 603//945 591//978 649//1016 +f 758//1188 269//862 740//861 +f 1595//81 1612//1228 1586//1244 +f 1694//1245 1048//1246 1699//612 +f 682//1247 740//861 186//379 +f 22//1099 801//977 603//945 +f 555//1063 570//402 554//401 +f 1053//166 110//1248 97//357 +f 615//1024 582//1007 601//1249 +f 814//547 668//772 188//249 +f 725//1192 705//1189 744//1191 +f 528//1064 700//383 759//1131 +f 640//567 648//964 620//1023 +f 703//942 701//941 562//1190 +f 886//1250 892//1251 582//1007 +f 631//388 731//723 576//1012 +f 1087//1252 1835//1253 1747//1254 +f 882//1255 864//525 895//1221 +f 956//1256 950//1257 1103//341 +f 1502//231 2500//233 2470//1258 +f 205//749 190//748 200//1045 +f 815//141 878//1132 616//987 +f 616//987 878//1132 995//642 +f 1183//143 878//1132 815//141 +f 1601//1259 1827//1260 881//232 +f 527//1261 535//588 526//1238 +f 2184//892 2183//894 2175//1262 +f 1142//1263 1125//1264 1133//107 +f 235//293 338//292 798//1061 +f 160//238 339//769 792//239 +f 599//986 92//354 75//335 +f 598//825 1116//1265 566//1168 +f 631//388 558//387 731//723 +f 771//1040 770//1223 744//1191 +f 730//1065 528//1064 642//1101 +f 841//1178 699//1102 642//1101 +f 668//772 401//316 188//249 +f 510//988 527//1261 526//1238 +f 749//1148 758//1188 740//861 +f 706//1018 721//1068 695//1229 +f 694//1170 726//1266 705//1189 +f 694//1170 744//1191 726//1266 +f 906//272 911//700 905//1037 +f 661//520 695//1229 161//448 +f 708//1267 815//141 616//987 +f 535//588 547//863 33//818 +f 794//1116 759//1131 591//978 +f 778//1051 808//1220 790//1052 +f 269//862 758//1188 783//937 +f 771//1040 744//1191 694//1170 +f 800//1194 808//1220 820//1179 +f 571//1008 886//1250 582//1007 +f 854//675 948//256 1010//319 +f 906//272 905//1037 887//524 +f 625//946 651//981 635//947 +f 2000//63 1226//217 534//1031 +f 2140//1268 1504//1269 2016//1270 +f 601//1249 620//1023 615//1024 +f 620//1023 601//1249 640//567 +f 648//964 640//567 669//35 +f 698//933 452//926 439//822 +f 671//1000 785//1030 657//1150 +f 1561//114 2356//1271 545//113 +f 685//1072 653//1026 667//1025 +f 685//1072 727//1039 684//1152 +f 568//1272 616//987 797//321 +f 708//1267 732//618 815//141 +f 93//993 229//770 339//769 +f 865//251 851//910 839//1173 +f 942//487 1103//341 950//1257 +f 589//572 614//847 125//501 +f 606//1075 610//1193 627//1181 +f 951//1273 834//1274 873//1275 +f 92//354 599//986 625//946 +f 1878//423 830//750 1902//1276 +f 2482//1126 2098//966 1899//967 +f 568//1272 708//1267 616//987 +f 708//1267 551//636 732//618 +f 2434//27 2487//310 2483//775 +f 160//238 964//183 665//185 +f 2316//1277 2391//1278 2309//1279 +f 762//837 758//1188 749//1148 +f 570//402 614//847 589//572 +f 888//242 897//254 883//342 +f 2000//63 1517//1032 1388//1280 +f 685//1072 721//1068 727//1039 +f 588//1074 610//1193 606//1075 +f 653//1026 685//1072 684//1152 +f 651//981 650//829 635//947 +f 760//999 1151//1281 6//1282 +f 793//919 622//1109 150//546 +f 651//981 676//980 650//829 +f 744//1191 769//1195 750//1042 +f 541//336 542//935 560//455 +f 476//413 500//441 690//1067 +f 473//907 1064//867 1057//891 +f 561//1108 578//968 560//455 +f 636//979 625//946 599//986 +f 876//641 995//642 949//982 +f 829//270 856//643 846//268 +f 682//1247 704//1283 740//861 +f 791//1050 790//1052 770//1223 +f 2466//1284 2500//233 2460//407 +f 579//969 587//1142 586//970 +f 1352//1285 1208//1286 1095//1287 +f 1684//1288 1479//1183 1916//1185 +f 604//985 609//1003 636//979 +f 751//1289 721//1068 706//1018 +f 810//1028 608//1290 782//1029 +f 672//943 603//945 649//1016 +f 475//286 447//309 476//413 +f 794//1116 591//978 801//977 +f 682//1247 186//379 650//829 +f 808//1220 800//1194 790//1052 +f 644//1107 598//825 813//938 +f 704//1283 719//957 740//861 +f 1011//1214 608//1290 810//1028 +f 1192//610 584//1198 737//1205 +f 687//1066 780//1106 796//381 +f 2337//1291 474//288 2312//1005 +f 638//960 667//1025 646//1027 +f 706//1018 1186//1292 728//773 +f 733//1293 575//1114 568//1272 +f 595//1294 551//636 708//1267 +f 595//1294 540//1295 551//636 +f 1308//1296 501//1297 1852//1298 +f 665//185 339//769 160//238 +f 527//1261 2447//1299 535//588 +f 558//387 9//728 731//723 +f 723//1151 793//919 773//1001 +f 660//1153 713//1041 694//1170 +f 693//1204 725//1192 666//1156 +f 562//1190 767//951 529//952 +f 550//1082 538//1078 531//1077 +f 2267//1300 2287//1301 2233//1302 +f 996//925 964//183 160//238 +f 2068//344 2470//1258 2466//1284 +f 704//1283 711//955 719//957 +f 741//1057 762//837 749//1148 +f 605//1090 606//1075 626//1047 +f 548//1080 542//935 530//936 +f 995//642 878//1132 709//1303 +f 1898//1304 1684//1288 1916//1185 +f 778//1051 791//1050 771//1040 +f 782//1029 163//410 785//1030 +f 789//836 758//1188 762//837 +f 857//243 883//342 847//523 +f 733//1293 970//320 1028//856 +f 838//1174 829//270 825//1305 +f 2447//1299 511//1306 535//588 +f 22//1099 603//945 137//944 +f 705//1189 726//1266 744//1191 +f 605//1090 587//1142 580//1207 +f 512//1136 548//1080 530//936 +f 743//1135 784//1134 742//1162 +f 790//1052 800//1194 770//1223 +f 778//1051 810//1028 808//1220 +f 1014//253 998//252 355//1180 +f 708//1267 568//1272 595//1294 +f 656//1307 697//692 551//636 +f 540//1295 656//1307 551//636 +f 143//644 125//501 614//847 +f 1000//1308 1020//360 983//370 +f 778//1051 178//1159 1011//1214 +f 676//980 704//1283 682//1247 +f 637//1166 627//1181 660//1153 +f 606//1075 627//1181 637//1166 +f 701//941 552//1199 481//545 +f 808//1220 810//1028 785//1030 +f 590//965 570//402 555//1063 +f 716//1309 595//1294 568//1272 +f 2355//1237 2335//1240 554//401 +f 912//271 1729//764 911//700 +f 1076//1310 1456//1311 1546//1312 +f 697//692 68//651 492//637 +f 676//980 711//955 704//1283 +f 839//1173 851//910 838//1174 +f 1028//856 575//1114 733//1293 +f 1020//360 844//1313 982//358 +f 716//1309 568//1272 575//1114 +f 844//1313 781//961 982//358 +f 1238//479 2156//1314 2034//175 +f 553//1081 580//1207 561//1108 +f 580//1207 579//969 561//1108 +f 452//926 461//666 453//668 +f 560//455 578//968 48//606 +f 564//1315 540//1295 595//1294 +f 632//1004 656//1307 540//1295 +f 564//1315 632//1004 540//1295 +f 75//335 578//968 599//986 +f 518//1206 27//586 535//588 +f 511//1306 518//1206 535//588 +f 783//937 798//1061 788//435 +f 642//1101 759//1131 663//1115 +f 720//956 742//1162 741//1057 +f 605//1090 626//1047 587//1142 +f 580//1207 587//1142 579//969 +f 725//1192 712//1155 666//1156 +f 562//1190 701//941 767//951 +f 1729//764 923//699 911//700 +f 712//1155 743//1135 742//1162 +f 619//1200 677//1167 658//1048 +f 161//448 695//1229 654//959 +f 770//1223 800//1194 562//1190 +f 2084//1006 2489//632 2472//812 +f 575//1114 559//1165 716//1309 +f 716//1309 564//1315 595//1294 +f 654//959 695//1229 685//1072 +f 843//1316 855//1317 2064//613 +f 34//701 731//723 9//728 +f 527//1261 510//988 1973//950 +f 723//1151 622//1109 793//919 +f 992//275 1726//300 987//371 +f 693//1204 666//1156 652//1062 +f 2472//812 853//813 573//1098 +f 624//295 159//649 148//296 +f 671//1000 657//1150 773//1001 +f 681//721 188//249 498//248 +f 797//321 970//320 733//1293 +f 565//1318 656//1307 632//1004 +f 565//1318 697//692 656//1307 +f 565//1318 731//723 697//692 +f 1949//1319 951//1273 920//663 +f 85//598 111//458 84//590 +f 662//953 200//1045 190//748 +f 44//815 324//1320 754//729 +f 33//818 547//863 40//807 +f 658//1048 693//1204 652//1062 +f 658//1048 652//1062 645//1049 +f 664//1117 794//1116 801//977 +f 666//1156 712//1155 692//1154 +f 639//954 648//964 662//953 +f 611//796 646//1027 610//1193 +f 850//209 559//1165 575//1114 +f 1447//1161 2490//1235 1106//1321 +f 1972//213 1955//1322 1935//85 +f 582//1007 615//1024 590//965 +f 66//583 581//758 539//1149 +f 780//1106 641//386 631//388 +f 796//381 780//1106 631//388 +f 1049//1323 1192//610 83//688 +f 1348//1324 13//1325 1519//1326 +f 799//1044 807//1043 562//1190 +f 581//758 611//796 588//1074 +f 687//1066 795//1058 644//1107 +f 663//1115 8//1327 642//1101 +f 1936//1328 1972//213 1935//85 +f 650//829 676//980 682//1247 +f 615//1024 630//958 590//965 +f 730//1065 795//1058 687//1066 +f 742//1162 762//837 741//1057 +f 548//1080 553//1081 542//935 +f 1048//1246 1692//1329 1074//826 +f 658//1048 659//1203 693//1204 +f 37//555 52//554 30//16 +f 611//796 610//1193 588//1074 +f 649//1016 632//1004 564//1315 +f 565//1318 576//1012 731//723 +f 2138//1330 922//136 1058//4 +f 1204//1331 854//675 965//676 +f 725//1192 743//1135 712//1155 +f 644//1107 813//938 641//386 +f 660//1153 653//1026 684//1152 +f 771//1040 791//1050 770//1223 +f 644//1107 795//1058 1074//826 +f 469//469 480//720 681//721 +f 559//1165 672//943 564//1315 +f 716//1309 559//1165 564//1315 +f 672//943 649//1016 564//1315 +f 2161//1332 1378//1333 2171//1334 +f 474//288 475//286 476//413 +f 816//940 765//1002 701//941 +f 765//1002 552//1199 701//941 +f 513//1076 538//1078 548//1080 +f 754//729 324//1320 107//761 +f 609//1003 586//970 618//1097 +f 25//566 523//1095 19//1129 +f 677//1167 659//1203 658//1048 +f 689//658 452//926 698//933 +f 1334//1335 1115//1336 1353//1337 +f 700//383 565//1318 632//1004 +f 700//383 576//1012 565//1318 +f 481//545 552//1199 793//919 +f 763//1338 901//312 2458//311 +f 550//1082 549//1079 538//1078 +f 781//961 964//183 996//925 +f 1596//80 1634//1339 1595//81 +f 198//1340 916//934 1124//93 +f 198//1340 1124//93 341//133 +f 842//1341 973//1342 1025//1343 +f 842//1341 1025//1343 836//789 +f 1009//1344 1024//116 934//1345 +f 573//1098 710//1100 2472//812 +f 1100//77 971//1346 1002//78 +f 1501//421 1081//118 1557//171 +f 1225//1347 1219//1348 955//1349 +f 413//1350 2138//1330 284//1351 +f 955//1349 1630//1352 522//1094 +f 341//133 1124//93 301//134 +f 2333//1353 2376//334 2350//1354 +f 1107//1355 218//1356 284//1351 +f 398//145 925//1357 1513//322 +f 1513//322 1442//1358 1495//68 +f 1935//85 1455//84 1744//527 +f 1723//1359 1935//85 1744//527 +f 825//1305 1872//1172 838//1174 +f 1495//68 1442//1358 1496//1360 +f 963//1361 1024//116 1009//1344 +f 1511//304 1514//303 966//1362 +f 1775//1363 1729//764 912//271 +f 688//160 262//146 1067//1364 +f 714//419 1007//1201 1512//420 +f 919//1365 1732//974 914//976 +f 2319//1366 2331//1367 2304//1368 +f 2400//1369 2407//1370 2391//1278 +f 1674//625 2164//1371 1780//1372 +f 843//1316 927//1373 899//1374 +f 1660//210 988//1375 1188//105 +f 1067//1364 262//146 1640//191 +f 1381//96 1109//98 1483//691 +f 1437//851 1381//96 1483//691 +f 2495//576 1010//319 948//256 +f 1514//303 1289//1376 1313//1377 +f 899//1374 374//677 961//679 +f 1438//1211 1430//1378 1422//276 +f 1634//1339 1095//1287 1632//30 +f 2487//310 973//1342 2461//776 +f 1003//565 499//1379 874//471 +f 849//1380 848//1242 827//1241 +f 1430//1378 1462//831 1453//1381 +f 2496//237 2084//1006 2471//634 +f 909//5 10//280 980//279 +f 730//1065 927//1373 835//1059 +f 2031//842 1540//1096 1536//1382 +f 831//1383 849//1380 2178//1384 +f 881//232 834//1274 951//1273 +f 1841//1385 1722//1386 1803//1387 +f 1005//1388 670//1389 1020//360 +f 1021//1390 670//1389 1005//1388 +f 1869//225 2059//788 2467//868 +f 903//1391 902//1392 1939//1393 +f 2476//616 2502//28 1651//478 +f 853//813 8//1327 573//1098 +f 1850//1394 831//1383 2178//1384 +f 934//1345 746//564 247//563 +f 934//1345 65//45 746//564 +f 301//134 285//1395 1077//823 +f 968//1396 944//1397 977//1398 +f 970//320 2495//576 1028//856 +f 974//1177 2465//678 374//677 +f 899//1374 927//1373 374//677 +f 1882//1399 1898//1304 1916//1185 +f 1613//1400 1634//1339 1596//80 +f 909//5 833//138 1396//1401 +f 2492//247 247//563 1003//565 +f 919//1365 914//976 1931//1208 +f 1459//854 1299//591 1458//1402 +f 1634//1339 1632//30 1633//1403 +f 844//1313 670//1389 228//1404 +f 2494//495 2497//494 2467//868 +f 901//312 973//1342 2487//310 +f 228//1404 1772//1405 734//184 +f 1701//1406 1709//1407 1666//1408 +f 963//1361 574//50 1024//116 +f 847//523 864//525 856//643 +f 1730//510 1736//1409 2239//1410 +f 870//973 859//972 848//1242 +f 2074//880 2111//1411 2103//1412 +f 1140//690 1590//852 1483//691 +f 927//1373 730//1065 974//1177 +f 2103//1412 978//878 2074//880 +f 756//1413 1745//1414 1718//1415 +f 848//1242 859//972 840//1243 +f 1296//652 1482//833 1320//1416 +f 2331//1367 51//582 66//583 +f 1067//1364 988//1375 962//1417 +f 1396//1401 833//138 1445//1418 +f 1001//1419 1005//1388 1000//1308 +f 901//312 1009//1344 973//1342 +f 1099//132 1077//823 817//1420 +f 933//1421 944//1397 936//1422 +f 952//1423 958//1424 1828//1425 +f 988//1375 1660//210 986//1426 +f 833//138 1067//1364 1445//1418 +f 1067//1364 1640//191 988//1375 +f 218//1356 413//1350 284//1351 +f 1843//1427 180//1428 347//1429 +f 1846//1430 1708//1431 1798//1432 +f 2469//1433 2477//1434 855//1317 +f 1006//623 1021//1390 1005//1388 +f 381//904 382//734 250//1435 +f 2369//1436 828//1437 531//1077 +f 968//1396 977//1398 1001//1419 +f 2460//407 1949//1319 779//345 +f 1194//1438 1441//1439 1115//1336 +f 1001//1419 1000//1308 968//1396 +f 756//1413 678//1440 1745//1414 +f 963//1361 1009//1344 901//312 +f 2471//634 2084//1006 2472//812 +f 841//1178 642//1101 8//1327 +f 982//358 991//274 1027//359 +f 670//1389 844//1313 1020//360 +f 1289//1376 1514//303 945//302 +f 869//971 904//1441 890//1442 +f 1161//1443 1115//1336 1639//603 +f 823//1444 2178//1384 849//1380 +f 746//564 12//47 499//1379 +f 263//365 428//1445 2366//1446 +f 1685//1447 1075//827 1692//1329 +f 1002//78 926//794 806//745 +f 1799//1448 1755//1449 216//1450 +f 944//1397 968//1396 993//1451 +f 943//1452 944//1397 993//1451 +f 31//659 38//608 19//1129 +f 531//1077 828//1437 550//1082 +f 1501//421 1078//211 1081//118 +f 1921//1216 1149//1453 431//1454 +f 936//1422 943//1452 932//1455 +f 1660//210 1489//117 1412//222 +f 301//134 980//279 285//1395 +f 903//1391 918//1456 902//1392 +f 869//971 890//1442 868//1457 +f 890//1442 903//1391 867//1458 +f 1003//565 746//564 499//1379 +f 951//1273 1949//1319 2500//233 +f 990//1459 841//1178 853//813 +f 1595//81 1634//1339 1611//187 +f 374//677 927//1373 974//1177 +f 836//789 1025//1343 247//563 +f 1653//190 1652//234 1638//223 +f 1303//1460 1545//1461 1142//1263 +f 1616//186 1631//330 1638//223 +f 1629//620 1546//1312 1628//306 +f 936//1422 932//1455 913//1462 +f 513//1076 506//1463 531//1077 +f 868//1457 890//1442 867//1458 +f 2330//1464 2369//1436 2353//1465 +f 924//975 918//1456 914//976 +f 907//1209 914//976 904//1441 +f 1258//1466 1421//277 1267//1467 +f 301//134 939//6 980//279 +f 1472//1468 1482//833 1296//652 +f 868//1457 867//1458 859//972 +f 472//500 491//541 313//611 +f 272//1130 519//680 2488//635 +f 1471//197 1472//1468 1296//652 +f 1025//1343 934//1345 247//563 +f 1634//1339 1633//1403 1611//187 +f 2176//1469 1847//1470 2177//1471 +f 1310//793 1289//1376 806//745 +f 924//975 933//1421 918//1456 +f 1969//1472 1968//1473 902//1392 +f 2107//927 2128//1474 2118//1475 +f 1428//1476 1436//1477 1287//1478 +f 1139//605 1564//604 1617//1479 +f 2378//1034 572//1015 2384//1480 +f 853//813 841//1178 8//1327 +f 2501//405 961//679 2465//678 +f 1221//1481 1240//1482 1408//1483 +f 1069//1 1578//3 1627//305 +f 1006//623 1005//1388 1001//1419 +f 1617//1479 1564//604 1578//3 +f 828//1437 539//1149 550//1082 +f 1791//1484 2168//1485 2160//1486 +f 1829//1487 1718//1415 1739//1488 +f 1968//1473 1939//1393 902//1392 +f 756//1413 1718//1415 665//185 +f 1998//64 2000//63 1388//1280 +f 2451//1489 545//113 2356//1271 +f 178//1159 997//1490 1011//1214 +f 1275//1491 325//200 1270//1492 +f 1709//1407 872//1493 1666//1408 +f 2176//1469 1959//1494 1847//1470 +f 944//1397 943//1452 936//1422 +f 2424//1495 518//1206 511//1306 +f 1445//1418 1067//1364 962//1417 +f 2007//1496 952//1423 1828//1425 +f 2052//1497 2061//1498 2081//840 +f 828//1437 2303//1499 539//1149 +f 835//1059 1699//612 1048//1246 +f 1709//1407 1706//1500 872//1493 +f 885//1501 574//50 963//1361 +f 1318//389 1296//652 1320//1416 +f 859//972 867//1458 1902//1276 +f 1452//1502 1448//1503 1421//277 +f 943//1452 993//1451 976//1504 +f 993//1451 1000//1308 983//370 +f 854//675 1010//319 876//641 +f 988//1375 986//1426 962//1417 +f 2031//842 2052//1497 2081//840 +f 924//975 1732//974 1828//1425 +f 965//676 949//982 1060//1505 +f 781//961 228//1404 734//184 +f 1718//1415 1765//994 665//185 +f 943//1452 976//1504 932//1455 +f 1680//1506 1794//1507 1783//1508 +f 1448//1503 1471//197 1276//196 +f 1276//196 1267//1467 1421//277 +f 1931//1208 914//976 907//1209 +f 991//274 781//961 996//925 +f 1276//196 1421//277 1448//1503 +f 10//280 909//5 1396//1401 +f 831//1383 860//1509 849//1380 +f 1523//1510 1762//1511 1774//1512 +f 924//975 1828//1425 937//1513 +f 307//327 994//240 1014//253 +f 946//657 963//1361 901//312 +f 978//878 2103//1412 977//1398 +f 977//1398 1006//623 1001//1419 +f 1007//1201 1161//1443 1639//603 +f 1639//603 1294//1514 1437//851 +f 885//1501 1032//48 574//50 +f 1294//1514 1381//96 1437//851 +f 733//1293 568//1272 797//321 +f 792//239 229//770 1112//1515 +f 119//449 581//758 108//416 +f 843//1316 835//1059 927//1373 +f 1889//1516 860//1509 831//1383 +f 2211//1517 2216//1518 2204//1519 +f 2400//1369 2431//1520 2422//1521 +f 2103//1412 1006//623 977//1398 +f 840//1243 1902//1276 830//750 +f 827//1241 840//1243 830//750 +f 827//1241 830//750 822//1133 +f 1003//565 874//471 2492//247 +f 1432//664 1439//855 1431//1212 +f 781//961 734//184 964//183 +f 1937//1144 1936//1328 1723//1359 +f 918//1456 913//1462 902//1392 +f 958//1424 977//1398 944//1397 +f 1850//1394 2178//1384 2177//1471 +f 1005//1388 1020//360 1000//1308 +f 991//274 996//925 307//327 +f 1396//1401 1445//1418 340//1522 +f 2179//1523 1763//858 889//1524 +f 939//6 909//5 980//279 +f 1828//1425 958//1424 937//1513 +f 978//878 977//1398 958//1424 +f 1590//852 1571//619 1563//850 +f 779//345 1949//1319 920//663 +f 1551//1525 1362//1526 1573//445 +f 2103//1412 2142//624 1006//623 +f 920//663 885//1501 963//1361 +f 946//657 920//663 963//1361 +f 1584//41 1616//186 1583//1527 +f 1453//1381 1472//1468 1452//1502 +f 1647//2 1617//1479 1578//3 +f 1578//3 1564//604 1627//305 +f 1628//306 938//905 1069//1 +f 869//971 868//1457 859//972 +f 993//1451 983//370 976//1504 +f 912//271 1762//1511 1775//1363 +f 752//774 751//1289 706//1018 +f 1628//306 1546//1312 938//905 +f 844//1313 228//1404 781//961 +f 840//1243 859//972 1902//1276 +f 898//1210 907//1209 904//1441 +f 1025//1343 973//1342 1009//1344 +f 663//1115 664//1117 573//1098 +f 763//1338 946//657 901//312 +f 898//1210 904//1441 869//971 +f 2172//1528 889//1524 1763//858 +f 1128//795 926//794 971//1346 +f 860//1509 848//1242 849//1380 +f 904//1441 903//1391 890//1442 +f 2486//568 2459//570 2479//648 +f 577//1529 782//1029 608//1290 +f 933//1421 936//1422 918//1456 +f 2177//1471 1847//1470 1851//1530 +f 665//185 1765//994 339//769 +f 937//1513 958//1424 944//1397 +f 894//1531 981//1164 724//1158 +f 968//1396 1000//1308 993//1451 +f 2192//1532 2195//1533 2205//1534 +f 1652//234 1099//132 817//1420 +f 997//1490 608//1290 1011//1214 +f 997//1490 577//1529 608//1290 +f 577//1529 163//410 782//1029 +f 1112//1515 998//252 792//239 +f 2177//1471 1851//1530 1850//1394 +f 1257//1535 1421//277 1258//1466 +f 951//1273 873//1275 920//663 +f 822//1133 830//750 2215//713 +f 1899//967 2496//237 2471//634 +f 1773//1536 1668//1537 1558//1538 +f 904//1441 914//976 903//1391 +f 932//1455 1671//1539 913//1462 +f 873//1275 885//1501 920//663 +f 1013//1202 1617//1479 1647//2 +f 873//1275 1032//48 885//1501 +f 894//1531 862//1196 981//1164 +f 2469//1433 855//1317 961//679 +f 913//1462 1671//1539 1969//1472 +f 2477//1434 2064//613 855//1317 +f 918//1456 936//1422 913//1462 +f 860//1509 870//973 848//1242 +f 937//1513 944//1397 933//1421 +f 1501//421 1013//1202 1647//2 +f 824//1540 178//1159 751//1289 +f 824//1540 997//1490 178//1159 +f 824//1540 577//1529 997//1490 +f 643//548 163//410 577//1529 +f 863//1541 856//643 882//1255 +f 2128//1474 2153//1542 2134//1543 +f 722//1544 774//1176 880//1545 +f 722//1544 894//1531 774//1176 +f 864//525 905//1037 895//1221 +f 850//209 575//1114 583//207 +f 914//976 918//1456 903//1391 +f 924//975 937//1513 933//1421 +f 1501//421 717//69 1013//1202 +f 1587//1546 1324//1547 928//1548 +f 717//69 1512//420 1013//1202 +f 602//711 577//1529 824//1540 +f 766//710 643//548 577//1529 +f 894//1531 709//1303 862//1196 +f 709//1303 878//1132 862//1196 +f 976//1504 975//911 932//1455 +f 1324//1547 1596//80 928//1548 +f 880//1545 524//530 1060//1505 +f 2434//27 2459//570 2499//569 +f 1324//1547 1613//1400 1596//80 +f 752//774 824//1540 751//1289 +f 602//711 766//710 577//1529 +f 1014//253 602//711 594//326 +f 1387//1549 1226//217 2152//1550 +f 2153//1542 1387//1549 2152//1550 +f 669//35 930//488 950//1257 +f 1710//614 1694//1245 1699//612 +f 768//518 326//519 762//837 +f 582//1007 892//1251 601//1249 +f 974//1177 990//1459 2465//678 +f 624//295 116//355 625//946 +f 835//1059 795//1058 730//1065 +f 2458//311 2484//343 763//1338 +f 989//757 602//711 824//1540 +f 2064//613 2477//1434 1710//614 +f 976//1504 983//370 975//911 +f 949//982 722//1544 880//1545 +f 996//925 160//238 994//240 +f 2305//1020 863//1541 556//1551 +f 556//1551 863//1541 886//1250 +f 601//1249 910//486 640//567 +f 2264//269 825//1305 829//270 +f 989//757 824//1540 752//774 +f 856//643 864//525 882//1255 +f 1595//81 1586//1244 2381//25 +f 1627//305 1629//620 1628//306 +f 2174//1552 2180//1553 2173//1554 +f 2128//1474 2134//1543 2118//1475 +f 137//944 272//1130 22//1099 +f 949//982 880//1545 1060//1505 +f 995//642 894//1531 722//1544 +f 894//1531 995//642 709//1303 +f 894//1531 724//1158 774//1176 +f 886//1250 895//1221 892//1251 +f 640//567 910//486 930//488 +f 871//1555 870//973 860//1509 +f 846//268 856//643 863//1541 +f 1026//328 875//756 1019//301 +f 838//1174 851//910 829//270 +f 1024//116 1171//1556 934//1345 +f 36//803 189//517 205//749 +f 863//1541 882//1255 886//1250 +f 886//1250 882//1255 895//1221 +f 875//756 1026//328 594//326 +f 52//554 1459//854 1269//509 +f 896//1222 917//339 910//486 +f 1025//1343 1009//1344 934//1345 +f 949//982 995//642 722//1544 +f 2152//1550 1226//217 1636//1557 +f 895//1221 896//1222 892//1251 +f 892//1251 910//486 601//1249 +f 942//487 950//1257 930//488 +f 875//756 989//757 752//774 +f 594//326 602//711 989//757 +f 766//710 355//1180 643//548 +f 355//1180 260//549 643//548 +f 905//1037 917//339 896//1222 +f 965//676 1060//1505 1162//392 +f 892//1251 896//1222 910//486 +f 1101//11 1052//1558 1042//12 +f 1029//1559 1031//1560 834//1274 +f 1101//11 1133//107 1118//55 +f 342//60 357//124 376//1561 +f 516//963 515//1147 2454//1139 +f 1656//1562 2494//495 2467//868 +f 1056//1563 1303//1460 1133//107 +f 1120//23 1130//22 862//1196 +f 69//192 342//60 376//1561 +f 1055//10 1056//1563 1133//107 +f 499//1379 69//192 165//472 +f 85//598 101//653 111//458 +f 1031//1560 1032//48 834//1274 +f 200//1045 679//1038 1166//34 +f 1031//1560 1042//12 1032//48 +f 1171//1556 65//45 934//1345 +f 1822//1564 1204//1331 1177//1565 +f 1096//765 956//1256 1103//341 +f 514//810 96//1113 97//357 +f 956//1256 1145//1566 1144//33 +f 1185//1567 1166//34 1144//33 +f 1145//1566 1185//1567 1144//33 +f 1185//1567 200//1045 1166//34 +f 375//1568 132//103 1041//1569 +f 1153//1570 1202//36 305//38 +f 32//170 1244//169 1249//817 +f 1096//765 1087//1252 956//1256 +f 554//401 78//414 2355//1237 +f 1191//1571 138//1572 110//1248 +f 65//45 35//115 432//46 +f 1087//1252 1110//1573 956//1256 +f 1110//1573 1146//1574 956//1256 +f 956//1256 1146//1574 1145//1566 +f 1146//1574 1156//1575 1145//1566 +f 1145//1566 1156//1575 1185//1567 +f 950//1257 956//1256 1144//33 +f 2481//418 2495//576 948//256 +f 1156//1575 1193//1576 1185//1567 +f 1050//459 1047//125 1051//128 +f 239//1577 151//760 107//761 +f 1185//1567 1193//1576 36//803 +f 1747//1254 1110//1573 1087//1252 +f 1134//1578 1146//1574 1110//1573 +f 1146//1574 1157//1579 1156//1575 +f 1156//1575 1157//1579 1193//1576 +f 1041//1569 1045//573 1034//574 +f 1397//1580 1134//1578 1110//1573 +f 1157//1579 1146//1574 1134//1578 +f 1157//1579 1175//1581 1193//1576 +f 1193//1576 199//522 36//803 +f 1090//39 1035//258 1196//65 +f 1456//1311 1150//87 1051//128 +f 1175//1581 199//522 1193//1576 +f 1186//1292 695//1229 199//522 +f 1186//1292 199//522 1175//1581 +f 1175//1581 1157//1579 1134//1578 +f 728//773 1186//1292 1175//1581 +f 197//845 760//999 6//1282 +f 1130//22 593//1146 862//1196 +f 1167//689 1109//98 182//109 +f 1194//1438 1115//1336 1161//1443 +f 2140//1268 1928//1582 1504//1269 +f 921//137 922//136 2138//1330 +f 1147//1583 1134//1578 1397//1580 +f 1719//1236 1147//1583 1397//1580 +f 1147//1583 1175//1581 1134//1578 +f 1175//1581 1147//1583 728//773 +f 341//133 1654//31 1208//1286 +f 754//729 151//760 9//728 +f 284//1351 2138//1330 1058//4 +f 1188//105 1557//171 1660//210 +f 1191//1571 110//1248 1053//166 +f 916//934 284//1351 1189//94 +f 284//1351 1058//4 1189//94 +f 2094//1092 1465//1584 2127//1071 +f 1726//300 1019//301 1147//1583 +f 1147//1583 1019//301 728//773 +f 593//1146 1130//22 96//1113 +f 239//1577 305//38 1038//694 +f 1036//1585 1131//159 315//179 +f 397//731 1131//159 1120//23 +f 1053//166 96//1113 1130//22 +f 2467//868 2485//596 1869//225 +f 517//866 1089//1586 421//7 +f 834//1274 1827//1260 1029//1559 +f 419//61 1047//125 1117//59 +f 1034//574 433//156 1306//155 +f 2239//1410 1862//451 1730//510 +f 1453//1381 1462//831 1472//1468 +f 1408//1483 1422//276 1399//1587 +f 471//158 23//178 1111//180 +f 1205//1588 1150//87 1456//1311 +f 1205//1588 1040//88 1150//87 +f 1131//159 1036//1585 293//1589 +f 293//1589 1068//1590 1044//165 +f 375//1568 1041//1569 138//1572 +f 1205//1588 1140//690 1046//102 +f 1040//88 1205//1588 1046//102 +f 1140//690 1167//689 1046//102 +f 1104//1591 1049//1323 83//688 +f 1052//1558 1085//49 1032//48 +f 1044//165 1068//1590 1191//1571 +f 1167//689 1483//691 1109//98 +f 208//82 1084//189 1035//258 +f 1040//88 132//103 375//1568 +f 1834//1592 20//1593 3//1594 +f 1050//459 1051//128 1070//1595 +f 1133//107 1125//1264 1174//43 +f 11//882 1440//37 1401//1596 +f 420//83 208//82 1071//18 +f 1135//1597 1079//1598 1094//1599 +f 1086//57 1101//11 1118//55 +f 1029//1559 1030//830 1031//1560 +f 1200//1600 1061//1601 294//1602 +f 1191//1571 1068//1590 138//1572 +f 1171//1556 1141//56 65//45 +f 1141//56 1172//1603 65//45 +f 1172//1603 35//115 65//45 +f 1172//1603 404//44 35//115 +f 404//44 99//58 35//115 +f 221//824 1104//1591 1063//1604 +f 802//1605 398//145 1083//144 +f 20//1593 1089//1586 3//1594 +f 2064//613 1699//612 835//1059 +f 1042//12 1052//1558 1032//48 +f 1433//1606 1261//17 1432//664 +f 1323//457 2338//1607 155//1608 +f 1076//1310 1205//1588 1456//1311 +f 1088//1609 1402//1610 1056//1563 +f 1150//87 348//89 1070//1595 +f 1200//1600 1089//1586 20//1593 +f 1097//1611 1162//392 100//391 +f 1032//48 873//1275 834//1274 +f 21//142 471//158 1111//180 +f 294//1602 1097//1611 1104//1591 +f 1072//1612 100//391 584//1198 +f 1151//1281 760//999 622//1109 +f 132//103 1045//573 1041//1569 +f 1050//459 1070//1595 1135//1597 +f 1088//1609 1039//153 940//152 +f 650//829 159//649 635//947 +f 100//391 1170//393 729//531 +f 729//531 584//1198 100//391 +f 1103//341 931//340 1096//765 +f 925//1357 1443//656 1513//322 +f 138//1572 1102//1613 110//1248 +f 1034//574 1306//155 1152//219 +f 1071//18 1035//258 1090//39 +f 100//391 1072//1612 1097//1611 +f 23//178 1158//1614 315//179 +f 1068//1590 375//1568 138//1572 +f 1586//1244 1612//1228 1585//26 +f 1819//1615 1030//830 1029//1559 +f 1041//1569 1034//574 1102//1613 +f 232//1616 375//1568 1068//1590 +f 348//89 1079//1598 1070//1595 +f 1061//1601 1097//1611 294//1602 +f 1513//322 1443//656 1442//1358 +f 1200//1600 294//1602 1119//361 +f 376//1561 1050//459 1062//1617 +f 1094//1599 1036//1585 315//179 +f 1200//1600 1119//361 1089//1586 +f 1111//180 1183//143 21//142 +f 1044//165 1191//1571 1053//166 +f 698//933 295//1618 689//658 +f 1079//1598 232//1616 1036//1585 +f 404//44 1117//59 99//58 +f 1495//68 1496//1360 717//69 +f 1119//361 294//1602 98//460 +f 3//1594 1089//1586 517//866 +f 1132//491 1063//1604 83//688 +f 1132//491 83//688 175//687 +f 132//103 1046//102 182//109 +f 1111//180 1195//730 1183//143 +f 1131//159 1044//165 1037//21 +f 127//329 402//72 1804//71 +f 219//167 1272//1619 1047//125 +f 1697//1620 1135//1597 1094//1599 +f 2140//1268 1854//1621 2117//235 +f 1111//180 397//731 1195//730 +f 1177//1565 1162//392 1097//1611 +f 1061//1601 1177//1565 1097//1611 +f 717//69 1509//1622 714//419 +f 2//110 1300//97 433//156 +f 462//615 290//562 461//666 +f 98//460 294//1602 221//824 +f 294//1602 1104//1591 221//824 +f 714//419 1161//1443 1007//1201 +f 1073//1623 1152//219 1143//220 +f 1697//1620 1094//1599 1360//1624 +f 1223//1625 1423//1626 1218//1627 +f 836//789 2479//648 842//1341 +f 1097//1611 1072//1612 1049//1323 +f 348//89 1040//88 375//1568 +f 3//1594 517//866 316//1628 +f 180//1428 1061//1601 1201//1629 +f 348//89 375//1568 232//1616 +f 1432//664 1431//1212 1415//1630 +f 220//104 1513//322 1495//68 +f 1104//1591 1097//1611 1049//1323 +f 306//227 674//1010 596//299 +f 777//409 455//1631 723//1151 +f 2170//1632 2151//1633 1641//1634 +f 1047//125 419//61 219//167 +f 1102//1613 1034//574 1073//1623 +f 1073//1623 1034//574 1152//219 +f 1035//258 1054//108 1196//65 +f 1177//1565 1204//1331 1162//392 +f 746//564 65//45 12//47 +f 751//1289 178//1159 721//1068 +f 1054//108 517//866 421//7 +f 1051//128 1150//87 1070//1595 +f 1102//1613 1073//1623 110//1248 +f 998//252 1136//1635 355//1180 +f 567//814 566//1168 1163//816 +f 1111//180 315//179 397//731 +f 1048//1246 1074//826 835//1059 +f 1158//1614 1094//1599 315//179 +f 1374//1636 1107//1355 1252//1637 +f 1112//1515 1136//1635 998//252 +f 472//500 629//1105 500//441 +f 355//1180 1136//1635 260//549 +f 260//549 118//1638 43//408 +f 1104//1591 83//688 1063//1604 +f 376//1561 357//124 1050//459 +f 1463//1639 1142//1263 1545//1461 +f 1036//1585 232//1616 293//1589 +f 1030//830 1042//12 1031//1560 +f 1079//1598 348//89 232//1616 +f 221//824 1063//1604 1132//491 +f 1094//1599 1079//1598 1036//1585 +f 1076//1310 1629//620 1205//1588 +f 1136//1635 1197//1640 260//549 +f 260//549 1197//1640 118//1638 +f 1204//1331 965//676 1162//392 +f 293//1589 232//1616 1068//1590 +f 1590//852 1205//1588 1629//620 +f 1205//1588 1590//852 1140//690 +f 250//1435 382//734 392//735 +f 1296//652 1318//389 1311//198 +f 347//1429 1201//1629 20//1593 +f 1201//1629 1200//1600 20//1593 +f 132//103 182//109 1045//573 +f 1101//11 1086//57 1052//1558 +f 1033//154 1039//153 1055//10 +f 138//1572 1041//1569 1102//1613 +f 970//320 1010//319 2495//576 +f 455//1631 777//409 43//408 +f 1992//214 1948//1641 2023//1642 +f 20//1593 1834//1592 347//1429 +f 1072//1612 584//1198 1049//1323 +f 584//1198 1192//610 1049//1323 +f 182//109 2//110 1045//573 +f 1163//816 324//1320 44//815 +f 1360//1624 1094//1599 1158//1614 +f 1450//1643 1360//1624 1158//1614 +f 1091//1644 1112//1515 229//770 +f 509//1645 723//1151 455//1631 +f 207//1646 509//1645 455//1631 +f 1251//1647 1257//1535 1266//1648 +f 1488//221 1489//117 1547//119 +f 2157//1649 1541//1650 1875//1651 +f 305//38 107//761 324//1320 +f 1045//573 2//110 433//156 +f 1070//1595 1079//1598 1135//1597 +f 1136//1635 1168//1652 1197//1640 +f 1197//1640 359//1653 118//1638 +f 118//1638 359//1653 43//408 +f 359//1653 356//1654 43//408 +f 356//1654 455//1631 43//408 +f 356//1654 207//1646 455//1631 +f 1240//1482 1422//276 1408//1483 +f 1163//816 1153//1570 324//1320 +f 1201//1629 1061//1601 1200//1600 +f 1052//1558 1086//57 1085//49 +f 1024//116 1141//56 1171//1556 +f 1112//1515 1105//1655 1136//1635 +f 1050//459 1135//1597 1062//1617 +f 1105//1655 1168//1652 1136//1635 +f 1168//1652 1178//1656 1197//1640 +f 1197//1640 1178//1656 359//1653 +f 1173//622 404//44 1172//1603 +f 465//1657 356//1654 359//1653 +f 1174//43 1125//1264 240//135 +f 1240//1482 1431//1212 1422//276 +f 1098//1658 1113//1659 1105//1655 +f 1112//1515 1098//1658 1105//1655 +f 1105//1655 1178//1656 1168//1652 +f 1178//1656 465//1657 359//1653 +f 1091//1644 1098//1658 1112//1515 +f 1133//107 1174//43 1118//55 +f 98//460 221//824 1059//13 +f 487//492 1132//491 175//687 +f 980//279 1017//1660 285//1395 +f 465//1657 207//1646 356//1654 +f 180//1428 1201//1629 347//1429 +f 1060//1505 524//530 1170//393 +f 445//188 127//329 316//1628 +f 1431//1212 1438//1211 1422//276 +f 498//248 469//469 681//721 +f 940//152 1807//1661 1759//1662 +f 381//904 250//1435 1290//932 +f 1113//1659 1122//1663 1105//1655 +f 1105//1655 1122//1663 1178//1656 +f 1151//1281 509//1645 207//1646 +f 1236//535 2035//989 525//1239 +f 1131//159 293//1589 1044//165 +f 346//1664 207//1646 465//1657 +f 346//1664 1151//1281 207//1646 +f 1822//1564 1796//1665 1204//1331 +f 1143//220 204//195 97//357 +f 123//1666 1128//795 971//1346 +f 2153//1542 2152//1550 2134//1543 +f 126//1667 1151//1281 346//1664 +f 517//866 445//188 316//1628 +f 1450//1643 1158//1614 23//178 +f 1458//1402 1462//831 1430//1378 +f 1129//476 152//1668 1182//101 +f 1122//1663 1159//1669 1178//1656 +f 1178//1656 1198//1670 465//1657 +f 79//1671 346//1664 465//1657 +f 126//1667 1155//1672 1151//1281 +f 1151//1281 1155//1672 6//1282 +f 295//1618 1129//476 689//658 +f 1073//1623 1143//220 97//357 +f 1098//1658 1123//1673 1113//1659 +f 1113//1659 1123//1673 1122//1663 +f 1123//1673 1169//1674 1122//1663 +f 1178//1656 1159//1669 1198//1670 +f 1198//1670 79//1671 465//1657 +f 392//735 383//99 152//1668 +f 1822//1564 1061//1601 180//1428 +f 116//355 92//354 625//946 +f 421//7 1089//1586 1119//361 +f 1129//476 295//1618 152//1668 +f 110//1248 1073//1623 97//357 +f 1173//622 1172//1603 1141//56 +f 1122//1663 1169//1674 1159//1669 +f 79//1671 126//1667 346//1664 +f 1155//1672 181//843 6//1282 +f 971//1346 926//794 1002//78 +f 295//1618 1043//931 152//1668 +f 1039//153 1088//1609 1056//1563 +f 1428//1476 1266//1648 1436//1477 +f 404//44 419//61 1117//59 +f 836//789 879//246 2479//648 +f 2464//617 2476//616 2458//311 +f 1198//1670 317//1675 79//1671 +f 1124//93 939//6 301//134 +f 44//815 754//729 567//814 +f 1039//153 1056//1563 1055//10 +f 1439//855 1459//854 1458//1402 +f 1660//210 1412//222 986//1426 +f 1169//1674 1160//364 1159//1669 +f 179//1676 1155//1672 126//1667 +f 1155//1672 131//844 181//843 +f 1061//1601 1822//1564 1177//1565 +f 1153//1570 305//38 324//1320 +f 175//687 314//630 327//640 +f 1160//364 1187//363 1159//1669 +f 1159//1669 1187//363 1198//1670 +f 1198//1670 1187//363 317//1675 +f 79//1671 179//1676 126//1667 +f 1043//931 250//1435 392//735 +f 152//1668 1043//931 392//735 +f 96//1113 819//1124 593//1146 +f 1123//1673 1127//1677 1169//1674 +f 317//1675 179//1676 79//1671 +f 1057//891 1155//1672 179//1676 +f 1155//1672 391//771 131//844 +f 131//844 391//771 668//772 +f 2381//25 1586//1244 1585//26 +f 12//47 69//192 499//1379 +f 262//146 398//145 1640//191 +f 2107//927 2118//1475 2060//841 +f 2130//1678 2094//1092 2002//1070 +f 1187//363 249//805 317//1675 +f 1155//1672 1057//891 391//771 +f 1290//932 439//822 1265//821 +f 305//38 239//1577 107//761 +f 1127//1677 1160//364 1169//1674 +f 317//1675 473//907 179//1676 +f 473//907 1057//891 179//1676 +f 83//688 1192//610 314//630 +f 1043//931 1290//932 250//1435 +f 1807//1661 940//152 1030//830 +f 517//866 1084//189 445//188 +f 1057//891 1164//804 391//771 +f 2492//247 2480//473 2493//597 +f 163//410 643//548 43//408 +f 1056//1563 1545//1461 1303//1460 +f 1069//1 1655//906 1023//1679 +f 249//805 473//907 317//1675 +f 1162//392 1060//1505 1170//393 +f 1086//57 1118//55 1154//54 +f 82//607 68//651 16//693 +f 1989//1680 1990//1681 1536//1382 +f 1633//1403 1632//30 1611//187 +f 1487//390 2372//1682 1305//997 +f 1494//212 1069//1 1023//1679 +f 1137//853 1160//364 1127//1677 +f 669//35 1166//34 679//1038 +f 390//806 1285//1683 426//828 +f 1955//1322 1972//213 1971//215 +f 1219//1348 1223//1625 2437//1684 +f 1254//15 1261//17 1223//1625 +f 1319//1685 1545//1461 1056//1563 +f 1320//1416 1328//1686 2443//1687 +f 1261//17 1433//1606 1223//1625 +f 1219//1348 1254//15 1223//1625 +f 254//592 222//593 2428//1128 +f 1237//1688 1290//932 1265//821 +f 1284//1689 1273//714 1263//1690 +f 1277//1691 1291//777 1301//1692 +f 1314//768 102//739 1301//1692 +f 1280//1693 363//346 377//260 +f 1313//1377 1353//1337 1514//303 +f 468//917 451//820 439//822 +f 1918//1143 1964//1694 1956//1695 +f 2026//1224 29//1696 2140//1268 +f 1354//890 381//904 1279//1697 +f 1224//1175 30//16 1254//15 +f 147//900 158//929 173//921 +f 1247//1698 1253//1699 274//762 +f 1271//1700 380//797 334//754 +f 2043//1701 2072//1231 2042//1232 +f 274//762 300//753 267//746 +f 1356//780 1392//1702 211//752 +f 13//1325 240//135 1142//1263 +f 1382//792 1330//1703 1392//1702 +f 1312//1704 1323//457 155//1608 +f 240//135 1125//1264 1142//1263 +f 2358//446 1573//445 1362//1526 +f 1236//535 1249//817 1244//169 +f 1272//1619 219//167 1348//1324 +f 1271//1700 1274//1705 380//797 +f 191//480 2034//175 1982//1706 +f 1992//214 2052//1497 1990//1681 +f 462//615 452//926 689//658 +f 2262//1707 2286//1708 2261//1709 +f 183//216 489//62 1642//1710 +f 2485//596 2480//473 1869//225 +f 84//590 111//458 1323//457 +f 1190//1711 353//875 1354//890 +f 446//287 434//1712 435//261 +f 1336//898 171//887 1341//1713 +f 2021//493 430//177 2059//788 +f 862//1196 878//1132 1120//23 +f 1263//1690 1273//714 1248//1714 +f 1966//1217 1921//1216 2144//1715 +f 1312//1704 84//590 1323//457 +f 240//135 13//1325 1348//1324 +f 1359//1716 1274//1705 1271//1700 +f 1392//1702 1330//1703 1247//1698 +f 1520//1717 1333//939 11//882 +f 1368//1718 1253//1699 1247//1698 +f 1279//1697 1285//1683 1190//1711 +f 2465//678 990//1459 2489//632 +f 1272//1619 1519//1326 805//1719 +f 1369//1720 1272//1619 805//1719 +f 1317//149 95//151 1344//1721 +f 1242//1722 1248//1714 1234//698 +f 1368//1718 242//883 1363//870 +f 274//762 1262//1723 1386//763 +f 532//1724 597//1725 1886//1726 +f 2117//235 2026//1224 2140//1268 +f 1392//1702 1247//1698 274//762 +f 2162//1727 508//1728 985//1729 +f 1964//1694 1469//1730 1965//1731 +f 1315//790 104//839 1331//791 +f 1392//1702 1356//780 1382//792 +f 128//534 1342//533 1336//898 +f 1285//1683 427//876 426//828 +f 1219//1348 1224//1175 1254//15 +f 1320//1416 1322//832 1321//1732 +f 1320//1416 1321//1732 1328//1686 +f 153//1733 2443//1687 1328//1686 +f 1321//1732 153//1733 1328//1686 +f 1235//1226 1244//169 1243//1734 +f 1225//1347 1224//1175 1219//1348 +f 1359//1716 353//875 1190//1711 +f 1312//1704 1473//1735 1458//1402 +f 1336//898 1342//533 147//900 +f 305//38 1333//939 1038//694 +f 1336//898 147//900 171//887 +f 516//963 31//659 19//1129 +f 2479//648 2461//776 842//1341 +f 1237//1688 1265//821 427//876 +f 1263//1690 1278//1736 1284//1689 +f 881//232 1827//1260 834//1274 +f 1237//1688 427//876 1285//1683 +f 1299//591 1312//1704 1458//1402 +f 1190//1711 1285//1683 1274//1705 +f 1363//870 286//869 1253//1699 +f 2330//1464 2303//1499 828//1437 +f 427//876 442//846 426//828 +f 2493//597 2463//245 2492//247 +f 1285//1683 380//797 1274//1705 +f 522//1094 18//490 1225//1347 +f 2471//634 2472//812 2488//635 +f 2338//1607 154//1737 1321//1732 +f 1423//1626 1415//1630 1218//1627 +f 1225//1347 18//490 1224//1175 +f 1253//1699 286//869 1262//1723 +f 286//869 353//875 1359//1716 +f 171//887 1368//1718 1383//1738 +f 1273//714 54//669 1234//698 +f 1973//950 2447//1299 527//1261 +f 1322//832 155//1608 1321//1732 +f 1203//127 1369//1720 1413//1739 +f 1307//347 363//346 1298//368 +f 1364//1740 1375//164 1329//1741 +f 1329//1741 227//163 1306//155 +f 296//366 1298//368 1343//367 +f 947//1160 2499//569 1447//1161 +f 1203//127 1047//125 1272//1619 +f 1098//1658 1748//1742 1123//1673 +f 1519//1326 1272//1619 1348//1324 +f 1277//1691 70//715 1273//714 +f 1282//1743 1337//1744 1361//1745 +f 286//869 302//871 353//875 +f 103//809 104//839 1315//790 +f 1377//262 435//261 434//1712 +f 1449//665 1261//17 1345//928 +f 926//794 1310//793 806//745 +f 1263//1690 1248//1714 1242//1722 +f 985//1729 508//1728 597//1725 +f 1415//1630 1222//1746 1218//1627 +f 88//865 1325//886 104//839 +f 170//456 111//458 156//645 +f 1384//1747 1282//1743 1361//1745 +f 274//762 1253//1699 1262//1723 +f 1371//1748 1317//149 1344//1721 +f 1371//1748 1366//1749 1337//1744 +f 1345//928 1459//854 1449//665 +f 171//887 1383//1738 1341//1713 +f 2438//1227 1235//1226 1227//962 +f 2134//1543 1582//1750 2118//1475 +f 428//1445 1260//1751 1379//1752 +f 1336//898 1341//1713 1325//886 +f 1235//1226 1242//1722 1227//962 +f 1228//578 1687//1753 2284//1754 +f 1854//1621 2140//1268 2016//1270 +f 1866//424 1887//1755 1873//1756 +f 1343//367 1298//368 1370//1757 +f 1384//1747 1361//1745 2440//1758 +f 171//887 242//883 1368//1718 +f 1344//1721 1309//1759 1366//1749 +f 1371//1748 1344//1721 1366//1749 +f 1280//1693 1377//262 1293//1760 +f 200//1045 1185//1567 205//749 +f 1330//1703 1383//1738 1368//1718 +f 1255//168 1264//778 1263//1690 +f 543//1761 1367//1762 1876//1763 +f 1343//367 1370//1757 1260//1751 +f 1293//1760 1326//1764 1370//1757 +f 2440//1758 1361//1745 1302//1765 +f 1282//1743 1384//1747 2406//1766 +f 271//161 1337//1744 1282//1743 +f 170//456 2338//1607 1323//457 +f 1528//1767 1503//437 2470//1258 +f 515//1147 1347//1768 2453//1140 +f 1997//1769 1705//1770 1998//64 +f 2285//579 1228//578 2284//1754 +f 1229//1771 1250//1772 1228//578 +f 1330//1703 1368//1718 1247//1698 +f 1919//1773 1619//1774 2045//1775 +f 1344//1721 1364//1740 1335//1776 +f 1222//1746 1240//1482 1221//1481 +f 1212//1777 858//1778 1741//1779 +f 2388//1780 1222//1746 1221//1481 +f 1528//1767 2470//1258 2068//344 +f 501//1297 1308//1296 2171//1334 +f 1295//1781 1311//198 1487//390 +f 2116//1782 1619//1774 1655//906 +f 1220//1783 1229//1771 1228//578 +f 8//1327 663//1115 573//1098 +f 1343//367 1260//1751 428//1445 +f 1337//1744 1366//1749 1361//1745 +f 1298//368 1280//1693 1293//1760 +f 1269//509 1345//928 1261//17 +f 1279//1697 381//904 1290//932 +f 1230//1784 1229//1771 1220//1783 +f 1230//1784 1245//1785 1229//1771 +f 1245//1785 1250//1772 1229//1771 +f 1227//962 1234//698 31//659 +f 1302//1765 1361//1745 1350//1786 +f 1245//1785 1266//1648 1428//1476 +f 1992//214 2023//1642 2052//1497 +f 2482//1126 2471//634 2475//633 +f 452//926 462//615 461//666 +f 271//161 1282//1743 1275//1491 +f 1991//1787 1989//1680 1934//1788 +f 1366//1749 1309//1759 1350//1786 +f 1344//1721 1335//1776 1309//1759 +f 730//1065 699//1102 974//1177 +f 1374//1636 1252//1637 1208//1286 +f 597//1725 508//1728 1912//1789 +f 1363//870 1253//1699 1368//1718 +f 1386//763 1271//1700 300//753 +f 1211//1790 1218//1627 1222//1746 +f 1376//1791 1377//262 434//1712 +f 2399//1792 2437//1684 1211//1790 +f 1284//1689 1291//777 1277//1691 +f 1230//1784 1251//1647 1245//1785 +f 1251//1647 1266//1648 1245//1785 +f 1317//149 1371//1748 1337//1744 +f 1288//1793 1286//1794 1095//1287 +f 1095//1287 1286//1794 1352//1285 +f 1241//1795 1208//1286 1352//1285 +f 1241//1795 1374//1636 1208//1286 +f 1284//1689 1278//1736 1291//777 +f 211//752 1392//1702 267//746 +f 1344//1721 1375//164 1364//1740 +f 929//208 583//207 1028//856 +f 1361//1745 1366//1749 1350//1786 +f 1115//1336 1294//1514 1639//603 +f 1291//777 103//809 1301//1692 +f 1220//1783 1231//1796 1230//1784 +f 1231//1796 1251//1647 1230//1784 +f 1234//698 1248//1714 1273//714 +f 1255//168 55//779 1264//778 +f 1360//1624 1450//1643 1702//1797 +f 363//346 1280//1693 1298//368 +f 1369//1720 1203//127 1272//1619 +f 1415//1630 1240//1482 1222//1746 +f 1216//1798 1231//1796 1220//1783 +f 1243//1734 1263//1690 1235//1226 +f 1375//164 227//163 1329//1741 +f 1264//778 1278//1736 1263//1690 +f 855//1317 899//1374 961//679 +f 1286//1794 1241//1795 1352//1285 +f 2081//840 2128//1474 2107//927 +f 1223//1625 1433//1606 1423//1626 +f 1473//1735 1312//1704 155//1608 +f 154//1737 153//1733 1321//1732 +f 1377//262 1376//1791 1293//1760 +f 1392//1702 274//762 267//746 +f 334//754 300//753 1271//1700 +f 1955//1322 1991//1787 1934//1788 +f 1613//1400 1327//1799 1288//1793 +f 1327//1799 1286//1794 1288//1793 +f 1349//1800 1374//1636 1241//1795 +f 2370//1801 2025//426 2367//428 +f 1315//790 1331//791 133//767 +f 434//1712 446//287 1256//1802 +f 1232//1803 1251//1647 1231//1796 +f 1243//1734 1244//169 1255//168 +f 1286//1794 1304//1804 1241//1795 +f 1349//1800 1107//1355 1374//1636 +f 1359//1716 1271//1700 1386//763 +f 1227//962 516//963 2431//1520 +f 219//167 240//135 1348//1324 +f 1270//1492 271//161 1275//1491 +f 1255//168 1263//1690 1243//1734 +f 2026//1224 1926//1805 29//1696 +f 1683//122 2157//1649 1212//1777 +f 1326//1764 1293//1760 1376//1791 +f 1255//168 32//170 55//779 +f 104//839 1325//886 1341//1713 +f 519//680 2462//325 2475//633 +f 2154//1806 2161//1332 2137//1807 +f 1376//1791 434//1712 1246//1808 +f 1246//1808 434//1712 1256//1802 +f 1257//1535 1251//1647 1232//1803 +f 1262//1723 1359//1716 1386//763 +f 2195//1533 2192//1532 2186//1809 +f 1308//1296 534//1031 1226//217 +f 2026//1224 2117//235 544//244 +f 1327//1799 1613//1400 1324//1547 +f 1327//1799 1326//1764 1286//1794 +f 1286//1794 1326//1764 1304//1804 +f 104//839 1341//1713 1331//791 +f 774//1176 524//530 880//1545 +f 837//1810 1517//1032 534//1031 +f 1127//1677 1123//1673 1567//1811 +f 1279//1697 1237//1688 1285//1683 +f 1297//1812 1381//96 1294//1514 +f 1217//1813 1232//1803 1216//1798 +f 1142//1263 1519//1326 13//1325 +f 1436//1477 1267//1467 1287//1478 +f 1324//1547 1372//1814 1327//1799 +f 1304//1804 1246//1808 1241//1795 +f 1246//1808 1349//1800 1241//1795 +f 1246//1808 1373//1815 1349//1800 +f 286//869 1359//1716 1262//1723 +f 1382//792 1383//1738 1330//1703 +f 1284//1689 1277//1691 1273//714 +f 489//62 1998//64 1799//1448 +f 1675//1816 1116//1265 1075//827 +f 106//147 1317//149 1337//1744 +f 1311//198 1295//1781 1281//1817 +f 1292//1818 1364//1740 1329//1741 +f 1335//1776 1364//1740 1292//1818 +f 1334//1335 1294//1514 1115//1336 +f 1334//1335 1297//1812 1294//1514 +f 1300//97 1381//96 1297//1812 +f 973//1342 842//1341 2461//776 +f 1217//1813 1239//1819 1232//1803 +f 1232//1803 1239//1819 1257//1535 +f 1258//1466 1267//1467 1436//1477 +f 1359//1716 1190//1711 1274//1705 +f 1862//451 1405//453 1877//462 +f 1372//1814 1339//1820 1327//1799 +f 1339//1820 1326//1764 1327//1799 +f 1373//1815 1351//1821 1349//1800 +f 1276//196 1311//198 1281//1817 +f 1256//1802 2386//1822 1351//1821 +f 2//110 1109//98 1300//97 +f 482//1823 1731//1824 520//1825 +f 803//1826 1604//1827 2022//1828 +f 1223//1625 1218//1627 1211//1790 +f 1341//1713 1383//1738 1382//792 +f 1298//368 1293//1760 1370//1757 +f 1190//1711 1354//890 1279//1697 +f 1324//1547 2398//1829 1372//1814 +f 1714//1830 1700//1831 2173//1554 +f 183//216 2000//63 489//62 +f 1701//1406 1666//1408 192//1832 +f 1227//962 1242//1722 1234//698 +f 1332//1833 1289//1376 1310//793 +f 1517//1032 2005//1834 2130//1678 +f 1331//791 1341//1713 1382//792 +f 525//1239 1249//817 1236//535 +f 23//178 1268//1835 1450//1643 +f 1264//778 1291//777 1278//1736 +f 1281//1817 1287//1478 1267//1467 +f 1295//1781 1305//997 1287//1478 +f 1281//1817 1295//1781 1287//1478 +f 1487//390 1305//997 1295//1781 +f 1605//1836 2097//1837 2058//1838 +f 1326//1764 1376//1791 1304//1804 +f 1304//1804 1376//1791 1246//1808 +f 1316//394 1919//1773 1984//1839 +f 2500//233 1949//1319 2460//407 +f 1332//1833 1313//1377 1289//1376 +f 2189//1840 2181//1841 2177//1471 +f 1335//1776 1334//1335 1353//1337 +f 1292//1818 1297//1812 1334//1335 +f 1428//1476 1250//1772 1245//1785 +f 969//879 958//1424 952//1423 +f 1217//1813 1233//278 1239//1819 +f 1233//278 1257//1535 1239//1819 +f 1876//1763 1367//1762 1338//1842 +f 1379//1752 1260//1751 1372//1814 +f 1372//1814 1260//1751 1339//1820 +f 1128//795 1302//1765 1310//793 +f 1310//793 1302//1765 1332//1833 +f 1335//1776 1353//1337 1313//1377 +f 1292//1818 1334//1335 1335//1776 +f 1297//1812 1329//1741 1300//97 +f 1279//1697 1290//932 1237//1688 +f 1301//1692 103//809 1314//768 +f 70//715 1301//1692 102//739 +f 23//178 1333//939 1268//1835 +f 380//797 1285//1683 390//806 +f 772//1843 325//200 1275//1491 +f 1314//768 103//809 1315//790 +f 2473//29 2458//311 2487//310 +f 1276//196 1281//1817 1267//1467 +f 1344//1721 95//151 1375//164 +f 2053//1844 1771//786 1572//785 +f 1246//1808 1256//1802 1373//1815 +f 1373//1815 1256//1802 1351//1821 +f 1340//1845 1302//1765 1128//795 +f 1350//1786 1313//1377 1332//1833 +f 1329//1741 1297//1812 1292//1818 +f 2434//27 2473//29 2487//310 +f 106//147 1337//1744 271//161 +f 23//178 471//158 1333//939 +f 622//1109 723//1151 509//1645 +f 1388//1280 1517//1032 2127//1071 +f 1991//1787 1990//1681 1989//1680 +f 183//216 1636//1557 1226//217 +f 2133//1846 1605//1836 2151//1633 +f 1260//1751 1370//1757 1339//1820 +f 1339//1820 1370//1757 1326//1764 +f 867//1458 1894//1847 1902//1276 +f 390//806 426//828 412//781 +f 1235//1226 1263//1690 1242//1722 +f 1399//1587 1422//276 1233//278 +f 305//38 11//882 1333//939 +f 1300//97 1329//1741 1306//155 +f 1302//1765 1350//1786 1332//1833 +f 1350//1786 1309//1759 1313//1377 +f 1309//1759 1335//1776 1313//1377 +f 2470//1258 2102//1848 1502//231 +f 1787//1849 1531//1850 1599//1851 +f 1724//1852 1725//1853 1691//1854 +f 1827//1260 1601//1259 1927//1855 +f 1678//1856 1358//1857 1476//1858 +f 1823//95 1812//307 1846//1430 +f 1805//120 1824//1859 1708//1431 +f 1746//1860 1676//1861 1797//1862 +f 325//200 2395//229 429//218 +f 1835//1253 1677//1125 1826//1863 +f 1507//123 1790//1864 1722//1386 +f 1526//1865 1672//1866 858//1778 +f 158//929 147//900 1342//533 +f 1462//831 1473//1735 1322//832 +f 1474//438 1414//1867 1565//436 +f 1761//1868 1900//463 1877//462 +f 940//152 1759//1662 1008//1869 +f 1565//436 1015//1870 1008//1869 +f 1924//1184 1533//1871 1933//1872 +f 1878//423 826//425 830//750 +f 1565//436 1414//1867 1015//1870 +f 1402//1610 1088//1609 1008//1869 +f 1538//1873 1532//1874 1651//478 +f 1015//1870 1552//1875 1008//1869 +f 1538//1873 1591//1876 1474//438 +f 1532//1874 1538//1873 1474//438 +f 1474//438 1591//1876 1414//1867 +f 1484//1877 1402//1610 1008//1869 +f 1552//1875 1484//1877 1008//1869 +f 1414//1867 1460//1878 1015//1870 +f 1015//1870 1460//1878 1552//1875 +f 806//745 1289//1376 945//302 +f 1597//1879 1538//1873 1659//1880 +f 1484//1877 1319//1685 1402//1610 +f 1056//1563 1402//1610 1319//1685 +f 1538//1873 1597//1879 1591//1876 +f 1591//1876 960//1881 1414//1867 +f 1414//1867 960//1881 1460//1878 +f 1925//86 1466//1882 1455//84 +f 1552//1875 1400//1883 1484//1877 +f 1484//1877 1400//1883 1319//1685 +f 1400//1883 113//1884 1319//1685 +f 1597//1879 1580//1885 1591//1876 +f 1460//1878 1400//1883 1552//1875 +f 1514//303 1441//1439 966//1362 +f 1597//1879 1659//1880 1409//744 +f 1657//1886 113//1884 1400//1883 +f 1460//1878 1657//1886 1400//1883 +f 1288//1793 1095//1287 1634//1339 +f 1551//1525 1597//1879 1409//744 +f 1580//1885 1598//1887 1591//1876 +f 1591//1876 1598//1887 960//1881 +f 1536//1382 1990//1681 2031//842 +f 960//1881 1657//1886 1460//1878 +f 1809//1888 1746//1860 1797//1862 +f 1423//1626 1433//1606 1432//664 +f 2478//743 1362//1526 1409//744 +f 1463//1639 1545//1461 113//1884 +f 1657//1886 1463//1639 113//1884 +f 1457//996 1287//1478 1305//997 +f 1682//1889 1716//1890 1746//1860 +f 1434//1891 1761//1868 1885//1892 +f 1013//1202 1139//605 1617//1479 +f 2379//1893 1362//1526 2478//743 +f 1420//1894 1597//1879 1551//1525 +f 1420//1894 1580//1885 1597//1879 +f 1664//1895 1808//1896 1712//1897 +f 2256//1898 2250//1899 2231//1900 +f 1362//1526 1551//1525 1409//744 +f 2196//1901 2214//1902 2213//1903 +f 1691//1854 1725//1853 1777//1904 +f 1626//1905 192//1832 1666//1408 +f 1534//1906 1574//1907 2058//1838 +f 1574//1907 1600//1908 1605//1836 +f 1600//1908 1606//1909 1605//1836 +f 1606//1909 1641//1634 1605//1836 +f 1573//445 1420//1894 1551//1525 +f 1657//1886 1485//1910 1463//1639 +f 678//1440 1806//1911 1742//1912 +f 1534//1906 1553//1913 1574//1907 +f 1574//1907 1575//1914 1600//1908 +f 1810//1915 2170//1632 585//1916 +f 1623//1917 1641//1634 1606//1909 +f 1407//1918 1657//1886 960//1881 +f 1598//1887 1407//1918 960//1881 +f 1485//1910 1142//1263 1463//1639 +f 1716//1890 1581//1919 1676//1861 +f 1738//1920 1743//1921 1733//1922 +f 843//1316 2064//613 835//1059 +f 1539//1923 1575//1914 1574//1907 +f 1553//1913 1539//1923 1574//1907 +f 1575//1914 1592//1924 1600//1908 +f 1592//1924 1624//1925 1606//1909 +f 1600//1908 1592//1924 1606//1909 +f 1642//1710 585//1916 1641//1634 +f 1623//1917 1642//1710 1641//1634 +f 1485//1910 164//1926 1142//1263 +f 1738//1920 1516//121 1743//1921 +f 1809//1888 1720//784 1798//1432 +f 1533//1871 1535//1927 1534//1906 +f 1592//1924 1607//1928 1624//1925 +f 1624//1925 1623//1917 1606//1909 +f 1163//816 566//1168 1116//1265 +f 1407//1918 1485//1910 1657//1886 +f 1432//664 1449//665 1439//855 +f 1100//77 802//1605 2382//1197 +f 1743//1921 1516//121 1722//1386 +f 1746//1860 1716//1890 1676//1861 +f 1535//1927 1539//1923 1534//1906 +f 1534//1906 1539//1923 1553//1913 +f 1642//1710 1623//1917 1624//1925 +f 1095//1287 1208//1286 1654//31 +f 967//1929 1407//1918 1598//1887 +f 1580//1885 967//1929 1598//1887 +f 1809//1888 1797//1862 1720//784 +f 1924//1184 1524//1930 1535//1927 +f 1533//1871 1924//1184 1535//1927 +f 1539//1923 1576//1931 1575//1914 +f 1642//1710 216//1450 585//1916 +f 1407//1918 1529//1932 1485//1910 +f 1485//1910 1529//1932 164//1926 +f 1472//1468 1462//831 1482//833 +f 1415//1630 1431//1212 1240//1482 +f 966//1362 1194//1438 714//419 +f 383//99 1182//101 152//1668 +f 474//288 2337//1291 446//287 +f 1743//1921 1841//1385 1757//1933 +f 1486//1934 1524//1930 1924//1184 +f 1535//1927 1525//1935 1539//1923 +f 1575//1914 1576//1931 1592//1924 +f 1420//1894 967//1929 1580//1885 +f 1288//1793 1634//1339 1613//1400 +f 459//857 427//876 1265//821 +f 1404//1936 2179//1523 1393//1937 +f 1404//1936 1403//859 1800//1938 +f 1404//1936 1410//1939 1403//859 +f 1410//1939 1749//1940 1403//859 +f 1349//1800 1351//1821 218//1356 +f 1486//1934 1498//1941 1524//1930 +f 1535//1927 1524//1930 1525//1935 +f 1607//1928 1636//1557 1624//1925 +f 183//216 1642//1710 1624//1925 +f 1636//1557 183//216 1624//1925 +f 1107//1355 1349//1800 218//1356 +f 1351//1821 845//1942 218//1356 +f 164//1926 1519//1326 1142//1263 +f 845//1942 413//1350 218//1356 +f 1525//1935 1576//1931 1539//1923 +f 1576//1931 1582//1750 1592//1924 +f 1592//1924 2134//1543 1607//1928 +f 2134//1543 1636//1557 1607//1928 +f 2147//1943 1491//1944 1401//1596 +f 1407//1918 1589//1945 1529//1932 +f 1529//1932 1519//1326 164//1926 +f 1693//1946 1763//858 1444//860 +f 1924//1184 1479//1183 1486//1934 +f 1592//1924 1582//1750 2134//1543 +f 499//1379 165//472 874//471 +f 2176//1469 1857//1947 1959//1494 +f 2327//1948 2368//1949 2326//1950 +f 2358//446 821//1951 953//444 +f 953//444 821//1951 1573//445 +f 1824//1859 1704//1952 1464//1953 +f 1731//1824 1358//1857 1678//1856 +f 1394//1954 1410//1939 1404//1936 +f 1394//1954 1418//529 1410//1939 +f 1466//1882 1479//1183 1839//1955 +f 1486//1934 1479//1183 1498//1941 +f 1498//1941 1525//1935 1524//1930 +f 1576//1931 2080//1956 1582//1750 +f 1785//1957 1684//1288 1898//1304 +f 804//79 398//145 802//1605 +f 804//79 925//1357 398//145 +f 1447//1161 1562//1958 2358//446 +f 2358//446 1562//1958 821//1951 +f 821//1951 1620//1959 1573//445 +f 1620//1959 1420//1894 1573//445 +f 1420//1894 1556//1960 967//1929 +f 1393//1937 1394//1954 1404//1936 +f 1525//1935 2080//1956 1576//1931 +f 1621//1961 1420//1894 1620//1959 +f 1621//1961 1556//1960 1420//1894 +f 967//1929 1589//1945 1407//1918 +f 1505//1962 5//1963 1357//1964 +f 1266//1648 1258//1466 1436//1477 +f 1393//1937 1395//1965 1394//1954 +f 2176//1469 2175//1262 1848//1966 +f 1455//84 1466//1882 1839//1955 +f 1525//1935 1540//1096 2080//1956 +f 1582//1750 2080//1956 2118//1475 +f 1100//77 804//79 802//1605 +f 1556//1960 1589//1945 967//1929 +f 1589//1945 1082//1967 1529//1932 +f 1093//1968 1685//1447 1357//1964 +f 1504//1269 1093//1968 1357//1964 +f 1425//1969 1418//529 1394//1954 +f 1475//1970 1479//1183 1466//1882 +f 1479//1183 1506//1971 1498//1941 +f 1789//51 1784//1972 1730//510 +f 2501//405 2465//678 2489//632 +f 1438//1211 1458//1402 1430//1378 +f 1462//831 1458//1402 1473//1735 +f 1454//1973 805//1719 1529//1932 +f 1082//1967 1454//1973 1529//1932 +f 1529//1932 805//1719 1519//1326 +f 1425//1969 1394//1954 1395//1965 +f 1425//1969 1744//527 1418//529 +f 1479//1183 1475//1970 1506//1971 +f 1540//1096 2060//841 2080//1956 +f 1556//1960 1082//1967 1589//1945 +f 1443//656 945//302 1511//304 +f 1506//1971 1536//1382 1498//1941 +f 1498//1941 1536//1382 1525//1935 +f 1525//1935 1536//1382 1540//1096 +f 1670//1974 852//1975 1672//1866 +f 1998//64 1388//1280 1389//1976 +f 1511//304 966//1362 1509//1622 +f 1509//1622 966//1362 714//419 +f 1442//1358 1443//656 1496//1360 +f 1562//1958 1635//1977 821//1951 +f 155//1608 1322//832 1473//1735 +f 1439//855 1458//1402 1438//1211 +f 1426//1978 1425//1969 1395//1965 +f 1475//1970 1499//1979 1506//1971 +f 1735//1980 1588//1981 1776//1982 +f 2422//1521 2454//1139 2421//1983 +f 1423//1626 1432//664 1415//1630 +f 1559//1984 2101//1985 2073//1986 +f 845//1942 866//1987 413//1350 +f 1429//1988 1620//1959 821//1951 +f 1620//1959 1429//1988 1621//1961 +f 1228//578 1250//1772 1687//1753 +f 1002//78 945//302 1443//656 +f 2382//1197 802//1605 1083//144 +f 1859//983 1411//1989 1395//1965 +f 1411//1989 1426//1978 1395//1965 +f 1426//1978 1744//527 1425//1969 +f 1590//852 1437//851 1483//691 +f 1480//1990 1475//1970 1466//1882 +f 1480//1990 1499//1979 1475//1970 +f 1510//1991 1733//1922 1743//1921 +f 1663//1992 1696//205 1658//1993 +f 1430//1378 1453//1381 1452//1502 +f 1452//1502 1472//1468 1471//197 +f 1452//1502 1471//197 1448//1503 +f 1430//1378 1452//1502 1421//277 +f 1430//1378 1421//277 1422//276 +f 1429//1988 1082//1967 1556//1960 +f 1621//1961 1429//1988 1556//1960 +f 1351//1821 2386//1822 845//1942 +f 1126//14 1059//13 487//492 +f 1639//603 1437//851 1563//850 +f 1504//1269 1928//1582 1093//1968 +f 1499//1979 1536//1382 1506//1971 +f 1588//1981 1770//1994 1727//1995 +f 1110//1573 1747//1254 1397//1580 +f 1776//1982 1588//1981 1531//1850 +f 1322//832 1320//1416 1482//833 +f 1590//852 1629//620 1571//619 +f 1730//510 1877//462 1838//461 +f 1429//1988 935//1996 1082//1967 +f 1082//1967 935//1996 1454//1973 +f 804//79 1443//656 925//1357 +f 1139//605 1007//1201 1639//603 +f 1925//86 1480//1990 1466//1882 +f 1934//1788 1989//1680 1480//1990 +f 1499//1979 1989//1680 1536//1382 +f 1727//1995 1526//1865 1531//1850 +f 1593//1997 1614//1998 502//1999 +f 2455//2000 2431//1520 2400//1369 +f 1755//1449 1680//1506 908//2001 +f 1563//850 1571//619 1564//604 +f 1647//2 1078//211 1501//421 +f 2490//1235 1635//1977 1106//1321 +f 1496//1360 1511//304 717//69 +f 2454//1139 2431//1520 516//963 +f 1478//2002 1153//1570 1093//1968 +f 1870//1234 1426//1978 1411//1989 +f 1426//1978 1723//1359 1744//527 +f 962//1417 986//1426 1412//222 +f 717//69 1511//304 1509//1622 +f 1825//2003 1704//1952 1824//1859 +f 2225//2004 2234//2005 2253//2006 +f 1490//70 1557//171 1188//105 +f 1635//1977 80//2007 821//1951 +f 805//1719 1454//1973 935//1996 +f 1186//1292 706//1018 695//1229 +f 1194//1438 1161//1443 714//419 +f 1512//420 1007//1201 1013//1202 +f 592//267 97//357 204//195 +f 1258//1466 1266//1648 1257//1535 +f 82//607 1333//939 471//158 +f 1694//1245 1710//614 1505//1962 +f 1643//2008 490//2009 1661//2010 +f 1661//2010 490//2009 1114//2011 +f 1518//1104 2068//344 2484//343 +f 1750//2012 1808//1896 1664//1895 +f 1656//1562 1635//1977 2490//1235 +f 935//1996 1521//2013 805//1719 +f 1546//1312 1629//620 1076//1310 +f 1301//1692 70//715 1277//1691 +f 966//1362 1441//1439 1194//1438 +f 1148//331 1825//2003 1824//1859 +f 1614//1998 1609//2014 1643//2008 +f 1114//2011 1092//2015 1921//1216 +f 1770//1994 1739//1488 1670//1974 +f 1631//330 1632//30 1646//32 +f 821//1951 1016//2016 1429//1988 +f 1429//1988 1016//2016 935//1996 +f 1632//30 1095//1287 1654//31 +f 1083//144 262//146 688//160 +f 1724//1852 1686//2017 1725//1853 +f 1644//2018 490//2009 1643//2008 +f 1092//2015 1149//1453 1921//1216 +f 3//1594 893//2019 1832//2020 +f 988//1375 1640//191 1188//105 +f 916//934 1107//1355 284//1351 +f 1656//1562 80//2007 1635//1977 +f 1016//2016 821//1951 80//2007 +f 1016//2016 1521//2013 935//1996 +f 1478//2002 1202//36 1153//1570 +f 1401//1596 1928//1582 29//1696 +f 1440//37 1478//2002 1928//1582 +f 1849//2021 1700//1831 1865//2022 +f 1595//81 1611//187 1612//1228 +f 1208//1286 198//1340 341//133 +f 1464//1953 1704//1952 1746//1860 +f 2143//2023 984//2024 1721//2025 +f 1848//1966 1849//2021 1868//2026 +f 1662//2027 1114//2011 490//2009 +f 1669//2028 1787//1849 1682//1889 +f 1656//1562 1618//2029 80//2007 +f 198//1340 1208//1286 916//934 +f 1440//37 1928//1582 1401//1596 +f 1521//2013 1369//1720 805//1719 +f 1252//1637 1107//1355 916//934 +f 1745//1414 678//1440 1672//1866 +f 1703//2030 1779//2031 1721//2025 +f 1750//2012 1465//1584 1808//1896 +f 1609//2014 1644//2018 1643//2008 +f 1092//2015 1114//2011 1662//2027 +f 1826//1863 1523//1510 1793//2032 +f 2262//1707 2261//1709 2224//2033 +f 1696//205 2166//2034 1767//206 +f 1016//2016 1648//2035 1521//2013 +f 1208//1286 1252//1637 916//934 +f 833//138 688//160 1067//1364 +f 1794//1507 1803//1387 1558//1538 +f 28//338 17//1230 512//1136 +f 1750//2012 861//2036 1566//2037 +f 1594//2038 1644//2018 1609//2014 +f 1644//2018 1645//2039 490//2009 +f 490//2009 1645//2039 1662//2027 +f 2229//2040 2262//1707 2224//2033 +f 1602//2041 861//2036 1760//2042 +f 1530//2043 1777//1904 1760//2042 +f 872//1493 1706//1500 1673//1056 +f 1696//205 1668//1537 2166//2034 +f 1708//1431 1809//1888 1798//1432 +f 1581//1919 1716//1890 1814//2044 +f 1709//1407 1794//1507 1680//1506 +f 1233//278 1421//277 1257//1535 +f 1724//1852 1476//1858 1686//2017 +f 1469//1730 1481//2045 1965//1731 +f 1965//1731 1481//2045 1492//2046 +f 2073//1986 1549//2047 1559//1984 +f 1594//2038 1615//2048 1644//2018 +f 1799//1448 1706//1500 1755//1449 +f 1725//1853 1686//2017 1837//2049 +f 1720//784 1797//1862 1572//785 +f 1618//2029 2467//868 2022//1828 +f 1618//2029 1579//2050 80//2007 +f 1648//2035 1016//2016 80//2007 +f 2134//1543 2152//1550 1636//1557 +f 1611//187 1632//30 1631//330 +f 1761//1868 1434//1891 1470//2051 +f 1559//1984 1577//2052 1594//2038 +f 1603//2053 1615//2048 1594//2038 +f 1615//2048 1645//2039 1644//2018 +f 1637//2054 1662//2027 1645//2039 +f 1662//2027 1199//2055 1092//2015 +f 1199//2055 1149//1453 1092//2015 +f 1451//2056 1108//2057 1149//1453 +f 665//185 734//184 756//1413 +f 1865//2022 1700//1831 1714//1830 +f 1709//1407 1841//1385 1794//1507 +f 1618//2029 2022//1828 1579//2050 +f 1648//2035 1413//1739 1369//1720 +f 1521//2013 1648//2035 1369//1720 +f 1520//1717 11//882 1401//1596 +f 1446//2058 1470//2051 1434//1891 +f 1798//1432 1691//1854 1754//2059 +f 2063//2060 1544//2061 2073//1986 +f 2073//1986 1544//2061 1549//2047 +f 1594//2038 1577//2052 1603//2053 +f 1615//2048 1637//2054 1645//2039 +f 1637//2054 1199//2055 1662//2027 +f 1427//2062 1149//1453 1199//2055 +f 2167//2063 1108//2057 1451//2056 +f 1997//1769 1673//1056 1705//1770 +f 1706//1500 1799//1448 1705//1770 +f 1841//1385 1709//1407 1757//1933 +f 1604//1827 1579//2050 2022//1828 +f 1579//2050 707//2064 80//2007 +f 80//2007 707//2064 1648//2035 +f 1520//1717 1401//1596 1491//1944 +f 1649//2065 1520//1717 1491//1944 +f 1435//2066 1434//1891 1885//1892 +f 1470//2051 1469//1730 1461//2067 +f 1481//2045 1508//2068 2024//2069 +f 2370//1801 1544//2061 2063//2060 +f 1549//2047 1568//2070 1559//1984 +f 1559//1984 1568//2070 1577//2052 +f 1603//2053 1610//2071 1615//2048 +f 1615//2048 1610//2071 1637//2054 +f 999//2072 1199//2055 1637//2054 +f 1451//2056 1149//1453 1427//2062 +f 1137//853 1825//2003 1148//331 +f 1706//1500 1705//1770 1673//1056 +f 1138//2073 1604//1827 2116//1782 +f 1138//2073 1579//2050 1604//1827 +f 1413//1739 1648//2035 707//2064 +f 2360//427 2024//2069 1508//2068 +f 598//825 1075//827 1116//1265 +f 229//770 93//993 1468//992 +f 1839//1955 1479//1183 1684//1288 +f 2216//1518 2229//2040 2224//2033 +f 1610//2071 1625//2074 1637//2054 +f 329//2075 999//2072 1637//2054 +f 1199//2055 1017//1660 1427//2062 +f 1017//1660 303//281 1427//2062 +f 303//281 1451//2056 1427//2062 +f 1792//2076 1754//2059 1777//1904 +f 2309//1279 2391//1278 2301//2077 +f 1655//906 1138//2073 2116//1782 +f 1138//2073 707//2064 1579//2050 +f 1649//2065 1491//1944 206//2078 +f 1406//2079 1885//1892 1398//75 +f 1406//2079 1419//2080 1885//1892 +f 1419//2080 1435//2066 1885//1892 +f 1434//1891 1435//2066 1446//2058 +f 1470//2051 1481//2045 1469//1730 +f 1577//2052 1583//1527 1603//2053 +f 999//2072 1017//1660 1199//2055 +f 81//2081 67//2082 941//2083 +f 67//2082 1650//2084 941//2083 +f 1259//2085 1815//2086 2164//1371 +f 1619//1774 2116//1782 2045//1775 +f 1424//2087 707//2064 1138//2073 +f 1702//1797 1649//2065 206//2078 +f 1687//1753 1406//2079 1398//75 +f 1477//998 1481//2045 1470//2051 +f 1568//2070 1569//2088 1577//2052 +f 1577//2052 1569//2088 1583//1527 +f 1603//2053 1583//1527 1610//2071 +f 1625//2074 329//2075 1637//2054 +f 2167//2063 340//1522 273//396 +f 81//2081 273//396 340//1522 +f 81//2081 962//1417 67//2082 +f 1547//119 1619//1774 1488//221 +f 1830//2089 1739//1488 1770//1994 +f 938//905 1424//2087 1138//2073 +f 1424//2087 1413//1739 707//2064 +f 1527//2090 1649//2065 1702//1797 +f 1527//2090 1520//1717 1649//2065 +f 1527//2090 1268//1835 1520//1717 +f 1250//1772 1406//2079 1687//1753 +f 1441//1439 1353//1337 1115//1336 +f 1203//127 1413//1739 1051//128 +f 1250//1772 1419//2080 1406//2079 +f 1477//998 2372//1682 1481//2045 +f 1481//2045 2372//1682 1508//2068 +f 2449//283 1560//2091 1568//2070 +f 1549//2047 2449//283 1568//2070 +f 1568//2070 1560//2091 1569//2088 +f 1569//2088 1584//41 1583//1527 +f 1652//234 329//2075 1625//2074 +f 329//2075 817//1420 999//2072 +f 285//1395 1017//1660 999//2072 +f 303//281 10//280 1451//2056 +f 10//280 2167//2063 1451//2056 +f 1412//222 1650//2084 67//2082 +f 1412//222 1488//221 1650//2084 +f 1547//119 1023//1679 1619//1774 +f 1023//1679 1655//906 1619//1774 +f 1655//906 938//905 1138//2073 +f 1456//1311 1413//1739 1424//2087 +f 1457//996 1470//2051 1446//2058 +f 1457//996 1477//998 1470//2051 +f 329//2075 1652//234 817//1420 +f 10//280 340//1522 2167//2063 +f 938//905 1546//1312 1424//2087 +f 1546//1312 1456//1311 1424//2087 +f 1259//2085 1548//2092 1779//2031 +f 2052//1497 2031//842 1990//1681 +f 1440//37 1202//36 1478//2002 +f 1428//1476 1419//2080 1250//1772 +f 1428//1476 1435//2066 1419//2080 +f 1428//1476 1446//2058 1435//2066 +f 1934//1788 1935//85 1955//1322 +f 1560//2091 1584//41 1569//2088 +f 1610//2071 1638//223 1625//2074 +f 1638//223 1652//234 1625//2074 +f 817//1420 1077//823 999//2072 +f 1077//823 285//1395 999//2072 +f 980//279 303//281 1017//1660 +f 962//1417 1412//222 67//2082 +f 1494//212 1023//1679 1547//119 +f 325//200 271//161 1270//1492 +f 1443//656 1511//304 1496//1360 +f 1450//1643 1268//1835 1527//2090 +f 1514//303 1353//1337 1441//1439 +f 1287//1478 1446//2058 1428//1476 +f 1446//2058 1287//1478 1457//996 +f 1305//997 2372//1682 1477//998 +f 1992//214 1990//1681 1991//1787 +f 1992//214 1991//1787 1971//215 +f 1971//215 1991//1787 1955//1322 +f 2449//283 1549//2047 2418//284 +f 1583//1527 1616//186 1610//2071 +f 1610//2071 1616//186 1638//223 +f 10//280 1396//1401 340//1522 +f 340//1522 1445//1418 81//2081 +f 1445//1418 962//1417 81//2081 +f 1790//1864 984//2024 1753//2093 +f 984//2024 2148//2094 1753//2093 +f 1588//1981 1713//2095 1770//1994 +f 969//879 978//878 958//1424 +f 1741//1779 1779//2031 1703//2030 +f 1758//2096 1846//1430 1754//2059 +f 1827//1260 1819//1615 1029//1559 +f 1818//2097 1530//2043 1712//1897 +f 1750//2012 1566//2037 2127//1071 +f 2459//570 2434//27 2483//775 +f 1798//1432 1720//784 1771//786 +f 1794//1507 1841//1385 1803//1387 +f 216//1450 1755//1449 1810//1915 +f 1098//1658 1735//1980 1748//1742 +f 1735//1980 1497//2098 1748//1742 +f 1502//231 2102//1848 1601//1259 +f 881//232 1502//231 1601//1259 +f 1455//84 1839//1955 1744//527 +f 1706//1500 1709//1407 1680//1506 +f 1212//1777 1741//1779 1703//2030 +f 1788//2099 1969//1472 1671//1539 +f 1075//827 1074//826 1692//1329 +f 951//1273 2500//233 881//232 +f 2490//1235 2486//568 2463//245 +f 1748//1742 1497//2098 1781//2100 +f 1721//2025 984//2024 1840//2101 +f 1815//2086 1259//2085 1741//1779 +f 1626//1905 1756//1055 1837//2049 +f 975//911 987//371 1542//2102 +f 2230//2103 2236//2104 2235//2105 +f 1772//1405 678//1440 734//184 +f 1542//2102 1671//1539 975//911 +f 1806//1911 1772//1405 1780//1372 +f 678//1440 1772//1405 1806//1911 +f 2218//2106 2225//2004 2268//2107 +f 1828//1425 1732//974 2007//1496 +f 1526//1865 1688//2108 1531//1850 +f 1752//2109 1526//1865 1554//2110 +f 1844//2111 1818//2097 1712//1897 +f 1823//95 1846//1430 1804//71 +f 1781//2100 1669//2028 1704//1952 +f 1721//2025 1779//2031 2143//2023 +f 1770//1994 1670//1974 1526//1865 +f 1497//2098 1669//2028 1781//2100 +f 1098//1658 1713//2095 1735//1980 +f 1742//1912 1815//2086 1741//1779 +f 1526//1865 858//1778 1875//1651 +f 1599//1851 1531//1850 1688//2108 +f 1803//1387 1790//1864 1558//1538 +f 1703//2030 1721//2025 1683//122 +f 1832//2020 1766//2112 957//2113 +f 1542//2102 1679//2114 1671//1539 +f 1679//2114 1788//2099 1671//1539 +f 1927//1855 1819//1615 1827//1260 +f 1718//1415 1745//1414 1739//1488 +f 1684//1288 1022//528 1839//1955 +f 1459//854 1283//556 1299//591 +f 1022//528 1410//1939 1418//529 +f 2368//1949 2393//2115 2326//1950 +f 1669//2028 1497//2098 1776//1982 +f 1875//1651 858//1778 1212//1777 +f 1739//1488 1745//1414 852//1975 +f 1964//1694 1918//1143 1461//2067 +f 1356//780 133//767 1331//791 +f 1765//994 1829//1487 1468//992 +f 858//1778 1742//1912 1741//1779 +f 1006//623 1674//625 1021//1390 +f 1723//1359 1936//1328 1935//85 +f 1468//992 1713//2095 1098//1658 +f 1724//1852 1678//1856 1476//1858 +f 1680//1506 1783//1508 908//2001 +f 1731//1824 1543//2116 520//1825 +f 1683//122 1721//2025 1840//2101 +f 1467//2117 1679//2114 1542//2102 +f 1812//307 1708//1431 1846//1430 +f 1679//2114 1975//2118 1788//2099 +f 1713//2095 1830//2089 1770//1994 +f 1803//1387 1722//1386 1790//1864 +f 2301//2077 2391//1278 2349//2119 +f 1713//2095 1588//1981 1735//1980 +f 1836//2120 1530//2043 1818//2097 +f 1837//2049 1756//1055 861//2036 +f 886//1250 571//1008 556//1551 +f 1181//111 1805//120 1812//307 +f 1706//1500 1680//1506 1755//1449 +f 1677//1125 1729//764 1775//1363 +f 1776//1982 1787//1849 1669//2028 +f 1526//1865 1670//1974 1672//1866 +f 1727//1995 1770//1994 1526//1865 +f 987//371 1467//2117 1542//2102 +f 1567//1811 1704//1952 1137//853 +f 1693//1946 1865//2022 1714//1830 +f 897//254 1762//1511 912//271 +f 1135//1597 1697//1620 1062//1617 +f 1697//1620 376//1561 1062//1617 +f 1543//2116 1731//1824 1678//1856 +f 1793//2032 1679//2114 1467//2117 +f 1777//1904 1602//2041 1760//2042 +f 1846//1430 1798//1432 1754//2059 +f 1835//1253 1096//765 1677//1125 +f 1033//154 1030//830 940//152 +f 1450//1643 1527//2090 1702//1797 +f 1717//2121 376//1561 1697//1620 +f 1711//2122 1717//2121 1697//1620 +f 1717//2121 165//472 376//1561 +f 1840//2101 984//2024 1790//1864 +f 1669//2028 1746//1860 1704//1952 +f 1669//2028 1682//1889 1746//1860 +f 2301//2077 2349//2119 2308//2123 +f 1882//1399 1444//860 1898//1304 +f 1820//1233 1789//51 1730//510 +f 861//2036 1380//1054 1566//2037 +f 2301//2077 2308//2123 2266//2124 +f 1771//786 1543//2116 1691//1854 +f 1958//477 1659//1880 1651//478 +f 1697//1620 1360//1624 1711//2122 +f 1711//2122 1737//2125 1717//2121 +f 1717//2121 1737//2125 165//472 +f 1790//1864 1753//2093 1558//1538 +f 1668//1537 1696//205 1663//1992 +f 1360//1624 1702//1797 1711//2122 +f 1702//1797 1707//2126 1711//2122 +f 1707//2126 1737//2125 1711//2122 +f 1737//2125 1751//835 165//472 +f 1444//860 1782//2127 1693//1946 +f 1716//1890 1787//1849 1599//1851 +f 1744//527 1839//1955 1022//528 +f 1898//1304 1444//860 1785//1957 +f 206//2078 1707//2126 1702//1797 +f 1764//417 2468//226 1751//835 +f 316//1628 1844//2111 893//2019 +f 893//2019 1844//2111 915//2128 +f 1845//2129 1804//71 1758//2096 +f 1380//1054 861//2036 1756//1055 +f 1780//1372 670//1389 1021//1390 +f 1714//1830 2172//1528 1763//858 +f 1783//1508 1558//1538 1663//1992 +f 1750//2012 2127//1071 1465//1584 +f 1798//1432 1771//786 1691//1854 +f 1691//1854 1543//2116 1724//1852 +f 1872//1172 1910//2130 839//1173 +f 1737//2125 2044//2131 1751//835 +f 1751//835 2044//2131 1764//417 +f 1757//1933 1701//1406 482//1823 +f 1725//1853 1602//2041 1777//1904 +f 1836//2120 1845//2129 1530//2043 +f 2102//1848 2470//1258 1503//437 +f 2496//237 1899//967 544//244 +f 763//1338 2484//343 946//657 +f 987//371 1719//1236 1467//2117 +f 1845//2129 1758//2096 1792//2076 +f 1725//1853 1837//2049 1602//2041 +f 1872//1172 1866//424 1873//1756 +f 1712//1897 1530//2043 1760//2042 +f 489//62 1799//1448 216//1450 +f 1760//2042 861//2036 1750//2012 +f 2068//344 2466//1284 2460//407 +f 1696//205 2159//204 2168//1485 +f 377//260 1377//262 1280//1693 +f 1797//1862 1676//1861 1572//785 +f 1581//1919 2053//1844 1572//785 +f 1676//1861 1581//1919 1572//785 +f 1764//417 2498//2132 2468//226 +f 2468//226 2498//2132 1994//2133 +f 1861//2134 1695//2135 1860//2136 +f 2481//418 2004//575 2495//576 +f 1826//1863 1677//1125 1523//1510 +f 1670//1974 1739//1488 852//1975 +f 2234//2005 2269//2137 2253//2006 +f 1724//1852 1543//2116 1678//1856 +f 1658//1993 2168//1485 1791//1484 +f 1397//1580 1747//1254 1719//1236 +f 1696//205 2168//1485 1658//1993 +f 979//681 519//680 272//1130 +f 1774//1512 1975//2118 1679//2114 +f 975//911 1671//1539 932//1455 +f 1787//1849 1716//1890 1682//1889 +f 1835//1253 1826//1863 1747//1254 +f 2501//405 2469//1433 961//679 +f 1810//1915 908//2001 1791//1484 +f 1982//1706 1768//2138 191//480 +f 1137//853 1704//1952 1825//2003 +f 1804//71 1846//1430 1758//2096 +f 2004//575 2044//2131 1737//2125 +f 913//1462 1969//1472 902//1392 +f 2498//2132 1795//255 1801//2139 +f 915//2128 1844//2111 1712//1897 +f 1689//2140 915//2128 1712//1897 +f 1740//2141 1752//2109 1541//1650 +f 695//1229 661//520 199//522 +f 1865//2022 1693//1946 1782//2127 +f 1824//1859 1464//1953 1809//1888 +f 1829//1487 1765//994 1718//1415 +f 1816//2142 1768//2138 1982//1706 +f 1816//2142 1622//2143 1768//2138 +f 1622//2143 2165//2144 1681//2145 +f 1768//2138 1622//2143 1681//2145 +f 670//1389 1772//1405 228//1404 +f 1283//556 1459//854 52//554 +f 1785//1957 1444//860 1749//1940 +f 1675//1816 1075//827 1685//1447 +f 1567//1811 1781//2100 1704//1952 +f 1858//2146 1857//1947 1848//1966 +f 1526//1865 1752//2109 1688//2108 +f 1791//1484 2160//1486 1810//1915 +f 908//2001 1658//1993 1791//1484 +f 1813//2147 1773//1536 1558//1538 +f 1845//2129 1792//2076 1530//2043 +f 69//192 376//1561 165//472 +f 3//1594 1832//2020 1834//1592 +f 1722//1386 1516//121 1507//123 +f 1801//2139 1821//2148 1994//2133 +f 1833//2149 1982//1706 2046//2150 +f 1821//2148 1833//2149 2046//2150 +f 1833//2149 1816//2142 1982//1706 +f 1022//528 1785//1957 1749//1940 +f 2160//1486 2170//1632 1810//1915 +f 1147//1583 1719//1236 1726//300 +f 1683//122 1840//2101 1507//123 +f 1467//2117 1719//1236 1793//2032 +f 1795//255 1802//257 1801//2139 +f 1802//257 1811//2151 1801//2139 +f 1801//2139 1811//2151 1821//2148 +f 1690//2152 2165//2144 1622//2143 +f 1934//1788 1480//1990 1925//86 +f 229//770 1468//992 1091//1644 +f 1780//1372 2164//1371 1742//1912 +f 1672//1866 1742//1912 858//1778 +f 1833//2149 1417//2153 1816//2142 +f 1417//2153 1622//2143 1816//2142 +f 1831//2154 2165//2144 1690//2152 +f 1668//1537 1663//1992 1558//1538 +f 1719//1236 1747//1254 1826//1863 +f 1760//2042 1750//2012 1664//1895 +f 1817//2155 1690//2152 1622//2143 +f 1530//2043 1792//2076 1777//1904 +f 948//256 1796//1665 1802//257 +f 1796//1665 1811//2151 1802//257 +f 1515//2156 1817//2155 1622//2143 +f 1695//2135 1861//2134 1831//2154 +f 1783//1508 1663//1992 1658//1993 +f 1749//1940 1410//1939 1022//528 +f 854//675 1796//1665 948//256 +f 1811//2151 1842//2157 1833//2149 +f 1821//2148 1811//2151 1833//2149 +f 1833//2149 1842//2157 1417//2153 +f 1622//2143 1417//2153 1515//2156 +f 127//329 1804//71 1845//2129 +f 1686//2017 1626//1905 1837//2049 +f 1608//2158 1690//2152 1817//2155 +f 1523//1510 1775//1363 1762//1511 +f 127//329 1845//2129 1836//2120 +f 1812//307 1805//120 1708//1431 +f 1523//1510 1677//1125 1775//1363 +f 1780//1372 1772//1405 670//1389 +f 1758//2096 1754//2059 1792//2076 +f 1204//1331 1796//1665 854//675 +f 1822//1564 1842//2157 1811//2151 +f 1608//2158 1831//2154 1690//2152 +f 1822//1564 1811//2151 1796//1665 +f 1842//2157 1416//2159 1417//2153 +f 1417//2153 1416//2159 1515//2156 +f 1515//2156 1608//2158 1817//2155 +f 1728//2160 1831//2154 1608//2158 +f 908//2001 1783//1508 1658//1993 +f 127//329 1836//2120 316//1628 +f 1805//120 1148//331 1824//1859 +f 852//1975 1745//1414 1672//1866 +f 1478//2002 1093//1968 1928//1582 +f 1822//1564 1843//1427 1842//2157 +f 1843//1427 959//2161 1842//2157 +f 1842//2157 959//2161 1416//2159 +f 1728//2160 1695//2135 1831//2154 +f 1728//2160 1860//2136 1695//2135 +f 2346//2162 446//287 2337//1291 +f 1602//2041 1837//2049 861//2036 +f 1087//1252 1096//765 1835//1253 +f 1708//1431 1824//1859 1809//1888 +f 2004//575 1737//2125 505//801 +f 1567//1811 1748//1742 1781//2100 +f 520//1825 1543//2116 1883//2163 +f 1760//2042 1664//1895 1712//1897 +f 128//534 1336//898 72//899 +f 2053//1844 1883//2163 1543//2116 +f 1822//1564 180//1428 1843//1427 +f 1786//2164 1608//2158 1515//2156 +f 929//208 2462//325 519//680 +f 512//1136 2402//2165 506//1463 +f 1212//1777 1703//2030 1683//122 +f 1830//2089 1829//1487 1739//1488 +f 2053//1844 1543//2116 1771//786 +f 1416//2159 1769//2166 1515//2156 +f 1769//2166 1786//2164 1515//2156 +f 1786//2164 1728//2160 1608//2158 +f 1712//1897 1808//1896 1689//2140 +f 1794//1507 1558//1538 1783//1508 +f 1497//2098 1735//1980 1776//1982 +f 1127//1677 1567//1811 1137//853 +f 1123//1673 1748//1742 1567//1811 +f 36//803 205//749 1185//1567 +f 959//2161 1734//2167 1416//2159 +f 1738//1920 1733//1922 1541//1650 +f 1774//1512 1762//1511 1974//2168 +f 1752//2109 1554//2110 1541//1650 +f 1752//2109 1740//2141 1688//2108 +f 1526//1865 1875//1651 1554//2110 +f 1468//992 1829//1487 1830//2089 +f 1755//1449 908//2001 1810//1915 +f 1716//1890 1599//1851 1814//2044 +f 1806//1911 1780//1372 1742//1912 +f 2308//2123 2349//2119 2340//2169 +f 1832//2020 915//2128 1689//2140 +f 1713//2095 1468//992 1830//2089 +f 1814//2044 1599//1851 1346//2170 +f 1832//2020 1689//2140 1766//2112 +f 1022//528 1684//1288 1785//1957 +f 1093//1968 1153//1570 1116//1265 +f 1672//1866 678//1440 1742//1912 +f 1675//1816 1685//1447 1093//1968 +f 1841//1385 1743//1921 1722//1386 +f 1814//2044 2053//1844 1581//1919 +f 1464//1953 1746//1860 1809//1888 +f 2485//596 2497//494 2493//597 +f 1416//2159 1734//2167 1769//2166 +f 1665//2171 1728//2160 1786//2164 +f 1665//2171 1951//2172 1728//2160 +f 1951//2172 1860//2136 1728//2160 +f 1951//2172 2094//1092 1860//2136 +f 1844//2111 1836//2120 1818//2097 +f 316//1628 1836//2120 1844//2111 +f 1776//1982 1531//1850 1787//1849 +f 1719//1236 1826//1863 1793//2032 +f 2147//1943 1401//1596 29//1696 +f 2111//1411 2121//2173 1548//2092 +f 1741//1779 1259//2085 1779//2031 +f 1843//1427 347//1429 1834//1592 +f 1843//1427 1734//2167 959//2161 +f 1766//2112 1769//2166 1734//2167 +f 957//2113 1766//2112 1734//2167 +f 1766//2112 1786//2164 1769//2166 +f 1766//2112 1689//2140 1786//2164 +f 1689//2140 1665//2171 1786//2164 +f 1754//2059 1691//1854 1777//1904 +f 1507//123 1840//2101 1790//1864 +f 1761//1868 1470//2051 1461//2067 +f 1523//1510 1679//2114 1793//2032 +f 1091//1644 1468//992 1098//1658 +f 1820//1233 1730//510 1838//461 +f 1843//1427 1834//1592 1734//2167 +f 1808//1896 1951//2172 1665//2171 +f 1588//1981 1727//1995 1531//1850 +f 893//2019 915//2128 1832//2020 +f 1523//1510 1774//1512 1679//2114 +f 272//1130 2488//635 710//1100 +f 1093//1968 1116//1265 1675//1816 +f 2340//2169 2349//2119 2348//2174 +f 1832//2020 1734//2167 1834//1592 +f 1832//2020 957//2113 1734//2167 +f 1951//2172 1808//1896 2094//1092 +f 1685//1447 1692//1329 1505//1962 +f 1043//931 295//1618 698//933 +f 2143//2023 1779//2031 2121//2173 +f 1689//2140 1808//1896 1665//2171 +f 1693//1946 1714//1830 1763//858 +f 1738//1920 2157//1649 1516//121 +f 1114//2011 1921//1216 236//1215 +f 1268//1835 1333//939 1520//1717 +f 1149//1453 1108//2057 431//1454 +f 508//1728 2144//1715 1912//1789 +f 1957//90 1108//2057 1537//91 +f 431//1454 1108//2057 1957//90 +f 1018//2175 1108//2057 2167//2063 +f 1338//1842 1957//90 1681//2145 +f 2163//2176 1957//90 1338//1842 +f 1983//395 1390//2177 2093//2178 +f 30//16 557//506 37//555 +f 1714//1830 2173//1554 2172//1528 +f 1983//395 1984//1839 1390//2177 +f 1984//1839 2065//2179 1390//2177 +f 884//241 1762//1511 897//254 +f 2065//2179 1984//1839 1214//2180 +f 1950//2181 1974//2168 1762//1511 +f 884//241 1950//2181 1762//1511 +f 2012//2182 1698//2183 1861//2134 +f 1214//2180 2116//1782 803//1826 +f 1950//2181 1938//2184 1974//2168 +f 1938//2184 1967//2185 1974//2168 +f 1900//463 1761//1868 1461//2067 +f 865//251 1929//2186 884//241 +f 884//241 1929//2186 1950//2181 +f 2062//172 2071//2187 2042//1232 +f 919//1365 1985//2188 1732//974 +f 1593//1997 502//1999 2146//2189 +f 1995//2190 1213//1213 2098//966 +f 1522//1103 2476//616 1651//478 +f 2174//1552 1849//2021 2175//1262 +f 1480//1990 1989//1680 1499//1979 +f 1929//2186 1938//2184 1950//2181 +f 1605//1836 2058//1838 1574//1907 +f 2097//1837 1605//1836 2133//1846 +f 1912//1789 2014//2191 1886//1726 +f 2092//2192 2082//2193 2083//2194 +f 206//2078 1930//2195 505//801 +f 2101//1985 2100//2196 2092//2192 +f 2073//1986 2101//1985 2092//2192 +f 839//1173 1910//2130 865//251 +f 1910//2130 1901//2197 1929//2186 +f 865//251 1910//2130 1929//2186 +f 1967//2185 1788//2099 1975//2118 +f 2073//1986 2092//2192 2063//2060 +f 2101//1985 1593//1997 2100//2196 +f 2015//2198 1876//1763 1698//2183 +f 1853//2199 1884//2200 2014//2191 +f 1831//2154 1698//2183 2165//2144 +f 1316//394 273//396 81//2081 +f 1901//2197 1920//2201 1929//2186 +f 1929//2186 1920//2201 1938//2184 +f 1920//2201 1968//1473 1967//2185 +f 1938//2184 1920//2201 1967//2185 +f 1849//2021 2174//1552 1700//1831 +f 2173//1554 1700//1831 2174//1552 +f 2062//172 2072//1231 2091//2202 +f 803//1826 2467//868 2059//788 +f 2239//1410 1736//1409 2240//2203 +f 1505//1962 1357//1964 1685//1447 +f 1358//1857 1686//2017 1476//1858 +f 1967//2185 1968//1473 1788//2099 +f 1968//1473 1969//1472 1788//2099 +f 2065//2179 2110//176 2156//1314 +f 2065//2179 1214//2180 2110//176 +f 2110//176 1214//2180 503//2204 +f 273//396 2093//2178 1018//2175 +f 273//396 1983//395 2093//2178 +f 532//1724 1886//1726 2155//2205 +f 2034//175 2021//493 1947//224 +f 216//1450 1810//1915 585//1916 +f 1912//1789 543//1761 2014//2191 +f 1390//2177 2051//92 1537//91 +f 1872//1172 1873//1756 1910//2130 +f 1984//1839 2045//1775 1214//2180 +f 597//1725 1912//1789 1886//1726 +f 1593//1997 2146//2189 2100//2196 +f 2071//2187 2062//172 2090//1169 +f 2034//175 2046//2150 1982//1706 +f 2034//175 1947//224 2046//2150 +f 1214//2180 2045//1775 2116//1782 +f 1873//1756 1887//1755 1910//2130 +f 1887//1755 1901//2197 1910//2130 +f 1562//1958 1447//1161 1106//1321 +f 2163//2176 431//1454 1957//90 +f 1948//1641 1972//213 1936//1328 +f 1972//213 1948//1641 1992//214 +f 2014//2191 2015//2198 2013//2206 +f 1853//2199 2014//2191 2013//2206 +f 1550//2207 1884//2200 1853//2199 +f 1947//224 2468//226 1994//2133 +f 1355//2208 1550//2207 2154//1806 +f 1355//2208 1884//2200 1550//2207 +f 2081//840 2108//2209 2128//1474 +f 2024//2069 1965//1731 1492//2046 +f 2024//2069 2032//2210 1965//1731 +f 2116//1782 1604//1827 803//1826 +f 1901//2197 1911//2211 1920//2201 +f 1939//1393 1968//1473 1920//2201 +f 1911//2211 1939//1393 1920//2201 +f 872//1493 1626//1905 1666//1408 +f 2062//172 2091//2202 2120//173 +f 1819//1615 1927//1855 1759//1662 +f 1021//1390 1674//625 1780//1372 +f 872//1493 1673//1056 1756//1055 +f 1550//2207 501//1297 2171//1334 +f 1378//1333 1550//2207 2171//1334 +f 2146//2189 2162//1727 2145//2212 +f 1358//1857 482//1823 192//1832 +f 2109//174 2120//173 2119//2213 +f 1866//424 1872//1172 2227//1219 +f 1391//2214 2012//2182 1860//2136 +f 2136//2215 2137//1807 2161//1332 +f 2162//1727 1661//2010 236//1215 +f 1887//1755 1894//1847 1901//2197 +f 1901//2197 1894//1847 1911//2211 +f 505//801 1707//2126 206//2078 +f 2120//173 2137//1807 2136//2215 +f 2142//624 2164//1371 1674//625 +f 1860//2136 2012//2182 1861//2134 +f 1894//1847 1939//1393 1911//2211 +f 2080//1956 2060//841 2118//1475 +f 2162//1727 236//1215 508//1728 +f 2164//1371 1815//2086 1742//1912 +f 1018//2175 2093//2178 1537//91 +f 2154//1806 1378//1333 2161//1332 +f 2041//2216 2098//966 2491//324 +f 2043//1701 2042//1232 2032//2210 +f 1108//2057 1018//2175 1537//91 +f 1465//1584 2094//1092 1808//1896 +f 502//1999 1643//2008 1661//2010 +f 2467//868 1618//2029 1656//1562 +f 2119//2213 2136//2215 2135//2217 +f 2119//2213 2108//2209 2071//2187 +f 878//1132 1183//143 1195//730 +f 2101//1985 1594//2038 1593//1997 +f 2033//2218 2370//1801 2063//2060 +f 2482//1126 2491//324 2098//966 +f 1282//1743 2406//1766 1275//1491 +f 2003//2219 1948//1641 1956//1695 +f 2043//1701 2032//2210 2024//2069 +f 2025//426 2043//1701 2024//2069 +f 2154//1806 1550//2207 1378//1333 +f 1795//255 2498//2132 1764//417 +f 2142//624 1548//2092 2164//1371 +f 2431//1520 2454//1139 2422//1521 +f 1981//2220 2011//2221 1993//2222 +f 2349//2119 2391//1278 2362//2223 +f 502//1999 2162//1727 2146//2189 +f 2025//426 2024//2069 2360//427 +f 2129//2224 2120//173 2091//2202 +f 1732//974 1985//2188 2007//1496 +f 2171//1334 1308//1296 209//2225 +f 1930//2195 1995//2190 2041//2216 +f 1390//2177 1238//479 2051//92 +f 1866//424 1878//423 1887//1755 +f 1878//423 1894//1847 1887//1755 +f 1965//1731 2032//2210 2011//2221 +f 874//471 2480//473 2492//247 +f 2071//2187 2108//2209 2069//2226 +f 1358//1857 1731//1824 482//1823 +f 430//177 2021//493 2034//175 +f 1965//1731 2003//2219 1964//1694 +f 1855//2227 1889//1516 831//1383 +f 1668//1537 1773//1536 2150//2228 +f 1390//2177 2156//1314 1238//479 +f 898//1210 869//971 1903//1083 +f 2391//1278 2407//1370 2362//2223 +f 2121//2173 2111//1411 2074//880 +f 1548//2092 1259//2085 2164//1371 +f 2099//2229 2129//2224 2091//2202 +f 1550//2207 1853//2199 501//1297 +f 1853//2199 1852//1298 501//1297 +f 952//1423 2017//2230 969//879 +f 2085//2231 2121//2173 2074//880 +f 2130//1678 2006//2232 1391//2214 +f 2144//1715 1367//1762 543//1761 +f 2100//2196 2146//2189 2099//2229 +f 1545//1461 1319//1685 113//1884 +f 1903//1083 1922//2233 898//1210 +f 1922//2233 1931//1208 898//1210 +f 585//1916 2170//1632 1641//1634 +f 2007//1496 2017//2230 952//1423 +f 2017//2230 2074//880 969//879 +f 1558//1538 1753//2093 1813//2147 +f 837//1810 2005//1834 1517//1032 +f 2005//1834 2006//2232 2130//1678 +f 1532//1874 1474//438 1528//1767 +f 2003//2219 1981//2220 1948//1641 +f 2070//2234 2071//2187 2069//2226 +f 1922//2233 919//1365 1931//1208 +f 2017//2230 2085//2231 2074//880 +f 2085//2231 2104//2235 2121//2173 +f 2100//2196 2099//2229 2082//2193 +f 2156//1314 2110//176 2034//175 +f 505//801 2474//323 2004//575 +f 1903//1083 871//1555 1922//2233 +f 1922//2233 1952//2236 919//1365 +f 919//1365 1952//2236 1985//2188 +f 1985//2188 2001//2237 2007//1496 +f 2001//2237 2036//2238 2017//2230 +f 2007//1496 2001//2237 2017//2230 +f 2017//2230 2036//2238 2085//2231 +f 2036//2238 2047//2239 2085//2231 +f 2047//2239 2075//2240 2085//2231 +f 2075//2240 2104//2235 2085//2231 +f 1948//1641 1993//2222 2023//1642 +f 2400//1369 2422//1521 2407//1370 +f 2011//2221 2070//2234 1993//2222 +f 2033//2218 2043//1701 2025//426 +f 2012//2182 2015//2198 1698//2183 +f 1876//1763 1338//1842 2165//2144 +f 871//1555 1940//2241 1922//2233 +f 1985//2188 1976//2242 2001//2237 +f 2121//2173 2104//2235 2143//2023 +f 1051//128 1413//1739 1456//1311 +f 2358//446 1362//1526 2379//1893 +f 1859//983 1789//51 1870//1234 +f 2090//1169 2109//174 2071//2187 +f 1405//453 1398//75 1885//1892 +f 1886//1726 1884//2200 1355//2208 +f 1922//2233 1960//2243 1952//2236 +f 1952//2236 1960//2243 1985//2188 +f 1960//2243 1976//2242 1985//2188 +f 1956//1695 1948//1641 1936//1328 +f 2135//2217 209//2225 2128//1474 +f 2157//1649 1875//1651 1212//1777 +f 2160//1486 2168//1485 2169//2244 +f 1900//463 1461//2067 1918//1143 +f 2001//2237 2018//2245 2036//2238 +f 2075//2240 2086//2246 2104//2235 +f 2111//1411 2142//624 2103//1412 +f 1937//1144 1956//1695 1936//1328 +f 2023//1642 2070//2234 2061//1498 +f 2135//2217 2128//1474 2108//2209 +f 2042//1232 2071//2187 2011//2221 +f 2138//1330 413//1350 2383//2247 +f 2033//2218 2072//1231 2043//1701 +f 1922//2233 1940//2241 1960//2243 +f 2070//2234 2069//2226 2061//1498 +f 2069//2226 2108//2209 2061//1498 +f 2108//2209 2119//2213 2135//2217 +f 1855//2227 1904//2248 1889//1516 +f 1889//1516 1904//2248 871//1555 +f 871//1555 1904//2248 1940//2241 +f 1976//2242 2018//2245 2001//2237 +f 2036//2238 2018//2245 2047//2239 +f 2122//2249 2143//2023 2104//2235 +f 216//1450 1642//1710 489//62 +f 2148//2094 984//2024 2143//2023 +f 1975//2118 1974//2168 1967//2185 +f 2157//1649 1683//122 1516//121 +f 1614//1998 1593//1997 1594//2038 +f 2269//2137 2270//2250 2276//2251 +f 1926//1805 2147//1943 29//1696 +f 2082//2193 2091//2202 2072//1231 +f 430//177 503//2204 2059//788 +f 1904//2248 1905//2252 1940//2241 +f 1940//2241 1961//2253 1960//2243 +f 1961//2253 1976//2242 1960//2243 +f 2087//2254 2086//2246 2075//2240 +f 2065//2179 2156//1314 1390//2177 +f 1820//1233 1838//461 1900//463 +f 534//1031 1308//1296 837//1810 +f 2167//2063 273//396 1018//2175 +f 831//1383 1850//1394 1855//2227 +f 2019//2255 2037//2256 2018//2245 +f 2018//2245 2037//2256 2047//2239 +f 2037//2256 2075//2240 2047//2239 +f 2086//2246 2095//2257 2104//2235 +f 2095//2257 2122//2249 2104//2235 +f 2122//2249 2148//2094 2143//2023 +f 1926//1805 1213//1213 1995//2190 +f 1405//453 1885//1892 1761//1868 +f 2006//2232 2013//2206 2012//2182 +f 2211//1517 2233//1302 2216//1518 +f 1855//2227 1890//2258 1904//2248 +f 1904//2248 1895//2259 1905//2252 +f 1905//2252 1932//2260 1940//2241 +f 1961//2253 1977//2261 1976//2242 +f 1976//2242 1986//2262 2018//2245 +f 2484//343 2476//616 1518//1104 +f 1870//1234 1411//1989 1859//983 +f 1548//2092 2142//624 2111//1411 +f 1904//2248 1890//2258 1895//2259 +f 1895//2259 1932//2260 1905//2252 +f 1940//2241 1932//2260 1961//2253 +f 1976//2242 1977//2261 1986//2262 +f 1986//2262 2008//2263 2018//2245 +f 2018//2245 2008//2263 2019//2255 +f 2087//2254 2075//2240 2037//2256 +f 2087//2254 2095//2257 2086//2246 +f 2094//1092 1391//2214 1860//2136 +f 1852//1298 1853//2199 2006//2232 +f 1853//2199 2013//2206 2006//2232 +f 929//208 979//681 850//209 +f 1855//2227 1874//2264 1890//2258 +f 2008//2263 2028//2265 2019//2255 +f 1993//2222 2070//2234 2023//1642 +f 1705//1770 1799//1448 1998//64 +f 1491//1944 2147//1943 206//2078 +f 1851//1530 1856//2266 1855//2227 +f 1895//2259 1890//2258 1874//2264 +f 2038//2267 2019//2255 2028//2265 +f 2038//2267 2048//2268 2037//2256 +f 2019//2255 2038//2267 2037//2256 +f 2048//2268 2067//2269 2087//2254 +f 2037//2256 2048//2268 2087//2254 +f 2087//2254 2067//2269 2095//2257 +f 2095//2257 2149//2270 2122//2249 +f 2149//2270 2148//2094 2122//2249 +f 1308//1296 2005//1834 837//1810 +f 209//2225 1308//1296 1387//1549 +f 1601//1259 2102//1848 1927//1855 +f 254//592 170//456 201//626 +f 1800//1938 1403//859 1763//858 +f 1510//1991 1346//2170 1740//2141 +f 870//973 871//1555 1903//1083 +f 1919//1773 1650//2084 1619//1774 +f 2148//2094 1667//2271 1753//2093 +f 1932//2260 1923//2272 1961//2253 +f 1977//2261 1953//2273 1986//2262 +f 2067//2269 2112//2274 2095//2257 +f 2112//2274 2149//2270 2095//2257 +f 2148//2094 2149//2270 1667//2271 +f 2422//1521 2421//1983 2407//1370 +f 1926//1805 2026//1224 1213//1213 +f 1912//1789 2144//1715 543//1761 +f 2128//1474 1387//1549 2153//1542 +f 1733//1922 1510//1991 1740//2141 +f 990//1459 853//813 2489//632 +f 503//2204 1214//2180 803//1826 +f 1921//1216 431//1454 2163//2176 +f 2146//2189 2145//2212 2129//2224 +f 2144//1715 1921//1216 2163//2176 +f 1855//2227 1856//2266 1874//2264 +f 1895//2259 1923//2272 1932//2260 +f 1923//2272 1941//2275 1961//2253 +f 1961//2253 1941//2275 1977//2261 +f 2048//2268 2076//2276 2067//2269 +f 2076//2276 2113//2277 2067//2269 +f 2067//2269 2113//2277 2112//2274 +f 1723//1359 1900//463 1937//1144 +f 1870//1234 1900//463 1723//1359 +f 1367//1762 2163//2176 1338//1842 +f 520//1825 1346//2170 1510//1991 +f 1698//2183 1831//2154 1861//2134 +f 1984//1839 1919//1773 2045//1775 +f 1895//2259 1891//2278 1923//2272 +f 2008//2263 1986//2262 2028//2265 +f 1948//1641 1981//2220 1993//2222 +f 1883//2163 1346//2170 520//1825 +f 1883//2163 1814//2044 1346//2170 +f 1930//2195 206//2078 2147//1943 +f 2499//569 2486//568 1447//1161 +f 1891//2278 1906//2279 1923//2272 +f 1923//2272 1953//2273 1941//2275 +f 1953//2273 1977//2261 1941//2275 +f 1953//2273 1987//2280 1986//2262 +f 2113//2277 2123//2281 2112//2274 +f 2123//2281 2149//2270 2112//2274 +f 1387//1549 1308//1296 1226//217 +f 1599//1851 1688//2108 1346//2170 +f 2093//2178 1390//2177 1537//91 +f 2003//2219 2011//2221 1981//2220 +f 1987//2280 2028//2265 1986//2262 +f 2038//2267 2049//2282 2048//2268 +f 2048//2268 2049//2282 2076//2276 +f 1813//2147 1667//2271 2149//2270 +f 2123//2281 1813//2147 2149//2270 +f 1461//2067 1469//1730 1964//1694 +f 1757//1933 1510//1991 1743//1921 +f 505//801 1930//2195 1999//802 +f 2223//53 1784//1972 1789//51 +f 1532//1874 1522//1103 1651//478 +f 1906//2279 1913//2283 1923//2272 +f 1913//2283 1943//2284 1923//2272 +f 1943//2284 1942//2285 1923//2272 +f 1923//2272 1942//2285 1953//2273 +f 1942//2285 1987//2280 1953//2273 +f 1308//1296 1852//1298 2005//1834 +f 2053//1844 1814//2044 1883//2163 +f 1733//1922 1740//2141 1541//1650 +f 2154//1806 1886//1726 1355//2208 +f 1503//437 1528//1767 1474//438 +f 1874//2264 1879//2286 1895//2259 +f 1895//2259 1879//2286 1891//2278 +f 2076//2276 2124//2287 2113//2277 +f 2113//2277 2124//2287 2123//2281 +f 1896//2288 1891//2278 1879//2286 +f 1891//2278 1896//2288 1906//2279 +f 1942//2285 1962//2289 1987//2280 +f 1962//2289 2009//2290 2028//2265 +f 1987//2280 1962//2289 2028//2265 +f 2009//2290 2038//2267 2028//2265 +f 2109//174 2119//2213 2071//2187 +f 1918//1143 1956//1695 1937//1144 +f 1851//1530 1864//2291 1856//2266 +f 1896//2288 1897//2292 1906//2279 +f 1906//2279 1897//2292 1913//2283 +f 1943//2284 1962//2289 1942//2285 +f 2049//2282 2077//2293 2076//2276 +f 2124//2287 2125//2294 2123//2281 +f 1930//2195 2147//1943 1926//1805 +f 1902//1276 1894//1847 1878//423 +f 482//1823 1510//1991 1757//1933 +f 2129//2224 2137//1807 2120//173 +f 503//2204 803//1826 2059//788 +f 1847//1470 1857//1947 1851//1530 +f 1851//1530 1857//1947 1864//2291 +f 2039//2295 2038//2267 2009//2290 +f 2038//2267 2039//2295 2049//2282 +f 2076//2276 2077//2293 2124//2287 +f 2150//2228 1813//2147 2123//2281 +f 482//1823 520//1825 1510//1991 +f 1994//2133 1821//2148 2046//2150 +f 2044//2131 2004//575 1764//417 +f 1864//2291 1867//2296 1856//2266 +f 1867//2296 1874//2264 1856//2266 +f 1897//2292 1944//2297 1913//2283 +f 1943//2284 1944//2297 1962//2289 +f 2124//2287 2126//2298 2125//2294 +f 2150//2228 2123//2281 2125//2294 +f 2099//2229 2146//2189 2129//2224 +f 2041//2216 1995//2190 2098//966 +f 1605//1836 1641//1634 2151//1633 +f 1847//1470 1959//1494 1857//1947 +f 1874//2264 1867//2296 1879//2286 +f 1913//2283 1944//2297 1943//2284 +f 1944//2297 1963//2299 1962//2289 +f 2077//2293 2096//2300 2124//2287 +f 2096//2300 2126//2298 2124//2287 +f 2126//2298 2150//2228 2125//2294 +f 941//2083 1650//2084 1919//1773 +f 2135//2217 2136//2215 209//2225 +f 1884//2200 1886//1726 2014//2191 +f 2049//2282 2029//2301 2077//2293 +f 1388//1280 2127//1071 1389//1976 +f 1389//1976 2127//1071 1566//2037 +f 1930//2195 1926//1805 1995//2190 +f 941//2083 1919//1773 1316//394 +f 2110//176 503//2204 430//177 +f 1867//2296 1880//2302 1879//2286 +f 1879//2286 1880//2302 1896//2288 +f 1897//2292 1907//2303 1944//2297 +f 1963//2299 1978//2304 1962//2289 +f 1962//2289 1978//2304 2009//2290 +f 2039//2295 2029//2301 2049//2282 +f 2077//2293 2078//2305 2096//2300 +f 822//1133 823//1444 827//1241 +f 2166//2034 1668//1537 2150//2228 +f 81//2081 941//2083 1316//394 +f 2204//1519 2216//1518 2203//2306 +f 2011//2221 2071//2187 2070//2234 +f 1880//2302 1892//2307 1896//2288 +f 1892//2307 1907//2303 1897//2292 +f 1896//2288 1892//2307 1897//2292 +f 1907//2303 1914//2308 1944//2297 +f 1978//2304 2010//2309 2009//2290 +f 2010//2309 2039//2295 2009//2290 +f 1688//2108 1740//2141 1346//2170 +f 1789//51 1820//1233 1870//1234 +f 2130//1678 1391//2214 2094//1092 +f 1944//2297 1945//2310 1963//2299 +f 2029//2301 2078//2305 2077//2293 +f 1767//206 2150//2228 2126//2298 +f 1767//206 2166//2034 2150//2228 +f 803//1826 2022//1828 2467//868 +f 1503//437 1927//1855 2102//1848 +f 1914//2308 1954//2311 1944//2297 +f 1944//2297 1954//2311 1945//2310 +f 1963//2299 1970//2312 1978//2304 +f 2078//2305 2105//2313 2096//2300 +f 2105//2313 2126//2298 2096//2300 +f 1965//1731 2011//2221 2003//2219 +f 192//1832 1626//1905 1358//1857 +f 2101//1985 1559//1984 1594//2038 +f 1930//2195 2041//2216 1999//802 +f 1698//2183 1876//1763 2165//2144 +f 1398//75 1871//452 891//76 +f 2165//2144 1338//1842 1681//2145 +f 1970//2312 2010//2309 1978//2304 +f 2010//2309 2030//2314 2029//2301 +f 2039//2295 2010//2309 2029//2301 +f 2030//2314 2055//2315 2078//2305 +f 2029//2301 2030//2314 2078//2305 +f 1849//2021 1848//1966 2175//1262 +f 1871//452 1862//451 891//76 +f 543//1761 2015//2198 2014//2191 +f 1857//1947 1858//2146 1864//2291 +f 1864//2291 1858//2146 1867//2296 +f 1963//2299 1945//2310 1970//2312 +f 2055//2315 2088//2316 2078//2305 +f 2078//2305 2088//2316 2105//2313 +f 2105//2313 2131//2317 2126//2298 +f 2126//2298 2131//2317 1767//206 +f 2063//2060 2083//2194 2033//2218 +f 2161//1332 2171//1334 209//2225 +f 2032//2210 2042//1232 2011//2221 +f 1813//2147 2150//2228 1773//1536 +f 1914//2308 1908//2318 1954//2311 +f 1970//2312 1979//2319 2010//2309 +f 2088//2316 2131//2317 2105//2313 +f 2015//2198 543//1761 1876//1763 +f 1694//1245 1692//1329 1048//1246 +f 1395//1965 2207//52 1859//983 +f 1395//1965 1393//1937 2207//52 +f 1730//510 1784//1972 1736//1409 +f 2500//233 2466//1284 2470//1258 +f 1709//1407 1701//1406 1757//1933 +f 1945//2310 1979//2319 1970//2312 +f 2030//2314 2050//2320 2055//2315 +f 2350//1354 2317//2321 2286//1708 +f 2154//1806 2155//2205 1886//1726 +f 871//1555 860//1509 1889//1516 +f 2161//1332 209//2225 2136//2215 +f 2497//494 2463//245 2493//597 +f 2190//2322 2204//1519 2203//2306 +f 1800//1938 2179//1523 1404//1936 +f 2477//1434 2469//1433 1385//404 +f 1385//404 1715//2323 2477//1434 +f 2128//1474 209//2225 1387//1549 +f 1858//2146 1868//2026 1867//2296 +f 1867//2296 1881//2324 1880//2302 +f 1893//2325 1892//2307 1880//2302 +f 1881//2324 1893//2325 1880//2302 +f 1893//2325 1907//2303 1892//2307 +f 1907//2303 1908//2318 1914//2308 +f 1954//2311 1979//2319 1945//2310 +f 1979//2319 1980//2326 2010//2309 +f 2131//2317 2159//204 1767//206 +f 1765//994 93//993 339//769 +f 1761//1868 1877//462 1405//453 +f 523//1095 1347//1768 515//1147 +f 1541//1650 2157//1649 1738//1920 +f 2144//1715 2163//2176 1367//1762 +f 1380//1054 1389//1976 1566//2037 +f 2317//2321 2392//2327 2316//1277 +f 1994//2133 2498//2132 1801//2139 +f 1867//2296 1868//2026 1881//2324 +f 1980//2326 2050//2320 2030//2314 +f 2010//2309 1980//2326 2030//2314 +f 2050//2320 2089//2328 2055//2315 +f 2055//2315 2089//2328 2088//2316 +f 2088//2316 2114//2329 2131//2317 +f 1538//1873 1651//478 1659//1880 +f 2145//2212 2155//2205 2129//2224 +f 2140//1268 29//1696 1928//1582 +f 2370//1801 2033//2218 2025//426 +f 2252//2330 2239//1410 2240//2203 +f 2239//1410 2252//2330 1862//451 +f 2392//2327 2391//1278 2316//1277 +f 2469//1433 2501//405 1385//404 +f 2477//1434 1715//2323 1710//614 +f 502//1999 1614//1998 1643//2008 +f 2438//1227 1227//962 2431//1520 +f 1915//2331 1907//2303 1893//2325 +f 1915//2331 1908//2318 1907//2303 +f 1954//2311 1908//2318 1979//2319 +f 1908//2318 1988//2332 1979//2319 +f 1979//2319 1988//2332 1980//2326 +f 2114//2329 2159//204 2131//2317 +f 2155//2205 2154//1806 2129//2224 +f 508//1728 1966//1217 2144//1715 +f 872//1493 1756//1055 1626//1905 +f 1710//614 1715//2323 1505//1962 +f 236//1215 1966//1217 508//1728 +f 2272//74 2284//1754 1398//75 +f 2325//2333 2355//1237 2319//1366 +f 1548//2092 2121//2173 1779//2031 +f 1532//1874 1528//1767 1522//1103 +f 1980//2326 2056//2334 2050//2320 +f 2050//2320 2056//2334 2089//2328 +f 2013//2206 2015//2198 2012//2182 +f 1964//1694 2003//2219 1956//1695 +f 2006//2232 2012//2182 1391//2214 +f 1565//436 1927//1855 1503//437 +f 2244//2335 2243//2336 2226//2337 +f 5//1963 1715//2323 1385//404 +f 1858//2146 1848//1966 1868//2026 +f 1915//2331 1946//2338 1908//2318 +f 1946//2338 1988//2332 1908//2318 +f 1980//2326 2020//2339 2056//2334 +f 2115//2340 2159//204 2114//2329 +f 2092//2192 2083//2194 2063//2060 +f 1398//75 2284//1754 1687//1753 +f 2162//1727 2155//2205 2145//2212 +f 519//680 2475//633 2488//635 +f 2158//2341 5//1963 1385//404 +f 5//1963 1505//1962 1715//2323 +f 1692//1329 1694//1245 1505//1962 +f 1988//2332 2020//2339 1980//2326 +f 2115//2340 2169//2244 2159//204 +f 2169//2244 2168//1485 2159//204 +f 2083//2194 2082//2193 2072//1231 +f 1316//394 1984//1839 1983//395 +f 1488//221 1619//1774 1650//2084 +f 2083//2194 2072//1231 2033//2218 +f 2361//2342 1210//2343 1233//278 +f 1933//1872 1946//2338 1915//2331 +f 2056//2334 2079//2344 2089//2328 +f 2088//2316 2115//2340 2114//2329 +f 2099//2229 2091//2202 2082//2193 +f 2162//1727 532//1724 2155//2205 +f 1852//1298 2006//2232 2005//1834 +f 2023//1642 2061//1498 2052//1497 +f 2176//1469 2184//892 2175//1262 +f 2162//1727 985//1729 532//1724 +f 1909//2345 1893//2325 1881//2324 +f 1909//2345 1915//2331 1893//2325 +f 1988//2332 2040//2346 2020//2339 +f 2040//2346 2056//2334 2020//2339 +f 2089//2328 2079//2344 2088//2316 +f 2088//2316 2079//2344 2115//2340 +f 1782//2127 1444//860 1882//1399 +f 1216//1798 1215//577 2320//2347 +f 867//1458 1939//1393 1894//1847 +f 867//1458 903//1391 1939//1393 +f 1372//1814 2398//1829 1379//1752 +f 1863//236 504//403 2027//631 +f 2158//2341 1385//404 504//403 +f 1868//2026 1782//2127 1881//2324 +f 1909//2345 1933//1872 1915//2331 +f 2040//2346 1988//2332 1946//2338 +f 1481//2045 2024//2069 1492//2046 +f 2120//173 2136//2215 2119//2213 +f 1522//1103 1528//1767 1518//1104 +f 1871//452 1398//75 1405//453 +f 1221//1481 1408//1483 1399//1587 +f 1357//1964 5//1963 2158//2341 +f 2179//1523 1800//1938 1763//858 +f 1868//2026 1865//2022 1782//2127 +f 1882//1399 1881//2324 1782//2127 +f 1882//1399 1909//2345 1881//2324 +f 2040//2346 2057//2348 2056//2334 +f 2106//2349 2079//2344 2056//2334 +f 2057//2348 2106//2349 2056//2334 +f 2106//2349 2132//2350 2079//2344 +f 2132//2350 2115//2340 2079//2344 +f 2115//2340 2132//2350 2169//2244 +f 532//1724 985//1729 597//1725 +f 2092//2192 2100//2196 2082//2193 +f 1210//2343 1221//1481 1399//1587 +f 1399//1587 1233//278 1210//2343 +f 2130//1678 2002//1070 1517//1032 +f 1849//2021 1865//2022 1868//2026 +f 1933//1872 2040//2346 1946//2338 +f 52//554 1269//509 30//16 +f 1667//2271 1813//2147 1753//2093 +f 1997//1769 1380//1054 1673//1056 +f 940//152 1008//1869 1088//1609 +f 1947//224 1994//2133 2046//2150 +f 1882//1399 1916//1185 1909//2345 +f 1924//1184 1933//1872 1909//2345 +f 1533//1871 2040//2346 1933//1872 +f 1533//1871 1534//1906 2040//2346 +f 2058//1838 2040//2346 1534//1906 +f 2058//1838 2057//2348 2040//2346 +f 1238//479 191//480 1768//2138 +f 1997//1769 1389//1976 1380//1054 +f 1875//1651 1541//1650 1554//2110 +f 1854//1621 504//403 1863//236 +f 1854//1621 2158//2341 504//403 +f 2396//2351 1275//1491 2406//1766 +f 2426//2352 2443//1687 153//1733 +f 1916//1185 1924//1184 1909//2345 +f 1925//86 1935//85 1934//1788 +f 1870//1234 1723//1359 1426//1978 +f 2058//1838 2097//1837 2057//2348 +f 2097//1837 2106//2349 2057//2348 +f 2132//2350 2151//1633 2169//2244 +f 2151//1633 2160//1486 2169//2244 +f 1106//1321 1635//1977 1562//1958 +f 1957//90 1768//2138 1681//2145 +f 1957//90 2051//92 1768//2138 +f 526//1238 535//588 33//818 +f 1614//1998 1594//2038 1609//2014 +f 2233//1302 2229//2040 2216//1518 +f 2496//237 2027//631 2084//1006 +f 2496//237 1863//236 2027//631 +f 2117//235 1854//1621 1863//236 +f 2016//1270 2158//2341 1854//1621 +f 2016//1270 1504//1269 1357//1964 +f 2158//2341 2016//1270 1357//1964 +f 1114//2011 236//1215 1661//2010 +f 2129//2224 2154//1806 2137//1807 +f 2133//1846 2106//2349 2097//1837 +f 2491//324 1999//802 2041//2216 +f 2051//92 1238//479 1768//2138 +f 2061//1498 2108//2209 2081//840 +f 2189//1840 2195//1533 2186//1809 +f 2348//2174 2349//2119 2362//2223 +f 1701//1406 192//1832 482//1823 +f 505//801 1737//2125 1707//2126 +f 2133//1846 2132//2350 2106//2349 +f 2132//2350 2133//1846 2151//1633 +f 2151//1633 2170//1632 2160//1486 +f 502//1999 1661//2010 2162//1727 +f 1998//64 1389//1976 1997//1769 +f 2297//2353 2352//2354 2329//2355 +f 2352//2354 2364//2356 2329//2355 +f 2394//2357 2414//2358 2364//2356 +f 2352//2354 2394//2357 2364//2356 +f 2402//2165 512//1136 2415//2359 +f 2255//2360 2254//2361 2243//2336 +f 2446//2362 1365//990 2456//2363 +f 2271//2364 2282//2365 2298//2366 +f 846//268 2283//2367 2264//269 +f 2293//2368 2310//2369 2318//2370 +f 2254//2361 2295//2371 2294//2372 +f 2283//2367 2290//2373 2278//507 +f 2270//2250 2294//2372 2293//2368 +f 2423//2374 2455//2000 2400//1369 +f 2281//2375 2287//1301 2267//1300 +f 2190//2322 2191//2376 2204//1519 +f 2271//2364 2263//2377 2282//2365 +f 2334//2378 2329//2355 2364//2356 +f 2424//1495 2432//2379 2409//2380 +f 2282//2365 2263//2377 2298//2366 +f 1409//744 1659//1880 1958//477 +f 2263//2377 2302//2381 2298//2366 +f 2297//2353 2329//2355 2296//2382 +f 1256//1802 446//287 2346//2162 +f 1958//477 2502//28 2478//743 +f 2437//1684 2399//1792 2444//2383 +f 263//365 2366//1446 2359//464 +f 849//1380 827//1241 823//1444 +f 2311//1019 2325//2333 2290//2373 +f 2499//569 2379//1893 2434//27 +f 2446//2362 2456//2363 2423//2374 +f 947//1160 2358//446 2379//1893 +f 2499//569 947//1160 2379//1893 +f 2205//1534 2195//1533 2212//2384 +f 2245//2385 2237//1218 2227//1219 +f 2245//2385 2256//1898 2237//1218 +f 2256//1898 2263//2377 2271//2364 +f 556//1551 571//1008 2305//1020 +f 1528//1767 2068//344 1518//1104 +f 2424//1495 2439//949 2432//2379 +f 2302//2381 2352//2354 2297//2353 +f 1866//424 2237//1218 826//425 +f 2248//2386 2242//2387 2211//1517 +f 2334//2378 2364//2356 2363//2388 +f 2235//2105 2244//2335 2226//2337 +f 2255//2360 2295//2371 2254//2361 +f 2329//2355 2324//2389 2296//2382 +f 2439//949 2447//1299 1973//950 +f 2329//2355 2334//2378 2324//2389 +f 2409//2380 2432//2379 2414//2358 +f 2293//2368 2318//2370 2276//2251 +f 866//1987 2425//2390 2416//2391 +f 1487//390 1493//2392 2372//1682 +f 2237//1218 2231//1900 2230//2103 +f 2415//2359 512//1136 17//1230 +f 2035//989 1236//535 26//536 +f 921//137 2138//1330 688//160 +f 2491//324 2482//1126 2462//325 +f 6//1282 181//843 197//845 +f 2481//418 948//256 1795//255 +f 2138//1330 2383//2247 2382//1197 +f 2377//2393 2394//2357 2352//2354 +f 2377//2393 506//1463 2394//2357 +f 2394//2357 506//1463 2402//2165 +f 2401//2394 2402//2165 2415//2359 +f 2394//2357 2402//2165 2401//2394 +f 2318//2370 2326//1950 2276//2251 +f 2439//949 2457//948 2432//2379 +f 2298//2366 2302//2381 2297//2353 +f 2244//2335 2249//2395 2243//2336 +f 2404//2396 1100//77 2382//1197 +f 2238//2397 2245//2385 2227//1219 +f 2245//2385 2257//2398 2256//1898 +f 2257//2398 2263//2377 2256//1898 +f 2324//2389 2334//2378 2328//2399 +f 2257//2398 2289//2400 2263//2377 +f 2289//2400 2302//2381 2263//2377 +f 2236//2104 2231//1900 2250//1899 +f 2138//1330 2382//1197 688//160 +f 2383//2247 2404//2396 2382//1197 +f 1100//77 2404//2396 2343//2401 +f 2353//1465 2352//2354 2302//2381 +f 2353//1465 2377//2393 2352//2354 +f 2237//1218 2230//2103 2220//712 +f 2335//1240 2355//1237 2325//2333 +f 2308//2123 2340//2169 2315//2402 +f 2253//2006 2269//2137 2276//2251 +f 2311//1019 2335//1240 2325//2333 +f 2439//949 2424//1495 511//1306 +f 2268//2107 2267//1300 2248//2386 +f 2383//2247 413//1350 2404//2396 +f 123//1666 971//1346 832//2403 +f 2234//2005 2243//2336 2269//2137 +f 2225//2004 2213//1903 2234//2005 +f 2219//2404 2213//1903 2225//2004 +f 2195//1533 2196//1901 2212//2384 +f 1544//2061 2418//284 1549//2047 +f 413//1350 866//1987 2404//2396 +f 2404//2396 866//1987 2416//2391 +f 2416//2391 2417//2405 2404//2396 +f 2404//2396 2417//2405 2343//2401 +f 2415//2359 2409//2380 2401//2394 +f 2196//1901 2219//2404 2212//2384 +f 2268//2107 2248//2386 2218//2106 +f 2206//2406 2214//1902 2197//2407 +f 2417//2405 2332//2408 2343//2401 +f 2343//2401 2332//2408 832//2403 +f 2330//1464 2302//2381 2289//2400 +f 2330//1464 2353//1465 2302//2381 +f 2453//1140 2454//1139 515//1147 +f 2218//2106 2248//2386 2217//2409 +f 2218//2106 2217//2409 2205//1534 +f 2276//2251 2281//2375 2268//2107 +f 2178//1384 2197//2407 2177//1471 +f 2197//2407 2189//1840 2177//1471 +f 2332//2408 2066//2410 832//2403 +f 832//2403 2066//2410 123//1666 +f 2231//1900 2236//2104 2230//2103 +f 669//35 950//1257 1144//33 +f 2217//2409 2211//1517 2199//2411 +f 1216//1798 1209//2412 1217//1813 +f 2066//2410 2365//2413 123//1666 +f 2230//2103 2226//2337 2214//1902 +f 2290//2373 2325//2333 2304//1368 +f 2325//2333 2319//1366 2304//1368 +f 2217//2409 2248//2386 2211//1517 +f 2191//2376 2192//1532 2199//2411 +f 510//988 525//1239 2035//989 +f 2417//2405 1917//2414 2332//2408 +f 2332//2408 1917//2414 2066//2410 +f 2408//2415 2413//333 2341//332 +f 2248//2386 2267//1300 2242//2387 +f 2326//1950 2333//1353 2281//2375 +f 1340//1845 2365//2413 2066//2410 +f 2440//1758 1302//1765 1340//1845 +f 2226//2337 2230//2103 2235//2105 +f 1153//1570 1163//816 1116//1265 +f 2431//1520 2455//2000 2438//1227 +f 2416//2391 2425//2390 2417//2405 +f 2495//576 2474//323 2462//325 +f 2290//2373 2304//1368 2277//2416 +f 825//1305 2227//1219 1872//1172 +f 151//760 239//1577 1038//694 +f 9//728 151//760 1038//694 +f 545//113 928//1548 2381//25 +f 2440//1758 2406//1766 1384//1747 +f 928//1548 1596//80 2381//25 +f 2186//1809 2188//893 2185//2417 +f 2456//2363 26//536 1888//1225 +f 2287//1301 2333//1353 2262//1707 +f 2425//2390 2342//2418 2417//2405 +f 2342//2418 1917//2414 2417//2405 +f 1917//2414 877//2419 2066//2410 +f 2336//2420 1340//1845 2066//2410 +f 2336//2420 2440//1758 1340//1845 +f 2328//2399 2351//2421 2327//1948 +f 825//1305 2238//2397 2227//1219 +f 2351//2421 2368//1949 2327//1948 +f 1222//1746 2388//1780 1211//1790 +f 678//1440 756//1413 734//184 +f 428//1445 263//365 1343//367 +f 2188//893 2191//2376 2190//2322 +f 2341//332 2376//334 2333//1353 +f 2066//2410 877//2419 2336//2420 +f 2290//2373 2277//2416 2278//507 +f 739//984 634//356 592//267 +f 675//1014 304//263 14//230 +f 2384//1480 675//1014 14//230 +f 2199//2411 2211//1517 2204//1519 +f 2191//2376 2199//2411 2204//1519 +f 2322//2422 2318//2370 2310//2369 +f 2287//1301 2262//1707 2233//1302 +f 2185//2417 2188//893 2184//892 +f 2386//1822 2425//2390 845//1942 +f 2384//1480 572//1015 675//1014 +f 1128//795 123//1666 2365//2413 +f 832//2403 971//1346 2343//2401 +f 2188//893 2186//1809 2191//2376 +f 2185//2417 2184//892 2176//1469 +f 2345//2423 1917//2414 2342//2418 +f 2345//2423 877//2419 1917//2414 +f 2336//2420 2406//1766 2440//1758 +f 971//1346 1100//77 2343//2401 +f 2299//2424 2289//2400 2257//2398 +f 2299//2424 2303//1499 2289//2400 +f 2249//2395 2255//2360 2243//2336 +f 506//1463 513//1076 512//1136 +f 2437//1684 955//1349 1219//1348 +f 1587//1546 2398//1829 1324//1547 +f 877//2419 2396//2351 2336//2420 +f 2336//2420 2396//2351 2406//1766 +f 2463//245 2479//648 879//246 +f 2376//334 2412//2425 2350//1354 +f 2281//2375 2267//1300 2268//2107 +f 2303//1499 2330//1464 2289//2400 +f 624//295 635//947 159//649 +f 1996//1009 2356//1271 1561//114 +f 2449//283 2436//282 1996//1009 +f 2356//1271 2054//2426 2451//1489 +f 928//1548 2398//1829 1587//1546 +f 2333//1353 2350//1354 2262//1707 +f 2035//989 26//536 2456//2363 +f 2346//2162 2342//2418 2425//2390 +f 2346//2162 2345//2423 2342//2418 +f 1544//2061 2380//2427 2418//284 +f 2412//2425 2392//2327 2350//1354 +f 622//1109 509//1645 1151//1281 +f 2436//282 2054//2426 1996//1009 +f 545//113 2451//1489 928//1548 +f 2326//1950 2341//332 2333//1353 +f 2346//2162 2425//2390 2386//1822 +f 1365//990 2035//989 2456//2363 +f 2369//1436 2377//2393 2353//1465 +f 2369//1436 506//1463 2377//2393 +f 2451//1489 900//2428 928//1548 +f 900//2428 2398//1829 928//1548 +f 1235//1226 1888//1225 1244//169 +f 2337//1291 2345//2423 2346//2162 +f 877//2419 772//1843 2396//2351 +f 772//1843 1275//1491 2396//2351 +f 2432//2379 2446//2362 2414//2358 +f 2294//2372 2295//2371 2310//2369 +f 2369//1436 2330//1464 828//1437 +f 2418//284 2419//2429 2436//282 +f 2450//2430 2429//2431 2436//282 +f 2436//282 2429//2431 2054//2426 +f 2490//1235 2494//495 1656//1562 +f 1321//1732 155//1608 2338//1607 +f 1256//1802 2346//2162 2386//1822 +f 2448//2432 877//2419 2345//2423 +f 877//2419 2448//2432 772//1843 +f 2446//2362 2423//2374 2414//2358 +f 2351//2421 2334//2378 2363//2388 +f 2243//2336 2254//2361 2269//2137 +f 2380//2427 2419//2429 2418//284 +f 2419//2429 2450//2430 2436//282 +f 2283//2367 2278//507 2264//269 +f 822//1133 2197//2407 823//1444 +f 1008//1869 1759//1662 1565//436 +f 2448//2432 2345//2423 2337//1291 +f 2270//2250 2293//2368 2276//2251 +f 2323//2433 2324//2389 2328//2399 +f 2429//2431 1012//2434 2054//2426 +f 2226//2337 2243//2336 2213//1903 +f 2395//229 325//200 772//1843 +f 2370//1801 2367//428 2380//2427 +f 2054//2426 2435//2435 2451//1489 +f 2435//2435 2397//2436 2451//1489 +f 2451//1489 2397//2436 900//2428 +f 1774//1512 1974//2168 1975//2118 +f 2305//1020 2290//2373 2283//2367 +f 846//268 2305//1020 2283//2367 +f 2320//2347 1215//577 2285//579 +f 2139//2437 2448//2432 2337//1291 +f 2448//2432 2395//229 772//1843 +f 1232//1803 1231//1796 1216//1798 +f 2272//74 2285//579 2284//1754 +f 2367//428 2371//2438 2380//2427 +f 2371//2438 2405//2439 2380//2427 +f 2380//2427 2405//2439 2419//2429 +f 2419//2429 2429//2431 2450//2430 +f 2429//2431 176//2440 1012//2434 +f 2397//2436 2373//2441 900//2428 +f 2373//2441 2398//1829 900//2428 +f 2373//2441 1379//1752 2398//1829 +f 2372//1682 1500//2442 1508//2068 +f 1133//107 1303//1460 1142//1263 +f 2252//2330 2273//2443 2272//74 +f 891//76 2252//2330 2272//74 +f 2419//2429 2405//2439 2429//2431 +f 2405//2439 2430//2444 2429//2431 +f 2429//2431 2430//2444 176//2440 +f 2189//1840 2186//1809 2181//1841 +f 2212//2384 2219//2404 2218//2106 +f 2312//1005 2139//2437 2337//1291 +f 2139//2437 2384//1480 2448//2432 +f 2448//2432 2384//1480 2395//229 +f 899//1374 855//1317 843//1316 +f 2272//74 2273//2443 2285//579 +f 2331//1367 2303//1499 2299//2424 +f 176//2440 2435//2435 2054//2426 +f 1012//2434 176//2440 2054//2426 +f 2177//1471 2185//2417 2176//1469 +f 2218//2106 2219//2404 2225//2004 +f 1216//1798 1220//1783 1215//577 +f 2378//1034 2139//2437 2312//1005 +f 2384//1480 14//230 2395//229 +f 2324//2389 2295//2371 2255//2360 +f 2240//2203 2273//2443 2252//2330 +f 2371//2438 2387//2445 2405//2439 +f 2410//2446 2430//2444 2405//2439 +f 2430//2444 2442//2447 176//2440 +f 2435//2435 2344//2448 2397//2436 +f 2397//2436 2344//2448 2373//2441 +f 2456//2363 1888//1225 2455//2000 +f 2242//2387 2267//1300 2233//1302 +f 2233//1302 2262//1707 2229//2040 +f 2378//1034 2384//1480 2139//2437 +f 2323//2433 2310//2369 2295//2371 +f 2323//2433 2322//2422 2310//2369 +f 2240//2203 2274//2449 2273//2443 +f 974//1177 841//1178 990//1459 +f 2490//1235 1447//1161 2486//568 +f 2387//2445 2410//2446 2405//2439 +f 2442//2447 2141//2450 176//2440 +f 2344//2448 1778//2451 2373//2441 +f 972//2452 1379//1752 2373//2441 +f 1778//2451 972//2452 2373//2441 +f 1379//1752 972//2452 428//1445 +f 1211//1790 2437//1684 1223//1625 +f 1228//578 1215//577 1220//1783 +f 702//1033 2378//1034 2312//1005 +f 17//1230 518//1206 2415//2359 +f 1888//1225 26//536 1244//169 +f 2324//2389 2323//2433 2295//2371 +f 2305//1020 2311//1019 2290//2373 +f 2307//2453 2285//579 2273//2443 +f 2274//2449 2307//2453 2273//2443 +f 2307//2453 2320//2347 2285//579 +f 2369//1436 531//1077 506//1463 +f 2435//2435 2258//2454 2344//2448 +f 2296//2382 2324//2389 2288//2455 +f 1233//278 1217//1813 2361//2342 +f 2360//427 2371//2438 2367//428 +f 2410//2446 2442//2447 2430//2444 +f 176//2440 2141//2450 2258//2454 +f 176//2440 2258//2454 2435//2435 +f 539//1149 2331//1367 66//583 +f 2350//1354 2392//2327 2317//2321 +f 2268//2107 2225//2004 2253//2006 +f 1508//2068 1500//2442 2371//2438 +f 2360//427 1508//2068 2371//2438 +f 2371//2438 1500//2442 2387//2445 +f 972//2452 2366//1446 428//1445 +f 1626//1905 1686//2017 1358//1857 +f 1759//1662 1807//1661 1819//1615 +f 2277//2416 2257//2398 2245//2385 +f 2277//2416 2299//2424 2257//2398 +f 1784//1972 2228//2456 1736//1409 +f 2265//2457 2240//2203 1736//1409 +f 2228//2456 2265//2457 1736//1409 +f 2265//2457 2274//2449 2240//2203 +f 1209//2412 2320//2347 2307//2453 +f 2320//2347 1209//2412 1216//1798 +f 1555//40 1584//41 1560//2091 +f 2387//2445 1500//2442 2372//1682 +f 2410//2446 2420//2458 2442//2447 +f 2433//2459 972//2452 1778//2451 +f 2433//2459 2366//1446 972//2452 +f 955//1349 522//1094 1225//1347 +f 2339//2460 2307//2453 2274//2449 +f 2372//1682 1493//2392 2387//2445 +f 2411//2461 2420//2458 2410//2446 +f 2420//2458 954//2462 2442//2447 +f 2442//2447 954//2462 2141//2450 +f 2344//2448 2433//2459 1778//2451 +f 2205//1534 2212//2384 2218//2106 +f 2328//2399 2334//2378 2351//2421 +f 2394//2357 2401//2394 2414//2358 +f 2250//1899 2256//1898 2271//2364 +f 2339//2460 1209//2412 2307//2453 +f 2328//2399 2322//2422 2323//2433 +f 866//1987 845//1942 2425//2390 +f 3//1594 316//1628 893//2019 +f 2387//2445 2411//2461 2410//2446 +f 2441//2463 2141//2450 954//2462 +f 2141//2450 2441//2463 2258//2454 +f 2354//2464 2433//2459 2344//2448 +f 2254//2361 2294//2372 2270//2250 +f 2269//2137 2254//2361 2270//2250 +f 863//1541 2305//1020 846//268 +f 2441//2463 2354//2464 2258//2454 +f 2258//2454 2354//2464 2344//2448 +f 2319//1366 2355//1237 51//582 +f 2223//53 2228//2456 1784//1972 +f 1493//2392 2411//2461 2387//2445 +f 1560//2091 2449//283 1555//40 +f 2288//2455 2324//2389 2255//2360 +f 825//1305 2251//508 2238//2397 +f 2251//508 2245//2385 2238//2397 +f 1299//591 84//590 1312//1704 +f 2246//2465 2265//2457 2228//2456 +f 2313//2466 2274//2449 2265//2457 +f 2313//2466 2339//2460 2274//2449 +f 2251//508 2277//2416 2245//2385 +f 2319//1366 51//582 2331//1367 +f 891//76 1862//451 2252//2330 +f 2443//1687 954//2462 2420//2458 +f 2443//1687 2441//2463 954//2462 +f 511//1306 2447//1299 2439//949 +f 2242//2387 2233//1302 2211//1517 +f 188//249 15//560 814//547 +f 2443//1687 2426//2352 2441//2463 +f 2426//2352 2354//2464 2441//2463 +f 2306//2467 2403//2468 2433//2459 +f 2433//2459 2403//2468 2366//1446 +f 539//1149 2303//1499 2331//1367 +f 2246//2465 2228//2456 2223//53 +f 1030//830 1819//1615 1807//1661 +f 2354//2464 2306//2467 2433//2459 +f 2413//333 2412//2425 2376//334 +f 2438//1227 2455//2000 1888//1225 +f 1848//1966 1857//1947 2176//1469 +f 2207//52 2208//2469 2223//53 +f 2208//2469 2246//2465 2223//53 +f 1209//2412 2339//2460 1217//1813 +f 2339//2460 2361//2342 1217//1813 +f 1221//1481 1210//2343 2388//1780 +f 554//401 109//400 78//414 +f 386//162 1375//164 95//151 +f 2327//1948 2326//1950 2318//2370 +f 2179//1523 2182//2470 1393//1937 +f 2182//2470 2208//2469 1393//1937 +f 1393//1937 2208//2469 2207//52 +f 2361//2342 2399//1792 2388//1780 +f 2388//1780 2399//1792 1211//1790 +f 2306//2467 2354//2464 2426//2352 +f 2403//2468 2359//464 2366//1446 +f 2214//1902 2226//2337 2213//1903 +f 2268//2107 2253//2006 2276//2251 +f 889//1524 2200//2471 2179//1523 +f 2200//2471 2182//2470 2179//1523 +f 2200//2471 2221//2472 2182//2470 +f 2221//2472 2208//2469 2182//2470 +f 2314//2473 2265//2457 2246//2465 +f 2314//2473 2313//2466 2265//2457 +f 2339//2460 2374//2474 2361//2342 +f 2478//743 2434//27 2379//1893 +f 2205//1534 2217//2409 2199//2411 +f 2208//2469 2259//2475 2246//2465 +f 2259//2475 2275//2476 2246//2465 +f 2314//2473 2321//2477 2313//2466 +f 2313//2466 2347//2478 2339//2460 +f 2347//2478 2374//2474 2339//2460 +f 2374//2474 2399//1792 2361//2342 +f 153//1733 154//1737 2426//2352 +f 154//1737 2306//2467 2426//2352 +f 2385//496 2359//464 2403//2468 +f 2221//2472 2259//2475 2208//2469 +f 2306//2467 2357//2479 2403//2468 +f 2357//2479 2385//496 2403//2468 +f 2237//1218 2256//1898 2231//1900 +f 2172//1528 2180//1553 889//1524 +f 2180//1553 2200//2471 889//1524 +f 2200//2471 2201//2480 2221//2472 +f 2246//2465 2291//2481 2314//2473 +f 2374//2474 2444//2383 2399//1792 +f 571//1008 555//1063 2311//1019 +f 2192//1532 2205//1534 2199//2411 +f 2173//1554 2180//1553 2172//1528 +f 2279//2482 2246//2465 2275//2476 +f 2279//2482 2291//2481 2246//2465 +f 2292//2483 2314//2473 2291//2481 +f 2321//2477 2362//2223 2313//2466 +f 2362//2223 2347//2478 2313//2466 +f 2347//2478 2389//2484 2374//2474 +f 2444//2383 955//1349 2437//1684 +f 2292//2483 2291//2481 2279//2482 +f 2452//2485 2444//2383 2374//2474 +f 2054//2426 2356//1271 1996//1009 +f 2338//1607 2306//2467 154//1737 +f 2186//1809 2192//1532 2191//2376 +f 2193//2486 2201//2480 2200//2471 +f 2259//2475 2221//2472 2201//2480 +f 2247//2487 2259//2475 2201//2480 +f 2452//2485 955//1349 2444//2383 +f 2278//507 2277//2416 2251//508 +f 2338//1607 2357//2479 2306//2467 +f 2181//1841 2186//1809 2185//2417 +f 2276//2251 2326//1950 2281//2375 +f 2432//2379 2457//948 2446//2362 +f 2198//2488 2201//2480 2193//2486 +f 2198//2488 2232//2489 2201//2480 +f 2232//2489 2247//2487 2201//2480 +f 2389//2484 2452//2485 2374//2474 +f 2452//2485 1630//1352 955//1349 +f 1403//859 1749//1940 1444//860 +f 1555//40 1996//1009 1561//114 +f 2357//2479 2427//2490 2385//496 +f 2385//496 2428//1128 230//465 +f 2409//2380 2415//2359 2424//1495 +f 2304//1368 2331//1367 2299//2424 +f 2193//2486 2200//2471 2180//1553 +f 2445//1141 2452//2485 2389//2484 +f 1565//436 1759//1662 1927//1855 +f 2380//2427 1544//2061 2370//1801 +f 2338//1607 2427//2490 2357//2479 +f 2427//2490 2428//1128 2385//496 +f 230//465 222//593 253//550 +f 2202//2491 2198//2488 2193//2486 +f 2202//2491 2209//2492 2198//2488 +f 2209//2492 2241//2493 2198//2488 +f 2241//2493 2232//2489 2198//2488 +f 2266//2124 2275//2476 2259//2475 +f 2365//2413 1340//1845 1128//795 +f 2415//2359 518//1206 2424//1495 +f 2338//1607 170//456 2427//2490 +f 170//456 2428//1128 2427//2490 +f 2181//1841 2185//2417 2177//1471 +f 2196//1901 2195//1533 2189//1840 +f 2183//894 2193//2486 2180//1553 +f 2453//1140 1630//1352 2452//2485 +f 2197//2407 2214//1902 2189//1840 +f 2401//2394 2409//2380 2414//2358 +f 822//1133 2220//712 2197//2407 +f 1210//2343 2361//2342 2388//1780 +f 2187//2494 2193//2486 2183//894 +f 2187//2494 2202//2491 2193//2486 +f 2266//2124 2279//2482 2275//2476 +f 2279//2482 2300//2495 2292//2483 +f 2375//2496 2347//2478 2362//2223 +f 2375//2496 2390//2497 2347//2478 +f 2390//2497 2389//2484 2347//2478 +f 2453//1140 2452//2485 2445//1141 +f 1347//1768 1630//1352 2453//1140 +f 1630//1352 1347//1768 522//1094 +f 2220//712 2206//2406 2197//2407 +f 2262//1707 2350//1354 2286//1708 +f 170//456 254//592 2428//1128 +f 2457//948 1973//950 2446//2362 +f 1973//950 1365//990 2446//2362 +f 2174//1552 2183//894 2180//1553 +f 2194//2498 2202//2491 2187//2494 +f 2222//2499 2241//2493 2209//2492 +f 2222//2499 2260//2500 2241//2493 +f 2266//2124 2259//2475 2247//2487 +f 2390//2497 2445//1141 2389//2484 +f 2264//269 2251//508 825//1305 +f 2363//2388 2368//1949 2351//2421 +f 2326//1950 2393//2115 2341//332 +f 1855//2227 1850//1394 1851//1530 +f 2210//2501 2209//2492 2202//2491 +f 2210//2501 2222//2499 2209//2492 +f 2261//1709 2260//2500 2222//2499 +f 2280//2502 2279//2482 2266//2124 +f 2280//2502 2300//2495 2279//2482 +f 251//429 263//365 2359//464 +f 2277//2416 2304//1368 2299//2424 +f 2220//712 2230//2103 2206//2406 +f 2202//2491 2194//2498 2210//2501 +f 2213//1903 2243//2336 2234//2005 +f 2328//2399 2327//1948 2322//2422 +f 2294//2372 2310//2369 2293//2368 +f 2214//1902 2196//1901 2189//1840 +f 2196//1901 2213//1903 2219//2404 +f 2224//2033 2222//2499 2210//2501 +f 2421//1983 2390//2497 2375//2496 +f 2206//2406 2230//2103 2214//1902 +f 2194//2498 2203//2306 2210//2501 +f 2224//2033 2261//1709 2222//2499 +f 2421//1983 2445//1141 2390//2497 +f 2322//2422 2327//1948 2318//2370 +f 2393//2115 2408//2415 2341//332 +f 1365//990 1973//950 510//988 +f 2216//1518 2210//2501 2203//2306 +f 2216//1518 2224//2033 2210//2501 +f 2266//2124 2308//2123 2280//2502 +f 2280//2502 2308//2123 2300//2495 +f 2407//1370 2421//1983 2375//2496 +f 2175//1262 2183//894 2174//1552 +f 2194//2498 2190//2322 2203//2306 +f 2454//1139 2445//1141 2421//1983 +f 522//1094 1347//1768 523//1095 +f 2456//2363 2455//2000 2423//2374 +f 823//1444 2197//2407 2178//1384 +f 2281//2375 2333//1353 2287//1301 +f 2188//893 2187//2494 2183//894 +f 2188//893 2190//2322 2194//2498 +f 2187//2494 2188//893 2194//2498 +f 2308//2123 2315//2402 2300//2495 +f 2407//1370 2375//2496 2362//2223 +f 2443//1687 2420//2458 2503//2503 +f 2420//2458 2411//2461 2503//2503 +f 2411//2461 1493//2392 2503//2503 +f 1493//2392 1487//390 2503//2503 +f 1487//390 1318//389 2503//2503 +f 1318//389 1320//1416 2503//2503 +f 1320//1416 2443//1687 2503//2503 diff --git a/objs/teapot.obj b/objs/teapot.obj new file mode 100644 index 0000000..f726a9c --- /dev/null +++ b/objs/teapot.obj @@ -0,0 +1,2089 @@ +# OBJ file created by ply_to_obj.c +# + +v 40.6266 28.3457 -1.10804 +v 40.0714 30.4443 -1.10804 +v 40.7155 31.1438 -1.10804 +v 42.0257 30.4443 -1.10804 +v 43.4692 28.3457 -1.10804 +v 37.5425 28.3457 14.5117 +v 37.0303 30.4443 14.2938 +v 37.6244 31.1438 14.5466 +v 38.8331 30.4443 15.0609 +v 40.1647 28.3457 15.6274 +v 29.0859 28.3457 27.1468 +v 28.6917 30.4443 26.7527 +v 29.149 31.1438 27.2099 +v 30.0792 30.4443 28.1402 +v 31.1041 28.3457 29.165 +v 16.4508 28.3457 35.6034 +v 16.2329 30.4443 35.0912 +v 16.4857 31.1438 35.6853 +v 16.9999 30.4443 36.894 +v 17.5665 28.3457 38.2256 +v 0.831025 28.3457 38.6876 +v 0.831025 30.4443 38.1324 +v 0.831025 31.1438 38.7764 +v 0.831025 30.4443 40.0866 +v 0.831025 28.3457 41.5301 +v -15.868 28.3457 35.6034 +v -15.0262 30.4443 35.0912 +v -14.9585 31.1438 35.6853 +v -15.3547 30.4443 36.894 +v -15.9044 28.3457 38.2256 +v -28.3832 28.3457 27.1468 +v -27.4344 30.4443 26.7527 +v -27.6068 31.1438 27.2099 +v -28.4322 30.4443 28.1402 +v -29.4421 28.3457 29.165 +v -36.2402 28.3457 14.5117 +v -35.52 30.4443 14.2938 +v -36.0073 31.1438 14.5466 +v -37.1767 30.4443 15.0609 +v -38.5027 28.3457 15.6274 +v -38.9646 28.3457 -1.10804 +v -38.4094 30.4443 -1.10804 +v -39.0534 31.1438 -1.10804 +v -40.3636 30.4443 -1.10804 +v -41.8071 28.3457 -1.10804 +v -35.8804 28.3457 -16.7278 +v -35.3683 30.4443 -16.5099 +v -35.9624 31.1438 -16.7627 +v -37.1711 30.4443 -17.2769 +v -38.5027 28.3457 -17.8435 +v -27.4238 28.3457 -29.3629 +v -27.0297 30.4443 -28.9687 +v -27.4869 31.1438 -29.426 +v -28.4172 30.4443 -30.3562 +v -29.4421 28.3457 -31.3811 +v -14.7887 28.3457 -37.8195 +v -14.5708 30.4443 -37.3073 +v -14.8236 31.1438 -37.9014 +v -15.3379 30.4443 -39.1101 +v -15.9044 28.3457 -40.4417 +v 0.831025 28.3457 -40.9036 +v 0.831025 30.4443 -40.3484 +v 0.831025 31.1438 -40.9925 +v 0.831025 30.4443 -42.3027 +v 0.831025 28.3457 -43.7462 +v 16.4508 28.3457 -37.8195 +v 16.2329 30.4443 -37.3073 +v 16.4857 31.1438 -37.9014 +v 16.9999 30.4443 -39.1101 +v 17.5665 28.3457 -40.4417 +v 29.0859 28.3457 -29.3629 +v 28.6917 30.4443 -28.9687 +v 29.149 31.1438 -29.426 +v 30.0792 30.4443 -30.3562 +v 31.1041 28.3457 -31.3811 +v 37.5425 28.3457 -16.7278 +v 37.0303 30.4443 -16.5099 +v 37.6244 31.1438 -16.7627 +v 38.8331 30.4443 -17.2769 +v 40.1647 28.3457 -17.8435 +v 48.6879 17.1865 -1.10804 +v 53.2404 6.22714 -1.10804 +v 56.4605 -4.33246 -1.10804 +v 57.6819 -14.2925 -1.10804 +v 44.979 17.1865 17.6758 +v 49.1787 6.22714 19.4626 +v 52.1492 -4.33246 20.7265 +v 53.2759 -14.2925 21.2059 +v 34.8094 17.1865 32.8703 +v 38.0417 6.22714 36.1026 +v 40.3279 -4.33246 38.3889 +v 41.1951 -14.2925 39.2561 +v 19.6148 17.1865 43.0399 +v 21.4017 6.22714 47.2396 +v 22.6656 -4.33246 50.2101 +v 23.145 -14.2925 51.3369 +v 0.831025 17.1865 46.7488 +v 0.831025 6.22714 51.3013 +v 0.831025 -4.33246 54.5214 +v 0.831025 -14.2925 55.7428 +v -17.9528 17.1865 43.0399 +v -19.7397 6.22714 47.2396 +v -21.0035 -4.33246 50.2101 +v -21.4829 -14.2925 51.3369 +v -33.1474 17.1865 32.8703 +v -36.3796 6.22714 36.1026 +v -38.6659 -4.33246 38.3889 +v -39.5331 -14.2925 39.2561 +v -43.3169 17.1865 17.6758 +v -47.5166 6.22714 19.4626 +v -50.4871 -4.33246 20.7265 +v -51.6139 -14.2925 21.2059 +v -47.0258 17.1865 -1.10804 +v -51.5784 6.22714 -1.10804 +v -54.7984 -4.33246 -1.10804 +v -56.0198 -14.2925 -1.10804 +v -43.3169 17.1865 -19.8919 +v -47.5166 6.22714 -21.6787 +v -50.4871 -4.33246 -22.9426 +v -51.6139 -14.2925 -23.422 +v -33.1474 17.1865 -35.0864 +v -36.3796 6.22714 -38.3187 +v -38.6659 -4.33246 -40.6049 +v -39.5331 -14.2925 -41.4721 +v -17.9528 17.1865 -45.256 +v -19.7397 6.22714 -49.4557 +v -21.0035 -4.33246 -52.4262 +v -21.4829 -14.2925 -53.5529 +v 0.831025 17.1865 -48.9649 +v 0.831025 6.22714 -53.5174 +v 0.831025 -4.33246 -56.7375 +v 0.831025 -14.2925 -57.9589 +v 19.6148 17.1865 -45.256 +v 21.4017 6.22714 -49.4557 +v 22.6656 -4.33246 -52.4262 +v 23.145 -14.2925 -53.5529 +v 34.8094 17.1865 -35.0864 +v 38.0417 6.22714 -38.3187 +v 40.3279 -4.33246 -40.6049 +v 41.1951 -14.2925 -41.4721 +v 44.979 17.1865 -19.8919 +v 49.1787 6.22714 -21.6787 +v 52.1492 -4.33246 -22.9426 +v 53.2759 -14.2925 -23.422 +v 55.4611 -22.7202 -1.10804 +v 50.5755 -28.9493 -1.10804 +v 45.6899 -33.1798 -1.10804 +v 43.4692 -35.6115 -1.10804 +v 51.2273 -22.7202 20.3343 +v 46.7203 -28.9493 18.4167 +v 42.2133 -33.1798 16.4991 +v 40.1647 -35.6115 15.6274 +v 39.6184 -22.7202 37.6793 +v 36.1496 -28.9493 34.2106 +v 32.6808 -33.1798 30.7418 +v 31.1041 -35.6115 29.165 +v 22.2733 -22.7202 49.2882 +v 20.3557 -28.9493 44.7813 +v 18.4381 -33.1798 40.2743 +v 17.5665 -35.6115 38.2256 +v 0.831025 -22.7202 53.5221 +v 0.831025 -28.9493 48.6365 +v 0.831025 -33.1798 43.7508 +v 0.831025 -35.6115 41.5301 +v -20.6113 -22.7202 49.2882 +v -18.6937 -28.9493 44.7813 +v -16.7761 -33.1798 40.2743 +v -15.9044 -35.6115 38.2256 +v -37.9564 -22.7202 37.6793 +v -34.4876 -28.9493 34.2106 +v -31.0188 -33.1798 30.7418 +v -29.4421 -35.6115 29.165 +v -49.5653 -22.7202 20.3343 +v -45.0583 -28.9493 18.4167 +v -40.5513 -33.1798 16.4991 +v -38.5027 -35.6115 15.6274 +v -53.7991 -22.7202 -1.10804 +v -48.9135 -28.9493 -1.10804 +v -44.0279 -33.1798 -1.10804 +v -41.8071 -35.6115 -1.10804 +v -49.5653 -22.7202 -22.5504 +v -45.0583 -28.9493 -20.6327 +v -40.5513 -33.1798 -18.7151 +v -38.5027 -35.6115 -17.8435 +v -37.9564 -22.7202 -39.8954 +v -34.4876 -28.9493 -36.4266 +v -31.0188 -33.1798 -32.9578 +v -29.4421 -35.6115 -31.3811 +v -20.6113 -22.7202 -51.5043 +v -18.6937 -28.9493 -46.9973 +v -16.7761 -33.1798 -42.4903 +v -15.9044 -35.6115 -40.4417 +v 0.831025 -22.7202 -55.7382 +v 0.831025 -28.9493 -50.8525 +v 0.831025 -33.1798 -45.9669 +v 0.831025 -35.6115 -43.7462 +v 22.2733 -22.7202 -51.5043 +v 20.3557 -28.9493 -46.9973 +v 18.4381 -33.1798 -42.4903 +v 17.5665 -35.6115 -40.4417 +v 39.6184 -22.7202 -39.8954 +v 36.1496 -28.9493 -36.4266 +v 32.6808 -33.1798 -32.9578 +v 31.1041 -35.6115 -31.3811 +v 51.2273 -22.7202 -22.5504 +v 46.7203 -28.9493 -20.6327 +v 42.2133 -33.1798 -18.7151 +v 40.1647 -35.6115 -17.8435 +v 42.5031 -37.1772 -1.10804 +v 37.3399 -38.5429 -1.10804 +v 24.5818 -39.5089 -1.10804 +v 0.831025 -39.8754 -1.10804 +v 39.2736 -37.1772 15.2483 +v 34.5105 -38.5429 13.2217 +v 22.7411 -39.5089 8.21414 +v 30.4182 -37.1772 28.4792 +v 26.7523 -38.5429 24.8133 +v 17.6941 -39.5089 15.755 +v 17.1873 -37.1772 37.3345 +v 15.1608 -38.5429 32.5714 +v 10.1532 -39.5089 20.8021 +v 0.831025 -37.1772 40.5641 +v 0.831025 -38.5429 35.4009 +v 0.831025 -39.5089 22.6427 +v -15.5253 -37.1772 37.3345 +v -13.4987 -38.5429 32.5714 +v -8.49115 -39.5089 20.8021 +v -28.7562 -37.1772 28.4792 +v -25.0903 -38.5429 24.8133 +v -16.032 -39.5089 15.755 +v -37.6115 -37.1772 15.2483 +v -32.8484 -38.5429 13.2217 +v -21.0791 -39.5089 8.21414 +v -40.8411 -37.1772 -1.10804 +v -35.6779 -38.5429 -1.10804 +v -22.9198 -39.5089 -1.10804 +v -37.6115 -37.1772 -17.4643 +v -32.8484 -38.5429 -15.4378 +v -21.0791 -39.5089 -10.4302 +v -28.7562 -37.1772 -30.6952 +v -25.0903 -38.5429 -27.0294 +v -16.032 -39.5089 -17.9711 +v -15.5253 -37.1772 -39.5506 +v -13.4987 -38.5429 -34.7875 +v -8.49115 -39.5089 -23.0181 +v 0.831025 -37.1772 -42.7802 +v 0.831025 -38.5429 -37.6169 +v 0.831025 -39.5089 -24.8588 +v 17.1873 -37.1772 -39.5506 +v 15.1608 -38.5429 -34.7875 +v 10.1532 -39.5089 -23.0181 +v 30.4182 -37.1772 -30.6952 +v 26.7523 -38.5429 -27.0294 +v 17.6941 -39.5089 -17.9711 +v 39.2736 -37.1772 -17.4643 +v 34.5105 -38.5429 -15.4378 +v 22.7411 -39.5089 -10.4302 +v -44.6497 17.6861 -1.10804 +v -57.9297 17.5862 -1.10804 +v -67.7453 16.8867 -1.10804 +v -73.8301 14.9879 -1.10804 +v -75.9176 11.2904 -1.10804 +v -44.2055 18.6855 3.68876 +v -58.3252 18.5699 3.68876 +v -68.6891 17.7611 3.68876 +v -75.0724 15.5657 3.68876 +v -77.2501 11.2904 3.68876 +v -43.2284 20.884 5.28769 +v -59.1955 20.7341 5.28769 +v -70.7655 19.6848 5.28769 +v -77.8053 16.8367 5.28769 +v -80.1814 11.2904 5.28769 +v -42.2513 23.0825 3.68876 +v -60.0657 22.8983 3.68876 +v -72.8419 21.6085 3.68876 +v -80.5381 18.1077 3.68876 +v -83.1128 11.2904 3.68876 +v -41.8071 24.0819 -1.10804 +v -60.4613 23.882 -1.10804 +v -73.7857 22.4829 -1.10804 +v -81.7804 18.6855 -1.10804 +v -84.4453 11.2904 -1.10804 +v -42.2513 23.0825 -5.90483 +v -60.0657 22.8983 -5.90483 +v -72.8419 21.6085 -5.90483 +v -80.5381 18.1077 -5.90483 +v -83.1128 11.2904 -5.90483 +v -43.2284 20.884 -7.50376 +v -59.1955 20.7341 -7.50376 +v -70.7655 19.6848 -7.50376 +v -77.8053 16.8367 -7.50376 +v -80.1814 11.2904 -7.50376 +v -44.2055 18.6855 -5.90483 +v -58.3252 18.5699 -5.90483 +v -68.6891 17.7611 -5.90483 +v -75.0724 15.5657 -5.90483 +v -77.2501 11.2904 -5.90483 +v -74.8073 5.4943 -1.10804 +v -71.2985 -1.50103 -1.10804 +v -65.1248 -8.49634 -1.10804 +v -56.0198 -14.2925 -1.10804 +v -76.0183 4.93477 3.68876 +v -72.159 -2.35462 3.68876 +v -65.4267 -9.55033 3.68876 +v -55.5757 -15.6249 3.68876 +v -78.6824 3.70383 5.28769 +v -74.0522 -4.23253 5.28769 +v -66.0909 -11.8691 5.28769 +v -54.5986 -18.5563 5.28769 +v -81.3466 2.47288 3.68876 +v -75.9454 -6.11044 3.68876 +v -66.755 -14.1878 3.68876 +v -53.6214 -21.4877 3.68876 +v -82.5576 1.91336 -1.10804 +v -76.8059 -6.96404 -1.10804 +v -67.0569 -15.2418 -1.10804 +v -53.1773 -22.8201 -1.10804 +v -81.3466 2.47288 -5.90483 +v -75.9454 -6.11044 -5.90483 +v -66.755 -14.1878 -5.90483 +v -53.6214 -21.4877 -5.90483 +v -78.6824 3.70383 -7.50376 +v -74.0522 -4.23253 -7.50376 +v -66.0909 -11.8691 -7.50376 +v -54.5986 -18.5563 -7.50376 +v -76.0183 4.93477 -5.90483 +v -72.159 -2.35462 -5.90483 +v -65.4267 -9.55033 -5.90483 +v -55.5757 -15.6249 -5.90483 +v 49.1543 0.630882 -1.10804 +v 62.7896 3.76212 -1.10804 +v 68.6967 11.2904 -1.10804 +v 71.939 20.4176 -1.10804 +v 77.5797 28.3457 -1.10804 +v 49.1543 -3.03333 9.4449 +v 63.8305 1.04519 8.42059 +v 70.0292 9.70814 6.1671 +v 73.5629 19.8451 3.91361 +v 80.2446 28.3457 2.88929 +v 49.1543 -11.0946 12.9626 +v 66.1207 -4.93206 11.5968 +v 72.9605 6.22714 8.59214 +v 77.1355 18.5855 5.58749 +v 86.1073 28.3457 4.22173 +v 49.1543 -19.1559 9.4449 +v 68.4108 -10.9093 8.42059 +v 75.8919 2.74614 6.1671 +v 80.7081 17.326 3.91361 +v 91.97 28.3457 2.88929 +v 49.1543 -22.8201 -1.10804 +v 69.4518 -13.6262 -1.10804 +v 77.2244 1.16386 -1.10804 +v 82.3321 16.7534 -1.10804 +v 94.6349 28.3457 -1.10804 +v 49.1543 -19.1559 -11.661 +v 68.4108 -10.9093 -10.6367 +v 75.8919 2.74614 -8.38317 +v 80.7081 17.326 -6.12968 +v 91.97 28.3457 -5.10536 +v 49.1543 -11.0946 -15.1786 +v 66.1207 -4.93206 -13.8129 +v 72.9605 6.22714 -10.8082 +v 77.1355 18.5855 -7.80356 +v 86.1073 28.3457 -6.4378 +v 49.1543 -3.03333 -11.661 +v 63.8305 1.04519 -10.6367 +v 70.0292 9.70814 -8.38317 +v 73.5629 19.8451 -6.12968 +v 80.2446 28.3457 -5.10536 +v 79.6227 29.5449 -1.10804 +v 81.1329 29.9446 -1.10804 +v 81.577 29.5449 -1.10804 +v 80.4222 28.3457 -1.10804 +v 82.4767 29.6034 2.63946 +v 83.8116 30.0383 2.08983 +v 83.8515 29.6268 1.54019 +v 82.1988 28.3457 1.29036 +v 88.7555 29.7322 3.88862 +v 89.7049 30.2444 3.15578 +v 88.8555 29.8072 2.42294 +v 86.1073 28.3457 2.08983 +v 95.0343 29.8611 2.63946 +v 95.5982 30.4505 2.08983 +v 93.8594 29.9875 1.54019 +v 90.0158 28.3457 1.29036 +v 97.8883 29.9196 -1.10804 +v 98.2769 30.5442 -1.10804 +v 96.1339 30.0695 -1.10804 +v 91.7924 28.3457 -1.10804 +v 95.0343 29.8611 -4.85553 +v 95.5982 30.4505 -4.3059 +v 93.8594 29.9875 -3.75626 +v 90.0158 28.3457 -3.50643 +v 88.7555 29.7322 -6.10469 +v 89.7049 30.2444 -5.37185 +v 88.8555 29.8072 -4.63901 +v 86.1073 28.3457 -4.3059 +v 82.4767 29.6034 -4.85553 +v 83.8116 30.0383 -4.3059 +v 83.8515 29.6268 -3.75626 +v 82.1988 28.3457 -3.50643 +v 0.831025 49.6647 -1.10804 +v 10.5134 48.2657 -1.10804 +v 10.0693 44.868 -1.10804 +v 6.42728 40.6708 -1.10804 +v 6.51611 36.8733 -1.10804 +v 9.76642 48.2657 2.70243 +v 9.35632 44.868 2.52698 +v 5.9947 40.6708 1.09187 +v 6.07552 36.8733 1.12336 +v 7.71453 48.2657 5.77547 +v 7.39819 44.868 5.45913 +v 4.80736 40.6708 2.8683 +v 4.86744 36.8733 2.92838 +v 4.64149 48.2657 7.82736 +v 4.46604 44.868 7.41726 +v 3.03093 40.6708 4.05564 +v 3.06242 36.8733 4.13646 +v 0.831025 48.2657 8.57438 +v 0.831025 44.868 8.13023 +v 0.831025 40.6708 4.48822 +v 0.831025 36.8733 4.57705 +v -2.97944 48.2657 7.82736 +v -2.80399 44.868 7.41726 +v -1.36888 40.6708 4.05564 +v -1.40037 36.8733 4.13646 +v -6.05248 48.2657 5.77547 +v -5.73614 44.868 5.45913 +v -3.14531 40.6708 2.8683 +v -3.20539 36.8733 2.92838 +v -8.10437 48.2657 2.70243 +v -7.69427 44.868 2.52698 +v -4.33265 40.6708 1.09187 +v -4.41347 36.8733 1.12336 +v -8.85139 48.2657 -1.10804 +v -8.40724 44.868 -1.10804 +v -4.76523 40.6708 -1.10804 +v -4.85406 36.8733 -1.10804 +v -8.10437 48.2657 -4.9185 +v -7.69427 44.868 -4.74305 +v -4.33265 40.6708 -3.30794 +v -4.41347 36.8733 -3.33943 +v -6.05248 48.2657 -7.99154 +v -5.73614 44.868 -7.6752 +v -3.14531 40.6708 -5.08437 +v -3.20539 36.8733 -5.14445 +v -2.97944 48.2657 -10.0434 +v -2.80399 44.868 -9.63333 +v -1.36888 40.6708 -6.27171 +v -1.40037 36.8733 -6.35253 +v 0.831025 48.2657 -10.7904 +v 0.831025 44.868 -10.3463 +v 0.831025 40.6708 -6.70429 +v 0.831025 36.8733 -6.79312 +v 4.64149 48.2657 -10.0434 +v 4.46604 44.868 -9.63333 +v 3.03093 40.6708 -6.27171 +v 3.06242 36.8733 -6.35253 +v 7.71453 48.2657 -7.99154 +v 7.39819 44.868 -7.6752 +v 4.80736 40.6708 -5.08437 +v 4.86744 36.8733 -5.14445 +v 9.76642 48.2657 -4.9185 +v 9.35632 44.868 -4.74305 +v 5.9947 40.6708 -3.30794 +v 6.07552 36.8733 -3.33943 +v 13.8001 34.3417 -1.10804 +v 24.282 32.6095 -1.10804 +v 33.6979 30.8773 -1.10804 +v 37.7841 28.3457 -1.10804 +v 12.795 34.3417 3.98234 +v 22.4646 32.6095 8.09647 +v 31.1507 30.8773 11.7922 +v 34.9202 28.3457 13.396 +v 10.0391 34.3417 8.10003 +v 17.4812 32.6095 15.5422 +v 24.1665 30.8773 22.2275 +v 27.0677 28.3457 25.1286 +v 5.9214 34.3417 10.856 +v 10.0355 32.6095 20.5255 +v 13.7313 30.8773 29.2117 +v 15.3351 28.3457 32.9812 +v 0.831025 34.3417 11.8611 +v 0.831025 32.6095 22.3429 +v 0.831025 30.8773 31.7589 +v 0.831025 28.3457 35.845 +v -4.25935 34.3417 10.856 +v -8.37348 32.6095 20.5255 +v -12.0692 30.8773 29.2117 +v -13.673 28.3457 32.9812 +v -8.37704 34.3417 8.10003 +v -15.8192 32.6095 15.5422 +v -22.5045 30.8773 22.2275 +v -25.4056 28.3457 25.1286 +v -11.133 34.3417 3.98234 +v -20.8025 32.6095 8.09647 +v -29.4887 30.8773 11.7922 +v -33.2582 28.3457 13.396 +v -12.1381 34.3417 -1.10804 +v -22.62 32.6095 -1.10804 +v -32.0359 30.8773 -1.10804 +v -36.122 28.3457 -1.10804 +v -11.133 34.3417 -6.19841 +v -20.8025 32.6095 -10.3125 +v -29.4887 30.8773 -14.0083 +v -33.2582 28.3457 -15.6121 +v -8.37704 34.3417 -10.3161 +v -15.8192 32.6095 -17.7582 +v -22.5045 30.8773 -24.4435 +v -25.4056 28.3457 -27.3447 +v -4.25935 34.3417 -13.072 +v -8.37348 32.6095 -22.7416 +v -12.0692 30.8773 -31.4277 +v -13.673 28.3457 -35.1972 +v 0.831025 34.3417 -14.0771 +v 0.831025 32.6095 -24.559 +v 0.831025 30.8773 -33.9749 +v 0.831025 28.3457 -38.0611 +v 5.9214 34.3417 -13.072 +v 10.0355 32.6095 -22.7416 +v 13.7313 30.8773 -31.4277 +v 15.3351 28.3457 -35.1972 +v 10.0391 34.3417 -10.3161 +v 17.4812 32.6095 -17.7582 +v 24.1665 30.8773 -24.4435 +v 27.0677 28.3457 -27.3447 +v 12.795 34.3417 -6.19841 +v 22.4646 32.6095 -10.3125 +v 31.1507 30.8773 -14.0083 +v 34.9202 28.3457 -15.6121 + +vn -0.966742 -0.255752 9.97231e-09 +vn -0.966824 0.255443 3.11149e-08 +vn -0.092052 0.995754 4.45989e-08 +vn 0.68205 0.731305 0 +vn 0.870301 0.492521 -4.87195e-09 +vn -0.893014 -0.256345 -0.369882 +vn -0.893437 0.255997 -0.369102 +vn -0.0838771 0.995843 -0.0355068 +vn 0.629724 0.73186 0.260439 +vn 0.803725 0.49337 0.332584 +vn -0.683407 -0.256729 -0.683407 +vn -0.683531 0.256067 -0.683531 +vn -0.0649249 0.995776 -0.0649248 +vn 0.481398 0.732469 0.481398 +vn 0.614804 0.493997 0.614804 +vn -0.369882 -0.256345 -0.893014 +vn -0.369102 0.255997 -0.893437 +vn -0.0355067 0.995843 -0.0838772 +vn 0.260439 0.73186 0.629724 +vn 0.332584 0.49337 0.803725 +vn -0.00284834 -0.257863 -0.966177 +vn -0.00192311 0.254736 -0.967009 +vn -0.000266114 0.995734 -0.0922702 +vn 2.39288e-05 0.731295 0.682061 +vn 2.43342e-09 0.492521 0.870301 +vn 0.379058 -0.3593 -0.852771 +vn 0.37711 0.149086 -0.914091 +vn 0.0275022 0.992081 -0.122551 +vn -0.26101 0.726762 0.635367 +vn -0.332485 0.492546 0.804271 +vn 0.663548 -0.410791 -0.625264 +vn 0.712664 0.0737216 -0.697621 +vn 0.0997268 0.987509 -0.121984 +vn -0.48732 0.723754 0.488568 +vn -0.615242 0.492602 0.615484 +vn 0.880028 -0.332908 -0.338709 +vn 0.917276 0.167113 -0.361493 +vn 0.113584 0.992365 -0.0480695 +vn -0.63415 0.727508 0.261889 +vn -0.804126 0.492634 0.332705 +vn 0.96669 -0.255738 0.0104537 +vn 0.967442 0.252962 0.00810329 +vn 0.0934365 0.995624 0.00128063 +vn -0.682167 0.731196 -0.00034353 +vn -0.870322 0.492483 -5.42436e-05 +vn 0.893014 -0.256345 0.369882 +vn 0.893437 0.255997 0.369102 +vn 0.0838768 0.995843 0.0355066 +vn -0.629724 0.73186 -0.260439 +vn -0.803725 0.49337 -0.332584 +vn 0.683407 -0.256729 0.683407 +vn 0.683531 0.256067 0.683531 +vn 0.0649249 0.995776 0.0649249 +vn -0.481398 0.732469 -0.481398 +vn -0.614804 0.493997 -0.614804 +vn 0.369882 -0.256345 0.893014 +vn 0.369102 0.255997 0.893437 +vn 0.0355067 0.995843 0.083877 +vn -0.260439 0.73186 -0.629724 +vn -0.332584 0.49337 -0.803725 +vn 3.83985e-09 -0.255752 0.966742 +vn 2.59359e-09 0.255443 0.966824 +vn 3.99081e-08 0.995754 0.092052 +vn 1.03862e-08 0.731305 -0.68205 +vn -2.43342e-09 0.492521 -0.870301 +vn -0.369882 -0.256345 0.893014 +vn -0.369102 0.255996 0.893437 +vn -0.0355068 0.995843 0.0838771 +vn 0.260439 0.73186 -0.629724 +vn 0.332584 0.49337 -0.803725 +vn -0.683407 -0.256729 0.683407 +vn -0.683531 0.256067 0.683531 +vn -0.0649249 0.995776 0.064925 +vn 0.481398 0.732469 -0.481398 +vn 0.614804 0.493997 -0.614804 +vn -0.893014 -0.256345 0.369882 +vn -0.893437 0.255997 0.369102 +vn -0.0838767 0.995843 0.0355066 +vn 0.629724 0.73186 -0.260439 +vn 0.803725 0.49337 -0.332584 +vn 0.915321 0.402725 4.83311e-09 +vn 0.941808 0.336151 -4.85769e-09 +vn 0.97869 0.205342 4.90003e-09 +vn 0.997804 -0.0662397 1.0073e-08 +vn 0.845438 0.403546 0.349835 +vn 0.869996 0.336859 0.360047 +vn 0.904193 0.205791 0.37428 +vn 0.921879 -0.0663697 0.381752 +vn 0.646802 0.404096 0.646802 +vn 0.665655 0.337351 0.665655 +vn 0.691923 0.20612 0.691923 +vn 0.705542 -0.0664796 0.705543 +vn 0.349835 0.403546 0.845438 +vn 0.360047 0.336859 0.869996 +vn 0.37428 0.205791 0.904193 +vn 0.381752 -0.0663697 0.921879 +vn -1.31462e-09 0.402725 0.915321 +vn 9.76689e-10 0.336151 0.941808 +vn -1.9304e-08 0.205342 0.97869 +vn -2.15056e-08 -0.0662397 0.997804 +vn -0.349835 0.403546 0.845438 +vn -0.360047 0.336859 0.869996 +vn -0.37428 0.205791 0.904193 +vn -0.381752 -0.0663697 0.921879 +vn -0.646802 0.404096 0.646802 +vn -0.665655 0.337351 0.665655 +vn -0.691923 0.20612 0.691923 +vn -0.705543 -0.0664796 0.705543 +vn -0.845438 0.403546 0.349835 +vn -0.869996 0.336859 0.360047 +vn -0.904193 0.205791 0.37428 +vn -0.921879 -0.0663697 0.381752 +vn -0.915321 0.402725 -2.41655e-09 +vn -0.941808 0.336151 -1.21442e-08 +vn -0.97869 0.205342 -3.18502e-08 +vn -0.997804 -0.0662397 -2.26643e-08 +vn -0.845438 0.403546 -0.349835 +vn -0.869996 0.336859 -0.360047 +vn -0.904193 0.205791 -0.37428 +vn -0.921879 -0.0663697 -0.381752 +vn -0.646802 0.404096 -0.646802 +vn -0.665655 0.337351 -0.665655 +vn -0.691923 0.20612 -0.691923 +vn -0.705542 -0.0664796 -0.705543 +vn -0.349835 0.403546 -0.845438 +vn -0.360047 0.336859 -0.869996 +vn -0.37428 0.205791 -0.904193 +vn -0.381752 -0.0663697 -0.921879 +vn 1.31462e-09 0.402725 -0.915321 +vn -9.76689e-10 0.336151 -0.941808 +vn 1.9304e-08 0.205342 -0.97869 +vn 2.15056e-08 -0.0662397 -0.997804 +vn 0.349835 0.403546 -0.845438 +vn 0.360047 0.336859 -0.869996 +vn 0.37428 0.205791 -0.904193 +vn 0.381752 -0.0663697 -0.921879 +vn 0.646802 0.404096 -0.646802 +vn 0.665655 0.337351 -0.665655 +vn 0.691923 0.20612 -0.691923 +vn 0.705543 -0.0664796 -0.705542 +vn 0.845438 0.403546 -0.349835 +vn 0.869996 0.336859 -0.360047 +vn 0.904193 0.205791 -0.37428 +vn 0.921879 -0.0663697 -0.381752 +vn 0.900182 -0.435513 -1.50883e-08 +vn 0.729611 -0.683863 -9.71212e-09 +vn 0.693951 -0.720022 -9.54282e-09 +vn 0.79395 -0.607984 2.6277e-08 +vn 0.831437 -0.43618 0.344179 +vn 0.673512 -0.684665 0.278594 +vn 0.640399 -0.720924 0.264874 +vn 0.732949 -0.608996 0.303166 +vn 0.636092 -0.436777 0.636092 +vn 0.514965 -0.685289 0.514965 +vn 0.489651 -0.721446 0.489651 +vn 0.560555 -0.609554 0.560555 +vn 0.344179 -0.43618 0.831437 +vn 0.278594 -0.684665 0.673512 +vn 0.264874 -0.720924 0.640399 +vn 0.303166 -0.608996 0.732949 +vn 1.18057e-08 -0.435513 0.900182 +vn -4.75784e-09 -0.683863 0.729611 +vn 9.10217e-09 -0.720022 0.693951 +vn -2.68996e-08 -0.607984 0.79395 +vn -0.344179 -0.43618 0.831437 +vn -0.278594 -0.684665 0.673512 +vn -0.264874 -0.720924 0.640399 +vn -0.303166 -0.608996 0.732949 +vn -0.636092 -0.436777 0.636092 +vn -0.514965 -0.685289 0.514965 +vn -0.489651 -0.721446 0.489651 +vn -0.560555 -0.609554 0.560555 +vn -0.831437 -0.43618 0.344179 +vn -0.673512 -0.684665 0.278595 +vn -0.640399 -0.720924 0.264874 +vn -0.732949 -0.608996 0.303166 +vn -0.900182 -0.435513 -7.54414e-09 +vn -0.729611 -0.683863 -7.28409e-09 +vn -0.693951 -0.720022 4.77141e-09 +vn -0.79395 -0.607983 -2.6277e-08 +vn -0.831437 -0.43618 -0.344179 +vn -0.673512 -0.684665 -0.278594 +vn -0.640399 -0.720924 -0.264874 +vn -0.732949 -0.608996 -0.303166 +vn -0.636092 -0.436777 -0.636092 +vn -0.514965 -0.685289 -0.514965 +vn -0.489651 -0.721446 -0.489651 +vn -0.560555 -0.609554 -0.560555 +vn -0.344179 -0.43618 -0.831437 +vn -0.278594 -0.684665 -0.673512 +vn -0.264874 -0.720924 -0.640399 +vn -0.303166 -0.608996 -0.732949 +vn -1.18057e-08 -0.435513 -0.900182 +vn 4.75784e-09 -0.683863 -0.729611 +vn -9.10217e-09 -0.720022 -0.693951 +vn 2.68996e-08 -0.607984 -0.79395 +vn 0.344179 -0.43618 -0.831437 +vn 0.278594 -0.684665 -0.673512 +vn 0.264874 -0.720924 -0.640399 +vn 0.303167 -0.608996 -0.732949 +vn 0.636092 -0.436777 -0.636092 +vn 0.514965 -0.685289 -0.514965 +vn 0.489651 -0.721446 -0.489651 +vn 0.560555 -0.609554 -0.560555 +vn 0.831437 -0.43618 -0.344179 +vn 0.673512 -0.684665 -0.278595 +vn 0.640399 -0.720924 -0.264874 +vn 0.732949 -0.608996 -0.303166 +vn 0.62386 -0.781536 3.04248e-08 +vn 0.177291 -0.984159 -3.28321e-09 +vn 0.0492072 -0.998789 1.48326e-09 +vn 1.94668e-11 -1 -7.78368e-10 +vn 0.576229 -0.781801 0.238217 +vn 0.163629 -0.984208 0.0675273 +vn 0.0454217 -0.998792 0.0187357 +vn 0.440416 -0.782348 0.440416 +vn 0.124903 -0.984276 0.124903 +vn 0.0346621 -0.998798 0.0346621 +vn 0.238217 -0.781801 0.576229 +vn 0.0675273 -0.984208 0.163629 +vn 0.0187357 -0.998792 0.0454217 +vn -3.18434e-08 -0.781536 0.62386 +vn 3.33958e-09 -0.984159 0.177291 +vn -1.80438e-09 -0.998789 0.0492072 +vn -0.238216 -0.781801 0.576229 +vn -0.0675273 -0.984208 0.163629 +vn -0.0187357 -0.998792 0.0454217 +vn -0.440416 -0.782348 0.440416 +vn -0.124903 -0.984276 0.124903 +vn -0.0346621 -0.998798 0.0346621 +vn -0.576229 -0.781801 0.238217 +vn -0.163629 -0.984208 0.0675273 +vn -0.0454217 -0.998792 0.0187357 +vn -0.62386 -0.781536 -3.17476e-08 +vn -0.177291 -0.984159 3.13397e-09 +vn -0.0492072 -0.998789 -1.33493e-09 +vn -0.576229 -0.781801 -0.238217 +vn -0.163629 -0.984208 -0.0675273 +vn -0.0454217 -0.998792 -0.0187357 +vn -0.440416 -0.782348 -0.440416 +vn -0.124903 -0.984276 -0.124903 +vn -0.0346621 -0.998798 -0.0346621 +vn -0.238217 -0.781801 -0.576229 +vn -0.0675273 -0.984208 -0.163629 +vn -0.0187357 -0.998792 -0.0454217 +vn 3.18434e-08 -0.781536 -0.62386 +vn -3.28168e-09 -0.984159 -0.177291 +vn 1.46144e-09 -0.998789 -0.0492072 +vn 0.238217 -0.781801 -0.576229 +vn 0.0675273 -0.984208 -0.163629 +vn 0.0187357 -0.998792 -0.0454217 +vn 0.440416 -0.782348 -0.440416 +vn 0.124903 -0.984276 -0.124903 +vn 0.0346621 -0.998798 -0.0346621 +vn 0.576229 -0.781801 -0.238217 +vn 0.163629 -0.984208 -0.0675273 +vn 0.0454217 -0.998792 -0.0187357 +vn 0.00778619 -0.99997 -0.000215809 +vn 0.0391385 -0.999233 -0.000988567 +vn 0.179511 -0.983746 -0.00436856 +vn 0.6123 -0.790556 -0.0104598 +vn 0.986152 -0.165707 -0.00666949 +vn 0.00703893 -0.812495 0.582926 +vn 0.0361273 -0.837257 0.545614 +vn 0.161845 -0.810421 0.563048 +vn 0.482365 -0.595148 0.642746 +vn 0.73872 -0.114593 0.664199 +vn -0.00190867 0.162121 0.986769 +vn 0.0027616 0.0171073 0.99985 +vn 0.0105326 0.0733989 0.997247 +vn -0.0660406 0.130069 0.989303 +vn -0.0944272 0.0165946 0.995393 +vn -0.009203 0.871509 0.490293 +vn -0.0486064 0.840609 0.539457 +vn -0.223298 0.802881 0.552739 +vn -0.596365 0.559971 0.575135 +vn -0.803337 0.0682361 0.591602 +vn -0.0105609 0.999944 0.000103364 +vn -0.0587986 0.99827 0.000709759 +vn -0.28071 0.959787 0.00326876 +vn -0.749723 0.661738 0.0042684 +vn -0.997351 0.0727144 0.00205923 +vn -0.00879197 0.871493 -0.49033 +vn -0.0464937 0.841178 -0.538756 +vn -0.217909 0.806807 -0.549161 +vn -0.597291 0.560026 -0.574121 +vn -0.804 0.0629127 -0.591291 +vn -0.00180555 0.161691 -0.98684 +vn 0.00203087 0.014555 -0.999892 +vn 0.00921499 0.0600698 -0.998152 +vn -0.0593333 0.113865 -0.991723 +vn -0.0868992 0.0122903 -0.996141 +vn 0.00641779 -0.812379 -0.583094 +vn 0.0337833 -0.837512 -0.545373 +vn 0.157112 -0.811947 -0.56219 +vn 0.484407 -0.589365 -0.646528 +vn 0.73887 -0.10132 -0.666187 +vn 0.946512 0.32265 -0.0033571 +vn 0.82583 0.56387 -0.00745213 +vn 0.650011 0.759893 -0.00693681 +vn 0.532429 0.846458 -0.00524544 +vn 0.725608 0.259351 0.637362 +vn 0.645945 0.461988 0.607719 +vn 0.531614 0.63666 0.558615 +vn 0.424964 0.681717 0.59554 +vn -0.0495616 -0.019755 0.998576 +vn -0.0378162 -0.0356243 0.99865 +vn -0.0379139 -0.0365122 0.998614 +vn -0.168854 -0.297946 0.93953 +vn -0.742342 -0.299166 0.599523 +vn -0.619602 -0.529406 0.579503 +vn -0.483708 -0.685761 0.543837 +vn -0.445293 -0.794355 0.413176 +vn -0.926513 -0.376257 0.00199587 +vn -0.75392 -0.656952 0.00431723 +vn -0.566224 -0.824244 0.00346105 +vn -0.481804 -0.876277 0.00185047 +vn -0.744675 -0.294424 -0.598977 +vn -0.621949 -0.528114 -0.578165 +vn -0.481171 -0.68834 -0.542828 +vn -0.438055 -0.797035 -0.415744 +vn -0.0443368 -0.0170558 -0.998871 +vn -0.0261761 -0.0281665 -0.99926 +vn -0.0252939 -0.0283323 -0.999278 +vn -0.157482 -0.289392 -0.944167 +vn 0.728244 0.25241 -0.637142 +vn 0.647055 0.459725 -0.608254 +vn 0.522994 0.640657 -0.562171 +vn 0.409978 0.682857 -0.604669 +vn -0.230787 0.972982 -0.00652338 +vn -0.548936 0.835863 -0.00151111 +vn -0.875671 0.482807 0.00989278 +vn -0.877554 0.479097 0.0190923 +vn -0.69619 0.717439 0.024497 +vn -0.152878 0.687211 0.71019 +vn -0.316721 0.63775 0.702113 +vn -0.601067 0.471452 0.64533 +vn -0.635889 0.44609 0.6298 +vn -0.435746 0.601008 0.670011 +vn 0.111112 -0.0850694 0.99016 +vn 0.22331 0.00654036 0.974726 +vn 0.190097 0.154964 0.969458 +vn 0.00527077 0.189482 0.98187 +vn -0.0117518 0.246688 0.969024 +vn 0.343906 -0.722796 0.599412 +vn 0.572489 -0.567656 0.591627 +vn 0.787436 -0.256459 0.560512 +vn 0.647097 -0.306374 0.698141 +vn 0.427528 -0.499343 0.753576 +vn 0.410926 -0.911668 0.00128446 +vn 0.67152 -0.740986 -0.000899122 +vn 0.922026 -0.38706 -0.00725269 +vn 0.84691 -0.531556 -0.0138542 +vn 0.535925 -0.8442 -0.0105045 +vn 0.341188 -0.722822 -0.600931 +vn 0.578664 -0.561139 -0.591838 +vn 0.784869 -0.25102 -0.566542 +vn 0.642681 -0.302257 -0.70399 +vn 0.418589 -0.500042 -0.758117 +vn 0.115806 -0.0791394 -0.990114 +vn 0.232811 0.0125652 -0.972441 +vn 0.206662 0.153601 -0.96628 +vn 0.0244996 0.161443 -0.986578 +vn 0.00338193 0.211115 -0.977455 +vn -0.134912 0.687491 -0.713551 +vn -0.31954 0.633073 -0.705062 +vn -0.603902 0.461442 -0.649903 +vn -0.631816 0.437169 -0.640072 +vn -0.424306 0.612706 -0.66675 +vn -0.4258 0.904753 0.0108049 +vn 0.0220472 0.999756 0.00162273 +vn 0.999599 0.0258705 0.0115556 +vn 0.709585 -0.704553 0.00967183 +vn -0.259858 0.791936 0.552549 +vn 0.00953916 0.99972 -0.0216718 +vn 0.410156 0.332912 -0.849083 +vn 0.541523 -0.54862 -0.637 +vn 0.0463104 0.455224 0.889172 +vn -0.0106883 0.988794 0.148901 +vn -0.0443756 0.682947 -0.729118 +vn 0.122825 0.00923214 -0.992385 +vn 0.481839 -0.180439 0.85748 +vn 0.455272 0.736752 0.499925 +vn -0.220542 0.907193 -0.358276 +vn -0.23592 0.657249 -0.715797 +vn 0.728092 -0.685302 -0.0155853 +vn 0.888739 0.45811 -0.0166791 +vn -0.260097 0.965582 0.000800195 +vn -0.371612 0.928378 -0.00441745 +vn 0.480166 -0.17836 -0.858853 +vn 0.488103 0.716801 -0.497947 +vn -0.222004 0.905399 0.361893 +vn -0.235405 0.66318 0.710477 +vn 0.0587203 0.437704 -0.8972 +vn 0.00132612 0.986459 -0.164003 +vn -0.0441901 0.681677 0.730317 +vn 0.138801 -0.0341896 0.98973 +vn -0.25889 0.797206 -0.54538 +vn 0.0122703 0.999739 0.0192865 +vn 0.39863 0.35489 0.845663 +vn 0.537564 -0.5814 0.610737 +vn -7.79193e-10 1 6.50944e-09 +vn 0.82454 0.565804 1.72913e-05 +vn 0.917701 -0.397272 3.35502e-05 +vn 0.935269 -0.353939 0.000112842 +vn 0.780712 0.624891 7.51916e-05 +vn 0.762641 0.565035 0.314825 +vn 0.847982 -0.397998 0.350034 +vn 0.864141 -0.355261 0.356441 +vn 0.720991 0.625625 0.297933 +vn 0.583357 0.565165 0.583338 +vn 0.648485 -0.398726 0.648448 +vn 0.660872 -0.355894 0.660748 +vn 0.551862 0.62529 0.55178 +vn 0.314824 0.565051 0.762629 +vn 0.350045 -0.397976 0.847988 +vn 0.356474 -0.3552 0.864153 +vn 0.297983 0.625515 0.721067 +vn -1.7299e-05 0.565804 0.82454 +vn -3.35448e-05 -0.397272 0.917701 +vn -0.000112839 -0.353939 0.935269 +vn -7.51869e-05 0.624891 0.780712 +vn -0.314825 0.565035 0.762641 +vn -0.350034 -0.397998 0.847982 +vn -0.356441 -0.355261 0.864141 +vn -0.297933 0.625625 0.720991 +vn -0.583338 0.565165 0.583357 +vn -0.648448 -0.398726 0.648485 +vn -0.660748 -0.355894 0.660872 +vn -0.55178 0.62529 0.551862 +vn -0.762629 0.565051 0.314824 +vn -0.847988 -0.397976 0.350045 +vn -0.864153 -0.3552 0.356474 +vn -0.721067 0.625515 0.297983 +vn -0.82454 0.565804 -1.72877e-05 +vn -0.917701 -0.397272 -3.35262e-05 +vn -0.935269 -0.353939 -0.000112839 +vn -0.780712 0.624891 -7.51882e-05 +vn -0.76264 0.565035 -0.314825 +vn -0.847982 -0.397998 -0.350034 +vn -0.864141 -0.355261 -0.356441 +vn -0.720991 0.625625 -0.297933 +vn -0.583357 0.565165 -0.583338 +vn -0.648485 -0.398726 -0.648448 +vn -0.660872 -0.355894 -0.660748 +vn -0.551862 0.62529 -0.55178 +vn -0.314824 0.565051 -0.762629 +vn -0.350045 -0.397976 -0.847988 +vn -0.356474 -0.3552 -0.864153 +vn -0.297983 0.625515 -0.721067 +vn 1.72918e-05 0.565804 -0.82454 +vn 3.35344e-05 -0.397272 -0.917701 +vn 0.000112839 -0.353939 -0.935269 +vn 7.51869e-05 0.624891 -0.780712 +vn 0.314825 0.565035 -0.762641 +vn 0.350034 -0.397998 -0.847982 +vn 0.356441 -0.355261 -0.864141 +vn 0.297933 0.625625 -0.720991 +vn 0.583338 0.565165 -0.583357 +vn 0.648448 -0.398726 -0.648485 +vn 0.660748 -0.355894 -0.660872 +vn 0.55178 0.62529 -0.551862 +vn 0.762629 0.565051 -0.314824 +vn 0.847988 -0.397976 -0.350045 +vn 0.864153 -0.3552 -0.356474 +vn 0.721067 0.625515 -0.297983 +vn 0.236584 0.971611 8.31862e-09 +vn 0.173084 0.984907 -1.18677e-09 +vn 0.379703 0.925108 2.44118e-09 +vn 0.526673 0.850068 2.66504e-09 +vn 0.217978 0.971775 0.0902162 +vn 0.15959 0.984977 0.0659615 +vn 0.350498 0.925312 0.14474 +vn 0.48559 0.850653 0.201474 +vn 0.166631 0.971838 0.166631 +vn 0.121908 0.985026 0.121908 +vn 0.267668 0.925585 0.267668 +vn 0.371315 0.851029 0.371315 +vn 0.0902162 0.971775 0.217978 +vn 0.0659615 0.984977 0.15959 +vn 0.14474 0.925312 0.350498 +vn 0.201474 0.850653 0.48559 +vn -8.2649e-09 0.971611 0.236584 +vn 1.37744e-09 0.984907 0.173084 +vn 2.79781e-10 0.925108 0.379703 +vn 2.55497e-09 0.850068 0.526673 +vn -0.0902162 0.971775 0.217978 +vn -0.0659615 0.984977 0.15959 +vn -0.14474 0.925312 0.350498 +vn -0.201474 0.850653 0.48559 +vn -0.166631 0.971838 0.166631 +vn -0.121908 0.985026 0.121908 +vn -0.267668 0.925585 0.267668 +vn -0.371315 0.851029 0.371315 +vn -0.217978 0.971775 0.0902162 +vn -0.15959 0.984977 0.0659615 +vn -0.350498 0.925312 0.14474 +vn -0.48559 0.850653 0.201474 +vn -0.236583 0.971611 -6.23897e-09 +vn -0.173084 0.984907 2.37354e-09 +vn -0.379703 0.925108 -2.44118e-09 +vn -0.526673 0.850068 0 +vn -0.217978 0.971775 -0.0902162 +vn -0.15959 0.984977 -0.0659615 +vn -0.350498 0.925312 -0.14474 +vn -0.48559 0.850653 -0.201474 +vn -0.166631 0.971838 -0.166631 +vn -0.121908 0.985026 -0.121908 +vn -0.267668 0.925585 -0.267668 +vn -0.371315 0.851029 -0.371315 +vn -0.0902162 0.971775 -0.217978 +vn -0.0659615 0.984977 -0.15959 +vn -0.14474 0.925312 -0.350498 +vn -0.201474 0.850653 -0.485589 +vn 6.16189e-09 0.971611 -0.236584 +vn -1.37744e-09 0.984907 -0.173084 +vn -2.79781e-10 0.925108 -0.379703 +vn -2.55497e-09 0.850068 -0.526673 +vn 0.0902162 0.971775 -0.217978 +vn 0.0659615 0.984977 -0.15959 +vn 0.14474 0.925312 -0.350498 +vn 0.201474 0.850653 -0.48559 +vn 0.166631 0.971838 -0.166631 +vn 0.121908 0.985026 -0.121908 +vn 0.267668 0.925585 -0.267668 +vn 0.371315 0.851029 -0.371315 +vn 0.217978 0.971775 -0.0902162 +vn 0.15959 0.984977 -0.0659615 +vn 0.350498 0.925312 -0.14474 +vn 0.48559 0.850653 -0.201474 + +f 7 6 1 +f 1 2 7 +f 8 7 2 +f 2 3 8 +f 9 8 3 +f 3 4 9 +f 10 9 4 +f 4 5 10 +f 12 11 6 +f 6 7 12 +f 13 12 7 +f 7 8 13 +f 14 13 8 +f 8 9 14 +f 15 14 9 +f 9 10 15 +f 17 16 11 +f 11 12 17 +f 18 17 12 +f 12 13 18 +f 19 18 13 +f 13 14 19 +f 20 19 14 +f 14 15 20 +f 22 21 16 +f 16 17 22 +f 23 22 17 +f 17 18 23 +f 24 23 18 +f 18 19 24 +f 25 24 19 +f 19 20 25 +f 27 26 21 +f 21 22 27 +f 28 27 22 +f 22 23 28 +f 29 28 23 +f 23 24 29 +f 30 29 24 +f 24 25 30 +f 32 31 26 +f 26 27 32 +f 33 32 27 +f 27 28 33 +f 34 33 28 +f 28 29 34 +f 35 34 29 +f 29 30 35 +f 37 36 31 +f 31 32 37 +f 38 37 32 +f 32 33 38 +f 39 38 33 +f 33 34 39 +f 40 39 34 +f 34 35 40 +f 42 41 36 +f 36 37 42 +f 43 42 37 +f 37 38 43 +f 44 43 38 +f 38 39 44 +f 45 44 39 +f 39 40 45 +f 47 46 41 +f 41 42 47 +f 48 47 42 +f 42 43 48 +f 49 48 43 +f 43 44 49 +f 50 49 44 +f 44 45 50 +f 52 51 46 +f 46 47 52 +f 53 52 47 +f 47 48 53 +f 54 53 48 +f 48 49 54 +f 55 54 49 +f 49 50 55 +f 57 56 51 +f 51 52 57 +f 58 57 52 +f 52 53 58 +f 59 58 53 +f 53 54 59 +f 60 59 54 +f 54 55 60 +f 62 61 56 +f 56 57 62 +f 63 62 57 +f 57 58 63 +f 64 63 58 +f 58 59 64 +f 65 64 59 +f 59 60 65 +f 67 66 61 +f 61 62 67 +f 68 67 62 +f 62 63 68 +f 69 68 63 +f 63 64 69 +f 70 69 64 +f 64 65 70 +f 72 71 66 +f 66 67 72 +f 73 72 67 +f 67 68 73 +f 74 73 68 +f 68 69 74 +f 75 74 69 +f 69 70 75 +f 77 76 71 +f 71 72 77 +f 78 77 72 +f 72 73 78 +f 79 78 73 +f 73 74 79 +f 80 79 74 +f 74 75 80 +f 2 1 76 +f 76 77 2 +f 3 2 77 +f 77 78 3 +f 4 3 78 +f 78 79 4 +f 5 4 79 +f 79 80 5 +f 85 10 5 +f 5 81 85 +f 86 85 81 +f 81 82 86 +f 87 86 82 +f 82 83 87 +f 88 87 83 +f 83 84 88 +f 89 15 10 +f 10 85 89 +f 90 89 85 +f 85 86 90 +f 91 90 86 +f 86 87 91 +f 92 91 87 +f 87 88 92 +f 93 20 15 +f 15 89 93 +f 94 93 89 +f 89 90 94 +f 95 94 90 +f 90 91 95 +f 96 95 91 +f 91 92 96 +f 97 25 20 +f 20 93 97 +f 98 97 93 +f 93 94 98 +f 99 98 94 +f 94 95 99 +f 100 99 95 +f 95 96 100 +f 101 30 25 +f 25 97 101 +f 102 101 97 +f 97 98 102 +f 103 102 98 +f 98 99 103 +f 104 103 99 +f 99 100 104 +f 105 35 30 +f 30 101 105 +f 106 105 101 +f 101 102 106 +f 107 106 102 +f 102 103 107 +f 108 107 103 +f 103 104 108 +f 109 40 35 +f 35 105 109 +f 110 109 105 +f 105 106 110 +f 111 110 106 +f 106 107 111 +f 112 111 107 +f 107 108 112 +f 113 45 40 +f 40 109 113 +f 114 113 109 +f 109 110 114 +f 115 114 110 +f 110 111 115 +f 116 115 111 +f 111 112 116 +f 117 50 45 +f 45 113 117 +f 118 117 113 +f 113 114 118 +f 119 118 114 +f 114 115 119 +f 120 119 115 +f 115 116 120 +f 121 55 50 +f 50 117 121 +f 122 121 117 +f 117 118 122 +f 123 122 118 +f 118 119 123 +f 124 123 119 +f 119 120 124 +f 125 60 55 +f 55 121 125 +f 126 125 121 +f 121 122 126 +f 127 126 122 +f 122 123 127 +f 128 127 123 +f 123 124 128 +f 129 65 60 +f 60 125 129 +f 130 129 125 +f 125 126 130 +f 131 130 126 +f 126 127 131 +f 132 131 127 +f 127 128 132 +f 133 70 65 +f 65 129 133 +f 134 133 129 +f 129 130 134 +f 135 134 130 +f 130 131 135 +f 136 135 131 +f 131 132 136 +f 137 75 70 +f 70 133 137 +f 138 137 133 +f 133 134 138 +f 139 138 134 +f 134 135 139 +f 140 139 135 +f 135 136 140 +f 141 80 75 +f 75 137 141 +f 142 141 137 +f 137 138 142 +f 143 142 138 +f 138 139 143 +f 144 143 139 +f 139 140 144 +f 81 5 80 +f 80 141 81 +f 82 81 141 +f 141 142 82 +f 83 82 142 +f 142 143 83 +f 84 83 143 +f 143 144 84 +f 149 88 84 +f 84 145 149 +f 150 149 145 +f 145 146 150 +f 151 150 146 +f 146 147 151 +f 152 151 147 +f 147 148 152 +f 153 92 88 +f 88 149 153 +f 154 153 149 +f 149 150 154 +f 155 154 150 +f 150 151 155 +f 156 155 151 +f 151 152 156 +f 157 96 92 +f 92 153 157 +f 158 157 153 +f 153 154 158 +f 159 158 154 +f 154 155 159 +f 160 159 155 +f 155 156 160 +f 161 100 96 +f 96 157 161 +f 162 161 157 +f 157 158 162 +f 163 162 158 +f 158 159 163 +f 164 163 159 +f 159 160 164 +f 165 104 100 +f 100 161 165 +f 166 165 161 +f 161 162 166 +f 167 166 162 +f 162 163 167 +f 168 167 163 +f 163 164 168 +f 169 108 104 +f 104 165 169 +f 170 169 165 +f 165 166 170 +f 171 170 166 +f 166 167 171 +f 172 171 167 +f 167 168 172 +f 173 112 108 +f 108 169 173 +f 174 173 169 +f 169 170 174 +f 175 174 170 +f 170 171 175 +f 176 175 171 +f 171 172 176 +f 177 116 112 +f 112 173 177 +f 178 177 173 +f 173 174 178 +f 179 178 174 +f 174 175 179 +f 180 179 175 +f 175 176 180 +f 181 120 116 +f 116 177 181 +f 182 181 177 +f 177 178 182 +f 183 182 178 +f 178 179 183 +f 184 183 179 +f 179 180 184 +f 185 124 120 +f 120 181 185 +f 186 185 181 +f 181 182 186 +f 187 186 182 +f 182 183 187 +f 188 187 183 +f 183 184 188 +f 189 128 124 +f 124 185 189 +f 190 189 185 +f 185 186 190 +f 191 190 186 +f 186 187 191 +f 192 191 187 +f 187 188 192 +f 193 132 128 +f 128 189 193 +f 194 193 189 +f 189 190 194 +f 195 194 190 +f 190 191 195 +f 196 195 191 +f 191 192 196 +f 197 136 132 +f 132 193 197 +f 198 197 193 +f 193 194 198 +f 199 198 194 +f 194 195 199 +f 200 199 195 +f 195 196 200 +f 201 140 136 +f 136 197 201 +f 202 201 197 +f 197 198 202 +f 203 202 198 +f 198 199 203 +f 204 203 199 +f 199 200 204 +f 205 144 140 +f 140 201 205 +f 206 205 201 +f 201 202 206 +f 207 206 202 +f 202 203 207 +f 208 207 203 +f 203 204 208 +f 145 84 144 +f 144 205 145 +f 146 145 205 +f 205 206 146 +f 147 146 206 +f 206 207 147 +f 148 147 207 +f 207 208 148 +f 213 152 148 +f 148 209 213 +f 214 213 209 +f 209 210 214 +f 215 214 210 +f 210 211 215 +f 212 215 211 +f 211 212 212 +f 216 156 152 +f 152 213 216 +f 217 216 213 +f 213 214 217 +f 218 217 214 +f 214 215 218 +f 212 218 215 +f 215 212 212 +f 219 160 156 +f 156 216 219 +f 220 219 216 +f 216 217 220 +f 221 220 217 +f 217 218 221 +f 212 221 218 +f 218 212 212 +f 222 164 160 +f 160 219 222 +f 223 222 219 +f 219 220 223 +f 224 223 220 +f 220 221 224 +f 212 224 221 +f 221 212 212 +f 225 168 164 +f 164 222 225 +f 226 225 222 +f 222 223 226 +f 227 226 223 +f 223 224 227 +f 212 227 224 +f 224 212 212 +f 228 172 168 +f 168 225 228 +f 229 228 225 +f 225 226 229 +f 230 229 226 +f 226 227 230 +f 212 230 227 +f 227 212 212 +f 231 176 172 +f 172 228 231 +f 232 231 228 +f 228 229 232 +f 233 232 229 +f 229 230 233 +f 212 233 230 +f 230 212 212 +f 234 180 176 +f 176 231 234 +f 235 234 231 +f 231 232 235 +f 236 235 232 +f 232 233 236 +f 212 236 233 +f 233 212 212 +f 237 184 180 +f 180 234 237 +f 238 237 234 +f 234 235 238 +f 239 238 235 +f 235 236 239 +f 212 239 236 +f 236 212 212 +f 240 188 184 +f 184 237 240 +f 241 240 237 +f 237 238 241 +f 242 241 238 +f 238 239 242 +f 212 242 239 +f 239 212 212 +f 243 192 188 +f 188 240 243 +f 244 243 240 +f 240 241 244 +f 245 244 241 +f 241 242 245 +f 212 245 242 +f 242 212 212 +f 246 196 192 +f 192 243 246 +f 247 246 243 +f 243 244 247 +f 248 247 244 +f 244 245 248 +f 212 248 245 +f 245 212 212 +f 249 200 196 +f 196 246 249 +f 250 249 246 +f 246 247 250 +f 251 250 247 +f 247 248 251 +f 212 251 248 +f 248 212 212 +f 252 204 200 +f 200 249 252 +f 253 252 249 +f 249 250 253 +f 254 253 250 +f 250 251 254 +f 212 254 251 +f 251 212 212 +f 255 208 204 +f 204 252 255 +f 256 255 252 +f 252 253 256 +f 257 256 253 +f 253 254 257 +f 212 257 254 +f 254 212 212 +f 209 148 208 +f 208 255 209 +f 210 209 255 +f 255 256 210 +f 211 210 256 +f 256 257 211 +f 212 211 257 +f 257 212 212 +f 264 263 258 +f 258 259 264 +f 265 264 259 +f 259 260 265 +f 266 265 260 +f 260 261 266 +f 267 266 261 +f 261 262 267 +f 269 268 263 +f 263 264 269 +f 270 269 264 +f 264 265 270 +f 271 270 265 +f 265 266 271 +f 272 271 266 +f 266 267 272 +f 274 273 268 +f 268 269 274 +f 275 274 269 +f 269 270 275 +f 276 275 270 +f 270 271 276 +f 277 276 271 +f 271 272 277 +f 279 278 273 +f 273 274 279 +f 280 279 274 +f 274 275 280 +f 281 280 275 +f 275 276 281 +f 282 281 276 +f 276 277 282 +f 284 283 278 +f 278 279 284 +f 285 284 279 +f 279 280 285 +f 286 285 280 +f 280 281 286 +f 287 286 281 +f 281 282 287 +f 289 288 283 +f 283 284 289 +f 290 289 284 +f 284 285 290 +f 291 290 285 +f 285 286 291 +f 292 291 286 +f 286 287 292 +f 294 293 288 +f 288 289 294 +f 295 294 289 +f 289 290 295 +f 296 295 290 +f 290 291 296 +f 297 296 291 +f 291 292 297 +f 259 258 293 +f 293 294 259 +f 260 259 294 +f 294 295 260 +f 261 260 295 +f 295 296 261 +f 262 261 296 +f 296 297 262 +f 302 267 262 +f 262 298 302 +f 303 302 298 +f 298 299 303 +f 304 303 299 +f 299 300 304 +f 305 304 300 +f 300 301 305 +f 306 272 267 +f 267 302 306 +f 307 306 302 +f 302 303 307 +f 308 307 303 +f 303 304 308 +f 309 308 304 +f 304 305 309 +f 310 277 272 +f 272 306 310 +f 311 310 306 +f 306 307 311 +f 312 311 307 +f 307 308 312 +f 313 312 308 +f 308 309 313 +f 314 282 277 +f 277 310 314 +f 315 314 310 +f 310 311 315 +f 316 315 311 +f 311 312 316 +f 317 316 312 +f 312 313 317 +f 318 287 282 +f 282 314 318 +f 319 318 314 +f 314 315 319 +f 320 319 315 +f 315 316 320 +f 321 320 316 +f 316 317 321 +f 322 292 287 +f 287 318 322 +f 323 322 318 +f 318 319 323 +f 324 323 319 +f 319 320 324 +f 325 324 320 +f 320 321 325 +f 326 297 292 +f 292 322 326 +f 327 326 322 +f 322 323 327 +f 328 327 323 +f 323 324 328 +f 329 328 324 +f 324 325 329 +f 298 262 297 +f 297 326 298 +f 299 298 326 +f 326 327 299 +f 300 299 327 +f 327 328 300 +f 301 300 328 +f 328 329 301 +f 336 335 330 +f 330 331 336 +f 337 336 331 +f 331 332 337 +f 338 337 332 +f 332 333 338 +f 339 338 333 +f 333 334 339 +f 341 340 335 +f 335 336 341 +f 342 341 336 +f 336 337 342 +f 343 342 337 +f 337 338 343 +f 344 343 338 +f 338 339 344 +f 346 345 340 +f 340 341 346 +f 347 346 341 +f 341 342 347 +f 348 347 342 +f 342 343 348 +f 349 348 343 +f 343 344 349 +f 351 350 345 +f 345 346 351 +f 352 351 346 +f 346 347 352 +f 353 352 347 +f 347 348 353 +f 354 353 348 +f 348 349 354 +f 356 355 350 +f 350 351 356 +f 357 356 351 +f 351 352 357 +f 358 357 352 +f 352 353 358 +f 359 358 353 +f 353 354 359 +f 361 360 355 +f 355 356 361 +f 362 361 356 +f 356 357 362 +f 363 362 357 +f 357 358 363 +f 364 363 358 +f 358 359 364 +f 366 365 360 +f 360 361 366 +f 367 366 361 +f 361 362 367 +f 368 367 362 +f 362 363 368 +f 369 368 363 +f 363 364 369 +f 331 330 365 +f 365 366 331 +f 332 331 366 +f 366 367 332 +f 333 332 367 +f 367 368 333 +f 334 333 368 +f 368 369 334 +f 374 339 334 +f 334 370 374 +f 375 374 370 +f 370 371 375 +f 376 375 371 +f 371 372 376 +f 377 376 372 +f 372 373 377 +f 378 344 339 +f 339 374 378 +f 379 378 374 +f 374 375 379 +f 380 379 375 +f 375 376 380 +f 381 380 376 +f 376 377 381 +f 382 349 344 +f 344 378 382 +f 383 382 378 +f 378 379 383 +f 384 383 379 +f 379 380 384 +f 385 384 380 +f 380 381 385 +f 386 354 349 +f 349 382 386 +f 387 386 382 +f 382 383 387 +f 388 387 383 +f 383 384 388 +f 389 388 384 +f 384 385 389 +f 390 359 354 +f 354 386 390 +f 391 390 386 +f 386 387 391 +f 392 391 387 +f 387 388 392 +f 393 392 388 +f 388 389 393 +f 394 364 359 +f 359 390 394 +f 395 394 390 +f 390 391 395 +f 396 395 391 +f 391 392 396 +f 397 396 392 +f 392 393 397 +f 398 369 364 +f 364 394 398 +f 399 398 394 +f 394 395 399 +f 400 399 395 +f 395 396 400 +f 401 400 396 +f 396 397 401 +f 370 334 369 +f 369 398 370 +f 371 370 398 +f 398 399 371 +f 372 371 399 +f 399 400 372 +f 373 372 400 +f 400 401 373 +f 407 402 402 +f 402 403 407 +f 408 407 403 +f 403 404 408 +f 409 408 404 +f 404 405 409 +f 410 409 405 +f 405 406 410 +f 411 402 402 +f 402 407 411 +f 412 411 407 +f 407 408 412 +f 413 412 408 +f 408 409 413 +f 414 413 409 +f 409 410 414 +f 415 402 402 +f 402 411 415 +f 416 415 411 +f 411 412 416 +f 417 416 412 +f 412 413 417 +f 418 417 413 +f 413 414 418 +f 419 402 402 +f 402 415 419 +f 420 419 415 +f 415 416 420 +f 421 420 416 +f 416 417 421 +f 422 421 417 +f 417 418 422 +f 423 402 402 +f 402 419 423 +f 424 423 419 +f 419 420 424 +f 425 424 420 +f 420 421 425 +f 426 425 421 +f 421 422 426 +f 427 402 402 +f 402 423 427 +f 428 427 423 +f 423 424 428 +f 429 428 424 +f 424 425 429 +f 430 429 425 +f 425 426 430 +f 431 402 402 +f 402 427 431 +f 432 431 427 +f 427 428 432 +f 433 432 428 +f 428 429 433 +f 434 433 429 +f 429 430 434 +f 435 402 402 +f 402 431 435 +f 436 435 431 +f 431 432 436 +f 437 436 432 +f 432 433 437 +f 438 437 433 +f 433 434 438 +f 439 402 402 +f 402 435 439 +f 440 439 435 +f 435 436 440 +f 441 440 436 +f 436 437 441 +f 442 441 437 +f 437 438 442 +f 443 402 402 +f 402 439 443 +f 444 443 439 +f 439 440 444 +f 445 444 440 +f 440 441 445 +f 446 445 441 +f 441 442 446 +f 447 402 402 +f 402 443 447 +f 448 447 443 +f 443 444 448 +f 449 448 444 +f 444 445 449 +f 450 449 445 +f 445 446 450 +f 451 402 402 +f 402 447 451 +f 452 451 447 +f 447 448 452 +f 453 452 448 +f 448 449 453 +f 454 453 449 +f 449 450 454 +f 455 402 402 +f 402 451 455 +f 456 455 451 +f 451 452 456 +f 457 456 452 +f 452 453 457 +f 458 457 453 +f 453 454 458 +f 459 402 402 +f 402 455 459 +f 460 459 455 +f 455 456 460 +f 461 460 456 +f 456 457 461 +f 462 461 457 +f 457 458 462 +f 463 402 402 +f 402 459 463 +f 464 463 459 +f 459 460 464 +f 465 464 460 +f 460 461 465 +f 466 465 461 +f 461 462 466 +f 403 402 402 +f 402 463 403 +f 404 403 463 +f 463 464 404 +f 405 404 464 +f 464 465 405 +f 406 405 465 +f 465 466 406 +f 471 410 406 +f 406 467 471 +f 472 471 467 +f 467 468 472 +f 473 472 468 +f 468 469 473 +f 474 473 469 +f 469 470 474 +f 475 414 410 +f 410 471 475 +f 476 475 471 +f 471 472 476 +f 477 476 472 +f 472 473 477 +f 478 477 473 +f 473 474 478 +f 479 418 414 +f 414 475 479 +f 480 479 475 +f 475 476 480 +f 481 480 476 +f 476 477 481 +f 482 481 477 +f 477 478 482 +f 483 422 418 +f 418 479 483 +f 484 483 479 +f 479 480 484 +f 485 484 480 +f 480 481 485 +f 486 485 481 +f 481 482 486 +f 487 426 422 +f 422 483 487 +f 488 487 483 +f 483 484 488 +f 489 488 484 +f 484 485 489 +f 490 489 485 +f 485 486 490 +f 491 430 426 +f 426 487 491 +f 492 491 487 +f 487 488 492 +f 493 492 488 +f 488 489 493 +f 494 493 489 +f 489 490 494 +f 495 434 430 +f 430 491 495 +f 496 495 491 +f 491 492 496 +f 497 496 492 +f 492 493 497 +f 498 497 493 +f 493 494 498 +f 499 438 434 +f 434 495 499 +f 500 499 495 +f 495 496 500 +f 501 500 496 +f 496 497 501 +f 502 501 497 +f 497 498 502 +f 503 442 438 +f 438 499 503 +f 504 503 499 +f 499 500 504 +f 505 504 500 +f 500 501 505 +f 506 505 501 +f 501 502 506 +f 507 446 442 +f 442 503 507 +f 508 507 503 +f 503 504 508 +f 509 508 504 +f 504 505 509 +f 510 509 505 +f 505 506 510 +f 511 450 446 +f 446 507 511 +f 512 511 507 +f 507 508 512 +f 513 512 508 +f 508 509 513 +f 514 513 509 +f 509 510 514 +f 515 454 450 +f 450 511 515 +f 516 515 511 +f 511 512 516 +f 517 516 512 +f 512 513 517 +f 518 517 513 +f 513 514 518 +f 519 458 454 +f 454 515 519 +f 520 519 515 +f 515 516 520 +f 521 520 516 +f 516 517 521 +f 522 521 517 +f 517 518 522 +f 523 462 458 +f 458 519 523 +f 524 523 519 +f 519 520 524 +f 525 524 520 +f 520 521 525 +f 526 525 521 +f 521 522 526 +f 527 466 462 +f 462 523 527 +f 528 527 523 +f 523 524 528 +f 529 528 524 +f 524 525 529 +f 530 529 525 +f 525 526 530 +f 467 406 466 +f 466 527 467 +f 468 467 527 +f 527 528 468 +f 469 468 528 +f 528 529 469 +f 470 469 529 +f 529 530 470 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a125d7c..5b7027c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,11 +7,18 @@ */ #include "main.hpp" +#include "glm/gtc/matrix_transform.hpp" +#include "glm/gtx/transform.hpp" +#include "GLFW/glfw3.h" + //------------------------------- //-------------MAIN-------------- //------------------------------- + + + int main(int argc, char **argv) { if (argc != 2) { cout << "Usage: [obj file]" << endl; @@ -28,19 +35,24 @@ int main(int argc, char **argv) { frame = 0; seconds = time(NULL); fpstracker = 0; - + // Launch CUDA/GL if (init(mesh)) { // GLFW main loop mainLoop(); } + delete mesh; return 0; } void mainLoop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); + + //MY + setupCamera(); + runCuda(); time_t seconds2 = time (NULL); @@ -68,17 +80,47 @@ void mainLoop() { glfwTerminate(); } + + + //------------------------------- //---------RUNTIME STUFF--------- //------------------------------- +//translate x,y, angle, scale for keyboard operations +float scale = 0.15f; +//float scale = 0.05f; +float x_trans = 0.0f, y_trans = 0.0f, z_trans = -10.0f; +float x_angle = 0.0f, y_angle = 0.0f; + + +glm::mat4 M_model; +glm::mat4 M_view; +glm::mat4 M_perspective; + +glm::mat4 inv_trans_M_view; //for normal transformation + + +//lights + + + void runCuda() { // Map OpenGL buffer object for writing from CUDA on a single GPU // No data is moved (Win & Linux). When mapped to CUDA, OpenGL should not use this buffer dptr = NULL; + //int xpos, ypos; + //glfwGetMousePos(&xpos, &ypos); + cudaGLMapBufferObject((void **)&dptr, pbo); + + vertexShader(M_perspective * M_view * M_model, M_view*M_model, inv_trans_M_view); + rasterize(dptr); + + + cudaGLUnmapBufferObject(pbo); frame++; @@ -86,10 +128,37 @@ void runCuda() { } +//MY +void setupCamera() +{ + + //model-view + //M_model = glm::mat4(1.0f); + //M_model = glm::translate(M_model, glm::vec3(0, 0, z_trans)); + + //x_angle, y_angle : radium + M_model = glm::translate(glm::vec3(x_trans, y_trans, z_trans)) + * glm::rotate(x_angle, glm::vec3(1.0f, 0.0f, 0.0f)) + * glm::rotate(y_angle, glm::vec3(0.0f, 1.0f, 0.0f)); + + M_view = glm::mat4(1.0f); + + //projection + //left, right, bottom, top, near, far + M_perspective = glm::frustum(-scale * ((float)width) / ((float)height), + scale * ((float)width / (float)height), + -scale, scale, 1.0, 1000.0); + + inv_trans_M_view = glm::transpose(glm::inverse(M_view * M_model)); +} + //------------------------------- //----------SETUP STUFF---------- //------------------------------- + + + bool init(obj *mesh) { glfwSetErrorCallback(errorCallback); @@ -107,6 +176,14 @@ bool init(obj *mesh) { glfwMakeContextCurrent(window); glfwSetKeyCallback(window, keyCallback); + //MY Mouse Control + glfwSetMouseButtonCallback(window, mouseButtonCallback); + glfwSetCursorPosCallback(window, mouseMotionCallback); + + + glfwSetScrollCallback(window,mouseWheelCallback); + ///// + // Set up GL context glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { @@ -124,9 +201,20 @@ bool init(obj *mesh) { 0.0, 0.0, 1.0, 1.0, 0.0, 0.0 }; + rasterizeSetBuffers(mesh->getBufIdxsize(), mesh->getBufIdx(), mesh->getBufPossize() / 3, - mesh->getBufPos(), mesh->getBufNor(), mesh->getBufCol()); + mesh->getFaces()->size(), + mesh->getBufPos(), mesh->getBufNor(), mesh->getBufCol() + , (mesh->getTextureCoords())->size() > 0, mesh->getBufTex()); + + + initTextureData(mesh->diffuse_tex.size() > 0, mesh->diffuse_width, mesh->diffuse_height, mesh->diffuse_tex.data(), + mesh->specular_tex.size() > 0, mesh->specular_width, mesh->specular_height, mesh->specular_tex.data(), + mesh->ambient_color,mesh->diffuse_color,mesh->specular_color,mesh->specular_exponent); + + + GLuint passthroughProgram; passthroughProgram = initShader(); @@ -273,4 +361,78 @@ void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GL_TRUE); } + else if (key == GLFW_KEY_W && action == GLFW_PRESS) + { + changeGeomMode(); + } + else if (key == GLFW_KEY_S && action == GLFW_PRESS) + { + + changeShaderMode( ) ; + } + else if (key == GLFW_KEY_B && action == GLFW_PRESS) + { + + changeBackFaceCulling(); + } + + + + +} + +enum ControlState {NONE=0,ROTATE,TRANSLATE}; +ControlState mouseState = NONE; +void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) +{ + if (action == GLFW_PRESS) + { + if (button == GLFW_MOUSE_BUTTON_LEFT) + { + mouseState = ROTATE; + } + else if (button == GLFW_MOUSE_BUTTON_RIGHT) + { + mouseState = TRANSLATE; + } + + } + else if (action == GLFW_RELEASE) + { + mouseState = NONE; + } + //printf("%d\n", mouseState); +} + +double lastx = (double)width / 2; +double lasty = (double)height / 2; +void mouseMotionCallback(GLFWwindow* window, double xpos, double ypos) +{ + const double s_r = 0.01; + const double s_t = 0.01; + + double diffx = xpos - lastx; + double diffy = ypos - lasty; + lastx = xpos; + lasty = ypos; + + if (mouseState == ROTATE) + { + //rotate + x_angle += (float)s_r * diffy; + y_angle += (float)s_r * diffx; + } + else if (mouseState == TRANSLATE) + { + //translate + x_trans += (float)(s_t * diffx); + y_trans += (float)(-s_t * diffy); + } +} + +void mouseWheelCallback(GLFWwindow* window, double xoffset, double yoffset) +{ + const double s_s = 0.01; + + scale += (float)(-s_s * yoffset); } diff --git a/src/main.hpp b/src/main.hpp index 49d3948..c664122 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -61,6 +61,7 @@ int main(int argc, char **argv); //------------------------------- void runCuda(); +void setupCamera(); #ifdef __APPLE__ void display(); @@ -93,3 +94,6 @@ void deleteTexture(GLuint *tex); void mainLoop(); void errorCallback(int error, const char *description); void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); +void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +void mouseMotionCallback(GLFWwindow* window, double xpos, double ypos); +void mouseWheelCallback(GLFWwindow* window, double xoffset, double yoffset); \ No newline at end of file diff --git a/src/rasterize.cu b/src/rasterize.cu index 53103b5..2a10478 100644 --- a/src/rasterize.cu +++ b/src/rasterize.cu @@ -8,27 +8,101 @@ #include "rasterize.h" +#include +#include #include #include #include +#include #include #include +#include +#include +#include +#include + +#include + #include "rasterizeTools.h" +#include "glm/gtc/matrix_transform.hpp" +//#include "glm/gtx/component_wise.hpp" + +#define BACKGROUND_COLOR (glm::vec3(0.0f)) + +#define BILINEAR_FILTERING + +//#define BACKFACE_CULLING + +//#define ANTIALIASING + +//#define SCISSOR_TEST + + struct VertexIn { glm::vec3 pos; glm::vec3 nor; glm::vec3 col; // TODO (optional) add other vertex attributes (e.g. texture coordinates) + glm::vec2 uv; }; + + struct VertexOut { // TODO + glm::vec4 pos; //in NDS + glm::vec3 color; + + glm::vec3 pos_eye_space; + glm::vec3 noraml_eye_space; + + float divide_w_clip; + + glm::vec2 uv; }; + +struct Edge +{ + VertexOut v[2]; + + float x, z; + float dx, dz; + + + // + //VertexOut cur_v; //used for interpolate between a scan line + float gap_y; +}; + + + + + + + + + + struct Triangle { VertexOut v[3]; }; struct Fragment { - glm::vec3 color; + //bool shade; + bool has_fragment; + + glm::vec3 color; + glm::vec3 normal_eye_space; + glm::vec2 uv; + + glm::vec3 pos_eye_space; + //float depth; + + //glm::vec3 color; + +#ifdef ANTIALIASING + float ratio; +#endif + }; static int width = 0; @@ -41,6 +115,76 @@ static glm::vec3 *dev_framebuffer = NULL; static int bufIdxSize = 0; static int vertCount = 0; +static int triCount = 0; + +//static FragmentIn * dev_fragments = NULL; +static int * dev_depth = NULL; + +//tex +static bool hasTexture = false; +static bool hasDiffuseTex = false, hasSpecularTex = false; +static glm::vec3 *dev_diffuse_texture_data = NULL; +static glm::vec3 *dev_specular_texture_data = NULL; +static int diffuse_width = 0,diffuse_height = 0; +static int specular_width = 0, specular_height = 0; +static glm::vec3 materialDiffuse; +static glm::vec3 materialSpecular; +static float materialNs; +static glm::vec3 materialAmbient; + + +static ShaderMode shaderMode = SHADER_WHITE_MATERIAL; +static GeomMode geomMode = GEOM_COMPLETE; +static bool backFaceCulling = false; + +static Light hst_lights[NUM_LIGHTS] = { + Light{ DIRECTION_LIGHT + , glm::vec3(1.0f, 1.0f, 1.0f) + , glm::normalize(glm::vec3(1.0f, -2.0f, 1.0f)), true }, + Light{ DIRECTION_LIGHT + , glm::vec3(1.0f, 1.0f, 1.0f) + , glm::normalize(glm::vec3(0.0f, 0.0f, -1.0f)), true } }; + +static int lightsCount = NUM_LIGHTS; +static Light* dev_lights = NULL; + + + +void changeShaderMode() +{ + shaderMode = (ShaderMode)((shaderMode+1) % 3); + + if (!hasTexture && shaderMode == SHADER_TEXTURE) + { + shaderMode = SHADER_NORMAL; + } + + printf("change shading mode %d\n",(int)shaderMode); +} + +void changeGeomMode() +{ + geomMode = (GeomMode)((geomMode + 1) % 3); + + + printf("change geometry shading mode %d\n", (int)geomMode); +} + +void changeBackFaceCulling() +{ + backFaceCulling = !backFaceCulling; + + if (backFaceCulling) + { + printf("enable back face culling \n"); + } + else + { + printf("disable back face culling \n"); + } + +} + /** * Kernel that writes the image to the OpenGL PBO directly. */ @@ -63,17 +207,7 @@ void sendImageToPBO(uchar4 *pbo, int w, int h, glm::vec3 *image) { } } -// Writes fragment colors to the framebuffer -__global__ -void render(int w, int h, Fragment *depthbuffer, glm::vec3 *framebuffer) { - int x = (blockIdx.x * blockDim.x) + threadIdx.x; - int y = (blockIdx.y * blockDim.y) + threadIdx.y; - int index = x + (y * w); - if (x < w && y < h) { - framebuffer[index] = depthbuffer[index].color; - } -} /** * Called once at the beginning of the program to allocate memory. @@ -84,9 +218,23 @@ void rasterizeInit(int w, int h) { cudaFree(dev_depthbuffer); cudaMalloc(&dev_depthbuffer, width * height * sizeof(Fragment)); cudaMemset(dev_depthbuffer, 0, width * height * sizeof(Fragment)); - cudaFree(dev_framebuffer); + + //cudaFree(dev_fragments); + //cudaMalloc(&dev_fragments, width * height *sizeof(FragmentIn)); + //cudaMemset(dev_fragments, 0, width * height * sizeof(FragmentIn)); + + cudaFree(dev_depth); + cudaMalloc(&dev_depth, width * height *sizeof(int)); + //cudaMemset(dev_depth, INT_MAX, width * height * sizeof(int)); + + cudaFree(dev_framebuffer); cudaMalloc(&dev_framebuffer, width * height * sizeof(glm::vec3)); cudaMemset(dev_framebuffer, 0, width * height * sizeof(glm::vec3)); + + + + + checkCUDAError("rasterizeInit"); } @@ -95,10 +243,19 @@ void rasterizeInit(int w, int h) { */ void rasterizeSetBuffers( int _bufIdxSize, int *bufIdx, - int _vertCount, float *bufPos, float *bufNor, float *bufCol) { + int _vertCount, int _faceCount, float *bufPos, float *bufNor, float *bufCol + , bool useTexture,float *bufUV) { bufIdxSize = _bufIdxSize; vertCount = _vertCount; + + + //MY + hasTexture = useTexture; + //triCount = vertCount / 3; //? can have vert not in use + triCount = _faceCount; + ///////// + cudaFree(dev_bufIdx); cudaMalloc(&dev_bufIdx, bufIdxSize * sizeof(int)); cudaMemcpy(dev_bufIdx, bufIdx, bufIdxSize * sizeof(int), cudaMemcpyHostToDevice); @@ -109,7 +266,19 @@ void rasterizeSetBuffers( bufVertex[i].pos = glm::vec3(bufPos[j + 0], bufPos[j + 1], bufPos[j + 2]); bufVertex[i].nor = glm::vec3(bufNor[j + 0], bufNor[j + 1], bufNor[j + 2]); bufVertex[i].col = glm::vec3(bufCol[j + 0], bufCol[j + 1], bufCol[j + 2]); + } + + if (useTexture) + { + for (int i = 0; i < vertCount; i++) { + int j = i * 2; + bufVertex[i].uv = glm::vec2(bufUV[j + 0], bufUV[j + 1]); + + //printf("%f,%f\n", bufVertex[i].uv.x, bufVertex[i].uv.y); + } + } + cudaFree(dev_bufVertex); cudaMalloc(&dev_bufVertex, vertCount * sizeof(VertexIn)); cudaMemcpy(dev_bufVertex, bufVertex, vertCount * sizeof(VertexIn), cudaMemcpyHostToDevice); @@ -118,9 +287,1025 @@ void rasterizeSetBuffers( cudaMalloc(&dev_primitives, vertCount / 3 * sizeof(Triangle)); cudaMemset(dev_primitives, 0, vertCount / 3 * sizeof(Triangle)); + + delete bufVertex; + + + + ////init lights + cudaFree(dev_lights); + cudaMalloc(&dev_lights, lightsCount*sizeof(Light)); + cudaMemcpy(dev_lights, hst_lights, lightsCount * sizeof(Light), cudaMemcpyHostToDevice); + //////////// + + checkCUDAError("rasterizeSetBuffers"); } + +//texture +//simple version, only support two texture +void initTextureData(bool has_diffuse_tex,int d_w, int d_h, glm::vec3 * diffuse_tex, + bool has_specular_tex, int s_w, int s_h, glm::vec3 * specular_tex, + const glm::vec3 & ambient,const glm::vec3 & diffuse,const glm::vec3 & specular, float Ns) +{ + diffuse_width = d_w; + diffuse_height = d_h; + specular_width = s_w; + specular_height = s_h; + + materialAmbient = ambient; + materialDiffuse = diffuse; + materialSpecular = specular; + materialNs = Ns; + if (hasTexture) + { + hasDiffuseTex = has_diffuse_tex; + hasSpecularTex = has_specular_tex; + + if (has_diffuse_tex) + { + cudaFree(dev_diffuse_texture_data); + cudaMalloc(&dev_diffuse_texture_data, d_w*d_h * sizeof(glm::vec3)); + cudaMemcpy(dev_diffuse_texture_data, diffuse_tex, d_w*d_h * sizeof(glm::vec3), cudaMemcpyHostToDevice); + } + + if (has_specular_tex) + { + cudaFree(dev_specular_texture_data); + cudaMalloc(&dev_specular_texture_data, s_w*s_h * sizeof(glm::vec3)); + cudaMemcpy(dev_specular_texture_data, specular_tex, s_w*s_h * sizeof(glm::vec3), cudaMemcpyHostToDevice); + } + } + +} + + + + +//------------------------------------------------------------------------------- +// Vertex Shader +//------------------------------------------------------------------------------- + +/** +* each thread copy info for one vertex +*/ +__global__ +void kernVertexShader(int width,int height,int N,glm::mat4 M, glm::mat4 M_model_view, glm::mat4 M_normal_view, VertexIn * dev_vertex, Triangle * dev_triangles) +{ + int vertexId = blockDim.x * blockIdx.x + threadIdx.x; + + + if (vertexId < N) + { + int triangleId = vertexId / 3; + int i = vertexId - triangleId * 3; + VertexIn & vi = dev_vertex[vertexId]; + VertexOut & vo = dev_triangles[triangleId].v[i]; + + vo.pos = M * glm::vec4(vi.pos, 1); + + //printf("%f,%f\n", vo.pos.x, vo.pos.w); + + vo.noraml_eye_space = glm::vec3(M_normal_view * glm::vec4(vi.nor, 0)); + vo.pos_eye_space = glm::vec3(M_model_view * glm::vec4(vi.pos, 1)); + + + vo.color = vi.col; + + + vo.uv = vi.uv; + + //printf("%f,%f\n", vo.uv.x, vo.uv.y); + + + + + + + //viewport + vo.divide_w_clip = 1.0f / vo.pos.w; + + vo.pos.x = 0.5f * (float)width * (vo.pos.x * vo.divide_w_clip + 1.0f); + vo.pos.y = 0.5f * (float)height * (vo.pos.y * vo.divide_w_clip + 1.0f); + vo.pos.z = 0.5f * (vo.pos.z * vo.divide_w_clip + 1.0f); + vo.pos.w = 1.0f; + + + + + //perspective correct interpolation + vo.color *= vo.divide_w_clip; + vo.noraml_eye_space *= vo.divide_w_clip; + vo.pos_eye_space *= vo.divide_w_clip; + vo.uv *= vo.divide_w_clip; + + + + //////// + + } +} + +/** +* MY: +* +* VertexIn dev_bufVertex => Triangle VertexOut +* M model-view +*/ +void vertexShader(const glm::mat4 & M, const glm::mat4 & M_model_view, const glm::mat4 & inv_trans_M) +{ + const int blockSize = 192; + dim3 blockCount( (vertCount + blockSize - 1 )/blockSize ); + + // get M, M_normal_view + + kernVertexShader << > >(width,height,vertCount, M, M_model_view, inv_trans_M, dev_bufVertex, dev_primitives); +} + +//------------------------------------------------------------------------------ + + + + + + + + +//MY +//------------------------------------------------------------------------------- +// Rasterization +//------------------------------------------------------------------------------- + +__host__ __device__ +VertexOut interpolateVertexOut(const VertexOut & a, const VertexOut & b,float u) +{ + VertexOut c; + + //if (u < 0.0f){ u = 0.0f; } + //else if (u > 1.0f){ u = 1.0f; } + + c.divide_w_clip = (1.0f - u) * a.divide_w_clip + u * b.divide_w_clip; + + c.pos = (1.0f - u) * a.pos + u * b.pos; + c.color = (1.0f - u) * a.color + u * b.color; + c.uv = (1.0f - u) * a.uv + u * b.uv; + + c.pos_eye_space = (1.0f - u) * a.pos_eye_space + u * b.pos_eye_space; + c.noraml_eye_space = glm::normalize((1.0f - u) * a.noraml_eye_space + u * b.noraml_eye_space); + + return c; +} + + +//e.v[0] is the one with smaller y value +//scan from v[0] to v[1] +__device__ +void constructEdge(Edge & e, const VertexOut & v0, const VertexOut & v1) +{ + if (v0.pos.y <= v1.pos.y) + { + e.v[0] = v0; + e.v[1] = v1; + } + else + { + e.v[0] = v1; + e.v[1] = v0; + } + + //TODO: other members + //e.cur_v = e.v[0]; + e.gap_y = 0.0f; + + //if (e.v[0].uv.x / e.v[0].divide_w_clip < 0.0f) + //{ + // printf("%f,%f,%f\n", e.v[0].uv.x / e.v[0].divide_w_clip, e.v[0].uv.y / e.v[0].divide_w_clip, e.v[0].divide_w_clip); + //} +} + + +__device__ +float initEdge(Edge & e, float y) +{ + e.gap_y = e.v[1].pos.y - e.v[0].pos.y; + + e.dx = (e.v[1].pos.x - e.v[0].pos.x) / e.gap_y; + e.dz = (e.v[1].pos.z - e.v[0].pos.z) / e.gap_y; + e.x = e.v[0].pos.x + (y - e.v[0].pos.y) * e.dx; + e.z = e.v[0].pos.z + (y - e.v[0].pos.y) * e.dz; + + //if (e.x < 0) + //{ + // printf("%f,%f \n", e.x, e.dx); + //} + + return (y - e.v[0].pos.y) / e.gap_y; +} + +__device__ +void updateEdge(Edge & e) +{ + e.x += e.dx; + e.z += e.dz; +} + + + +__device__ +void drawOneScanLine(int width, const Edge & e1, const Edge & e2, int y, float u1, float u2, Fragment * fragments, int * depth, const Triangle & tri, GeomMode gm) +{ +#ifdef ANTIALIASING + glm::vec2 aa_offset[9] = {glm::vec2(-0.5f,-0.5f) + , glm::vec2(-0.5f, 0.0f) + , glm::vec2(-0.5f, 0.5f) + , glm::vec2(0.0f, -0.5f) + , glm::vec2(0.0f, 0.0f) + , glm::vec2(0.0f, 0.5f) + , glm::vec2(0.5f, -0.5f) + , glm::vec2(0.5f, 0.0f) + , glm::vec2(0.5f, 0.5f) + }; +#endif + + + // Find the starting and ending x coordinates and + // clamp them to be within the visible region + int x_left = (int)(ceilf(e1.x) + EPSILON); + int x_right = (int)(ceilf(e2.x) + EPSILON); + +#ifdef ANTIALIASING + //x_left -= 1; + //x_right += 1; +#endif + + float x_left_origin = e1.x; + float x_right_origin = e2.x; + + if (x_left < 0) + { + x_left = 0; + } + + if (x_right > width) + { + x_right = width; + } + + // Discard scanline with no actual rasterization and also + // ensure that the length is larger than zero + if (x_left >= x_right) { return; } + + + + + + + + + + //TODO: get two interpolated segment end points + //VertexOut cur_v_e1 = interpolateVertexOut(e1.v[0], e1.v[1], u1); + //VertexOut cur_v_e2 = interpolateVertexOut(e2.v[0], e2.v[1], u2); + + + //Initialize attributes + float dz = (e2.z - e1.z) / (e2.x - e1.x); + float z = e1.z + (x_left_origin - e1.x) * dz; + + + + + + //Interpolate + //printf("%d,%d\n", x_left, x_right); + //float gap_x = x_right_origin - x_left_origin; + for (int x = x_left; x < x_right; ++x) + { +#ifdef ANTIALIASING + if (x < 0 || x >= width) + { + continue; + } +#endif + + + + int idx = x + y * width; + + if (gm == GEOM_WIREFRAME) + { + if (x != x_left && x != x_right) + { + x = x_right; + continue; + } + + + } + + //VertexOut p = interpolateVertexOut(cur_v_e1, cur_v_e2, ((float)x-x_left_origin) / gap_x); + + + //using barycentric + glm::vec3 t[3] = { glm::vec3(tri.v[0].pos), glm::vec3(tri.v[1].pos), glm::vec3(tri.v[2].pos) }; + glm::vec3 u = calculateBarycentricCoordinate(t, glm::vec2(x,y)); + + +#ifdef ANTIALIASING + float r = 1.0; + if (x <= x_left+3 || x >= x_right-3) + { + int count = 0; + glm::vec2 tmp((float)x, (float)y); + for (int i = 0; i < 9; i++) + { + if (isBarycentricCoordInBounds(calculateBarycentricCoordinate(t, tmp + aa_offset[i]))) + { + count++; + } + + } + r = (float)count / 9.0f; + } +#endif + + + VertexOut p; + p.divide_w_clip = u.x * tri.v[0].divide_w_clip + u.y * tri.v[1].divide_w_clip + u.z * tri.v[2].divide_w_clip; + + p.pos = u.x * tri.v[0].pos + u.y * tri.v[1].pos + u.z * tri.v[2].pos; + p.color = u.x * tri.v[0].color + u.y * tri.v[1].color + u.z * tri.v[2].color; + p.uv = u.x * tri.v[0].uv + u.y * tri.v[1].uv + u.z * tri.v[2].uv; + + p.pos_eye_space = u.x * tri.v[0].pos_eye_space + u.y * tri.v[1].pos_eye_space + u.z * tri.v[2].pos_eye_space; + p.noraml_eye_space = u.x * tri.v[0].noraml_eye_space + u.y * tri.v[1].noraml_eye_space + u.z * tri.v[2].noraml_eye_space; + + + + //z = 1/p.divide_w_clip; + ////atomic + //int assumed; + //int* address = &depth[idx]; + //int old = *address; + ////lock method, don't know why it doesn't work on some cases + //do{ + // assumed = old; + // old = atomicCAS(address, assumed, 1); + //} while (assumed != old); + //if (*address == 0) + //{ + // printf(" -%d- ", *address); + //} +//#ifdef ANTIALIASING +// int z_int = (int)((z -1.0f + 0.00001f*r) * INT_MAX); +//#else + int z_int = (int)(z * INT_MAX); +//#endif + int* address = &depth[idx]; + + atomicMin(address, z_int); + + //if (fragments[idx].shade == false) + //{ + // fragments[idx].shade = true; + // fragments[idx].depth = FLT_MAX; + //} + + + //if (z < fragments[idx].depth) + if (*address == z_int) + { + //fragments[idx].depth = z; + fragments[idx].color = p.color / p.divide_w_clip; + fragments[idx].normal_eye_space = glm::normalize( p.noraml_eye_space / p.divide_w_clip ); + fragments[idx].pos_eye_space = p.noraml_eye_space / p.divide_w_clip; + fragments[idx].uv = p.uv / p.divide_w_clip; + + fragments[idx].has_fragment = true; + +#ifdef ANTIALIASING + fragments[idx].ratio = r; + +#endif + } + + + ////unlock + //old = *address; + //do{ + // assumed = old; + // old = atomicCAS(address, assumed, 0); + //} while (assumed != old); + ////if (*address == 1) + ////{ + //// printf("%d,%d\t", *address,old); + ////} + + + z += dz; + } +} + + + + + + + + +/** +* Rasterize the area between two edges as the left and right limit. +* e1 - longest y span +*/ +__device__ +void drawAllScanLines(int width, int height, Edge e1, Edge e2, Fragment * fragments, int * depth, const Triangle & tri, GeomMode gm) +{ + // Discard horizontal edge as there is nothing to rasterize + if (e2.v[1].pos.y - e2.v[0].pos.y == 0.0f) { return; } + + // Find the starting and ending y positions and + // clamp them to be within the visible region + int y_bot = (int)(ceilf(e2.v[0].pos.y) + EPSILON); + int y_top = (int)(ceilf(e2.v[1].pos.y) + EPSILON); + + + + float y_bot_origin = ceilf( e2.v[0].pos.y ); + float y_top_origin = floorf(e2.v[1].pos.y); + + if (y_bot < 0) + { + y_bot = 0; + + } + + if (y_top > height) + { + y_top = height; + } + + + //Initialize edge's structure + float u1_base = initEdge(e1, y_bot_origin); + initEdge(e2, y_bot_origin); + + + //printf("%f,%f\n", e1.v[0].uv.x / e1.v[0].divide_w_clip, e1.v[0].uv.y / e1.v[0].divide_w_clip ); + + for (int y = y_bot; y < y_top; ++y) + { +#ifdef ANTIALIASING + if (y < 0 || y >= height) + { + continue; + } +#endif + + float u2 = ((float)y - y_bot_origin) / e2.gap_y; + float u1 = u1_base + ((float)y - y_bot_origin) / e1.gap_y; + if (e1.x <= e2.x) + { + drawOneScanLine(width, e1, e2, y ,u1,u2, fragments, depth, tri,gm); + } + else + { + drawOneScanLine(width, e2, e1, y, u2,u1, fragments, depth , tri,gm); + } + + //update edge + updateEdge(e1); + updateEdge(e2); + } +} + + + + + +/** +* Each thread handles one triangle +* rasterization +*/ +__global__ +void kernScanLineForOneTriangle(int num_tri, int width,int height +, Triangle * triangles, Fragment * depth_fragment, int * depth +, GeomMode gm) +{ + int triangleId = blockDim.x * blockIdx.x + threadIdx.x; + + if (triangleId >= num_tri) + { + return; + } + + + Triangle tri = triangles[triangleId]; //copy + + + + bool outside = true; + + //currently tri.v are in clipped coordinates + //need to transform to viewport coordinate + for (int i = 0; i < 3; i++) + { + //if (tri.v[i].uv.x < 0.0f) + //{ + // printf("%f,%f,%f\n", tri.v[i].uv.x , tri.v[i].uv.y, tri.v[i].pos.w); + //} + + //if (tri.v[i].pos.w == 0.0f) + //{ + // tri.v[i].divide_w_clip = 0; + //} + //else + //{ + + //} + + //tri.v[i].divide_w_clip = 1.0f / tri.v[i].pos.w; + // + ////view port + //tri.v[i].pos.x = 0.5f * (float)width * (tri.v[i].pos.x * tri.v[i].divide_w_clip + 1.0f); + //tri.v[i].pos.y = 0.5f * (float)height * (tri.v[i].pos.y * tri.v[i].divide_w_clip + 1.0f); + //tri.v[i].pos.z = 0.5f * (tri.v[i].pos.z * tri.v[i].divide_w_clip + 1.0f); + //tri.v[i].pos.w = 1.0f; + + + // + + ////perspective correct interpolation + //tri.v[i].color *= tri.v[i].divide_w_clip; + //tri.v[i].noraml_eye_space *= tri.v[i].divide_w_clip; + //tri.v[i].pos_eye_space *= tri.v[i].divide_w_clip; + //tri.v[i].uv *= tri.v[i].divide_w_clip; + + + + //////// + if (tri.v[i].pos.x < (float)width && tri.v[i].pos.x >= 0 + && tri.v[i].pos.y < (float)height && tri.v[i].pos.y >= 0) + { + outside = false; + } + } + + + //discard triangles that are totally out of the viewport + if (outside) + { + return; + } + ///// + + + + //build edge + // for line scan + Edge edges[3]; + + constructEdge(edges[0], tri.v[0], tri.v[1]); + constructEdge(edges[1], tri.v[1], tri.v[2]); + constructEdge(edges[2], tri.v[2], tri.v[0]); + + //if (!(edges[0].x >= 0.0f)) + //{ + // printf("%f,%f\n", edges[0].x, edges[0].dx); + //} + //if (!(edges[1].x >= 0.0f)) + //{ + // printf("%f,%f\n", edges[1].x, edges[1].dx); + //} + //if (!(edges[2].x >= 0.0f)) + //{ + // printf("%f,%f\n", edges[2].x, edges[2].dx); + //} + + + //Find the edge with longest y span + float maxLength = 0.0f; + int longEdge = -1; + for (int i = 0; i < 3; ++i) + { + float length = edges[i].v[1].pos.y - edges[i].v[0].pos.y; + if (length > maxLength) + { + maxLength = length; + longEdge = i; + } + } + + + // get indices for other two shorter edges + int shortEdge0 = (longEdge + 1) % 3; + int shortEdge1 = (longEdge + 2) % 3; + + // Rasterize two parts separately + drawAllScanLines(width, height, edges[longEdge], edges[shortEdge0], depth_fragment, depth , tri,gm); + drawAllScanLines(width, height, edges[longEdge], edges[shortEdge1], depth_fragment, depth , tri,gm); + + + +} + +//--------------------------------------------------------------------------- + + +__global__ +void kernVertexRasterize(int num_tri, int width, int height, Triangle* triangles +,Fragment * depth_fragment, int * depth) +{ + int triId = blockDim.x * blockIdx.x + threadIdx.x; + + if (triId >= num_tri) + { + return; + } + + + for (int i = 0; i < 2; i++) + { + VertexOut p = triangles[triId].v[i]; + + + + + int x = (int)p.pos.x; + int y = (int)p.pos.y; + if (x < 0 || x >= width || y < 0 || y >= height) + { + return; + } + + + int idx = x + y * width; + + int z_int = (int)(p.pos.z * INT_MAX); + int* address = &depth[idx]; + + atomicMin(address, z_int); + + //if (fragments[idx].shade == false) + //{ + // fragments[idx].shade = true; + // fragments[idx].depth = FLT_MAX; + //} + + + //if (z < fragments[idx].depth) + if (*address == z_int) + { + //fragments[idx].depth = z; + depth_fragment[idx].color = p.color / p.divide_w_clip; + depth_fragment[idx].normal_eye_space = p.noraml_eye_space / p.divide_w_clip; + depth_fragment[idx].pos_eye_space = p.noraml_eye_space / p.divide_w_clip; + depth_fragment[idx].uv = p.uv / p.divide_w_clip; + + depth_fragment[idx].has_fragment = true; + + } + + } + + + +} + + + + + + + + + + + + + + + +//------------------------------------------------------------------------------- +// Fragment Shader +//------------------------------------------------------------------------------- + +//__global__ +//void fragmentShader(int width, int height, Fragment* depthBuffer, FragmentIn* fragments ) +//{ +// //currently +// int x = (blockIdx.x * blockDim.x) + threadIdx.x; +// int y = (blockIdx.y * blockDim.y) + threadIdx.y; +// +// if (x < width && y < height) +// { +// int index = x + y*width; +// +// if (fragments[index].shade) +// { +// //depthBuffer[index].color = glm::vec3(1.0f); +// +// //test: normal +// depthBuffer[index].color = fragments[index].normal_eye_space; +// } +// else +// { +// depthBuffer[index].color = BACKGROUND_COLOR; +// } +// } +//} + + +// Writes fragment colors to the framebuffer +__host__ __device__ +glm::vec3 phongShading(Light* lights, int num_lights + , const glm::vec3 & pos, const glm::vec3 & n + , const glm::vec3 & ambient, const glm::vec3 & diffuse,const glm::vec3 & specular, float shiniess + ) +{ + glm::vec3 ambient_term(0.0f); + glm::vec3 diffuse_term(0.0f); + glm::vec3 specular_term(0.0f); + + for (int i = 0; i < num_lights; i++) + { + if (!lights[i].enabled) + { + continue; + } + + //ambient + ambient_term += lights[i].intensity * ambient; + + //diffuse + glm::vec3 l; + if (lights[i].type == POINT_LIGHT) + { + l = glm::normalize(lights[i].vec - pos); + } + else + { + //directional light + //should be normalized already + l = -lights[i].vec; + } + diffuse_term += max(glm::dot(l, n), 0.0f) * diffuse * lights[i].intensity; + + + //specular + glm::vec3 v = glm::normalize(pos); //? + glm::vec3 r = (2 * glm::dot(l, n) * n) - l; + //glm::vec3 h = (l + v) / glm::length(l + v); + specular_term += powf(max(glm::dot(r,v), 0.0f), shiniess) * specular * lights[i].intensity; + } + + return ambient_term + diffuse_term + specular_term; +} + + + + +__device__ +glm::vec3 getTextureValue_Naive(int w, int h, glm::vec3 * data, glm::vec2 uv) +{ + if (uv.x < 0.0f) + { + uv.x = 0.0f; + } + else if (uv.x > 1.0f) + { + uv.x = 1.0f; + } + + if (uv.y < 0.0f) + { + uv.y = 0.0f; + } + else if (uv.y > 1.0f) + { + uv.y = 1.0f; + } + + int ui = uv.x * w; + int vi = uv.y * h; + + return data[ui + vi * w]; +} + + +__device__ +glm::vec3 getTextureValue_Bilinear(int w,int h, glm::vec3 * data, glm::vec2 uv) +{ + if (uv.x < 0.0f) + { + uv.x = 0.0f; + } + else if (uv.x > 1.0f) + { + uv.x = 1.0f; + } + + if (uv.y < 0.0f) + { + uv.y = 0.0f; + } + else if (uv.y > 1.0f) + { + uv.y = 1.0f; + } + + + //if (uv.x < 0.0f || uv.x > 1.0f + // || uv.y < 0.0f || uv.y > 1.0f) + //{ + // printf("ERROR: UV %f,%f!\n",uv.x,uv.y); + // uv.x = 0.0f; + // uv.y = 0.0f; + //} + + float u = (float)w * uv.x + 0.5; + float v = (float)h * uv.y + 0.5; + + + int ui = floorf(u); + int vi = floorf(v); + + //edge case + int ui1 = ui + 1; + ui1 = (ui1 >= w) ? w-1 : ui1; + int vi1 = vi + 1; + vi1 = (vi1 >= h) ? h-1 : vi1; + + float uf = u - ui; + float vf = v - vi; + + //printf("%d,%d\n", ui, vi); + + glm::vec3 z11 = data[ui + vi*w]; + glm::vec3 z12 = data[ui1 + vi*w]; + glm::vec3 z21 = data[ui + vi1*w]; + glm::vec3 z22 = data[ui1 + vi1*w]; + + //glm::vec3 z21 = data[ui + vi*w]; + //glm::vec3 z22 = data[ui1 + vi*w]; + //glm::vec3 z11 = data[ui + vi1*w]; + //glm::vec3 z12 = data[ui1 + vi1*w]; + + + return ( + (1 - uf)*((1-vf) * z11 + vf * z21) + + uf *((1-vf) * z12 + vf * z22) + ); + +} + + + + + +__global__ +void render(int w, int h, Fragment *depthbuffer, glm::vec3 *framebuffer,Light* lights,int num_lights, ShaderMode s + ,bool useTexture, bool useDiffuseTex, bool useSpecularTex + ,int d_wt,int d_ht, int s_wt, int s_ht + ,glm::vec3 * diffuseTex, glm::vec3 * specularTex + ,glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular, float Ns) { + int x = (blockIdx.x * blockDim.x) + threadIdx.x; + int y = (blockIdx.y * blockDim.y) + threadIdx.y; + + +#ifdef SCISSOR_TEST + if (x < w / 2) + { + return; + } +#endif + + + + //flip + int index_framebuffer = (w - 1 - x) + w * (h - 1 - y); + /// + + int index = x + (y * w); + + if (x < w && y < h) { + //framebuffer[index] = depthbuffer[index].color; + Fragment & db = depthbuffer[index]; + glm::vec3 & fb = framebuffer[index_framebuffer]; + + if (!db.has_fragment) + { + fb = BACKGROUND_COLOR; + return; + } + + + switch (s) + { + case SHADER_NORMAL: + { + fb = db.normal_eye_space; + break; + } + + case SHADER_WHITE_MATERIAL: + { + //using lights + //default shading + glm::vec3 zero(0.0f); + fb = phongShading(lights, num_lights + , db.pos_eye_space, db.normal_eye_space + , zero//glm::vec3(0.1f, 0.1f, 0.1f) + , glm::vec3(1.0f, 0.0f, 0.0f) + , glm::vec3(1.0f, 1.0f, 1.0f), 32 + ); + break; + } + + case SHADER_TEXTURE: + { + if (useTexture) + { + if (useDiffuseTex) + { +#ifdef BILINEAR_FILTERING + diffuse *= getTextureValue_Bilinear(d_wt, d_ht, diffuseTex, db.uv); +#else + diffuse *= getTextureValue_Naive(d_wt, d_ht, diffuseTex, db.uv); +#endif + } +// + if (useSpecularTex) + { +#ifdef BILINEAR_FILTERING + specular *= getTextureValue_Bilinear(s_wt, s_ht, specularTex, db.uv); +#else + specular *= getTextureValue_Naive(s_wt, s_ht, specularTex, db.uv); +#endif + } + } + + fb = phongShading(lights, num_lights + , db.pos_eye_space, db.normal_eye_space + , ambient + , diffuse + , specular, Ns + ); + break; + } + + } + + + + + +#ifdef ANTIALIASING + //fb *= db.ratio; + if (depthbuffer[index - 1].has_fragment == false || depthbuffer[index + 1].has_fragment == false + || depthbuffer[index - w].has_fragment == false || depthbuffer[index + w].has_fragment == false) + { + fb *= db.ratio; + } + +#endif + + + } +} + +//-------------------------------------------------------------------------------- + + +__global__ +void initDepth(int w,int h,int * depth) +{ + int x = (blockIdx.x * blockDim.x) + threadIdx.x; + int y = (blockIdx.y * blockDim.y) + threadIdx.y; + + if ( x < w && y < h) + { + int index = x + (y * w); + + depth[index] = INT_MAX; + + } + + +} + +struct is_backface +{ + __host__ __device__ + bool operator()(const Triangle tri) + { + //bool isback = true; + + glm::vec3 n = 0.33333f * tri.v[0].noraml_eye_space + 0.33333f * tri.v[1].noraml_eye_space + 0.33333f * tri.v[2].noraml_eye_space; + + return glm::dot(n, glm::vec3(0, 0, 1.0f)) < 0; + } +}; /** * Perform rasterization. */ @@ -133,13 +1318,74 @@ void rasterize(uchar4 *pbo) { // TODO: Execute your rasterization pipeline here // (See README for rasterization pipeline outline.) + //cudaMemset(dev_fragments, 0, width * height * sizeof(FragmentIn)); + //cudaMemset(dev_depth, INT_MAX, width * height * sizeof(int)); + cudaMemset(dev_depthbuffer, 0, width * height * sizeof(Fragment)); + + + + initDepth << > >(width,height,dev_depth); + + + int cur_triCount = triCount; + if (backFaceCulling) + { + // back surface sculling + Triangle * primitives_end = dev_primitives + (triCount); + primitives_end = thrust::remove_if(thrust::device, dev_primitives, primitives_end, is_backface()); + int cur_triCount = primitives_end - dev_primitives; + } + + + + + + + + //rasterization + dim3 blockSize_Rasterize(64); + dim3 blockCount_tri((triCount + blockSize_Rasterize.x - 1) / blockSize_Rasterize.x); + + cudaDeviceSynchronize(); + + if (geomMode == GEOM_VERTEX) + { + //dim3 bs(128); + //dim3 bn((vertCount + bs.x - 1) / bs.x); + kernVertexRasterize << > >(cur_triCount, width, height, dev_primitives, dev_depthbuffer, dev_depth); + } + else + { + kernScanLineForOneTriangle << > >(cur_triCount, width, height, dev_primitives, dev_depthbuffer, dev_depth, geomMode); + } + + + + + //fragment shader + //fragmentShader << > >(width, height, dev_depthbuffer, dev_fragments); + + // Copy depthbuffer colors into framebuffer - render<<>>(width, height, dev_depthbuffer, dev_framebuffer); + cudaDeviceSynchronize(); + + render << > >(width, height, + dev_depthbuffer, dev_framebuffer, + dev_lights, lightsCount, shaderMode + , hasTexture, hasDiffuseTex, hasSpecularTex + , diffuse_width,diffuse_height,specular_width,specular_height + , dev_diffuse_texture_data, dev_specular_texture_data + , materialAmbient, materialDiffuse, materialSpecular, materialNs); + // Copy framebuffer into OpenGL buffer for OpenGL previewing + cudaDeviceSynchronize(); sendImageToPBO<<>>(pbo, width, height, dev_framebuffer); + cudaDeviceSynchronize(); checkCUDAError("rasterize"); } + + /** * Called once at the end of the program to free CUDA memory. */ @@ -156,8 +1402,28 @@ void rasterizeFree() { cudaFree(dev_depthbuffer); dev_depthbuffer = NULL; + //cudaFree(dev_fragments); + //dev_fragments = NULL; + + cudaFree(dev_depth); + dev_depth = NULL; + cudaFree(dev_framebuffer); dev_framebuffer = NULL; + + cudaFree(dev_lights); + dev_lights = NULL; + + + cudaFree(dev_diffuse_texture_data); + dev_diffuse_texture_data = NULL; + + cudaFree(dev_specular_texture_data); + dev_specular_texture_data = NULL; + + + + checkCUDAError("rasterizeFree"); } diff --git a/src/rasterize.h b/src/rasterize.h index a06b339..d593a77 100644 --- a/src/rasterize.h +++ b/src/rasterize.h @@ -10,9 +10,66 @@ #include +#define NUM_LIGHTS (2) + +enum ShaderMode +{ + SHADER_NORMAL = 0, + SHADER_WHITE_MATERIAL, + SHADER_TEXTURE +}; + +enum GeomMode +{ + GEOM_COMPLETE = 0, + GEOM_WIREFRAME, + GEOM_VERTEX +}; + + + +enum LightType +{ + POINT_LIGHT = 0, + DIRECTION_LIGHT +}; + + +struct Light +{ + LightType type; + + //glm::vec3 ambient; + //glm::vec3 diffuse; + //glm::vec3 specular; + glm::vec3 intensity; + + //Point light + glm::vec3 vec; + + bool enabled; +}; + + + + + void rasterizeInit(int width, int height); void rasterizeSetBuffers( int bufIdxSize, int *bufIdx, - int vertCount, float *bufPos, float *bufNor, float *bufCol); -void rasterize(uchar4 *pbo); + int vertCount, int _faceCount, float *bufPos, float *bufNor, float *bufCol, bool useTexture, float *bufUV); + +//texture init +void initTextureData(bool has_diffuse_tex, int d_w, int d_h, glm::vec3 * diffuse_tex, + bool has_specular_tex, int s_w, int s_h, glm::vec3 * specular_tex, + const glm::vec3 & ambient, const glm::vec3 & diffuse, const glm::vec3 & specular, float Ns); + + +void vertexShader(const glm::mat4 & M, const glm::mat4 & M_model_view, const glm::mat4 & inv_trans_M); +void rasterize(uchar4 * pbo); void rasterizeFree(); + + +void changeShaderMode(); +void changeGeomMode(); +void changeBackFaceCulling(); \ No newline at end of file diff --git a/src/rasterizeTools.h b/src/rasterizeTools.h index 46c701e..dc4997c 100644 --- a/src/rasterizeTools.h +++ b/src/rasterizeTools.h @@ -12,6 +12,8 @@ #include #include +#include + struct AABB { glm::vec3 min; glm::vec3 max; diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index afa80f3..da1b3b1 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -8,6 +8,8 @@ set(SOURCE_FILES "obj.cpp" "objloader.hpp" "objloader.cpp" + "lodepng.cpp" + "lodepng.h" ) cuda_add_library(util diff --git a/util/lodepng.cpp b/util/lodepng.cpp new file mode 100644 index 0000000..fbcecb5 --- /dev/null +++ b/util/lodepng.cpp @@ -0,0 +1,6150 @@ +/* +LodePNG version 20150912 + +Copyright (c) 2005-2015 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +/* +The manual and changelog are in the header file "lodepng.h" +Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. +*/ + +#include "lodepng.h" + +#include +#include + +#ifdef LODEPNG_COMPILE_CPP +#include +#endif /*LODEPNG_COMPILE_CPP*/ + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ +#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ +#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ +#endif /*_MSC_VER */ + +const char* LODEPNG_VERSION_STRING = "20150912"; + +/* +This source file is built up in the following large parts. The code sections +with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. +-Tools for C and common code for PNG and Zlib +-C Code for Zlib (huffman, deflate, ...) +-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) +-The C++ wrapper around all of the above +*/ + +/*The malloc, realloc and free functions defined here with "lodepng_" in front +of the name, so that you can easily change them to others related to your +platform if needed. Everything else in the code calls these. Pass +-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out +#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and +define them in your own project's source files without needing to change +lodepng source code. Don't forget to remove "static" if you copypaste them +from here.*/ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +static void* lodepng_malloc(size_t size) +{ + return malloc(size); +} + +static void* lodepng_realloc(void* ptr, size_t new_size) +{ + return realloc(ptr, new_size); +} + +static void lodepng_free(void* ptr) +{ + free(ptr); +} +#else /*LODEPNG_COMPILE_ALLOCATORS*/ +void* lodepng_malloc(size_t size); +void* lodepng_realloc(void* ptr, size_t new_size); +void lodepng_free(void* ptr); +#endif /*LODEPNG_COMPILE_ALLOCATORS*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // Tools for C, and common code for PNG and Zlib. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/* +Often in case of an error a value is assigned to a variable and then it breaks +out of a loop (to go to the cleanup phase of a function). This macro does that. +It makes the error handling code shorter and more readable. + +Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83); +*/ +#define CERROR_BREAK(errorvar, code)\ +{\ + errorvar = code;\ + break;\ +} + +/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ +#define ERROR_BREAK(code) CERROR_BREAK(error, code) + +/*Set error var to the error code, and return it.*/ +#define CERROR_RETURN_ERROR(errorvar, code)\ +{\ + errorvar = code;\ + return code;\ +} + +/*Try the code, if it returns error, also return the error.*/ +#define CERROR_TRY_RETURN(call)\ +{\ + unsigned error = call;\ + if(error) return error;\ +} + +/*Set error var to the error code, and return from the void function.*/ +#define CERROR_RETURN(errorvar, code)\ +{\ + errorvar = code;\ + return;\ +} + +/* +About uivector, ucvector and string: +-All of them wrap dynamic arrays or text strings in a similar way. +-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. +-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. +-They're not used in the interface, only internally in this file as static functions. +-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. +*/ + +#ifdef LODEPNG_COMPILE_ZLIB +/*dynamic vector of unsigned ints*/ +typedef struct uivector +{ + unsigned* data; + size_t size; /*size in number of unsigned longs*/ + size_t allocsize; /*allocated size in bytes*/ +} uivector; + +static void uivector_cleanup(void* p) +{ + ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; + lodepng_free(((uivector*)p)->data); + ((uivector*)p)->data = NULL; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_reserve(uivector* p, size_t allocsize) +{ + if(allocsize > p->allocsize) + { + size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); + void* data = lodepng_realloc(p->data, newsize); + if(data) + { + p->allocsize = newsize; + p->data = (unsigned*)data; + } + else return 0; /*error: not enough memory*/ + } + return 1; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_resize(uivector* p, size_t size) +{ + if(!uivector_reserve(p, size * sizeof(unsigned))) return 0; + p->size = size; + return 1; /*success*/ +} + +/*resize and give all new elements the value*/ +static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) +{ + size_t oldsize = p->size, i; + if(!uivector_resize(p, size)) return 0; + for(i = oldsize; i < size; ++i) p->data[i] = value; + return 1; +} + +static void uivector_init(uivector* p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} + +#ifdef LODEPNG_COMPILE_ENCODER +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_push_back(uivector* p, unsigned c) +{ + if(!uivector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* /////////////////////////////////////////////////////////////////////////// */ + +/*dynamic vector of unsigned chars*/ +typedef struct ucvector +{ + unsigned char* data; + size_t size; /*used size*/ + size_t allocsize; /*allocated size*/ +} ucvector; + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_reserve(ucvector* p, size_t allocsize) +{ + if(allocsize > p->allocsize) + { + size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); + void* data = lodepng_realloc(p->data, newsize); + if(data) + { + p->allocsize = newsize; + p->data = (unsigned char*)data; + } + else return 0; /*error: not enough memory*/ + } + return 1; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_resize(ucvector* p, size_t size) +{ + if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0; + p->size = size; + return 1; /*success*/ +} + +#ifdef LODEPNG_COMPILE_PNG + +static void ucvector_cleanup(void* p) +{ + ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; + lodepng_free(((ucvector*)p)->data); + ((ucvector*)p)->data = NULL; +} + +static void ucvector_init(ucvector* p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} + +#ifdef LODEPNG_COMPILE_DECODER +/*resize and give all new elements the value*/ +static unsigned ucvector_resizev(ucvector* p, size_t size, unsigned char value) +{ + size_t oldsize = p->size, i; + if(!ucvector_resize(p, size)) return 0; + for(i = oldsize; i < size; ++i) p->data[i] = value; + return 1; +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ZLIB +/*you can both convert from vector to buffer&size and vica versa. If you use +init_buffer to take over a buffer and size, it is not needed to use cleanup*/ +static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) +{ + p->data = buffer; + p->allocsize = p->size = size; +} +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER) +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_push_back(ucvector* p, unsigned char c) +{ + if(!ucvector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned string_resize(char** out, size_t size) +{ + char* data = (char*)lodepng_realloc(*out, size + 1); + if(data) + { + data[size] = 0; /*null termination char*/ + *out = data; + } + return data != 0; +} + +/*init a {char*, size_t} pair for use as string*/ +static void string_init(char** out) +{ + *out = NULL; + string_resize(out, 0); +} + +/*free the above pair again*/ +static void string_cleanup(char** out) +{ + lodepng_free(*out); + *out = NULL; +} + +static void string_set(char** out, const char* in) +{ + size_t insize = strlen(in), i; + if(string_resize(out, insize)) + { + for(i = 0; i != insize; ++i) + { + (*out)[i] = in[i]; + } + } +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_read32bitInt(const unsigned char* buffer) +{ + return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); +} + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) +/*buffer must have at least 4 allocated bytes available*/ +static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) +{ + buffer[0] = (unsigned char)((value >> 24) & 0xff); + buffer[1] = (unsigned char)((value >> 16) & 0xff); + buffer[2] = (unsigned char)((value >> 8) & 0xff); + buffer[3] = (unsigned char)((value ) & 0xff); +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + +#ifdef LODEPNG_COMPILE_ENCODER +static void lodepng_add32bitInt(ucvector* buffer, unsigned value) +{ + ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/ + lodepng_set32bitInt(&buffer->data[buffer->size - 4], value); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / File IO / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DISK + +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) +{ + FILE* file; + long size; + + /*provide some proper output values if error will happen*/ + *out = 0; + *outsize = 0; + + file = fopen(filename, "rb"); + if(!file) return 78; + + /*get filesize:*/ + fseek(file , 0 , SEEK_END); + size = ftell(file); + rewind(file); + + /*read contents of the file into the vector*/ + *outsize = 0; + *out = (unsigned char*)lodepng_malloc((size_t)size); + if(size && (*out)) (*outsize) = fread(*out, 1, (size_t)size, file); + + fclose(file); + if(!(*out) && size) return 83; /*the above malloc failed*/ + return 0; +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) +{ + FILE* file; + file = fopen(filename, "wb" ); + if(!file) return 79; + fwrite((char*)buffer , 1 , buffersize, file); + fclose(file); + return 0; +} + +#endif /*LODEPNG_COMPILE_DISK*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of common code and tools. Begin of Zlib related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER +/*TODO: this ignores potential out of memory errors*/ +#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\ +{\ + /*add a new byte at the end*/\ + if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\ + /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\ + (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\ + ++(*bitpointer);\ +} + +static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) +{ + size_t i; + for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); +} + +static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) +{ + size_t i; + for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1) + +static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) +{ + unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream)); + ++(*bitpointer); + return result; +} + +static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) +{ + unsigned result = 0, i; + for(i = 0; i != nbits; ++i) + { + result += ((unsigned)READBIT(*bitpointer, bitstream)) << i; + ++(*bitpointer); + } + return result; +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflate - Huffman / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#define FIRST_LENGTH_CODE_INDEX 257 +#define LAST_LENGTH_CODE_INDEX 285 +/*256 literals, the end code, some length codes, and 2 unused codes*/ +#define NUM_DEFLATE_CODE_SYMBOLS 288 +/*the distance codes have their own symbols, 30 used, 2 unused*/ +#define NUM_DISTANCE_SYMBOLS 32 +/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ +#define NUM_CODE_LENGTH_CODES 19 + +/*the base lengths represented by codes 257-285*/ +static const unsigned LENGTHBASE[29] + = {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}; + +/*the extra bits used by codes 257-285 (added to base length)*/ +static const unsigned LENGTHEXTRA[29] + = {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}; + +/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ +static const unsigned DISTANCEBASE[30] + = {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}; + +/*the extra bits of backwards distances (added to base)*/ +static const unsigned DISTANCEEXTRA[30] + = {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}; + +/*the order in which "code length alphabet code lengths" are stored, out of this +the huffman tree of the dynamic huffman tree lengths is generated*/ +static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] + = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* +Huffman tree struct, containing multiple representations of the tree +*/ +typedef struct HuffmanTree +{ + unsigned* tree2d; + unsigned* tree1d; + unsigned* lengths; /*the lengths of the codes of the 1d-tree*/ + unsigned maxbitlen; /*maximum number of bits a single code can get*/ + unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ +} HuffmanTree; + +/*function used for debug purposes to draw the tree in ascii art with C++*/ +/* +static void HuffmanTree_draw(HuffmanTree* tree) +{ + std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; + for(size_t i = 0; i != tree->tree1d.size; ++i) + { + if(tree->lengths.data[i]) + std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; + } + std::cout << std::endl; +}*/ + +static void HuffmanTree_init(HuffmanTree* tree) +{ + tree->tree2d = 0; + tree->tree1d = 0; + tree->lengths = 0; +} + +static void HuffmanTree_cleanup(HuffmanTree* tree) +{ + lodepng_free(tree->tree2d); + lodepng_free(tree->tree1d); + lodepng_free(tree->lengths); +} + +/*the tree representation used by the decoder. return value is error*/ +static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) +{ + unsigned nodefilled = 0; /*up to which node it is filled*/ + unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ + unsigned n, i; + + tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned)); + if(!tree->tree2d) return 83; /*alloc fail*/ + + /* + convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means + uninited, a value >= numcodes is an address to another bit, a value < numcodes + is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as + many columns as codes - 1. + A good huffmann tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. + Here, the internal nodes are stored (what their 0 and 1 option point to). + There is only memory for such good tree currently, if there are more nodes + (due to too long length codes), error 55 will happen + */ + for(n = 0; n < tree->numcodes * 2; ++n) + { + tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ + } + + for(n = 0; n < tree->numcodes; ++n) /*the codes*/ + { + for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/ + { + unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1); + /*oversubscribed, see comment in lodepng_error_text*/ + if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55; + if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/ + { + if(i + 1 == tree->lengths[n]) /*last bit*/ + { + tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/ + treepos = 0; + } + else + { + /*put address of the next step in here, first that address has to be found of course + (it's just nodefilled + 1)...*/ + ++nodefilled; + /*addresses encoded with numcodes added to it*/ + tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes; + treepos = nodefilled; + } + } + else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes; + } + } + + for(n = 0; n < tree->numcodes * 2; ++n) + { + if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/ + } + + return 0; +} + +/* +Second step for the ...makeFromLengths and ...makeFromFrequencies functions. +numcodes, lengths and maxbitlen must already be filled in correctly. return +value is error. +*/ +static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) +{ + uivector blcount; + uivector nextcode; + unsigned error = 0; + unsigned bits, n; + + uivector_init(&blcount); + uivector_init(&nextcode); + + tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); + if(!tree->tree1d) error = 83; /*alloc fail*/ + + if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0) + || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) + error = 83; /*alloc fail*/ + + if(!error) + { + /*step 1: count number of instances of each code length*/ + for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]]; + /*step 2: generate the nextcode values*/ + for(bits = 1; bits <= tree->maxbitlen; ++bits) + { + nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; + } + /*step 3: generate all the codes*/ + for(n = 0; n != tree->numcodes; ++n) + { + if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++; + } + } + + uivector_cleanup(&blcount); + uivector_cleanup(&nextcode); + + if(!error) return HuffmanTree_make2DTree(tree); + else return error; +} + +/* +given the code lengths (as stored in the PNG file), generate the tree as defined +by Deflate. maxbitlen is the maximum bits that a code in the tree can have. +return value is error. +*/ +static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, + size_t numcodes, unsigned maxbitlen) +{ + unsigned i; + tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->maxbitlen = maxbitlen; + return HuffmanTree_makeFromLengths2(tree); +} + +#ifdef LODEPNG_COMPILE_ENCODER + +/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", +Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ + +/*chain node for boundary package merge*/ +typedef struct BPMNode +{ + int weight; /*the sum of all weights in this chain*/ + unsigned index; /*index of this leaf node (called "count" in the paper)*/ + struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ + int in_use; +} BPMNode; + +/*lists of chains*/ +typedef struct BPMLists +{ + /*memory pool*/ + unsigned memsize; + BPMNode* memory; + unsigned numfree; + unsigned nextfree; + BPMNode** freelist; + /*two heads of lookahead chains per list*/ + unsigned listsize; + BPMNode** chains0; + BPMNode** chains1; +} BPMLists; + +/*creates a new chain node with the given parameters, from the memory in the lists */ +static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) +{ + unsigned i; + BPMNode* result; + + /*memory full, so garbage collect*/ + if(lists->nextfree >= lists->numfree) + { + /*mark only those that are in use*/ + for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; + for(i = 0; i != lists->listsize; ++i) + { + BPMNode* node; + for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; + for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; + } + /*collect those that are free*/ + lists->numfree = 0; + for(i = 0; i != lists->memsize; ++i) + { + if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; + } + lists->nextfree = 0; + } + + result = lists->freelist[lists->nextfree++]; + result->weight = weight; + result->index = index; + result->tail = tail; + return result; +} + +static int bpmnode_compare(const void* a, const void* b) +{ + int wa = ((const BPMNode*)a)->weight; + int wb = ((const BPMNode*)b)->weight; + if(wa < wb) return -1; + if(wa > wb) return 1; + /*make the qsort a stable sort*/ + return ((const BPMNode*)a)->index < ((const BPMNode*)b)->index ? 1 : -1; +} + +/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ +static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) +{ + unsigned lastindex = lists->chains1[c]->index; + + if(c == 0) + { + if(lastindex >= numpresent) return; + lists->chains0[c] = lists->chains1[c]; + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); + } + else + { + /*sum of the weights of the head nodes of the previous lookahead chains.*/ + int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; + lists->chains0[c] = lists->chains1[c]; + if(lastindex < numpresent && sum > leaves[lastindex].weight) + { + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); + return; + } + lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); + /*in the end we are only interested in the chain of the last list, so no + need to recurse if we're at the last one (this gives measurable speedup)*/ + if(num + 1 < (int)(2 * numpresent - 2)) + { + boundaryPM(lists, leaves, numpresent, c - 1, num); + boundaryPM(lists, leaves, numpresent, c - 1, num); + } + } +} + +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen) +{ + unsigned error = 0; + unsigned i; + size_t numpresent = 0; /*number of symbols with non-zero frequency*/ + BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ + + if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ + if((1u << maxbitlen) < numcodes) return 80; /*error: represent all symbols*/ + + leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); + if(!leaves) return 83; /*alloc fail*/ + + for(i = 0; i != numcodes; ++i) + { + if(frequencies[i] > 0) + { + leaves[numpresent].weight = frequencies[i]; + leaves[numpresent].index = i; + ++numpresent; + } + } + + for(i = 0; i != numcodes; ++i) lengths[i] = 0; + + /*ensure at least two present symbols. There should be at least one symbol + according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To + make these work as well ensure there are at least two symbols. The + Package-Merge code below also doesn't work correctly if there's only one + symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/ + if(numpresent == 0) + { + lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ + } + else if(numpresent == 1) + { + lengths[leaves[0].index] = 1; + lengths[leaves[0].index == 0 ? 1 : 0] = 1; + } + else + { + BPMLists lists; + BPMNode* node; + + qsort(leaves, numpresent, sizeof(BPMNode), bpmnode_compare); + + lists.listsize = maxbitlen; + lists.memsize = 2 * maxbitlen * (maxbitlen + 1); + lists.nextfree = 0; + lists.numfree = lists.memsize; + lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); + lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); + lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ + + if(!error) + { + for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; + + bpmnode_create(&lists, leaves[0].weight, 1, 0); + bpmnode_create(&lists, leaves[1].weight, 2, 0); + + for(i = 0; i != lists.listsize; ++i) + { + lists.chains0[i] = &lists.memory[0]; + lists.chains1[i] = &lists.memory[1]; + } + + /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ + for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, maxbitlen - 1, i); + + for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) + { + for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; + } + } + + lodepng_free(lists.memory); + lodepng_free(lists.freelist); + lodepng_free(lists.chains0); + lodepng_free(lists.chains1); + } + + lodepng_free(leaves); + return error; +} + +/*Create the Huffman tree given the symbol frequencies*/ +static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, + size_t mincodes, size_t numcodes, unsigned maxbitlen) +{ + unsigned error = 0; + while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ + tree->maxbitlen = maxbitlen; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + /*initialize all lengths to 0*/ + memset(tree->lengths, 0, numcodes * sizeof(unsigned)); + + error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); + if(!error) error = HuffmanTree_makeFromLengths2(tree); + return error; +} + +static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) +{ + return tree->tree1d[index]; +} + +static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) +{ + return tree->lengths[index]; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ +static unsigned generateFixedLitLenTree(HuffmanTree* tree) +{ + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ + for(i = 0; i <= 143; ++i) bitlen[i] = 8; + for(i = 144; i <= 255; ++i) bitlen[i] = 9; + for(i = 256; i <= 279; ++i) bitlen[i] = 7; + for(i = 280; i <= 287; ++i) bitlen[i] = 8; + + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static unsigned generateFixedDistanceTree(HuffmanTree* tree) +{ + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*there are 32 distance codes, but 30-31 are unused*/ + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* +returns the code, or (unsigned)(-1) if error happened +inbitlength is the length of the complete buffer, in bits (so its byte length times 8) +*/ +static unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp, + const HuffmanTree* codetree, size_t inbitlength) +{ + unsigned treepos = 0, ct; + for(;;) + { + if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/ + /* + decode the symbol from the tree. The "readBitFromStream" code is inlined in + the expression below because this is the biggest bottleneck while decoding + */ + ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)]; + ++(*bp); + if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/ + else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/ + + if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/ + } +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Inflator (Decompressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) +{ + /*TODO: check for out of memory errors*/ + generateFixedLitLenTree(tree_ll); + generateFixedDistanceTree(tree_d); +} + +/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ +static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, + const unsigned char* in, size_t* bp, size_t inlength) +{ + /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ + unsigned error = 0; + unsigned n, HLIT, HDIST, HCLEN, i; + size_t inbitlength = inlength * 8; + + /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ + unsigned* bitlen_ll = 0; /*lit,len code lengths*/ + unsigned* bitlen_d = 0; /*dist code lengths*/ + /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ + unsigned* bitlen_cl = 0; + HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ + + if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/ + + /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ + HLIT = readBitsFromStream(bp, in, 5) + 257; + /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ + HDIST = readBitsFromStream(bp, in, 5) + 1; + /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ + HCLEN = readBitsFromStream(bp, in, 4) + 4; + + if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/ + + HuffmanTree_init(&tree_cl); + + while(!error) + { + /*read the code length codes out of 3 * (amount of code length codes) bits*/ + + bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); + if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/); + + for(i = 0; i != NUM_CODE_LENGTH_CODES; ++i) + { + if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3); + else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/ + } + + error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*now we can use this tree to read the lengths for the tree that this function will return*/ + bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); + for(i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0; + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0; + + /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ + i = 0; + while(i < HLIT + HDIST) + { + unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength); + if(code <= 15) /*a length code*/ + { + if(i < HLIT) bitlen_ll[i] = code; + else bitlen_d[i - HLIT] = code; + ++i; + } + else if(code == 16) /*repeat previous*/ + { + unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ + unsigned value; /*set value to the previous code*/ + + if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ + + if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + replength += readBitsFromStream(bp, in, 2); + + if(i < HLIT + 1) value = bitlen_ll[i - 1]; + else value = bitlen_d[i - HLIT - 1]; + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) + { + if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ + if(i < HLIT) bitlen_ll[i] = value; + else bitlen_d[i - HLIT] = value; + ++i; + } + } + else if(code == 17) /*repeat "0" 3-10 times*/ + { + unsigned replength = 3; /*read in the bits that indicate repeat length*/ + if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + replength += readBitsFromStream(bp, in, 3); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) + { + if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } + else if(code == 18) /*repeat "0" 11-138 times*/ + { + unsigned replength = 11; /*read in the bits that indicate repeat length*/ + if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + replength += readBitsFromStream(bp, in, 7); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) + { + if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } + else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ + { + if(code == (unsigned)(-1)) + { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + error = (*bp) > inbitlength ? 10 : 11; + } + else error = 16; /*unexisting code, this can never happen*/ + break; + } + } + if(error) break; + + if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ + + /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ + error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); + if(error) break; + error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); + + break; /*end of error-while*/ + } + + lodepng_free(bitlen_cl); + lodepng_free(bitlen_ll); + lodepng_free(bitlen_d); + HuffmanTree_cleanup(&tree_cl); + + return error; +} + +/*inflate a block with dynamic of fixed Huffman tree*/ +static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp, + size_t* pos, size_t inlength, unsigned btype) +{ + unsigned error = 0; + HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ + HuffmanTree tree_d; /*the huffman tree for distance codes*/ + size_t inbitlength = inlength * 8; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d); + else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength); + + while(!error) /*decode all symbols until end reached, breaks at end code*/ + { + /*code_ll is literal, length or end code*/ + unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength); + if(code_ll <= 255) /*literal symbol*/ + { + /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/ + if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/); + out->data[*pos] = (unsigned char)code_ll; + ++(*pos); + } + else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ + { + unsigned code_d, distance; + unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ + size_t start, forward, backward, length; + + /*part 1: get length base*/ + length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; + + /*part 2: get extra bits and add the value of that to length*/ + numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; + if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ + length += readBitsFromStream(bp, in, numextrabits_l); + + /*part 3: get distance code*/ + code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength); + if(code_d > 29) + { + if(code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ + { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + error = (*bp) > inlength * 8 ? 10 : 11; + } + else error = 18; /*error: invalid distance code (30-31 are never used)*/ + break; + } + distance = DISTANCEBASE[code_d]; + + /*part 4: get extra bits from distance*/ + numextrabits_d = DISTANCEEXTRA[code_d]; + if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ + distance += readBitsFromStream(bp, in, numextrabits_d); + + /*part 5: fill in all the out[n] values based on the length and dist*/ + start = (*pos); + if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ + backward = start - distance; + + if(!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/); + if (distance < length) { + for(forward = 0; forward < length; ++forward) + { + out->data[(*pos)++] = out->data[backward++]; + } + } else { + memcpy(out->data + *pos, out->data + backward, length); + *pos += length; + } + } + else if(code_ll == 256) + { + break; /*end code, break the loop*/ + } + else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ + { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + error = ((*bp) > inlength * 8) ? 10 : 11; + break; + } + } + + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) +{ + size_t p; + unsigned LEN, NLEN, n, error = 0; + + /*go to first boundary of byte*/ + while(((*bp) & 0x7) != 0) ++(*bp); + p = (*bp) / 8; /*byte position*/ + + /*read LEN (2 bytes) and NLEN (2 bytes)*/ + if(p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/ + LEN = in[p] + 256u * in[p + 1]; p += 2; + NLEN = in[p] + 256u * in[p + 1]; p += 2; + + /*check if 16-bit NLEN is really the one's complement of LEN*/ + if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/ + + if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/ + + /*read the literal data: LEN bytes are now stored in the out buffer*/ + if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/ + for(n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++]; + + (*bp) = p * 8; + + return error; +} + +static unsigned lodepng_inflatev(ucvector* out, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) +{ + /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/ + size_t bp = 0; + unsigned BFINAL = 0; + size_t pos = 0; /*byte position in the out buffer*/ + unsigned error = 0; + + (void)settings; + + while(!BFINAL) + { + unsigned BTYPE; + if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/ + BFINAL = readBitFromStream(&bp, in); + BTYPE = 1u * readBitFromStream(&bp, in); + BTYPE += 2u * readBitFromStream(&bp, in); + + if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ + else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/ + else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/ + + if(error) return error; + } + + return error; +} + +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) +{ + unsigned error; + ucvector v; + ucvector_init_buffer(&v, *out, *outsize); + error = lodepng_inflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) +{ + if(settings->custom_inflate) + { + return settings->custom_inflate(out, outsize, in, insize, settings); + } + else + { + return lodepng_inflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflator (Compressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; + +/*bitlen is the size in bits of the code*/ +static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) +{ + addBitsToStreamReversed(bp, compressed, code, bitlen); +} + +/*search the index in the array, that has the largest value smaller than or equal to the given value, +given array must be sorted (if no value is smaller, it returns the size of the given array)*/ +static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) +{ + /*linear search implementation*/ + /*for(size_t i = 1; i < array_size; ++i) if(array[i] > value) return i - 1; + return array_size - 1;*/ + + /*binary search implementation (not that much faster) (precondition: array_size > 0)*/ + size_t left = 1; + size_t right = array_size - 1; + while(left <= right) + { + size_t mid = (left + right) / 2; + if(array[mid] <= value) left = mid + 1; /*the value to find is more to the right*/ + else if(array[mid - 1] > value) right = mid - 1; /*the value to find is more to the left*/ + else return mid - 1; + } + return array_size - 1; +} + +static void addLengthDistance(uivector* values, size_t length, size_t distance) +{ + /*values in encoded vector are those used by deflate: + 0-255: literal bytes + 256: end + 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) + 286-287: invalid*/ + + unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); + unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); + unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); + unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); + + uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX); + uivector_push_back(values, extra_length); + uivector_push_back(values, dist_code); + uivector_push_back(values, extra_distance); +} + +/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 +bytes as input because 3 is the minimum match length for deflate*/ +static const unsigned HASH_NUM_VALUES = 65536; +static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ + +typedef struct Hash +{ + int* head; /*hash value to head circular pos - can be outdated if went around window*/ + /*circular pos to prev circular pos*/ + unsigned short* chain; + int* val; /*circular pos to hash value*/ + + /*TODO: do this not only for zeros but for any repeated byte. However for PNG + it's always going to be the zeros that dominate, so not important for PNG*/ + int* headz; /*similar to head, but for chainz*/ + unsigned short* chainz; /*those with same amount of zeros*/ + unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ +} Hash; + +static unsigned hash_init(Hash* hash, unsigned windowsize) +{ + unsigned i; + hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); + hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); + hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); + hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) + { + return 83; /*alloc fail*/ + } + + /*initialize hash table*/ + for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; + for(i = 0; i != windowsize; ++i) hash->val[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ + + for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ + + return 0; +} + +static void hash_cleanup(Hash* hash) +{ + lodepng_free(hash->head); + lodepng_free(hash->val); + lodepng_free(hash->chain); + + lodepng_free(hash->zeros); + lodepng_free(hash->headz); + lodepng_free(hash->chainz); +} + + + +static unsigned getHash(const unsigned char* data, size_t size, size_t pos) +{ + unsigned result = 0; + if(pos + 2 < size) + { + /*A simple shift and xor hash is used. Since the data of PNGs is dominated + by zeroes due to the filters, a better hash does not have a significant + effect on speed in traversing the chain, and causes more time spend on + calculating the hash.*/ + result ^= (unsigned)(data[pos + 0] << 0u); + result ^= (unsigned)(data[pos + 1] << 4u); + result ^= (unsigned)(data[pos + 2] << 8u); + } else { + size_t amount, i; + if(pos >= size) return 0; + amount = size - pos; + for(i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u)); + } + return result & HASH_BIT_MASK; +} + +static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) +{ + const unsigned char* start = data + pos; + const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; + if(end > data + size) end = data + size; + data = start; + while(data != end && *data == 0) ++data; + /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ + return (unsigned)(data - start); +} + +/*wpos = pos & (windowsize - 1)*/ +static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) +{ + hash->val[wpos] = (int)hashval; + if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; + hash->head[hashval] = wpos; + + hash->zeros[wpos] = numzeros; + if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; + hash->headz[numzeros] = wpos; +} + +/* +LZ77-encode the data. Return value is error code. The input are raw bytes, the output +is in the form of unsigned integers with codes representing for example literal bytes, or +length/distance pairs. +It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a +sliding window (of windowsize) is used, and all past bytes in that window can be used as +the "dictionary". A brute force search through all possible distances would be slow, and +this hash technique is one out of several ways to speed this up. +*/ +static unsigned encodeLZ77(uivector* out, Hash* hash, + const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, + unsigned minmatch, unsigned nicematch, unsigned lazymatching) +{ + size_t pos; + unsigned i, error = 0; + /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ + unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8; + unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; + + unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ + unsigned numzeros = 0; + + unsigned offset; /*the offset represents the distance in LZ77 terminology*/ + unsigned length; + unsigned lazy = 0; + unsigned lazylength = 0, lazyoffset = 0; + unsigned hashval; + unsigned current_offset, current_length; + unsigned prev_offset; + const unsigned char *lastptr, *foreptr, *backptr; + unsigned hashpos; + + if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ + if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ + + if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; + + for(pos = inpos; pos < insize; ++pos) + { + size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ + unsigned chainlength = 0; + + hashval = getHash(in, insize, pos); + + if(usezeros && hashval == 0) + { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } + else + { + numzeros = 0; + } + + updateHashChain(hash, wpos, hashval, numzeros); + + /*the length and offset found for the current position*/ + length = 0; + offset = 0; + + hashpos = hash->chain[wpos]; + + lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; + + /*search for the longest string*/ + prev_offset = 0; + for(;;) + { + if(chainlength++ >= maxchainlength) break; + current_offset = hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize; + + if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ + prev_offset = current_offset; + if(current_offset > 0) + { + /*test the next characters*/ + foreptr = &in[pos]; + backptr = &in[pos - current_offset]; + + /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ + if(numzeros >= 3) + { + unsigned skip = hash->zeros[hashpos]; + if(skip > numzeros) skip = numzeros; + backptr += skip; + foreptr += skip; + } + + while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ + { + ++backptr; + ++foreptr; + } + current_length = (unsigned)(foreptr - &in[pos]); + + if(current_length > length) + { + length = current_length; /*the longest length*/ + offset = current_offset; /*the offset that is related to this longest length*/ + /*jump out once a length of max length is found (speed gain). This also jumps + out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ + if(current_length >= nicematch) break; + } + } + + if(hashpos == hash->chain[hashpos]) break; + + if(numzeros >= 3 && length > numzeros) + { + hashpos = hash->chainz[hashpos]; + if(hash->zeros[hashpos] != numzeros) break; + } + else + { + hashpos = hash->chain[hashpos]; + /*outdated hash value, happens if particular value was not encountered in whole last window*/ + if(hash->val[hashpos] != (int)hashval) break; + } + } + + if(lazymatching) + { + if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) + { + lazy = 1; + lazylength = length; + lazyoffset = offset; + continue; /*try the next byte*/ + } + if(lazy) + { + lazy = 0; + if(pos == 0) ERROR_BREAK(81); + if(length > lazylength + 1) + { + /*push the previous character as literal*/ + if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); + } + else + { + length = lazylength; + offset = lazyoffset; + hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ + hash->headz[numzeros] = -1; /*idem*/ + --pos; + } + } + } + if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); + + /*encode it as length/distance pair or literal value*/ + if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ + { + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } + else if(length < minmatch || (length == 3 && offset > 4096)) + { + /*compensate for the fact that longer offsets have more extra bits, a + length of only 3 may be not worth it then*/ + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } + else + { + addLengthDistance(out, length, offset); + for(i = 1; i < length; ++i) + { + ++pos; + wpos = pos & (windowsize - 1); + hashval = getHash(in, insize, pos); + if(usezeros && hashval == 0) + { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } + else + { + numzeros = 0; + } + updateHashChain(hash, wpos, hashval, numzeros); + } + } + } /*end of the loop through each character of input*/ + + return error; +} + +/* /////////////////////////////////////////////////////////////////////////// */ + +static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) +{ + /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, + 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ + + size_t i, j, numdeflateblocks = (datasize + 65534) / 65535; + unsigned datapos = 0; + for(i = 0; i != numdeflateblocks; ++i) + { + unsigned BFINAL, BTYPE, LEN, NLEN; + unsigned char firstbyte; + + BFINAL = (i == numdeflateblocks - 1); + BTYPE = 0; + + firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); + ucvector_push_back(out, firstbyte); + + LEN = 65535; + if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; + NLEN = 65535 - LEN; + + ucvector_push_back(out, (unsigned char)(LEN % 256)); + ucvector_push_back(out, (unsigned char)(LEN / 256)); + ucvector_push_back(out, (unsigned char)(NLEN % 256)); + ucvector_push_back(out, (unsigned char)(NLEN / 256)); + + /*Decompressed data*/ + for(j = 0; j < 65535 && datapos < datasize; ++j) + { + ucvector_push_back(out, data[datapos++]); + } + } + + return 0; +} + +/* +write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. +tree_ll: the tree for lit and len codes. +tree_d: the tree for distance codes. +*/ +static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded, + const HuffmanTree* tree_ll, const HuffmanTree* tree_d) +{ + size_t i = 0; + for(i = 0; i != lz77_encoded->size; ++i) + { + unsigned val = lz77_encoded->data[i]; + addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val)); + if(val > 256) /*for a length code, 3 more things have to be added*/ + { + unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; + unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; + unsigned length_extra_bits = lz77_encoded->data[++i]; + + unsigned distance_code = lz77_encoded->data[++i]; + + unsigned distance_index = distance_code; + unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; + unsigned distance_extra_bits = lz77_encoded->data[++i]; + + addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits); + addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code), + HuffmanTree_getLength(tree_d, distance_code)); + addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits); + } + } +} + +/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ +static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, + const unsigned char* data, size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) +{ + unsigned error = 0; + + /* + A block is compressed as follows: The PNG data is lz77 encoded, resulting in + literal bytes and length/distance pairs. This is then huffman compressed with + two huffman trees. One huffman tree is used for the lit and len values ("ll"), + another huffman tree is used for the dist values ("d"). These two trees are + stored using their code lengths, and to compress even more these code lengths + are also run-length encoded and huffman compressed. This gives a huffman tree + of code lengths "cl". The code lenghts used to describe this third tree are + the code length code lengths ("clcl"). + */ + + /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ + uivector lz77_encoded; + HuffmanTree tree_ll; /*tree for lit,len values*/ + HuffmanTree tree_d; /*tree for distance codes*/ + HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ + uivector frequencies_ll; /*frequency of lit,len codes*/ + uivector frequencies_d; /*frequency of dist codes*/ + uivector frequencies_cl; /*frequency of code length codes*/ + uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/ + uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/ + /*bitlen_cl is the code length code lengths ("clcl"). The bit lengths of codes to represent tree_cl + (these are written as is in the file, it would be crazy to compress these using yet another huffman + tree that needs to be represented by yet another set of code lengths)*/ + uivector bitlen_cl; + size_t datasize = dataend - datapos; + + /* + Due to the huffman compression of huffman tree representations ("two levels"), there are some anologies: + bitlen_lld is to tree_cl what data is to tree_ll and tree_d. + bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. + bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. + */ + + unsigned BFINAL = final; + size_t numcodes_ll, numcodes_d, i; + unsigned HLIT, HDIST, HCLEN; + + uivector_init(&lz77_encoded); + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + HuffmanTree_init(&tree_cl); + uivector_init(&frequencies_ll); + uivector_init(&frequencies_d); + uivector_init(&frequencies_cl); + uivector_init(&bitlen_lld); + uivector_init(&bitlen_lld_e); + uivector_init(&bitlen_cl); + + /*This while loop never loops due to a break at the end, it is here to + allow breaking out of it to the cleanup phase on error conditions.*/ + while(!error) + { + if(settings->use_lz77) + { + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(error) break; + } + else + { + if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); + for(i = datapos; i < dataend; ++i) lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/ + } + + if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/); + if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/); + + /*Count the frequencies of lit, len and dist codes*/ + for(i = 0; i != lz77_encoded.size; ++i) + { + unsigned symbol = lz77_encoded.data[i]; + ++frequencies_ll.data[symbol]; + if(symbol > 256) + { + unsigned dist = lz77_encoded.data[i + 2]; + ++frequencies_d.data[dist]; + i += 3; + } + } + frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ + + /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ + error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15); + if(error) break; + /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ + error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15); + if(error) break; + + numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286; + numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30; + /*store the code lengths of both generated trees in bitlen_lld*/ + for(i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i)); + for(i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i)); + + /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), + 17 (3-10 zeroes), 18 (11-138 zeroes)*/ + for(i = 0; i != (unsigned)bitlen_lld.size; ++i) + { + unsigned j = 0; /*amount of repititions*/ + while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j; + + if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/ + { + ++j; /*include the first zero*/ + if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ + { + uivector_push_back(&bitlen_lld_e, 17); + uivector_push_back(&bitlen_lld_e, j - 3); + } + else /*repeat code 18 supports max 138 zeroes*/ + { + if(j > 138) j = 138; + uivector_push_back(&bitlen_lld_e, 18); + uivector_push_back(&bitlen_lld_e, j - 11); + } + i += (j - 1); + } + else if(j >= 3) /*repeat code for value other than zero*/ + { + size_t k; + unsigned num = j / 6, rest = j % 6; + uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]); + for(k = 0; k < num; ++k) + { + uivector_push_back(&bitlen_lld_e, 16); + uivector_push_back(&bitlen_lld_e, 6 - 3); + } + if(rest >= 3) + { + uivector_push_back(&bitlen_lld_e, 16); + uivector_push_back(&bitlen_lld_e, rest - 3); + } + else j -= rest; + i += j; + } + else /*too short to benefit from repeat code*/ + { + uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]); + } + } + + /*generate tree_cl, the huffmantree of huffmantrees*/ + + if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/); + for(i = 0; i != bitlen_lld_e.size; ++i) + { + ++frequencies_cl.data[bitlen_lld_e.data[i]]; + /*after a repeat code come the bits that specify the number of repetitions, + those don't need to be in the frequencies_cl calculation*/ + if(bitlen_lld_e.data[i] >= 16) ++i; + } + + error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data, + frequencies_cl.size, frequencies_cl.size, 7); + if(error) break; + + if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/); + for(i = 0; i != tree_cl.numcodes; ++i) + { + /*lenghts of code length tree is in the order as specified by deflate*/ + bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]); + } + while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4) + { + /*remove zeros at the end, but minimum size must be 4*/ + if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/); + } + if(error) break; + + /* + Write everything into the output + + After the BFINAL and BTYPE, the dynamic block consists out of the following: + - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN + - (HCLEN+4)*3 bits code lengths of code length alphabet + - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - HDIST + 1 code lengths of distance alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - compressed data + - 256 (end code) + */ + + /*Write block type*/ + addBitToStream(bp, out, BFINAL); + addBitToStream(bp, out, 0); /*first bit of BTYPE "dynamic"*/ + addBitToStream(bp, out, 1); /*second bit of BTYPE "dynamic"*/ + + /*write the HLIT, HDIST and HCLEN values*/ + HLIT = (unsigned)(numcodes_ll - 257); + HDIST = (unsigned)(numcodes_d - 1); + HCLEN = (unsigned)bitlen_cl.size - 4; + /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/ + while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN; + addBitsToStream(bp, out, HLIT, 5); + addBitsToStream(bp, out, HDIST, 5); + addBitsToStream(bp, out, HCLEN, 4); + + /*write the code lenghts of the code length alphabet*/ + for(i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3); + + /*write the lenghts of the lit/len AND the dist alphabet*/ + for(i = 0; i != bitlen_lld_e.size; ++i) + { + addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]), + HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i])); + /*extra bits of repeat codes*/ + if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2); + else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3); + else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7); + } + + /*write the compressed data symbols*/ + writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d); + /*error: the length of the end code 256 must be larger than 0*/ + if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64); + + /*write the end code*/ + addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256)); + + break; /*end of error-while*/ + } + + /*cleanup*/ + uivector_cleanup(&lz77_encoded); + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + HuffmanTree_cleanup(&tree_cl); + uivector_cleanup(&frequencies_ll); + uivector_cleanup(&frequencies_d); + uivector_cleanup(&frequencies_cl); + uivector_cleanup(&bitlen_lld_e); + uivector_cleanup(&bitlen_lld); + uivector_cleanup(&bitlen_cl); + + return error; +} + +static unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash, + const unsigned char* data, + size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) +{ + HuffmanTree tree_ll; /*tree for literal values and length codes*/ + HuffmanTree tree_d; /*tree for distance codes*/ + + unsigned BFINAL = final; + unsigned error = 0; + size_t i; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + generateFixedLitLenTree(&tree_ll); + generateFixedDistanceTree(&tree_d); + + addBitToStream(bp, out, BFINAL); + addBitToStream(bp, out, 1); /*first bit of BTYPE*/ + addBitToStream(bp, out, 0); /*second bit of BTYPE*/ + + if(settings->use_lz77) /*LZ77 encoded*/ + { + uivector lz77_encoded; + uivector_init(&lz77_encoded); + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d); + uivector_cleanup(&lz77_encoded); + } + else /*no LZ77, but still will be Huffman compressed*/ + { + for(i = datapos; i < dataend; ++i) + { + addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i])); + } + } + /*add END code*/ + if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256)); + + /*cleanup*/ + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) +{ + unsigned error = 0; + size_t i, blocksize, numdeflateblocks; + size_t bp = 0; /*the bit pointer*/ + Hash hash; + + if(settings->btype > 2) return 61; + else if(settings->btype == 0) return deflateNoCompression(out, in, insize); + else if(settings->btype == 1) blocksize = insize; + else /*if(settings->btype == 2)*/ + { + /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ + blocksize = insize / 8 + 8; + if(blocksize < 65536) blocksize = 65536; + if(blocksize > 262144) blocksize = 262144; + } + + numdeflateblocks = (insize + blocksize - 1) / blocksize; + if(numdeflateblocks == 0) numdeflateblocks = 1; + + error = hash_init(&hash, settings->windowsize); + if(error) return error; + + for(i = 0; i != numdeflateblocks && !error; ++i) + { + unsigned final = (i == numdeflateblocks - 1); + size_t start = i * blocksize; + size_t end = start + blocksize; + if(end > insize) end = insize; + + if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final); + else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final); + } + + hash_cleanup(&hash); + + return error; +} + +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) +{ + unsigned error; + ucvector v; + ucvector_init_buffer(&v, *out, *outsize); + error = lodepng_deflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) +{ + if(settings->custom_deflate) + { + return settings->custom_deflate(out, outsize, in, insize, settings); + } + else + { + return lodepng_deflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Adler32 */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) +{ + unsigned s1 = adler & 0xffff; + unsigned s2 = (adler >> 16) & 0xffff; + + while(len > 0) + { + /*at least 5550 sums can be done before the sums overflow, saving a lot of module divisions*/ + unsigned amount = len > 5550 ? 5550 : len; + len -= amount; + while(amount > 0) + { + s1 += (*data++); + s2 += s1; + --amount; + } + s1 %= 65521; + s2 %= 65521; + } + + return (s2 << 16) | s1; +} + +/*Return the adler32 of the bytes data[0..len-1]*/ +static unsigned adler32(const unsigned char* data, unsigned len) +{ + return update_adler32(1L, data, len); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Zlib / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) +{ + unsigned error = 0; + unsigned CM, CINFO, FDICT; + + if(insize < 2) return 53; /*error, size of zlib data too small*/ + /*read information from zlib header*/ + if((in[0] * 256 + in[1]) % 31 != 0) + { + /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ + return 24; + } + + CM = in[0] & 15; + CINFO = (in[0] >> 4) & 15; + /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ + FDICT = (in[1] >> 5) & 1; + /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ + + if(CM != 8 || CINFO > 7) + { + /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ + return 25; + } + if(FDICT != 0) + { + /*error: the specification of PNG says about the zlib stream: + "The additional flags shall not specify a preset dictionary."*/ + return 26; + } + + error = inflate(out, outsize, in + 2, insize - 2, settings); + if(error) return error; + + if(!settings->ignore_adler32) + { + unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); + unsigned checksum = adler32(*out, (unsigned)(*outsize)); + if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ + } + + return 0; /*no error*/ +} + +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) +{ + if(settings->custom_zlib) + { + return settings->custom_zlib(out, outsize, in, insize, settings); + } + else + { + return lodepng_zlib_decompress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) +{ + /*initially, *out must be NULL and outsize 0, if you just give some random *out + that's pointing to a non allocated buffer, this'll crash*/ + ucvector outv; + size_t i; + unsigned error; + unsigned char* deflatedata = 0; + size_t deflatesize = 0; + + /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ + unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ + unsigned FLEVEL = 0; + unsigned FDICT = 0; + unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; + unsigned FCHECK = 31 - CMFFLG % 31; + CMFFLG += FCHECK; + + /*ucvector-controlled version of the output buffer, for dynamic array*/ + ucvector_init_buffer(&outv, *out, *outsize); + + ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256)); + ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256)); + + error = deflate(&deflatedata, &deflatesize, in, insize, settings); + + if(!error) + { + unsigned ADLER32 = adler32(in, (unsigned)insize); + for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]); + lodepng_free(deflatedata); + lodepng_add32bitInt(&outv, ADLER32); + } + + *out = outv.data; + *outsize = outv.size; + + return error; +} + +/* compress using the default or custom zlib function */ +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) +{ + if(settings->custom_zlib) + { + return settings->custom_zlib(out, outsize, in, insize, settings); + } + else + { + return lodepng_zlib_compress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#else /*no LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DECODER +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) +{ + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) +{ + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/*this is a good tradeoff between speed and compression ratio*/ +#define DEFAULT_WINDOWSIZE 2048 + +void lodepng_compress_settings_init(LodePNGCompressSettings* settings) +{ + /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ + settings->btype = 2; + settings->use_lz77 = 1; + settings->windowsize = DEFAULT_WINDOWSIZE; + settings->minmatch = 3; + settings->nicematch = 128; + settings->lazymatching = 1; + + settings->custom_zlib = 0; + settings->custom_deflate = 0; + settings->custom_context = 0; +} + +const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; + + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) +{ + settings->ignore_adler32 = 0; + + settings->custom_zlib = 0; + settings->custom_inflate = 0; + settings->custom_context = 0; +} + +const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0}; + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of Zlib related code. Begin of PNG related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / CRC32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +#ifndef LODEPNG_NO_COMPILE_CRC +/* CRC polynomial: 0xedb88320 */ +static unsigned lodepng_crc32_table[256] = { + 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, + 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, + 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, + 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, + 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, + 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, + 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, + 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, + 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, + 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, + 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, + 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, + 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, + 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, + 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, + 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, + 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, + 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, + 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, + 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, + 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, + 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, + 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, + 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, + 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, + 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, + 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, + 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, + 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, + 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, + 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, + 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u +}; + +/*Return the CRC of the bytes buf[0..len-1].*/ +unsigned lodepng_crc32(const unsigned char* buf, size_t len) +{ + unsigned c = 0xffffffffL; + size_t n; + + for(n = 0; n < len; ++n) + { + c = lodepng_crc32_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c ^ 0xffffffffL; +} +#endif /* !LODEPNG_NO_COMPILE_CRC */ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Reading and writing single bits and bytes from/to stream for LodePNG / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) +{ + unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); + ++(*bitpointer); + return result; +} + +static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) +{ + unsigned result = 0; + size_t i; + for(i = nbits - 1; i < nbits; --i) + { + result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i; + } + return result; +} + +#ifdef LODEPNG_COMPILE_DECODER +static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) +{ + /*the current bit in bitstream must be 0 for this to work*/ + if(bit) + { + /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ + bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); + } + ++(*bitpointer); +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) +{ + /*the current bit in bitstream may be 0 or 1 for this to work*/ + if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7)))); + else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7))); + ++(*bitpointer); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG chunks / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_chunk_length(const unsigned char* chunk) +{ + return lodepng_read32bitInt(&chunk[0]); +} + +void lodepng_chunk_type(char type[5], const unsigned char* chunk) +{ + unsigned i; + for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; + type[4] = 0; /*null termination char*/ +} + +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) +{ + if(strlen(type) != 4) return 0; + return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); +} + +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) +{ + return((chunk[4] & 32) != 0); +} + +unsigned char lodepng_chunk_private(const unsigned char* chunk) +{ + return((chunk[6] & 32) != 0); +} + +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) +{ + return((chunk[7] & 32) != 0); +} + +unsigned char* lodepng_chunk_data(unsigned char* chunk) +{ + return &chunk[8]; +} + +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) +{ + return &chunk[8]; +} + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk) +{ + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); + /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ + unsigned checksum = lodepng_crc32(&chunk[4], length + 4); + if(CRC != checksum) return 1; + else return 0; +} + +void lodepng_chunk_generate_crc(unsigned char* chunk) +{ + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_crc32(&chunk[4], length + 4); + lodepng_set32bitInt(chunk + 8 + length, CRC); +} + +unsigned char* lodepng_chunk_next(unsigned char* chunk) +{ + unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; + return &chunk[total_chunk_length]; +} + +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk) +{ + unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; + return &chunk[total_chunk_length]; +} + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk) +{ + unsigned i; + unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; + unsigned char *chunk_start, *new_buffer; + size_t new_length = (*outlength) + total_chunk_length; + if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/ + + new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outlength) = new_length; + chunk_start = &(*out)[new_length - total_chunk_length]; + + for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; + + return 0; +} + +unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, + const char* type, const unsigned char* data) +{ + unsigned i; + unsigned char *chunk, *new_buffer; + size_t new_length = (*outlength) + length + 12; + if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/ + new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outlength) = new_length; + chunk = &(*out)[(*outlength) - length - 12]; + + /*1: length*/ + lodepng_set32bitInt(chunk, (unsigned)length); + + /*2: chunk name (4 letters)*/ + chunk[4] = (unsigned char)type[0]; + chunk[5] = (unsigned char)type[1]; + chunk[6] = (unsigned char)type[2]; + chunk[7] = (unsigned char)type[3]; + + /*3: the data*/ + for(i = 0; i != length; ++i) chunk[8 + i] = data[i]; + + /*4: CRC (of the chunkname characters and the data)*/ + lodepng_chunk_generate_crc(chunk); + + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Color types and such / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*return type is a LodePNG error code*/ +static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/ +{ + switch(colortype) + { + case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/ + case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/ + case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/ + case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/ + case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/ + default: return 31; + } + return 0; /*allowed color type / bits combination*/ +} + +static unsigned getNumColorChannels(LodePNGColorType colortype) +{ + switch(colortype) + { + case 0: return 1; /*grey*/ + case 2: return 3; /*RGB*/ + case 3: return 1; /*palette*/ + case 4: return 2; /*grey + alpha*/ + case 6: return 4; /*RGBA*/ + } + return 0; /*unexisting color type*/ +} + +static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) +{ + /*bits per pixel is amount of channels * bits per channel*/ + return getNumColorChannels(colortype) * bitdepth; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +void lodepng_color_mode_init(LodePNGColorMode* info) +{ + info->key_defined = 0; + info->key_r = info->key_g = info->key_b = 0; + info->colortype = LCT_RGBA; + info->bitdepth = 8; + info->palette = 0; + info->palettesize = 0; +} + +void lodepng_color_mode_cleanup(LodePNGColorMode* info) +{ + lodepng_palette_clear(info); +} + +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) +{ + size_t i; + lodepng_color_mode_cleanup(dest); + *dest = *source; + if(source->palette) + { + dest->palette = (unsigned char*)lodepng_malloc(1024); + if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ + for(i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i]; + } + return 0; +} + +static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) +{ + size_t i; + if(a->colortype != b->colortype) return 0; + if(a->bitdepth != b->bitdepth) return 0; + if(a->key_defined != b->key_defined) return 0; + if(a->key_defined) + { + if(a->key_r != b->key_r) return 0; + if(a->key_g != b->key_g) return 0; + if(a->key_b != b->key_b) return 0; + } + if(a->palettesize != b->palettesize) return 0; + for(i = 0; i != a->palettesize * 4; ++i) + { + if(a->palette[i] != b->palette[i]) return 0; + } + return 1; +} + +void lodepng_palette_clear(LodePNGColorMode* info) +{ + if(info->palette) lodepng_free(info->palette); + info->palette = 0; + info->palettesize = 0; +} + +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + unsigned char* data; + /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with + the max of 256 colors, it'll have the exact alloc size*/ + if(!info->palette) /*allocate palette if empty*/ + { + /*room for 256 colors with 4 bytes each*/ + data = (unsigned char*)lodepng_realloc(info->palette, 1024); + if(!data) return 83; /*alloc fail*/ + else info->palette = data; + } + info->palette[4 * info->palettesize + 0] = r; + info->palette[4 * info->palettesize + 1] = g; + info->palette[4 * info->palettesize + 2] = b; + info->palette[4 * info->palettesize + 3] = a; + ++info->palettesize; + return 0; +} + +unsigned lodepng_get_bpp(const LodePNGColorMode* info) +{ + /*calculate bits per pixel out of colortype and bitdepth*/ + return lodepng_get_bpp_lct(info->colortype, info->bitdepth); +} + +unsigned lodepng_get_channels(const LodePNGColorMode* info) +{ + return getNumColorChannels(info->colortype); +} + +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) +{ + return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; +} + +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) +{ + return (info->colortype & 4) != 0; /*4 or 6*/ +} + +unsigned lodepng_is_palette_type(const LodePNGColorMode* info) +{ + return info->colortype == LCT_PALETTE; +} + +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) +{ + size_t i; + for(i = 0; i != info->palettesize; ++i) + { + if(info->palette[i * 4 + 3] < 255) return 1; + } + return 0; +} + +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) +{ + return info->key_defined + || lodepng_is_alpha_type(info) + || lodepng_has_palette_alpha(info); +} + +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) +{ + return (w * h * lodepng_get_bpp(color) + 7) / 8; +} + +size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +{ + return (w * h * lodepng_get_bpp_lct(colortype, bitdepth) + 7) / 8; +} + + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_DECODER +/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer*/ +static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) +{ + return h * ((w * lodepng_get_bpp(color) + 7) / 8); +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static void LodePNGUnknownChunks_init(LodePNGInfo* info) +{ + unsigned i; + for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; + for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; +} + +static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) +{ + unsigned i; + for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); +} + +static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) +{ + unsigned i; + + LodePNGUnknownChunks_cleanup(dest); + + for(i = 0; i != 3; ++i) + { + size_t j; + dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; + dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); + if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ + for(j = 0; j < src->unknown_chunks_size[i]; ++j) + { + dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; + } + } + + return 0; +} + +/******************************************************************************/ + +static void LodePNGText_init(LodePNGInfo* info) +{ + info->text_num = 0; + info->text_keys = NULL; + info->text_strings = NULL; +} + +static void LodePNGText_cleanup(LodePNGInfo* info) +{ + size_t i; + for(i = 0; i != info->text_num; ++i) + { + string_cleanup(&info->text_keys[i]); + string_cleanup(&info->text_strings[i]); + } + lodepng_free(info->text_keys); + lodepng_free(info->text_strings); +} + +static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) +{ + size_t i = 0; + dest->text_keys = 0; + dest->text_strings = 0; + dest->text_num = 0; + for(i = 0; i != source->text_num; ++i) + { + CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); + } + return 0; +} + +void lodepng_clear_text(LodePNGInfo* info) +{ + LodePNGText_cleanup(info); +} + +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) +{ + char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); + if(!new_keys || !new_strings) + { + lodepng_free(new_keys); + lodepng_free(new_strings); + return 83; /*alloc fail*/ + } + + ++info->text_num; + info->text_keys = new_keys; + info->text_strings = new_strings; + + string_init(&info->text_keys[info->text_num - 1]); + string_set(&info->text_keys[info->text_num - 1], key); + + string_init(&info->text_strings[info->text_num - 1]); + string_set(&info->text_strings[info->text_num - 1], str); + + return 0; +} + +/******************************************************************************/ + +static void LodePNGIText_init(LodePNGInfo* info) +{ + info->itext_num = 0; + info->itext_keys = NULL; + info->itext_langtags = NULL; + info->itext_transkeys = NULL; + info->itext_strings = NULL; +} + +static void LodePNGIText_cleanup(LodePNGInfo* info) +{ + size_t i; + for(i = 0; i != info->itext_num; ++i) + { + string_cleanup(&info->itext_keys[i]); + string_cleanup(&info->itext_langtags[i]); + string_cleanup(&info->itext_transkeys[i]); + string_cleanup(&info->itext_strings[i]); + } + lodepng_free(info->itext_keys); + lodepng_free(info->itext_langtags); + lodepng_free(info->itext_transkeys); + lodepng_free(info->itext_strings); +} + +static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) +{ + size_t i = 0; + dest->itext_keys = 0; + dest->itext_langtags = 0; + dest->itext_transkeys = 0; + dest->itext_strings = 0; + dest->itext_num = 0; + for(i = 0; i != source->itext_num; ++i) + { + CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], + source->itext_transkeys[i], source->itext_strings[i])); + } + return 0; +} + +void lodepng_clear_itext(LodePNGInfo* info) +{ + LodePNGIText_cleanup(info); +} + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str) +{ + char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); + char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); + char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); + if(!new_keys || !new_langtags || !new_transkeys || !new_strings) + { + lodepng_free(new_keys); + lodepng_free(new_langtags); + lodepng_free(new_transkeys); + lodepng_free(new_strings); + return 83; /*alloc fail*/ + } + + ++info->itext_num; + info->itext_keys = new_keys; + info->itext_langtags = new_langtags; + info->itext_transkeys = new_transkeys; + info->itext_strings = new_strings; + + string_init(&info->itext_keys[info->itext_num - 1]); + string_set(&info->itext_keys[info->itext_num - 1], key); + + string_init(&info->itext_langtags[info->itext_num - 1]); + string_set(&info->itext_langtags[info->itext_num - 1], langtag); + + string_init(&info->itext_transkeys[info->itext_num - 1]); + string_set(&info->itext_transkeys[info->itext_num - 1], transkey); + + string_init(&info->itext_strings[info->itext_num - 1]); + string_set(&info->itext_strings[info->itext_num - 1], str); + + return 0; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +void lodepng_info_init(LodePNGInfo* info) +{ + lodepng_color_mode_init(&info->color); + info->interlace_method = 0; + info->compression_method = 0; + info->filter_method = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + info->background_defined = 0; + info->background_r = info->background_g = info->background_b = 0; + + LodePNGText_init(info); + LodePNGIText_init(info); + + info->time_defined = 0; + info->phys_defined = 0; + + LodePNGUnknownChunks_init(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +void lodepng_info_cleanup(LodePNGInfo* info) +{ + lodepng_color_mode_cleanup(&info->color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + LodePNGText_cleanup(info); + LodePNGIText_cleanup(info); + + LodePNGUnknownChunks_cleanup(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) +{ + lodepng_info_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->color); + CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); + CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); + + LodePNGUnknownChunks_init(dest); + CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + return 0; +} + +void lodepng_info_swap(LodePNGInfo* a, LodePNGInfo* b) +{ + LodePNGInfo temp = *a; + *a = *b; + *b = temp; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ +static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) +{ + unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ + /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ + unsigned p = index & m; + in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ + in = in << (bits * (m - p)); + if(p == 0) out[index * bits / 8] = in; + else out[index * bits / 8] |= in; +} + +typedef struct ColorTree ColorTree; + +/* +One node of a color tree +This is the data structure used to count the number of unique colors and to get a palette +index for a color. It's like an octree, but because the alpha channel is used too, each +node has 16 instead of 8 children. +*/ +struct ColorTree +{ + ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ + int index; /*the payload. Only has a meaningful value if this is in the last level*/ +}; + +static void color_tree_init(ColorTree* tree) +{ + int i; + for(i = 0; i != 16; ++i) tree->children[i] = 0; + tree->index = -1; +} + +static void color_tree_cleanup(ColorTree* tree) +{ + int i; + for(i = 0; i != 16; ++i) + { + if(tree->children[i]) + { + color_tree_cleanup(tree->children[i]); + lodepng_free(tree->children[i]); + } + } +} + +/*returns -1 if color not present, its index otherwise*/ +static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + int bit = 0; + for(bit = 0; bit < 8; ++bit) + { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) return -1; + else tree = tree->children[i]; + } + return tree ? tree->index : -1; +} + +#ifdef LODEPNG_COMPILE_ENCODER +static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + return color_tree_get(tree, r, g, b, a) >= 0; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*color is not allowed to already exist. +Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")*/ +static void color_tree_add(ColorTree* tree, + unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) +{ + int bit; + for(bit = 0; bit < 8; ++bit) + { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) + { + tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); + color_tree_init(tree->children[i]); + } + tree = tree->children[i]; + } + tree->index = (int)index; +} + +/*put a pixel, given its RGBA color, into image of any color type*/ +static unsigned rgba8ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + if(mode->colortype == LCT_GREY) + { + unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/; + if(mode->bitdepth == 8) out[i] = grey; + else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = grey; + else + { + /*take the most significant bits of grey*/ + grey = (grey >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1); + addColorBits(out, i, mode->bitdepth, grey); + } + } + else if(mode->colortype == LCT_RGB) + { + if(mode->bitdepth == 8) + { + out[i * 3 + 0] = r; + out[i * 3 + 1] = g; + out[i * 3 + 2] = b; + } + else + { + out[i * 6 + 0] = out[i * 6 + 1] = r; + out[i * 6 + 2] = out[i * 6 + 3] = g; + out[i * 6 + 4] = out[i * 6 + 5] = b; + } + } + else if(mode->colortype == LCT_PALETTE) + { + int index = color_tree_get(tree, r, g, b, a); + if(index < 0) return 82; /*color not in palette*/ + if(mode->bitdepth == 8) out[i] = index; + else addColorBits(out, i, mode->bitdepth, (unsigned)index); + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/; + if(mode->bitdepth == 8) + { + out[i * 2 + 0] = grey; + out[i * 2 + 1] = a; + } + else if(mode->bitdepth == 16) + { + out[i * 4 + 0] = out[i * 4 + 1] = grey; + out[i * 4 + 2] = out[i * 4 + 3] = a; + } + } + else if(mode->colortype == LCT_RGBA) + { + if(mode->bitdepth == 8) + { + out[i * 4 + 0] = r; + out[i * 4 + 1] = g; + out[i * 4 + 2] = b; + out[i * 4 + 3] = a; + } + else + { + out[i * 8 + 0] = out[i * 8 + 1] = r; + out[i * 8 + 2] = out[i * 8 + 3] = g; + out[i * 8 + 4] = out[i * 8 + 5] = b; + out[i * 8 + 6] = out[i * 8 + 7] = a; + } + } + + return 0; /*no error*/ +} + +/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ +static void rgba16ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, + unsigned short r, unsigned short g, unsigned short b, unsigned short a) +{ + if(mode->colortype == LCT_GREY) + { + unsigned short grey = r; /*((unsigned)r + g + b) / 3*/; + out[i * 2 + 0] = (grey >> 8) & 255; + out[i * 2 + 1] = grey & 255; + } + else if(mode->colortype == LCT_RGB) + { + out[i * 6 + 0] = (r >> 8) & 255; + out[i * 6 + 1] = r & 255; + out[i * 6 + 2] = (g >> 8) & 255; + out[i * 6 + 3] = g & 255; + out[i * 6 + 4] = (b >> 8) & 255; + out[i * 6 + 5] = b & 255; + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + unsigned short grey = r; /*((unsigned)r + g + b) / 3*/; + out[i * 4 + 0] = (grey >> 8) & 255; + out[i * 4 + 1] = grey & 255; + out[i * 4 + 2] = (a >> 8) & 255; + out[i * 4 + 3] = a & 255; + } + else if(mode->colortype == LCT_RGBA) + { + out[i * 8 + 0] = (r >> 8) & 255; + out[i * 8 + 1] = r & 255; + out[i * 8 + 2] = (g >> 8) & 255; + out[i * 8 + 3] = g & 255; + out[i * 8 + 4] = (b >> 8) & 255; + out[i * 8 + 5] = b & 255; + out[i * 8 + 6] = (a >> 8) & 255; + out[i * 8 + 7] = a & 255; + } +} + +/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ +static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, + unsigned char* b, unsigned char* a, + const unsigned char* in, size_t i, + const LodePNGColorMode* mode) +{ + if(mode->colortype == LCT_GREY) + { + if(mode->bitdepth == 8) + { + *r = *g = *b = in[i]; + if(mode->key_defined && *r == mode->key_r) *a = 0; + else *a = 255; + } + else if(mode->bitdepth == 16) + { + *r = *g = *b = in[i * 2 + 0]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 255; + } + else + { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = i * mode->bitdepth; + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + *r = *g = *b = (value * 255) / highest; + if(mode->key_defined && value == mode->key_r) *a = 0; + else *a = 255; + } + } + else if(mode->colortype == LCT_RGB) + { + if(mode->bitdepth == 8) + { + *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; + if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; + else *a = 255; + } + else + { + *r = in[i * 6 + 0]; + *g = in[i * 6 + 2]; + *b = in[i * 6 + 4]; + if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 255; + } + } + else if(mode->colortype == LCT_PALETTE) + { + unsigned index; + if(mode->bitdepth == 8) index = in[i]; + else + { + size_t j = i * mode->bitdepth; + index = readBitsFromReversedStream(&j, in, mode->bitdepth); + } + + if(index >= mode->palettesize) + { + /*This is an error according to the PNG spec, but common PNG decoders make it black instead. + Done here too, slightly faster due to no error handling needed.*/ + *r = *g = *b = 0; + *a = 255; + } + else + { + *r = mode->palette[index * 4 + 0]; + *g = mode->palette[index * 4 + 1]; + *b = mode->palette[index * 4 + 2]; + *a = mode->palette[index * 4 + 3]; + } + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + if(mode->bitdepth == 8) + { + *r = *g = *b = in[i * 2 + 0]; + *a = in[i * 2 + 1]; + } + else + { + *r = *g = *b = in[i * 4 + 0]; + *a = in[i * 4 + 2]; + } + } + else if(mode->colortype == LCT_RGBA) + { + if(mode->bitdepth == 8) + { + *r = in[i * 4 + 0]; + *g = in[i * 4 + 1]; + *b = in[i * 4 + 2]; + *a = in[i * 4 + 3]; + } + else + { + *r = in[i * 8 + 0]; + *g = in[i * 8 + 2]; + *b = in[i * 8 + 4]; + *a = in[i * 8 + 6]; + } + } +} + +/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color +mode test cases, optimized to convert the colors much faster, when converting +to RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with +enough memory, if has_alpha is true the output is RGBA. mode has the color mode +of the input buffer.*/ +static void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels, + unsigned has_alpha, const unsigned char* in, + const LodePNGColorMode* mode) +{ + unsigned num_channels = has_alpha ? 4 : 3; + size_t i; + if(mode->colortype == LCT_GREY) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i]; + if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255; + } + } + else if(mode->bitdepth == 16) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; + } + } + else + { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; + } + } + } + else if(mode->colortype == LCT_RGB) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 3 + 0]; + buffer[1] = in[i * 3 + 1]; + buffer[2] = in[i * 3 + 2]; + if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r + && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255; + } + } + else + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + if(has_alpha) buffer[3] = mode->key_defined + && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; + } + } + } + else if(mode->colortype == LCT_PALETTE) + { + unsigned index; + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + if(mode->bitdepth == 8) index = in[i]; + else index = readBitsFromReversedStream(&j, in, mode->bitdepth); + + if(index >= mode->palettesize) + { + /*This is an error according to the PNG spec, but most PNG decoders make it black instead. + Done here too, slightly faster due to no error handling needed.*/ + buffer[0] = buffer[1] = buffer[2] = 0; + if(has_alpha) buffer[3] = 255; + } + else + { + buffer[0] = mode->palette[index * 4 + 0]; + buffer[1] = mode->palette[index * 4 + 1]; + buffer[2] = mode->palette[index * 4 + 2]; + if(has_alpha) buffer[3] = mode->palette[index * 4 + 3]; + } + } + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + if(has_alpha) buffer[3] = in[i * 2 + 1]; + } + } + else + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + if(has_alpha) buffer[3] = in[i * 4 + 2]; + } + } + } + else if(mode->colortype == LCT_RGBA) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 4 + 0]; + buffer[1] = in[i * 4 + 1]; + buffer[2] = in[i * 4 + 2]; + if(has_alpha) buffer[3] = in[i * 4 + 3]; + } + } + else + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + if(has_alpha) buffer[3] = in[i * 8 + 6]; + } + } + } +} + +/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with +given color type, but the given color type must be 16-bit itself.*/ +static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, + const unsigned char* in, size_t i, const LodePNGColorMode* mode) +{ + if(mode->colortype == LCT_GREY) + { + *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 65535; + } + else if(mode->colortype == LCT_RGB) + { + *r = 256 * in[i * 6 + 0] + in[i * 6 + 1]; + *g = 256 * in[i * 6 + 2] + in[i * 6 + 3]; + *b = 256 * in[i * 6 + 4] + in[i * 6 + 5]; + if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 65535; + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + *r = *g = *b = 256 * in[i * 4 + 0] + in[i * 4 + 1]; + *a = 256 * in[i * 4 + 2] + in[i * 4 + 3]; + } + else if(mode->colortype == LCT_RGBA) + { + *r = 256 * in[i * 8 + 0] + in[i * 8 + 1]; + *g = 256 * in[i * 8 + 2] + in[i * 8 + 3]; + *b = 256 * in[i * 8 + 4] + in[i * 8 + 5]; + *a = 256 * in[i * 8 + 6] + in[i * 8 + 7]; + } +} + +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h) +{ + size_t i; + ColorTree tree; + size_t numpixels = w * h; + + if(lodepng_color_mode_equal(mode_out, mode_in)) + { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + for(i = 0; i != numbytes; ++i) out[i] = in[i]; + return 0; + } + + if(mode_out->colortype == LCT_PALETTE) + { + size_t palsize = 1u << mode_out->bitdepth; + if(mode_out->palettesize < palsize) palsize = mode_out->palettesize; + color_tree_init(&tree); + for(i = 0; i != palsize; ++i) + { + unsigned char* p = &mode_out->palette[i * 4]; + color_tree_add(&tree, p[0], p[1], p[2], p[3], i); + } + } + + if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) + { + for(i = 0; i != numpixels; ++i) + { + unsigned short r = 0, g = 0, b = 0, a = 0; + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + rgba16ToPixel(out, i, mode_out, r, g, b, a); + } + } + else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) + { + getPixelColorsRGBA8(out, numpixels, 1, in, mode_in); + } + else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) + { + getPixelColorsRGBA8(out, numpixels, 0, in, mode_in); + } + else + { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); + } + } + + if(mode_out->colortype == LCT_PALETTE) + { + color_tree_cleanup(&tree); + } + + return 0; /*no error (this function currently never has one, but maybe OOM detection added later.)*/ +} + +#ifdef LODEPNG_COMPILE_ENCODER + +void lodepng_color_profile_init(LodePNGColorProfile* profile) +{ + profile->colored = 0; + profile->key = 0; + profile->alpha = 0; + profile->key_r = profile->key_g = profile->key_b = 0; + profile->numcolors = 0; + profile->bits = 1; +} + +/*function used for debug purposes with C++*/ +/*void printColorProfile(LodePNGColorProfile* p) +{ + std::cout << "colored: " << (int)p->colored << ", "; + std::cout << "key: " << (int)p->key << ", "; + std::cout << "key_r: " << (int)p->key_r << ", "; + std::cout << "key_g: " << (int)p->key_g << ", "; + std::cout << "key_b: " << (int)p->key_b << ", "; + std::cout << "alpha: " << (int)p->alpha << ", "; + std::cout << "numcolors: " << (int)p->numcolors << ", "; + std::cout << "bits: " << (int)p->bits << std::endl; +}*/ + +/*Returns how many bits needed to represent given value (max 8 bit)*/ +static unsigned getValueRequiredBits(unsigned char value) +{ + if(value == 0 || value == 255) return 1; + /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ + if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; + return 8; +} + +/*profile must already have been inited with mode. +It's ok to set some parameters of profile to done already.*/ +unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, + const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* mode) +{ + unsigned error = 0; + size_t i; + ColorTree tree; + size_t numpixels = w * h; + + unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0; + unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1; + unsigned numcolors_done = 0; + unsigned bpp = lodepng_get_bpp(mode); + unsigned bits_done = bpp == 1 ? 1 : 0; + unsigned maxnumcolors = 257; + unsigned sixteen = 0; + if(bpp <= 8) maxnumcolors = bpp == 1 ? 2 : (bpp == 2 ? 4 : (bpp == 4 ? 16 : 256)); + + color_tree_init(&tree); + + /*Check if the 16-bit input is truly 16-bit*/ + if(mode->bitdepth == 16) + { + unsigned short r, g, b, a; + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode); + if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || + (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ + { + sixteen = 1; + break; + } + } + } + + if(sixteen) + { + unsigned short r = 0, g = 0, b = 0, a = 0; + profile->bits = 16; + bits_done = numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ + + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode); + + if(!colored_done && (r != g || r != b)) + { + profile->colored = 1; + colored_done = 1; + } + + if(!alpha_done) + { + unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b); + if(a != 65535 && (a != 0 || (profile->key && !matchkey))) + { + profile->alpha = 1; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + else if(a == 0 && !profile->alpha && !profile->key) + { + profile->key = 1; + profile->key_r = r; + profile->key_g = g; + profile->key_b = b; + } + else if(a == 65535 && profile->key && matchkey) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + alpha_done = 1; + } + } + + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + } + else /* < 16-bit */ + { + for(i = 0; i != numpixels; ++i) + { + unsigned char r = 0, g = 0, b = 0, a = 0; + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode); + + if(!bits_done && profile->bits < 8) + { + /*only r is checked, < 8 bits is only relevant for greyscale*/ + unsigned bits = getValueRequiredBits(r); + if(bits > profile->bits) profile->bits = bits; + } + bits_done = (profile->bits >= bpp); + + if(!colored_done && (r != g || r != b)) + { + profile->colored = 1; + colored_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ + } + + if(!alpha_done) + { + unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b); + if(a != 255 && (a != 0 || (profile->key && !matchkey))) + { + profile->alpha = 1; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + else if(a == 0 && !profile->alpha && !profile->key) + { + profile->key = 1; + profile->key_r = r; + profile->key_g = g; + profile->key_b = b; + } + else if(a == 255 && profile->key && matchkey) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + + if(!numcolors_done) + { + if(!color_tree_has(&tree, r, g, b, a)) + { + color_tree_add(&tree, r, g, b, a, profile->numcolors); + if(profile->numcolors < 256) + { + unsigned char* p = profile->palette; + unsigned n = profile->numcolors; + p[n * 4 + 0] = r; + p[n * 4 + 1] = g; + p[n * 4 + 2] = b; + p[n * 4 + 3] = a; + } + ++profile->numcolors; + numcolors_done = profile->numcolors >= maxnumcolors; + } + } + + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + /*make the profile's key always 16-bit for consistency - repeat each byte twice*/ + profile->key_r += (profile->key_r << 8); + profile->key_g += (profile->key_g << 8); + profile->key_b += (profile->key_b << 8); + } + + color_tree_cleanup(&tree); + return error; +} + +/*Automatically chooses color type that gives smallest amount of bits in the +output image, e.g. grey if there are only greyscale pixels, palette if there +are less than 256 colors, ... +Updates values of mode with a potentially smaller color model. mode_out should +contain the user chosen color model, but will be overwritten with the new chosen one.*/ +unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in) +{ + LodePNGColorProfile prof; + unsigned error = 0; + unsigned i, n, palettebits, grey_ok, palette_ok; + + lodepng_color_profile_init(&prof); + error = lodepng_get_color_profile(&prof, image, w, h, mode_in); + if(error) return error; + mode_out->key_defined = 0; + + if(prof.key && w * h <= 16) + { + prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ + if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + grey_ok = !prof.colored && !prof.alpha; /*grey without alpha, with potentially low bits*/ + n = prof.numcolors; + palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); + palette_ok = n <= 256 && (n * 2 < w * h) && prof.bits <= 8; + if(w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ + if(grey_ok && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/ + + if(palette_ok) + { + unsigned char* p = prof.palette; + lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ + for(i = 0; i != prof.numcolors; ++i) + { + error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); + if(error) break; + } + + mode_out->colortype = LCT_PALETTE; + mode_out->bitdepth = palettebits; + + if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize + && mode_in->bitdepth == mode_out->bitdepth) + { + /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ + lodepng_color_mode_cleanup(mode_out); + lodepng_color_mode_copy(mode_out, mode_in); + } + } + else /*8-bit or 16-bit per channel*/ + { + mode_out->bitdepth = prof.bits; + mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA) + : (prof.colored ? LCT_RGB : LCT_GREY); + + if(prof.key && !prof.alpha) + { + unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/ + mode_out->key_r = prof.key_r & mask; + mode_out->key_g = prof.key_g & mask; + mode_out->key_b = prof.key_b & mask; + mode_out->key_defined = 1; + } + } + + return error; +} + +#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ + +/* +Paeth predicter, used by PNG filter type 4 +The parameters are of type short, but should come from unsigned chars, the shorts +are only needed to make the paeth calculation correct. +*/ +static unsigned char paethPredictor(short a, short b, short c) +{ + short pa = abs(b - c); + short pb = abs(a - c); + short pc = abs(a + b - c - c); + + if(pc < pa && pc < pb) return (unsigned char)c; + else if(pb < pa) return (unsigned char)b; + else return (unsigned char)a; +} + +/*shared values used by multiple Adam7 related functions*/ + +static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ +static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ +static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ +static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ + +/* +Outputs various dimensions and positions in the image related to the Adam7 reduced images. +passw: output containing the width of the 7 passes +passh: output containing the height of the 7 passes +filter_passstart: output containing the index of the start and end of each + reduced image with filter bytes +padded_passstart output containing the index of the start and end of each + reduced image when without filter bytes but with padded scanlines +passstart: output containing the index of the start and end of each reduced + image without padding between scanlines, but still padding between the images +w, h: width and height of non-interlaced image +bpp: bits per pixel +"padded" is only relevant if bpp is less than 8 and a scanline or image does not + end at a full byte +*/ +static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], + size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) +{ + /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ + unsigned i; + + /*calculate width and height in pixels of each pass*/ + for(i = 0; i != 7; ++i) + { + passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; + passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; + if(passw[i] == 0) passh[i] = 0; + if(passh[i] == 0) passw[i] = 0; + } + + filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; + for(i = 0; i != 7; ++i) + { + /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ + filter_passstart[i + 1] = filter_passstart[i] + + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); + /*bits padded if needed to fill full byte at end of each scanline*/ + padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); + /*only padded at end of reduced image*/ + passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; + } +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Decoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*read the information from the header and store it in the LodePNGInfo. return value is error*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, + const unsigned char* in, size_t insize) +{ + LodePNGInfo* info = &state->info_png; + if(insize == 0 || in == 0) + { + CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ + } + if(insize < 33) + { + CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ + } + + /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ + lodepng_info_cleanup(info); + lodepng_info_init(info); + + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 + || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) + { + CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ + } + if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') + { + CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ + } + + /*read the values given in the header*/ + *w = lodepng_read32bitInt(&in[16]); + *h = lodepng_read32bitInt(&in[20]); + info->color.bitdepth = in[24]; + info->color.colortype = (LodePNGColorType)in[25]; + info->compression_method = in[26]; + info->filter_method = in[27]; + info->interlace_method = in[28]; + + if(*w == 0 || *h == 0) + { + CERROR_RETURN_ERROR(state->error, 93); + } + + if(!state->decoder.ignore_crc) + { + unsigned CRC = lodepng_read32bitInt(&in[29]); + unsigned checksum = lodepng_crc32(&in[12], 17); + if(CRC != checksum) + { + CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ + } + } + + /*error: only compression method 0 is allowed in the specification*/ + if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); + /*error: only filter method 0 is allowed in the specification*/ + if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); + /*error: only interlace methods 0 and 1 exist in the specification*/ + if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); + + state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); + return state->error; +} + +static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, + size_t bytewidth, unsigned char filterType, size_t length) +{ + /* + For PNG filter method 0 + unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, + the filter works byte per byte (bytewidth = 1) + precon is the previous unfiltered scanline, recon the result, scanline the current one + the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead + recon and scanline MAY be the same memory address! precon must be disjoint. + */ + + size_t i; + switch(filterType) + { + case 0: + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + break; + case 1: + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth]; + break; + case 2: + if(precon) + { + for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; + } + else + { + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + } + break; + case 3: + if(precon) + { + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + precon[i] / 2; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); + } + else + { + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth] / 2; + } + break; + case 4: + if(precon) + { + for(i = 0; i != bytewidth; ++i) + { + recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ + } + for(i = bytewidth; i < length; ++i) + { + recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); + } + } + else + { + for(i = 0; i != bytewidth; ++i) + { + recon[i] = scanline[i]; + } + for(i = bytewidth; i < length; ++i) + { + /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ + recon[i] = (scanline[i] + recon[i - bytewidth]); + } + } + break; + default: return 36; /*error: unexisting filter type given*/ + } + return 0; +} + +static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) +{ + /* + For PNG filter method 0 + this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) + out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline + w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel + in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) + */ + + unsigned y; + unsigned char* prevline = 0; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7) / 8; + size_t linebytes = (w * bpp + 7) / 8; + + for(y = 0; y < h; ++y) + { + size_t outindex = linebytes * y; + size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + unsigned char filterType = in[inindex]; + + CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); + + prevline = &out[outindex]; + } + + return 0; +} + +/* +in: Adam7 interlaced image, with no padding bits between scanlines, but between + reduced images so that each reduced image starts at a byte. +out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h +bpp: bits per pixel +out has the following size in bits: w * h * bpp. +in is possibly bigger due to padding bits between reduced images. +out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation +(because that's likely a little bit faster) +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) +{ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + size_t bytewidth = bpp / 8; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; + size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + for(b = 0; b < bytewidth; ++b) + { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } + else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + for(b = 0; b < bpp; ++b) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/ + setBitOfReversedStream0(&obp, out, bit); + } + } + } + } +} + +static void removePaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) +{ + /* + After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need + to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers + for the Adam7 code, the color convert code and the output to the user. + in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must + have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits + also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 + only useful if (ilinebits - olinebits) is a value in the range 1..7 + */ + unsigned y; + size_t diff = ilinebits - olinebits; + size_t ibp = 0, obp = 0; /*input and output bit pointers*/ + for(y = 0; y < h; ++y) + { + size_t x; + for(x = 0; x < olinebits; ++x) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + ibp += diff; + } +} + +/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from +the IDAT chunks (with filter index bytes and possible padding bits) +return value is error*/ +static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, + unsigned w, unsigned h, const LodePNGInfo* info_png) +{ + /* + This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. + Steps: + *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8) + *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace + NOTE: the in buffer will be overwritten with intermediate data! + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + if(bpp == 0) return 31; /*error: invalid colortype*/ + + if(info_png->interlace_method == 0) + { + if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) + { + CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); + removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h); + } + /*we can immediatly filter into the out buffer, no other steps needed*/ + else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); + } + else /*interlace_method is 1 (Adam7)*/ + { + unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + for(i = 0; i != 7; ++i) + { + CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); + /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, + move bytes instead of bits or move not at all*/ + if(bpp < 8) + { + /*remove padding bits in scanlines; after this there still may be padding + bits between the different reduced images: each reduced image still starts nicely at a byte*/ + removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, + ((passw[i] * bpp + 7) / 8) * 8, passh[i]); + } + } + + Adam7_deinterlace(out, in, w, h, bpp); + } + + return 0; +} + +static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) +{ + unsigned pos = 0, i; + if(color->palette) lodepng_free(color->palette); + color->palettesize = chunkLength / 3; + color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize); + if(!color->palette && color->palettesize) + { + color->palettesize = 0; + return 83; /*alloc fail*/ + } + if(color->palettesize > 256) return 38; /*error: palette too big*/ + + for(i = 0; i != color->palettesize; ++i) + { + color->palette[4 * i + 0] = data[pos++]; /*R*/ + color->palette[4 * i + 1] = data[pos++]; /*G*/ + color->palette[4 * i + 2] = data[pos++]; /*B*/ + color->palette[4 * i + 3] = 255; /*alpha*/ + } + + return 0; /* OK */ +} + +static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) +{ + unsigned i; + if(color->colortype == LCT_PALETTE) + { + /*error: more alpha values given than there are palette entries*/ + if(chunkLength > color->palettesize) return 38; + + for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; + } + else if(color->colortype == LCT_GREY) + { + /*error: this chunk must be 2 bytes for greyscale image*/ + if(chunkLength != 2) return 30; + + color->key_defined = 1; + color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; + } + else if(color->colortype == LCT_RGB) + { + /*error: this chunk must be 6 bytes for RGB image*/ + if(chunkLength != 6) return 41; + + color->key_defined = 1; + color->key_r = 256u * data[0] + data[1]; + color->key_g = 256u * data[2] + data[3]; + color->key_b = 256u * data[4] + data[5]; + } + else return 42; /*error: tRNS chunk not allowed for other color models*/ + + return 0; /* OK */ +} + + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*background color chunk (bKGD)*/ +static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(info->color.colortype == LCT_PALETTE) + { + /*error: this chunk must be 1 byte for indexed color image*/ + if(chunkLength != 1) return 43; + + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = data[0]; + } + else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) + { + /*error: this chunk must be 2 bytes for greyscale image*/ + if(chunkLength != 2) return 44; + + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; + } + else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) + { + /*error: this chunk must be 6 bytes for greyscale image*/ + if(chunkLength != 6) return 45; + + info->background_defined = 1; + info->background_r = 256u * data[0] + data[1]; + info->background_g = 256u * data[2] + data[3]; + info->background_b = 256u * data[4] + data[5]; + } + + return 0; /* OK */ +} + +/*text chunk (tEXt)*/ +static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + char *key = 0, *str = 0; + unsigned i; + + while(!error) /*not really a while loop, only used to break on error*/ + { + unsigned length, string2_begin; + + length = 0; + while(length < chunkLength && data[length] != 0) ++length; + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + key[length] = 0; + for(i = 0; i != length; ++i) key[i] = (char)data[i]; + + string2_begin = length + 1; /*skip keyword null terminator*/ + + length = chunkLength < string2_begin ? 0 : chunkLength - string2_begin; + str = (char*)lodepng_malloc(length + 1); + if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ + + str[length] = 0; + for(i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i]; + + error = lodepng_add_text(info, key, str); + + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*compressed text chunk (zTXt)*/ +static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, + const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + + unsigned length, string2_begin; + char *key = 0; + ucvector decoded; + + ucvector_init(&decoded); + + while(!error) /*not really a while loop, only used to break on error*/ + { + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + key[length] = 0; + for(i = 0; i != length; ++i) key[i] = (char)data[i]; + + if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + + length = chunkLength - string2_begin; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&decoded.data, &decoded.size, + (unsigned char*)(&data[string2_begin]), + length, zlibsettings); + if(error) break; + ucvector_push_back(&decoded, 0); + + error = lodepng_add_text(info, key, (char*)decoded.data); + + break; + } + + lodepng_free(key); + ucvector_cleanup(&decoded); + + return error; +} + +/*international text chunk (iTXt)*/ +static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, + const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + + unsigned length, begin, compressed; + char *key = 0, *langtag = 0, *transkey = 0; + ucvector decoded; + ucvector_init(&decoded); + + while(!error) /*not really a while loop, only used to break on error*/ + { + /*Quick check if the chunk length isn't too small. Even without check + it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ + if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ + + /*read the key*/ + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + key[length] = 0; + for(i = 0; i != length; ++i) key[i] = (char)data[i]; + + /*read the compression method*/ + compressed = data[length + 1]; + if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty for the next 3 texts*/ + + /*read the langtag*/ + begin = length + 3; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + langtag = (char*)lodepng_malloc(length + 1); + if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ + + langtag[length] = 0; + for(i = 0; i != length; ++i) langtag[i] = (char)data[begin + i]; + + /*read the transkey*/ + begin += length + 1; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + transkey = (char*)lodepng_malloc(length + 1); + if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ + + transkey[length] = 0; + for(i = 0; i != length; ++i) transkey[i] = (char)data[begin + i]; + + /*read the actual text*/ + begin += length + 1; + + length = chunkLength < begin ? 0 : chunkLength - begin; + + if(compressed) + { + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&decoded.data, &decoded.size, + (unsigned char*)(&data[begin]), + length, zlibsettings); + if(error) break; + if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size; + ucvector_push_back(&decoded, 0); + } + else + { + if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/); + + decoded.data[length] = 0; + for(i = 0; i != length; ++i) decoded.data[i] = data[begin + i]; + } + + error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data); + + break; + } + + lodepng_free(key); + lodepng_free(langtag); + lodepng_free(transkey); + ucvector_cleanup(&decoded); + + return error; +} + +static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ + + info->time_defined = 1; + info->time.year = 256u * data[0] + data[1]; + info->time.month = data[2]; + info->time.day = data[3]; + info->time.hour = data[4]; + info->time.minute = data[5]; + info->time.second = data[6]; + + return 0; /* OK */ +} + +static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ + + info->phys_defined = 1; + info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; + info->phys_unit = data[8]; + + return 0; /* OK */ +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ +static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) +{ + unsigned char IEND = 0; + const unsigned char* chunk; + size_t i; + ucvector idat; /*the data from idat chunks*/ + ucvector scanlines; + size_t predict; + size_t numpixels; + + /*for unknown chunk order*/ + unsigned unknown = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + /*provide some proper output values if error will happen*/ + *out = 0; + + state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ + if(state->error) return; + + numpixels = *w * *h; + + /*multiplication overflow*/ + if(*h != 0 && numpixels / *h != *w) CERROR_RETURN(state->error, 92); + /*multiplication overflow possible further below. Allows up to 2^31-1 pixel + bytes with 16-bit RGBA, the rest is room for filter bytes.*/ + if(numpixels > 268435455) CERROR_RETURN(state->error, 92); + + ucvector_init(&idat); + chunk = &in[33]; /*first byte of the first chunk after the header*/ + + /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. + IDAT data is put at the start of the in buffer*/ + while(!IEND && !state->error) + { + unsigned chunkLength; + const unsigned char* data; /*the data in the chunk*/ + + /*error: size of the in buffer too small to contain next chunk*/ + if((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30); + + /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ + chunkLength = lodepng_chunk_length(chunk); + /*error: chunk length larger than the max PNG chunk size*/ + if(chunkLength > 2147483647) CERROR_BREAK(state->error, 63); + + if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) + { + CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ + } + + data = lodepng_chunk_data_const(chunk); + + /*IDAT chunk, containing compressed image data*/ + if(lodepng_chunk_type_equals(chunk, "IDAT")) + { + size_t oldsize = idat.size; + if(!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/); + for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i]; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 3; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + /*IEND chunk*/ + else if(lodepng_chunk_type_equals(chunk, "IEND")) + { + IEND = 1; + } + /*palette chunk (PLTE)*/ + else if(lodepng_chunk_type_equals(chunk, "PLTE")) + { + state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 2; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + /*palette transparency chunk (tRNS)*/ + else if(lodepng_chunk_type_equals(chunk, "tRNS")) + { + state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); + if(state->error) break; + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*background color chunk (bKGD)*/ + else if(lodepng_chunk_type_equals(chunk, "bKGD")) + { + state->error = readChunk_bKGD(&state->info_png, data, chunkLength); + if(state->error) break; + } + /*text chunk (tEXt)*/ + else if(lodepng_chunk_type_equals(chunk, "tEXt")) + { + if(state->decoder.read_text_chunks) + { + state->error = readChunk_tEXt(&state->info_png, data, chunkLength); + if(state->error) break; + } + } + /*compressed text chunk (zTXt)*/ + else if(lodepng_chunk_type_equals(chunk, "zTXt")) + { + if(state->decoder.read_text_chunks) + { + state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + if(state->error) break; + } + } + /*international text chunk (iTXt)*/ + else if(lodepng_chunk_type_equals(chunk, "iTXt")) + { + if(state->decoder.read_text_chunks) + { + state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + if(state->error) break; + } + } + else if(lodepng_chunk_type_equals(chunk, "tIME")) + { + state->error = readChunk_tIME(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "pHYs")) + { + state->error = readChunk_pHYs(&state->info_png, data, chunkLength); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + else /*it's not an implemented chunk type, so ignore it: skip over the data*/ + { + /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ + if(!lodepng_chunk_ancillary(chunk)) CERROR_BREAK(state->error, 69); + + unknown = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->decoder.remember_unknown_chunks) + { + state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], + &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + + if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ + { + if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ + } + + if(!IEND) chunk = lodepng_chunk_next_const(chunk); + } + + ucvector_init(&scanlines); + /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. + If the decompressed size does not match the prediction, the image must be corrupt.*/ + if(state->info_png.interlace_method == 0) + { + /*The extra *h is added because this are the filter bytes every scanline starts with*/ + predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h; + } + else + { + /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/ + const LodePNGColorMode* color = &state->info_png.color; + predict = 0; + predict += lodepng_get_raw_size_idat((*w + 7) / 8, (*h + 7) / 8, color) + (*h + 7) / 8; + if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) / 8, (*h + 7) / 8, color) + (*h + 7) / 8; + predict += lodepng_get_raw_size_idat((*w + 3) / 4, (*h + 3) / 8, color) + (*h + 3) / 8; + if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) / 4, (*h + 3) / 4, color) + (*h + 3) / 4; + predict += lodepng_get_raw_size_idat((*w + 1) / 2, (*h + 1) / 4, color) + (*h + 1) / 4; + if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) / 2, (*h + 1) / 2, color) + (*h + 1) / 2; + predict += lodepng_get_raw_size_idat((*w + 0) / 1, (*h + 0) / 2, color) + (*h + 0) / 2; + } + if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/ + if(!state->error) + { + state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data, + idat.size, &state->decoder.zlibsettings); + if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/ + } + ucvector_cleanup(&idat); + + if(!state->error) + { + size_t outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); + ucvector outv; + ucvector_init(&outv); + if(!ucvector_resizev(&outv, outsize, 0)) state->error = 83; /*alloc fail*/ + if(!state->error) state->error = postProcessScanlines(outv.data, scanlines.data, *w, *h, &state->info_png); + *out = outv.data; + } + ucvector_cleanup(&scanlines); +} + +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) +{ + *out = 0; + decodeGeneric(out, w, h, state, in, insize); + if(state->error) return state->error; + if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) + { + /*same color type, no copying or converting of data needed*/ + /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype + the raw image has to the end user*/ + if(!state->decoder.color_convert) + { + state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); + if(state->error) return state->error; + } + } + else + { + /*color conversion needed; sort of copy of the data*/ + unsigned char* data = *out; + size_t outsize; + + /*TODO: check if this works according to the statement in the documentation: "The converter can convert + from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/ + if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) + && !(state->info_raw.bitdepth == 8)) + { + return 56; /*unsupported color mode conversion*/ + } + + outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!(*out)) + { + state->error = 83; /*alloc fail*/ + } + else state->error = lodepng_convert(*out, data, &state->info_raw, + &state->info_png.color, *w, *h); + lodepng_free(data); + } + return state->error; +} + +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + error = lodepng_decode(out, w, h, &state, in, insize); + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) +{ + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); +} + +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) +{ + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error; + error = lodepng_load_file(&buffer, &buffersize, filename); + if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) +{ + return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); +} + +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) +{ + return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) +{ + settings->color_convert = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->read_text_chunks = 1; + settings->remember_unknown_chunks = 0; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + settings->ignore_crc = 0; + lodepng_decompress_settings_init(&settings->zlibsettings); +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) + +void lodepng_state_init(LodePNGState* state) +{ +#ifdef LODEPNG_COMPILE_DECODER + lodepng_decoder_settings_init(&state->decoder); +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + lodepng_encoder_settings_init(&state->encoder); +#endif /*LODEPNG_COMPILE_ENCODER*/ + lodepng_color_mode_init(&state->info_raw); + lodepng_info_init(&state->info_png); + state->error = 1; +} + +void lodepng_state_cleanup(LodePNGState* state) +{ + lodepng_color_mode_cleanup(&state->info_raw); + lodepng_info_cleanup(&state->info_png); +} + +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) +{ + lodepng_state_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->info_raw); + lodepng_info_init(&dest->info_png); + dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return; + dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return; +} + +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Encoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*chunkName must be string of 4 characters*/ +static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) +{ + CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data)); + out->allocsize = out->size; /*fix the allocsize again*/ + return 0; +} + +static void writeSignature(ucvector* out) +{ + /*8 bytes PNG signature, aka the magic bytes*/ + ucvector_push_back(out, 137); + ucvector_push_back(out, 80); + ucvector_push_back(out, 78); + ucvector_push_back(out, 71); + ucvector_push_back(out, 13); + ucvector_push_back(out, 10); + ucvector_push_back(out, 26); + ucvector_push_back(out, 10); +} + +static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) +{ + unsigned error = 0; + ucvector header; + ucvector_init(&header); + + lodepng_add32bitInt(&header, w); /*width*/ + lodepng_add32bitInt(&header, h); /*height*/ + ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/ + ucvector_push_back(&header, (unsigned char)colortype); /*color type*/ + ucvector_push_back(&header, 0); /*compression method*/ + ucvector_push_back(&header, 0); /*filter method*/ + ucvector_push_back(&header, interlace_method); /*interlace method*/ + + error = addChunk(out, "IHDR", header.data, header.size); + ucvector_cleanup(&header); + + return error; +} + +static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) +{ + unsigned error = 0; + size_t i; + ucvector PLTE; + ucvector_init(&PLTE); + for(i = 0; i != info->palettesize * 4; ++i) + { + /*add all channels except alpha channel*/ + if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]); + } + error = addChunk(out, "PLTE", PLTE.data, PLTE.size); + ucvector_cleanup(&PLTE); + + return error; +} + +static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) +{ + unsigned error = 0; + size_t i; + ucvector tRNS; + ucvector_init(&tRNS); + if(info->colortype == LCT_PALETTE) + { + size_t amount = info->palettesize; + /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ + for(i = info->palettesize; i != 0; --i) + { + if(info->palette[4 * (i - 1) + 3] == 255) --amount; + else break; + } + /*add only alpha channel*/ + for(i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]); + } + else if(info->colortype == LCT_GREY) + { + if(info->key_defined) + { + ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); + } + } + else if(info->colortype == LCT_RGB) + { + if(info->key_defined) + { + ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_g / 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_g % 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_b / 256)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_b % 256)); + } + } + + error = addChunk(out, "tRNS", tRNS.data, tRNS.size); + ucvector_cleanup(&tRNS); + + return error; +} + +static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, + LodePNGCompressSettings* zlibsettings) +{ + ucvector zlibdata; + unsigned error = 0; + + /*compress with the Zlib compressor*/ + ucvector_init(&zlibdata); + error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings); + if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size); + ucvector_cleanup(&zlibdata); + + return error; +} + +static unsigned addChunk_IEND(ucvector* out) +{ + unsigned error = 0; + error = addChunk(out, "IEND", 0, 0); + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) +{ + unsigned error = 0; + size_t i; + ucvector text; + ucvector_init(&text); + for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&text, 0); /*0 termination char*/ + for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]); + error = addChunk(out, "tEXt", text.data, text.size); + ucvector_cleanup(&text); + + return error; +} + +static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, + LodePNGCompressSettings* zlibsettings) +{ + unsigned error = 0; + ucvector data, compressed; + size_t i, textsize = strlen(textstring); + + ucvector_init(&data); + ucvector_init(&compressed); + for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&data, 0); /*0 termination char*/ + ucvector_push_back(&data, 0); /*compression method: 0*/ + + error = zlib_compress(&compressed.data, &compressed.size, + (unsigned char*)textstring, textsize, zlibsettings); + if(!error) + { + for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]); + error = addChunk(out, "zTXt", data.data, data.size); + } + + ucvector_cleanup(&compressed); + ucvector_cleanup(&data); + return error; +} + +static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag, + const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) +{ + unsigned error = 0; + ucvector data; + size_t i, textsize = strlen(textstring); + + ucvector_init(&data); + + for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&data, 0); /*null termination char*/ + ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/ + ucvector_push_back(&data, 0); /*compression method*/ + for(i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]); + ucvector_push_back(&data, 0); /*null termination char*/ + for(i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]); + ucvector_push_back(&data, 0); /*null termination char*/ + + if(compressed) + { + ucvector compressed_data; + ucvector_init(&compressed_data); + error = zlib_compress(&compressed_data.data, &compressed_data.size, + (unsigned char*)textstring, textsize, zlibsettings); + if(!error) + { + for(i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]); + } + ucvector_cleanup(&compressed_data); + } + else /*not compressed*/ + { + for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]); + } + + if(!error) error = addChunk(out, "iTXt", data.data, data.size); + ucvector_cleanup(&data); + return error; +} + +static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) +{ + unsigned error = 0; + ucvector bKGD; + ucvector_init(&bKGD); + if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) + { + ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); + } + else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) + { + ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_g / 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_g % 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_b / 256)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_b % 256)); + } + else if(info->color.colortype == LCT_PALETTE) + { + ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); /*palette index*/ + } + + error = addChunk(out, "bKGD", bKGD.data, bKGD.size); + ucvector_cleanup(&bKGD); + + return error; +} + +static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) +{ + unsigned error = 0; + unsigned char* data = (unsigned char*)lodepng_malloc(7); + if(!data) return 83; /*alloc fail*/ + data[0] = (unsigned char)(time->year / 256); + data[1] = (unsigned char)(time->year % 256); + data[2] = (unsigned char)time->month; + data[3] = (unsigned char)time->day; + data[4] = (unsigned char)time->hour; + data[5] = (unsigned char)time->minute; + data[6] = (unsigned char)time->second; + error = addChunk(out, "tIME", data, 7); + lodepng_free(data); + return error; +} + +static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) +{ + unsigned error = 0; + ucvector data; + ucvector_init(&data); + + lodepng_add32bitInt(&data, info->phys_x); + lodepng_add32bitInt(&data, info->phys_y); + ucvector_push_back(&data, info->phys_unit); + + error = addChunk(out, "pHYs", data.data, data.size); + ucvector_cleanup(&data); + + return error; +} + +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, + size_t length, size_t bytewidth, unsigned char filterType) +{ + size_t i; + switch(filterType) + { + case 0: /*None*/ + for(i = 0; i != length; ++i) out[i] = scanline[i]; + break; + case 1: /*Sub*/ + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; + break; + case 2: /*Up*/ + if(prevline) + { + for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; + } + else + { + for(i = 0; i != length; ++i) out[i] = scanline[i]; + } + break; + case 3: /*Average*/ + if(prevline) + { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - prevline[i] / 2; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) / 2); + } + else + { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth] / 2; + } + break; + case 4: /*Paeth*/ + if(prevline) + { + /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ + for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); + for(i = bytewidth; i < length; ++i) + { + out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); + } + } + else + { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ + for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); + } + break; + default: return; /*unexisting filter type given*/ + } +} + +/* log2 approximation. A slight bit faster than std::log. */ +static float flog2(float f) +{ + float result = 0; + while(f > 32) { result += 4; f /= 16; } + while(f > 2) { ++result; f /= 2; } + return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f); +} + +static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) +{ + /* + For PNG filter method 0 + out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are + the scanlines with 1 extra byte per scanline + */ + + unsigned bpp = lodepng_get_bpp(info); + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = (w * bpp + 7) / 8; + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7) / 8; + const unsigned char* prevline = 0; + unsigned x, y; + unsigned error = 0; + LodePNGFilterStrategy strategy = settings->filter_strategy; + + /* + There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: + * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. + use fixed filtering, with the filter None). + * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is + not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply + all five filters and select the filter that produces the smallest sum of absolute values per row. + This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. + + If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, + but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum + heuristic is used. + */ + if(settings->filter_palette_zero && + (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO; + + if(bpp == 0) return 31; /*error: invalid color type*/ + + if(strategy == LFS_ZERO) + { + for(y = 0; y != h; ++y) + { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + out[outindex] = 0; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0); + prevline = &in[inindex]; + } + } + else if(strategy == LFS_MINSUM) + { + /*adaptive filtering*/ + size_t sum[5]; + ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned char type, bestType = 0; + + for(type = 0; type != 5; ++type) + { + ucvector_init(&attempt[type]); + if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/ + } + + if(!error) + { + for(y = 0; y != h; ++y) + { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) + { + filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); + + /*calculate the sum of the result*/ + sum[type] = 0; + if(type == 0) + { + for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type].data[x]); + } + else + { + for(x = 0; x != linebytes; ++x) + { + /*For differences, each byte should be treated as signed, values above 127 are negative + (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. + This means filtertype 0 is almost never chosen, but that is justified.*/ + unsigned char s = attempt[type].data[x]; + sum[type] += s < 128 ? s : (255U - s); + } + } + + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum[type] < smallest) + { + bestType = type; + smallest = sum[type]; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; + } + } + + for(type = 0; type != 5; ++type) ucvector_cleanup(&attempt[type]); + } + else if(strategy == LFS_ENTROPY) + { + float sum[5]; + ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ + float smallest = 0; + unsigned type, bestType = 0; + unsigned count[256]; + + for(type = 0; type != 5; ++type) + { + ucvector_init(&attempt[type]); + if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/ + } + + for(y = 0; y != h; ++y) + { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) + { + filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); + for(x = 0; x != 256; ++x) count[x] = 0; + for(x = 0; x != linebytes; ++x) ++count[attempt[type].data[x]]; + ++count[type]; /*the filter type itself is part of the scanline*/ + sum[type] = 0; + for(x = 0; x != 256; ++x) + { + float p = count[x] / (float)(linebytes + 1); + sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p; + } + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum[type] < smallest) + { + bestType = type; + smallest = sum[type]; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; + } + + for(type = 0; type != 5; ++type) ucvector_cleanup(&attempt[type]); + } + else if(strategy == LFS_PREDEFINED) + { + for(y = 0; y != h; ++y) + { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + unsigned char type = settings->predefined_filters[y]; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } + else if(strategy == LFS_BRUTE_FORCE) + { + /*brute force filter chooser. + deflate the scanline after every filter attempt to see which one deflates best. + This is very slow and gives only slightly smaller, sometimes even larger, result*/ + size_t size[5]; + ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned type = 0, bestType = 0; + unsigned char* dummy; + LodePNGCompressSettings zlibsettings = settings->zlibsettings; + /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, + to simulate the true case where the tree is the same for the whole image. Sometimes it gives + better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare + cases better compression. It does make this a bit less slow, so it's worth doing this.*/ + zlibsettings.btype = 1; + /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG + images only, so disable it*/ + zlibsettings.custom_zlib = 0; + zlibsettings.custom_deflate = 0; + for(type = 0; type != 5; ++type) + { + ucvector_init(&attempt[type]); + ucvector_resize(&attempt[type], linebytes); /*todo: give error if resize failed*/ + } + for(y = 0; y != h; ++y) /*try the 5 filter types*/ + { + for(type = 0; type != 5; ++type) + { + unsigned testsize = attempt[type].size; + /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ + + filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); + size[type] = 0; + dummy = 0; + zlib_compress(&dummy, &size[type], attempt[type].data, testsize, &zlibsettings); + lodepng_free(dummy); + /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || size[type] < smallest) + { + bestType = type; + smallest = size[type]; + } + } + prevline = &in[y * linebytes]; + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; + } + for(type = 0; type != 5; ++type) ucvector_cleanup(&attempt[type]); + } + else return 88; /* unknown filter strategy */ + + return error; +} + +static void addPaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) +{ + /*The opposite of the removePaddingBits function + olinebits must be >= ilinebits*/ + unsigned y; + size_t diff = olinebits - ilinebits; + size_t obp = 0, ibp = 0; /*bit pointers*/ + for(y = 0; y != h; ++y) + { + size_t x; + for(x = 0; x < ilinebits; ++x) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + /*obp += diff; --> no, fill in some value in the padding bits too, to avoid + "Use of uninitialised value of size ###" warning from valgrind*/ + for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); + } +} + +/* +in: non-interlaced image with size w*h +out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with + no padding bits between scanlines, but between reduced images so that each + reduced image starts at a byte. +bpp: bits per pixel +there are no padding bits, not between scanlines, not between reduced images +in has the following size in bits: w * h * bpp. +out is possibly bigger due to padding bits between reduced images +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) +{ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + size_t bytewidth = bpp / 8; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; + for(b = 0; b < bytewidth; ++b) + { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } + else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + for(b = 0; b < bpp; ++b) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. +return value is error**/ +static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, + unsigned w, unsigned h, + const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) +{ + /* + This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: + *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter + *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + unsigned error = 0; + + if(info_png->interlace_method == 0) + { + *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ + + if(!error) + { + /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ + if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) + { + unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8)); + if(!padded) error = 83; /*alloc fail*/ + if(!error) + { + addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h); + error = filter(*out, padded, w, h, &info_png->color, settings); + } + lodepng_free(padded); + } + else + { + /*we can immediatly filter into the out buffer, no other steps needed*/ + error = filter(*out, in, w, h, &info_png->color, settings); + } + } + } + else /*interlace_method is 1 (Adam7)*/ + { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned char* adam7; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out)) error = 83; /*alloc fail*/ + + adam7 = (unsigned char*)lodepng_malloc(passstart[7]); + if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ + + if(!error) + { + unsigned i; + + Adam7_interlace(adam7, in, w, h, bpp); + for(i = 0; i != 7; ++i) + { + if(bpp < 8) + { + unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); + if(!padded) ERROR_BREAK(83); /*alloc fail*/ + addPaddingBits(padded, &adam7[passstart[i]], + ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]); + error = filter(&(*out)[filter_passstart[i]], padded, + passw[i], passh[i], &info_png->color, settings); + lodepng_free(padded); + } + else + { + error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], + passw[i], passh[i], &info_png->color, settings); + } + + if(error) break; + } + } + + lodepng_free(adam7); + } + + return error; +} + +/* +palette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA... +returns 0 if the palette is opaque, +returns 1 if the palette has a single color with alpha 0 ==> color key +returns 2 if the palette is semi-translucent. +*/ +static unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize) +{ + size_t i; + unsigned key = 0; + unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/ + for(i = 0; i != palettesize; ++i) + { + if(!key && palette[4 * i + 3] == 0) + { + r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2]; + key = 1; + i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/ + } + else if(palette[4 * i + 3] != 255) return 2; + /*when key, no opaque RGB may have key's RGB*/ + else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2; + } + return key; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) +{ + unsigned char* inchunk = data; + while((size_t)(inchunk - data) < datasize) + { + CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); + out->allocsize = out->size; /*fix the allocsize again*/ + inchunk = lodepng_chunk_next(inchunk); + } + return 0; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state) +{ + LodePNGInfo info; + ucvector outv; + unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ + size_t datasize = 0; + + /*provide some proper output values if error will happen*/ + *out = 0; + *outsize = 0; + state->error = 0; + + lodepng_info_init(&info); + lodepng_info_copy(&info, &state->info_png); + + if((info.color.colortype == LCT_PALETTE || state->encoder.force_palette) + && (info.color.palettesize == 0 || info.color.palettesize > 256)) + { + state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ + return state->error; + } + + if(state->encoder.auto_convert) + { + state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw); + } + if(state->error) return state->error; + + if(state->encoder.zlibsettings.btype > 2) + { + CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/ + } + if(state->info_png.interlace_method > 1) + { + CERROR_RETURN_ERROR(state->error, 71); /*error: unexisting interlace mode*/ + } + + state->error = checkColorValidity(info.color.colortype, info.color.bitdepth); + if(state->error) return state->error; /*error: unexisting color type given*/ + state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); + if(state->error) return state->error; /*error: unexisting color type given*/ + + if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) + { + unsigned char* converted; + size_t size = (w * h * lodepng_get_bpp(&info.color) + 7) / 8; + + converted = (unsigned char*)lodepng_malloc(size); + if(!converted && size) state->error = 83; /*alloc fail*/ + if(!state->error) + { + state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); + } + if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); + lodepng_free(converted); + } + else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); + + ucvector_init(&outv); + while(!state->error) /*while only executed once, to break on error*/ + { +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + size_t i; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*write signature and chunks*/ + writeSignature(&outv); + /*IHDR*/ + addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*unknown chunks between IHDR and PLTE*/ + if(info.unknown_chunks_data[0]) + { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*PLTE*/ + if(info.color.colortype == LCT_PALETTE) + { + addChunk_PLTE(&outv, &info.color); + } + if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) + { + addChunk_PLTE(&outv, &info.color); + } + /*tRNS*/ + if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0) + { + addChunk_tRNS(&outv, &info.color); + } + if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined) + { + addChunk_tRNS(&outv, &info.color); + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*bKGD (must come between PLTE and the IDAt chunks*/ + if(info.background_defined) addChunk_bKGD(&outv, &info); + /*pHYs (must come before the IDAT chunks)*/ + if(info.phys_defined) addChunk_pHYs(&outv, &info); + + /*unknown chunks between PLTE and IDAT*/ + if(info.unknown_chunks_data[1]) + { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*IDAT (multiple IDAT chunks must be consecutive)*/ + state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*tIME*/ + if(info.time_defined) addChunk_tIME(&outv, &info.time); + /*tEXt and/or zTXt*/ + for(i = 0; i != info.text_num; ++i) + { + if(strlen(info.text_keys[i]) > 79) + { + state->error = 66; /*text chunk too large*/ + break; + } + if(strlen(info.text_keys[i]) < 1) + { + state->error = 67; /*text chunk too small*/ + break; + } + if(state->encoder.text_compression) + { + addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); + } + else + { + addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); + } + } + /*LodePNG version id in text chunk*/ + if(state->encoder.add_id) + { + unsigned alread_added_id_text = 0; + for(i = 0; i != info.text_num; ++i) + { + if(!strcmp(info.text_keys[i], "LodePNG")) + { + alread_added_id_text = 1; + break; + } + } + if(alread_added_id_text == 0) + { + addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ + } + } + /*iTXt*/ + for(i = 0; i != info.itext_num; ++i) + { + if(strlen(info.itext_keys[i]) > 79) + { + state->error = 66; /*text chunk too large*/ + break; + } + if(strlen(info.itext_keys[i]) < 1) + { + state->error = 67; /*text chunk too small*/ + break; + } + addChunk_iTXt(&outv, state->encoder.text_compression, + info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], + &state->encoder.zlibsettings); + } + + /*unknown chunks between IDAT and IEND*/ + if(info.unknown_chunks_data[2]) + { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + addChunk_IEND(&outv); + + break; /*this isn't really a while loop; no error happened so break out now!*/ + } + + lodepng_info_cleanup(&info); + lodepng_free(data); + /*instead of cleaning the vector up, give it to the output*/ + *out = outv.data; + *outsize = outv.size; + + return state->error; +} + +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, + unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + state.info_png.color.colortype = colortype; + state.info_png.color.bitdepth = bitdepth; + lodepng_encode(out, outsize, image, w, h, &state); + error = state.error; + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); + if(!error) error = lodepng_save_file(buffer, buffersize, filename); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) +{ + lodepng_compress_settings_init(&settings->zlibsettings); + settings->filter_palette_zero = 1; + settings->filter_strategy = LFS_MINSUM; + settings->auto_convert = 1; + settings->force_palette = 0; + settings->predefined_filters = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->add_id = 0; + settings->text_compression = 1; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/* +This returns the description of a numerical error code in English. This is also +the documentation of all the error codes. +*/ +const char* lodepng_error_text(unsigned code) +{ + switch(code) + { + case 0: return "no error, everything went ok"; + case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ + case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ + case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ + case 13: return "problem while processing dynamic deflate block"; + case 14: return "problem while processing dynamic deflate block"; + case 15: return "problem while processing dynamic deflate block"; + case 16: return "unexisting code while processing dynamic deflate block"; + case 17: return "end of out buffer memory reached while inflating"; + case 18: return "invalid distance code while inflating"; + case 19: return "end of out buffer memory reached while inflating"; + case 20: return "invalid deflate block BTYPE encountered while decoding"; + case 21: return "NLEN is not ones complement of LEN in a deflate block"; + /*end of out buffer memory reached while inflating: + This can happen if the inflated deflate data is longer than the amount of bytes required to fill up + all the pixels of the image, given the color depth and image dimensions. Something that doesn't + happen in a normal, well encoded, PNG image.*/ + case 22: return "end of out buffer memory reached while inflating"; + case 23: return "end of in buffer memory reached while inflating"; + case 24: return "invalid FCHECK in zlib header"; + case 25: return "invalid compression method in zlib header"; + case 26: return "FDICT encountered in zlib header while it's not used for PNG"; + case 27: return "PNG file is smaller than a PNG header"; + /*Checks the magic file header, the first 8 bytes of the PNG file*/ + case 28: return "incorrect PNG signature, it's no PNG or corrupted"; + case 29: return "first chunk is not the header chunk"; + case 30: return "chunk length too large, chunk broken off at end of file"; + case 31: return "illegal PNG color type or bpp"; + case 32: return "illegal PNG compression method"; + case 33: return "illegal PNG filter method"; + case 34: return "illegal PNG interlace method"; + case 35: return "chunk length of a chunk is too large or the chunk too small"; + case 36: return "illegal PNG filter type encountered"; + case 37: return "illegal bit depth for this color type given"; + case 38: return "the palette is too big"; /*more than 256 colors*/ + case 39: return "more palette alpha values given in tRNS chunk than there are colors in the palette"; + case 40: return "tRNS chunk has wrong size for greyscale image"; + case 41: return "tRNS chunk has wrong size for RGB image"; + case 42: return "tRNS chunk appeared while it was not allowed for this color type"; + case 43: return "bKGD chunk has wrong size for palette image"; + case 44: return "bKGD chunk has wrong size for greyscale image"; + case 45: return "bKGD chunk has wrong size for RGB image"; + /*the input data is empty, maybe a PNG file doesn't exist or is in the wrong path*/ + case 48: return "empty input or file doesn't exist"; + case 49: return "jumped past memory while generating dynamic huffman tree"; + case 50: return "jumped past memory while generating dynamic huffman tree"; + case 51: return "jumped past memory while inflating huffman block"; + case 52: return "jumped past memory while inflating"; + case 53: return "size of zlib data too small"; + case 54: return "repeat symbol in tree while there was no value symbol yet"; + /*jumped past tree while generating huffman tree, this could be when the + tree will have more leaves than symbols after generating it out of the + given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ + case 55: return "jumped past tree while generating huffman tree"; + case 56: return "given output image colortype or bitdepth not supported for color conversion"; + case 57: return "invalid CRC encountered (checking CRC can be disabled)"; + case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; + case 59: return "requested color conversion not supported"; + case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; + case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; + /*LodePNG leaves the choice of RGB to greyscale conversion formula to the user.*/ + case 62: return "conversion from color to greyscale not supported"; + case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; /*(2^31-1)*/ + /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ + case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; + case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; + case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; + case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; + case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; + case 71: return "unexisting interlace mode given to encoder (must be 0 or 1)"; + case 72: return "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)"; + case 73: return "invalid tIME chunk size"; + case 74: return "invalid pHYs chunk size"; + /*length could be wrong, or data chopped off*/ + case 75: return "no null termination char found while decoding text chunk"; + case 76: return "iTXt chunk too short to contain required bytes"; + case 77: return "integer overflow in buffer size"; + case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ + case 79: return "failed to open file for writing"; + case 80: return "tried creating a tree of 0 symbols"; + case 81: return "lazy matching at pos 0 is impossible"; + case 82: return "color conversion to palette requested while a color isn't in palette"; + case 83: return "memory allocation failed"; + case 84: return "given image too small to contain all pixels to be encoded"; + case 86: return "impossible offset in lz77 encoding (internal bug)"; + case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; + case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; + case 89: return "text chunk keyword too short or long: must have size 1-79"; + /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ + case 90: return "windowsize must be a power of two"; + case 91: return "invalid decompressed idat size"; + case 92: return "too many pixels, not supported"; + case 93: return "zero width or height is invalid"; + } + return "unknown error code"; +} +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // C++ Wrapper // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng +{ + +#ifdef LODEPNG_COMPILE_DISK +void load_file(std::vector& buffer, const std::string& filename) +{ + std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate); + + /*get filesize*/ + std::streamsize size = 0; + if(file.seekg(0, std::ios::end).good()) size = file.tellg(); + if(file.seekg(0, std::ios::beg).good()) size -= file.tellg(); + + /*read contents of the file into the vector*/ + buffer.resize(size_t(size)); + if(size > 0) file.read((char*)(&buffer[0]), size); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned save_file(const std::vector& buffer, const std::string& filename) +{ + std::ofstream file(filename.c_str(), std::ios::out|std::ios::binary); + if(!file) return 79; + file.write(buffer.empty() ? 0 : (char*)&buffer[0], std::streamsize(buffer.size())); + return 0; +} +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings) +{ + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings) +{ + return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings) +{ + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings) +{ + return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ + + +#ifdef LODEPNG_COMPILE_PNG + +State::State() +{ + lodepng_state_init(this); +} + +State::State(const State& other) +{ + lodepng_state_init(this); + lodepng_state_copy(this, &other); +} + +State::~State() +{ + lodepng_state_cleanup(this); +} + +State& State::operator=(const State& other) +{ + lodepng_state_copy(this, &other); + return *this; +} + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); + if(buffer && !error) + { + State state; + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) +{ + return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize) +{ + unsigned char* buffer = NULL; + unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); + if(buffer && !error) + { + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in) +{ + return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, + LodePNGColorType colortype, unsigned bitdepth) +{ + std::vector buffer; + load_file(buffer, filename); + return decode(out, w, h, buffer, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DECODER */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} + +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state) +{ + if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, state); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + std::vector buffer; + unsigned error = encode(buffer, in, w, h, colortype, bitdepth); + if(!error) error = save_file(buffer, filename); + return error; +} + +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_PNG */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ diff --git a/util/lodepng.h b/util/lodepng.h new file mode 100644 index 0000000..0f87bc2 --- /dev/null +++ b/util/lodepng.h @@ -0,0 +1,1711 @@ +/* +LodePNG version 20150912 + +Copyright (c) 2005-2015 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef LODEPNG_H +#define LODEPNG_H + +#include /*for size_t*/ + +#ifdef __cplusplus +#include +#include +#endif /*__cplusplus*/ + +extern const char* LODEPNG_VERSION_STRING; + +/* +The following #defines are used to create code sections. They can be disabled +to disable code sections, which can give faster compile time and smaller binary. +The "NO_COMPILE" defines are designed to be used to pass as defines to the +compiler command to disable them without modifying this header, e.g. +-DLODEPNG_NO_COMPILE_ZLIB for gcc. +In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to +allow implementing a custom lodepng_crc32. +*/ +/*deflate & zlib. If disabled, you must specify alternative zlib functions in +the custom_zlib field of the compress and decompress settings*/ +#ifndef LODEPNG_NO_COMPILE_ZLIB +#define LODEPNG_COMPILE_ZLIB +#endif +/*png encoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_PNG +#define LODEPNG_COMPILE_PNG +#endif +/*deflate&zlib decoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_DECODER +#define LODEPNG_COMPILE_DECODER +#endif +/*deflate&zlib encoder and png encoder*/ +#ifndef LODEPNG_NO_COMPILE_ENCODER +#define LODEPNG_COMPILE_ENCODER +#endif +/*the optional built in harddisk file loading and saving functions*/ +#ifndef LODEPNG_NO_COMPILE_DISK +#define LODEPNG_COMPILE_DISK +#endif +/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ +#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS +#define LODEPNG_COMPILE_ANCILLARY_CHUNKS +#endif +/*ability to convert error numerical codes to English text string*/ +#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT +#define LODEPNG_COMPILE_ERROR_TEXT +#endif +/*Compile the default allocators (C's free, malloc and realloc). If you disable this, +you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your +source files with custom allocators.*/ +#ifndef LODEPNG_NO_COMPILE_ALLOCATORS +#define LODEPNG_COMPILE_ALLOCATORS +#endif +/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ +#ifdef __cplusplus +#ifndef LODEPNG_NO_COMPILE_CPP +#define LODEPNG_COMPILE_CPP +#endif +#endif + +#ifdef LODEPNG_COMPILE_PNG +/*The PNG color types (also used for raw).*/ +typedef enum LodePNGColorType +{ + LCT_GREY = 0, /*greyscale: 1,2,4,8,16 bit*/ + LCT_RGB = 2, /*RGB: 8,16 bit*/ + LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ + LCT_GREY_ALPHA = 4, /*greyscale with alpha: 8,16 bit*/ + LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/ +} LodePNGColorType; + +#ifdef LODEPNG_COMPILE_DECODER +/* +Converts PNG data in memory to raw pixel data. +out: Output parameter. Pointer to buffer that will contain the raw pixel data. + After decoding, its size is w * h * (bytes per pixel) bytes larger than + initially. Bytes per pixel depends on colortype and bitdepth. + Must be freed after usage with free(*out). + Note: for 16-bit per channel colors, uses big endian format like PNG does. +w: Output parameter. Pointer to width of pixel data. +h: Output parameter. Pointer to height of pixel data. +in: Memory buffer with the PNG file. +insize: size of the in buffer. +colortype: the desired color type for the raw output image. See explanation on PNG color types. +bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_DISK +/* +Load PNG from disk, from file with given name. +Same as the other decode functions, but instead takes a filename as input. +*/ +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/ +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); + +/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/ +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Converts raw pixel data into a PNG image in memory. The colortype and bitdepth + of the output PNG image cannot be chosen, they are automatically determined + by the colortype, bitdepth and content of the input pixel data. + Note: for 16-bit per channel colors, needs big endian format like PNG does. +out: Output parameter. Pointer to buffer that will contain the PNG image data. + Must be freed after usage with free(*out). +outsize: Output parameter. Pointer to the size in bytes of the out buffer. +image: The raw pixel data to encode. The size of this buffer should be + w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. +w: width of the raw pixel data in pixels. +h: height of the raw pixel data in pixels. +colortype: the color type of the raw input image. See explanation on PNG color types. +bitdepth: the bit depth of the raw input image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DISK +/* +Converts raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. +NOTE: This overwrites existing files without warning! +*/ +unsigned lodepng_encode_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng +{ +#ifdef LODEPNG_COMPILE_DECODER +/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype +is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts PNG file from disk to raw pixel data in memory. +Same as the other decode functions, but instead takes a filename as input. +*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::string& filename, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype +is that of the raw input data. The output PNG color type will be auto chosen.*/ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts 32-bit RGBA raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. +NOTE: This overwrites existing files without warning! +*/ +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/*Returns an English description of the numerical error code.*/ +const char* lodepng_error_text(unsigned code); +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Settings for zlib decompression*/ +typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; +struct LodePNGDecompressSettings +{ + unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ + + /*use custom zlib decoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + /*use custom deflate decoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_inflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGDecompressSettings lodepng_default_decompress_settings; +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Settings for zlib compression. Tweaking these settings tweaks the balance +between speed and compression ratio. +*/ +typedef struct LodePNGCompressSettings LodePNGCompressSettings; +struct LodePNGCompressSettings /*deflate = compress*/ +{ + /*LZ77 related settings*/ + unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ + unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ + unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ + unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ + unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ + unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ + + /*use custom zlib encoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + /*use custom deflate encoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_deflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGCompressSettings lodepng_default_compress_settings; +void lodepng_compress_settings_init(LodePNGCompressSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_PNG +/* +Color mode of an image. Contains all information required to decode the pixel +bits to RGBA colors. This information is the same as used in the PNG file +format, and is used both for PNG and raw image data in LodePNG. +*/ +typedef struct LodePNGColorMode +{ + /*header (IHDR)*/ + LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ + unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ + + /* + palette (PLTE and tRNS) + + Dynamically allocated with the colors of the palette, including alpha. + When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use + lodepng_palette_clear, then for each color use lodepng_palette_add. + If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette. + + When decoding, by default you can ignore this palette, since LodePNG already + fills the palette colors in the pixels of the raw RGBA output. + + The palette is only supported for color type 3. + */ + unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/ + size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/ + + /* + transparent color key (tRNS) + + This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. + For greyscale PNGs, r, g and b will all 3 be set to the same. + + When decoding, by default you can ignore this information, since LodePNG sets + pixels with this key to transparent already in the raw RGBA output. + + The color key is only supported for color types 0 and 2. + */ + unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ + unsigned key_r; /*red/greyscale component of color key*/ + unsigned key_g; /*green component of color key*/ + unsigned key_b; /*blue component of color key*/ +} LodePNGColorMode; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_color_mode_init(LodePNGColorMode* info); +void lodepng_color_mode_cleanup(LodePNGColorMode* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); + +void lodepng_palette_clear(LodePNGColorMode* info); +/*add 1 color to the palette*/ +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info); +/*get the amount of color channels used, based on colortype in the struct. +If a palette is used, it counts as 1 channel.*/ +unsigned lodepng_get_channels(const LodePNGColorMode* info); +/*is it a greyscale type? (only colortype 0 or 4)*/ +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); +/*has it got an alpha channel? (only colortype 2 or 6)*/ +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); +/*has it got a palette? (only colortype 3)*/ +unsigned lodepng_is_palette_type(const LodePNGColorMode* info); +/*only returns true if there is a palette and there is a value in the palette with alpha < 255. +Loops through the palette to check this.*/ +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); +/* +Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. +Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). +Returns false if the image can only have opaque pixels. +In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, +or if "key_defined" is true. +*/ +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); +/*Returns the byte size of a raw image buffer with given width, height and color mode*/ +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*The information of a Time chunk in PNG.*/ +typedef struct LodePNGTime +{ + unsigned year; /*2 bytes used (0-65535)*/ + unsigned month; /*1-12*/ + unsigned day; /*1-31*/ + unsigned hour; /*0-23*/ + unsigned minute; /*0-59*/ + unsigned second; /*0-60 (to allow for leap seconds)*/ +} LodePNGTime; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Information about the PNG image, except pixels, width and height.*/ +typedef struct LodePNGInfo +{ + /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ + unsigned compression_method;/*compression method of the original file. Always 0.*/ + unsigned filter_method; /*filter method of the original file*/ + unsigned interlace_method; /*interlace method of the original file*/ + LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /* + suggested background color chunk (bKGD) + This color uses the same color mode as the PNG (except alpha channel), which can be 1-bit to 16-bit. + + For greyscale PNGs, r, g and b will all 3 be set to the same. When encoding + the encoder writes the red one. For palette PNGs: When decoding, the RGB value + will be stored, not a palette index. But when encoding, specify the index of + the palette in background_r, the other two are then ignored. + + The decoder does not use this background color to edit the color of pixels. + */ + unsigned background_defined; /*is a suggested background color given?*/ + unsigned background_r; /*red component of suggested background color*/ + unsigned background_g; /*green component of suggested background color*/ + unsigned background_b; /*blue component of suggested background color*/ + + /* + non-international text chunks (tEXt and zTXt) + + The char** arrays each contain num strings. The actual messages are in + text_strings, while text_keys are keywords that give a short description what + the actual text represents, e.g. Title, Author, Description, or anything else. + + A keyword is minimum 1 character and maximum 79 characters long. It's + discouraged to use a single line length longer than 79 characters for texts. + + Don't allocate these text buffers yourself. Use the init/cleanup functions + correctly and use lodepng_add_text and lodepng_clear_text. + */ + size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ + char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ + char** text_strings; /*the actual text*/ + + /* + international text chunks (iTXt) + Similar to the non-international text chunks, but with additional strings + "langtags" and "transkeys". + */ + size_t itext_num; /*the amount of international texts in this PNG*/ + char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ + char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ + char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ + char** itext_strings; /*the actual international text - UTF-8 string*/ + + /*time chunk (tIME)*/ + unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ + LodePNGTime time; + + /*phys chunk (pHYs)*/ + unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ + unsigned phys_x; /*pixels per unit in x direction*/ + unsigned phys_y; /*pixels per unit in y direction*/ + unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ + + /* + unknown chunks + There are 3 buffers, one for each position in the PNG where unknown chunks can appear + each buffer contains all unknown chunks for that position consecutively + The 3 buffers are the unknown chunks between certain critical chunks: + 0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND + Do not allocate or traverse this data yourself. Use the chunk traversing functions declared + later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. + */ + unsigned char* unknown_chunks_data[3]; + size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGInfo; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_info_init(LodePNGInfo* info); +void lodepng_info_cleanup(LodePNGInfo* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ + +void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/* +Converts raw buffer from one color type to another color type, based on +LodePNGColorMode structs to describe the input and output color type. +See the reference manual at the end of this header file to see which color conversions are supported. +return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) +The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel +of the output color type (lodepng_get_bpp). +For < 8 bpp images, there should not be padding bits at the end of scanlines. +For 16-bit per channel colors, uses big endian format like PNG does. +Return value is LodePNG error code +*/ +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DECODER +/* +Settings for the decoder. This contains settings for the PNG and the Zlib +decoder, but not the Info settings from the Info structs. +*/ +typedef struct LodePNGDecoderSettings +{ + LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ + + unsigned ignore_crc; /*ignore CRC checksums*/ + + unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ + unsigned remember_unknown_chunks; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGDecoderSettings; + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ +typedef enum LodePNGFilterStrategy +{ + /*every filter at zero*/ + LFS_ZERO, + /*Use filter that gives minumum sum, as described in the official PNG filter heuristic.*/ + LFS_MINSUM, + /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending + on the image, this is better or worse than minsum.*/ + LFS_ENTROPY, + /* + Brute-force-search PNG filters by compressing each filter for each scanline. + Experimental, very slow, and only rarely gives better compression than MINSUM. + */ + LFS_BRUTE_FORCE, + /*use predefined_filters buffer: you specify the filter type for each scanline*/ + LFS_PREDEFINED +} LodePNGFilterStrategy; + +/*Gives characteristics about the colors of the image, which helps decide which color model to use for encoding. +Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ +typedef struct LodePNGColorProfile +{ + unsigned colored; /*not greyscale*/ + unsigned key; /*if true, image is not opaque. Only if true and alpha is false, color key is possible.*/ + unsigned short key_r; /*these values are always in 16-bit bitdepth in the profile*/ + unsigned short key_g; + unsigned short key_b; + unsigned alpha; /*alpha channel or alpha palette required*/ + unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/ + unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/ + unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/ +} LodePNGColorProfile; + +void lodepng_color_profile_init(LodePNGColorProfile* profile); + +/*Get a LodePNGColorProfile of the image.*/ +unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); +/*The function LodePNG uses internally to decide the PNG color with auto_convert. +Chooses an optimal color model, e.g. grey if only grey pixels, palette if < 256 colors, ...*/ +unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); + +/*Settings for the encoder.*/ +typedef struct LodePNGEncoderSettings +{ + LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ + + unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ + + /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than + 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to + completely follow the official PNG heuristic, filter_palette_zero must be true and + filter_strategy must be LFS_MINSUM*/ + unsigned filter_palette_zero; + /*Which filter strategy to use when not using zeroes due to filter_palette_zero. + Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ + LodePNGFilterStrategy filter_strategy; + /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with + the same length as the amount of scanlines in the image, and each value must <= 5. You + have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero + must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ + const unsigned char* predefined_filters; + + /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). + If colortype is 3, PLTE is _always_ created.*/ + unsigned force_palette; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*add LodePNG identifier and version as a text chunk, for debugging*/ + unsigned add_id; + /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ + unsigned text_compression; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGEncoderSettings; + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) +/*The settings, state and information for extended encoding and decoding.*/ +typedef struct LodePNGState +{ +#ifdef LODEPNG_COMPILE_DECODER + LodePNGDecoderSettings decoder; /*the decoding settings*/ +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + LodePNGEncoderSettings encoder; /*the encoding settings*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ + LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ + unsigned error; +#ifdef LODEPNG_COMPILE_CPP + /* For the lodepng::State subclass. */ + virtual ~LodePNGState(){} +#endif +} LodePNGState; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_state_init(LodePNGState* state); +void lodepng_state_cleanup(LodePNGState* state); +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_DECODER +/* +Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and +getting much more information about the PNG image and color mode. +*/ +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); + +/* +Read the PNG header, but not the actual data. This returns only the information +that is in the header chunk of the PNG, such as width, height and color type. The +information is placed in the info_png field of the LodePNGState. +*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); +#endif /*LODEPNG_COMPILE_DECODER*/ + + +#ifdef LODEPNG_COMPILE_ENCODER +/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* +The lodepng_chunk functions are normally not needed, except to traverse the +unknown chunks stored in the LodePNGInfo struct, or add new ones to it. +It also allows traversing the chunks of an encoded PNG file yourself. + +PNG standard chunk naming conventions: +First byte: uppercase = critical, lowercase = ancillary +Second byte: uppercase = public, lowercase = private +Third byte: must be uppercase +Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy +*/ + +/* +Gets the length of the data of the chunk. Total chunk length has 12 bytes more. +There must be at least 4 bytes to read from. If the result value is too large, +it may be corrupt data. +*/ +unsigned lodepng_chunk_length(const unsigned char* chunk); + +/*puts the 4-byte type in null terminated string*/ +void lodepng_chunk_type(char type[5], const unsigned char* chunk); + +/*check if the type is the given type*/ +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); + +/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); + +/*0: public, 1: private (see PNG standard)*/ +unsigned char lodepng_chunk_private(const unsigned char* chunk); + +/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); + +/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ +unsigned char* lodepng_chunk_data(unsigned char* chunk); +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); + +/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ +unsigned lodepng_chunk_check_crc(const unsigned char* chunk); + +/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ +void lodepng_chunk_generate_crc(unsigned char* chunk); + +/*iterate to next chunks. don't use on IEND chunk, as there is no next chunk then*/ +unsigned char* lodepng_chunk_next(unsigned char* chunk); +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk); + +/* +Appends chunk to the data in out. The given chunk should already have its chunk header. +The out variable and outlength are updated to reflect the new reallocated buffer. +Returns error code (0 if it went ok) +*/ +unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk); + +/* +Appends new chunk to out. The chunk to append is given by giving its length, type +and data separately. The type is a 4-letter string. +The out variable and outlength are updated to reflect the new reallocated buffer. +Returne error code (0 if it went ok) +*/ +unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, + const char* type, const unsigned char* data); + + +/*Calculate CRC32 of buffer*/ +unsigned lodepng_crc32(const unsigned char* buf, size_t len); +#endif /*LODEPNG_COMPILE_PNG*/ + + +#ifdef LODEPNG_COMPILE_ZLIB +/* +This zlib part can be used independently to zlib compress and decompress a +buffer. It cannot be used to create gzip files however, and it only supports the +part of zlib that is required for PNG, it does not support dictionaries. +*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); + +/* +Decompresses Zlib data. Reallocates the out buffer and appends the data. The +data must be according to the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Compresses data with Zlib. Reallocates the out buffer and appends the data. +Zlib adds a small header and trailer around the deflate data. +The data is output in the format of the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +/* +Find length-limited Huffman code for given frequencies. This function is in the +public interface only for tests, it's used internally by lodepng_deflate. +*/ +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen); + +/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into buffer. The function allocates the out buffer, and +after usage you should free it. +out: output parameter, contains pointer to loaded buffer. +outsize: output parameter, size of the allocated out buffer +filename: the path to the file to load +return value: error code (0 means ok) +*/ +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); + +/* +Save a file from buffer to disk. Warning, if it exists, this function overwrites +the file without warning! +buffer: the buffer to write +buffersize: size of the buffer to write +filename: the path to the file to save to +return value: error code (0 means ok) +*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ + +#ifdef LODEPNG_COMPILE_CPP +/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ +namespace lodepng +{ +#ifdef LODEPNG_COMPILE_PNG +class State : public LodePNGState +{ + public: + State(); + State(const State& other); + virtual ~State(); + State& operator=(const State& other); +}; + +#ifdef LODEPNG_COMPILE_DECODER +/* Same as other lodepng::decode, but using a State for more settings and information. */ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Same as other lodepng::encode, but using a State for more settings and information. */ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into an std::vector. If the vector is empty, then either +the file doesn't exist or is an empty file. +*/ +void load_file(std::vector& buffer, const std::string& filename); + +/* +Save the binary data in an std::vector to a file on disk. The file is overwritten +without warning. +*/ +unsigned save_file(const std::vector& buffer, const std::string& filename); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_PNG */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +/* Zlib-decompress an unsigned char buffer */ +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); + +/* Zlib-decompress an std::vector */ +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Zlib-compress an unsigned char buffer */ +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); + +/* Zlib-compress an std::vector */ +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ + +/* +TODO: +[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often +[.] check compatibility with vareous compilers - done but needs to be redone for every newer version +[X] converting color to 16-bit per channel types +[ ] read all public PNG chunk types (but never let the color profile and gamma ones touch RGB values) +[ ] make sure encoder generates no chunks with size > (2^31)-1 +[ ] partial decoding (stream processing) +[X] let the "isFullyOpaque" function check color keys and transparent palettes too +[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" +[ ] don't stop decoding on errors like 69, 57, 58 (make warnings) +[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes +[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... +*/ + +#endif /*LODEPNG_H inclusion guard*/ + +/* +LodePNG Documentation +--------------------- + +0. table of contents +-------------------- + + 1. about + 1.1. supported features + 1.2. features not supported + 2. C and C++ version + 3. security + 4. decoding + 5. encoding + 6. color conversions + 6.1. PNG color types + 6.2. color conversions + 6.3. padding bits + 6.4. A note about 16-bits per channel and endianness + 7. error values + 8. chunks and PNG editing + 9. compiler support + 10. examples + 10.1. decoder C++ example + 10.2. decoder C example + 11. changes + 12. contact information + + +1. about +-------- + +PNG is a file format to store raster images losslessly with good compression, +supporting different color types and alpha channel. + +LodePNG is a PNG codec according to the Portable Network Graphics (PNG) +Specification (Second Edition) - W3C Recommendation 10 November 2003. + +The specifications used are: + +*) Portable Network Graphics (PNG) Specification (Second Edition): + http://www.w3.org/TR/2003/REC-PNG-20031110 +*) RFC 1950 ZLIB Compressed Data Format version 3.3: + http://www.gzip.org/zlib/rfc-zlib.html +*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: + http://www.gzip.org/zlib/rfc-deflate.html + +The most recent version of LodePNG can currently be found at +http://lodev.org/lodepng/ + +LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds +extra functionality. + +LodePNG exists out of two files: +-lodepng.h: the header file for both C and C++ +-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage + +If you want to start using LodePNG right away without reading this doc, get the +examples from the LodePNG website to see how to use it in code, or check the +smaller examples in chapter 13 here. + +LodePNG is simple but only supports the basic requirements. To achieve +simplicity, the following design choices were made: There are no dependencies +on any external library. There are functions to decode and encode a PNG with +a single function call, and extended versions of these functions taking a +LodePNGState struct allowing to specify or get more information. By default +the colors of the raw image are always RGB or RGBA, no matter what color type +the PNG file uses. To read and write files, there are simple functions to +convert the files to/from buffers in memory. + +This all makes LodePNG suitable for loading textures in games, demos and small +programs, ... It's less suitable for full fledged image editors, loading PNGs +over network (it requires all the image data to be available before decoding can +begin), life-critical systems, ... + +1.1. supported features +----------------------- + +The following features are supported by the decoder: + +*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, + or the same color type as the PNG +*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image +*) Adam7 interlace and deinterlace for any color type +*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk +*) support for alpha channels, including RGBA color model, translucent palettes and color keying +*) zlib decompression (inflate) +*) zlib compression (deflate) +*) CRC32 and ADLER32 checksums +*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. +*) the following chunks are supported (generated/interpreted) by both encoder and decoder: + IHDR: header information + PLTE: color palette + IDAT: pixel data + IEND: the final chunk + tRNS: transparency for palettized images + tEXt: textual information + zTXt: compressed textual information + iTXt: international textual information + bKGD: suggested background color + pHYs: physical dimensions + tIME: modification time + +1.2. features not supported +--------------------------- + +The following features are _not_ supported: + +*) some features needed to make a conformant PNG-Editor might be still missing. +*) partial loading/stream processing. All data must be available and is processed in one call. +*) The following public chunks are not supported but treated as unknown chunks by LodePNG + cHRM, gAMA, iCCP, sRGB, sBIT, hIST, sPLT + Some of these are not supported on purpose: LodePNG wants to provide the RGB values + stored in the pixels, not values modified by system dependent gamma or color models. + + +2. C and C++ version +-------------------- + +The C version uses buffers allocated with alloc that you need to free() +yourself. You need to use init and cleanup functions for each struct whenever +using a struct from the C version to avoid exploits and memory leaks. + +The C++ version has extra functions with std::vectors in the interface and the +lodepng::State class which is a LodePNGState with constructor and destructor. + +These files work without modification for both C and C++ compilers because all +the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers +ignore it, and the C code is made to compile both with strict ISO C90 and C++. + +To use the C++ version, you need to rename the source file to lodepng.cpp +(instead of lodepng.c), and compile it with a C++ compiler. + +To use the C version, you need to rename the source file to lodepng.c (instead +of lodepng.cpp), and compile it with a C compiler. + + +3. Security +----------- + +Even if carefully designed, it's always possible that LodePNG contains possible +exploits. If you discover one, please let me know, and it will be fixed. + +When using LodePNG, care has to be taken with the C version of LodePNG, as well +as the C-style structs when working with C++. The following conventions are used +for all C-style structs: + +-if a struct has a corresponding init function, always call the init function when making a new one +-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks +-if a struct has a corresponding copy function, use the copy function instead of "=". + The destination must also be inited already. + + +4. Decoding +----------- + +Decoding converts a PNG compressed image to a raw pixel buffer. + +Most documentation on using the decoder is at its declarations in the header +above. For C, simple decoding can be done with functions such as +lodepng_decode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_decode. For C++, all decoding can be done with the +various lodepng::decode functions, and lodepng::State can be used for advanced +features. + +When using the LodePNGState, it uses the following fields for decoding: +*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here +*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get +*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use + +LodePNGInfo info_png +-------------------- + +After decoding, this contains extra information of the PNG image, except the actual +pixels, width and height because these are already gotten directly from the decoder +functions. + +It contains for example the original color type of the PNG image, text comments, +suggested background color, etc... More details about the LodePNGInfo struct are +at its declaration documentation. + +LodePNGColorMode info_raw +------------------------- + +When decoding, here you can specify which color type you want +the resulting raw image to be. If this is different from the colortype of the +PNG, then the decoder will automatically convert the result. This conversion +always works, except if you want it to convert a color PNG to greyscale or to +a palette with missing colors. + +By default, 32-bit color is used for the result. + +LodePNGDecoderSettings decoder +------------------------------ + +The settings can be used to ignore the errors created by invalid CRC and Adler32 +chunks, and to disable the decoding of tEXt chunks. + +There's also a setting color_convert, true by default. If false, no conversion +is done, the resulting data will be as it was in the PNG (after decompression) +and you'll have to puzzle the colors of the pixels together yourself using the +color type information in the LodePNGInfo. + + +5. Encoding +----------- + +Encoding converts a raw pixel buffer to a PNG compressed image. + +Most documentation on using the encoder is at its declarations in the header +above. For C, simple encoding can be done with functions such as +lodepng_encode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_encode. For C++, all encoding can be done with the +various lodepng::encode functions, and lodepng::State can be used for advanced +features. + +Like the decoder, the encoder can also give errors. However it gives less errors +since the encoder input is trusted, the decoder input (a PNG image that could +be forged by anyone) is not trusted. + +When using the LodePNGState, it uses the following fields for encoding: +*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. +*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has +*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use + +LodePNGInfo info_png +-------------------- + +When encoding, you use this the opposite way as when decoding: for encoding, +you fill in the values you want the PNG to have before encoding. By default it's +not needed to specify a color type for the PNG since it's automatically chosen, +but it's possible to choose it yourself given the right settings. + +The encoder will not always exactly match the LodePNGInfo struct you give, +it tries as close as possible. Some things are ignored by the encoder. The +encoder uses, for example, the following settings from it when applicable: +colortype and bitdepth, text chunks, time chunk, the color key, the palette, the +background color, the interlace method, unknown chunks, ... + +When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. +If the palette contains any colors for which the alpha channel is not 255 (so +there are translucent colors in the palette), it'll add a tRNS chunk. + +LodePNGColorMode info_raw +------------------------- + +You specify the color type of the raw image that you give to the input here, +including a possible transparent color key and palette you happen to be using in +your raw image data. + +By default, 32-bit color is assumed, meaning your input has to be in RGBA +format with 4 bytes (unsigned chars) per pixel. + +LodePNGEncoderSettings encoder +------------------------------ + +The following settings are supported (some are in sub-structs): +*) auto_convert: when this option is enabled, the encoder will +automatically choose the smallest possible color mode (including color key) that +can encode the colors of all pixels without information loss. +*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, + 2 = dynamic huffman tree (best compression). Should be 2 for proper + compression. +*) use_lz77: whether or not to use LZ77 for compressed block types. Should be + true for proper compression. +*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value + 2048 by default, but can be set to 32768 for better, but slow, compression. +*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE + chunk if force_palette is true. This can used as suggested palette to convert + to by viewers that don't support more than 256 colors (if those still exist) +*) add_id: add text chunk "Encoder: LodePNG " to the image. +*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. + zTXt chunks use zlib compression on the text. This gives a smaller result on + large texts but a larger result on small texts (such as a single program name). + It's all tEXt or all zTXt though, there's no separate setting per text yet. + + +6. color conversions +-------------------- + +An important thing to note about LodePNG, is that the color type of the PNG, and +the color type of the raw image, are completely independent. By default, when +you decode a PNG, you get the result as a raw image in the color type you want, +no matter whether the PNG was encoded with a palette, greyscale or RGBA color. +And if you encode an image, by default LodePNG will automatically choose the PNG +color type that gives good compression based on the values of colors and amount +of colors in the image. It can be configured to let you control it instead as +well, though. + +To be able to do this, LodePNG does conversions from one color mode to another. +It can convert from almost any color type to any other color type, except the +following conversions: RGB to greyscale is not supported, and converting to a +palette when the palette doesn't have a required color is not supported. This is +not supported on purpose: this is information loss which requires a color +reduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to grey +is easy, but there are multiple ways if you want to give some channels more +weight). + +By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB +color, no matter what color type the PNG has. And by default when encoding, +LodePNG automatically picks the best color model for the output PNG, and expects +the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control +the color format of the images yourself, you can skip this chapter. + +6.1. PNG color types +-------------------- + +A PNG image can have many color types, ranging from 1-bit color to 64-bit color, +as well as palettized color modes. After the zlib decompression and unfiltering +in the PNG image is done, the raw pixel data will have that color type and thus +a certain amount of bits per pixel. If you want the output raw image after +decoding to have another color type, a conversion is done by LodePNG. + +The PNG specification gives the following color types: + +0: greyscale, bit depths 1, 2, 4, 8, 16 +2: RGB, bit depths 8 and 16 +3: palette, bit depths 1, 2, 4 and 8 +4: greyscale with alpha, bit depths 8 and 16 +6: RGBA, bit depths 8 and 16 + +Bit depth is the amount of bits per pixel per color channel. So the total amount +of bits per pixel is: amount of channels * bitdepth. + +6.2. color conversions +---------------------- + +As explained in the sections about the encoder and decoder, you can specify +color types and bit depths in info_png and info_raw to change the default +behaviour. + +If, when decoding, you want the raw image to be something else than the default, +you need to set the color type and bit depth you want in the LodePNGColorMode, +or the parameters colortype and bitdepth of the simple decoding function. + +If, when encoding, you use another color type than the default in the raw input +image, you need to specify its color type and bit depth in the LodePNGColorMode +of the raw image, or use the parameters colortype and bitdepth of the simple +encoding function. + +If, when encoding, you don't want LodePNG to choose the output PNG color type +but control it yourself, you need to set auto_convert in the encoder settings +to false, and specify the color type you want in the LodePNGInfo of the +encoder (including palette: it can generate a palette if auto_convert is true, +otherwise not). + +If the input and output color type differ (whether user chosen or auto chosen), +LodePNG will do a color conversion, which follows the rules below, and may +sometimes result in an error. + +To avoid some confusion: +-the decoder converts from PNG to raw image +-the encoder converts from raw image to PNG +-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image +-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG +-when encoding, the color type in LodePNGInfo is ignored if auto_convert + is enabled, it is automatically generated instead +-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original + PNG image, but it can be ignored since the raw image has the color type you requested instead +-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion + between the color types is done if the color types are supported. If it is not + supported, an error is returned. If the types are the same, no conversion is done. +-even though some conversions aren't supported, LodePNG supports loading PNGs from any + colortype and saving PNGs to any colortype, sometimes it just requires preparing + the raw image correctly before encoding. +-both encoder and decoder use the same color converter. + +Non supported color conversions: +-color to greyscale: no error is thrown, but the result will look ugly because +only the red channel is taken +-anything to palette when that palette does not have that color in it: in this +case an error is thrown + +Supported color conversions: +-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA +-any grey or grey+alpha, to grey or grey+alpha +-anything to a palette, as long as the palette has the requested colors in it +-removing alpha channel +-higher to smaller bitdepth, and vice versa + +If you want no color conversion to be done (e.g. for speed or control): +-In the encoder, you can make it save a PNG with any color type by giving the +raw color mode and LodePNGInfo the same color mode, and setting auto_convert to +false. +-In the decoder, you can make it store the pixel data in the same color type +as the PNG has, by setting the color_convert setting to false. Settings in +info_raw are then ignored. + +The function lodepng_convert does the color conversion. It is available in the +interface but normally isn't needed since the encoder and decoder already call +it. + +6.3. padding bits +----------------- + +In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines +have a bit amount that isn't a multiple of 8, then padding bits are used so that each +scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. +The raw input image you give to the encoder, and the raw output image you get from the decoder +will NOT have these padding bits, e.g. in the case of a 1-bit image with a width +of 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte, +not the first bit of a new byte. + +6.4. A note about 16-bits per channel and endianness +---------------------------------------------------- + +LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like +for any other color format. The 16-bit values are stored in big endian (most +significant byte first) in these arrays. This is the opposite order of the +little endian used by x86 CPU's. + +LodePNG always uses big endian because the PNG file format does so internally. +Conversions to other formats than PNG uses internally are not supported by +LodePNG on purpose, there are myriads of formats, including endianness of 16-bit +colors, the order in which you store R, G, B and A, and so on. Supporting and +converting to/from all that is outside the scope of LodePNG. + +This may mean that, depending on your use case, you may want to convert the big +endian output of LodePNG to little endian with a for loop. This is certainly not +always needed, many applications and libraries support big endian 16-bit colors +anyway, but it means you cannot simply cast the unsigned char* buffer to an +unsigned short* buffer on x86 CPUs. + + +7. error values +--------------- + +All functions in LodePNG that return an error code, return 0 if everything went +OK, or a non-zero code if there was an error. + +The meaning of the LodePNG error values can be retrieved with the function +lodepng_error_text: given the numerical error code, it returns a description +of the error in English as a string. + +Check the implementation of lodepng_error_text to see the meaning of each code. + + +8. chunks and PNG editing +------------------------- + +If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG +editor that should follow the rules about handling of unknown chunks, or if your +program is able to read other types of chunks than the ones handled by LodePNG, +then that's possible with the chunk functions of LodePNG. + +A PNG chunk has the following layout: + +4 bytes length +4 bytes type name +length bytes data +4 bytes CRC + +8.1. iterating through chunks +----------------------------- + +If you have a buffer containing the PNG image data, then the first chunk (the +IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the +signature of the PNG and are not part of a chunk. But if you start at byte 8 +then you have a chunk, and can check the following things of it. + +NOTE: none of these functions check for memory buffer boundaries. To avoid +exploits, always make sure the buffer contains all the data of the chunks. +When using lodepng_chunk_next, make sure the returned value is within the +allocated memory. + +unsigned lodepng_chunk_length(const unsigned char* chunk): + +Get the length of the chunk's data. The total chunk length is this length + 12. + +void lodepng_chunk_type(char type[5], const unsigned char* chunk): +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): + +Get the type of the chunk or compare if it's a certain type + +unsigned char lodepng_chunk_critical(const unsigned char* chunk): +unsigned char lodepng_chunk_private(const unsigned char* chunk): +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): + +Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). +Check if the chunk is private (public chunks are part of the standard, private ones not). +Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical +chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your +program doesn't handle that type of unknown chunk. + +unsigned char* lodepng_chunk_data(unsigned char* chunk): +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): + +Get a pointer to the start of the data of the chunk. + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk): +void lodepng_chunk_generate_crc(unsigned char* chunk): + +Check if the crc is correct or generate a correct one. + +unsigned char* lodepng_chunk_next(unsigned char* chunk): +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): + +Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these +functions do no boundary checking of the allocated data whatsoever, so make sure there is enough +data available in the buffer to be able to go to the next chunk. + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk): +unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, + const char* type, const unsigned char* data): + +These functions are used to create new chunks that are appended to the data in *out that has +length *outlength. The append function appends an existing chunk to the new data. The create +function creates a new chunk with the given parameters and appends it. Type is the 4-letter +name of the chunk. + +8.2. chunks in info_png +----------------------- + +The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 +buffers (each with size) to contain 3 types of unknown chunks: +the ones that come before the PLTE chunk, the ones that come between the PLTE +and the IDAT chunks, and the ones that come after the IDAT chunks. +It's necessary to make the distionction between these 3 cases because the PNG +standard forces to keep the ordering of unknown chunks compared to the critical +chunks, but does not force any other ordering rules. + +info_png.unknown_chunks_data[0] is the chunks before PLTE +info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT +info_png.unknown_chunks_data[2] is the chunks after IDAT + +The chunks in these 3 buffers can be iterated through and read by using the same +way described in the previous subchapter. + +When using the decoder to decode a PNG, you can make it store all unknown chunks +if you set the option settings.remember_unknown_chunks to 1. By default, this +option is off (0). + +The encoder will always encode unknown chunks that are stored in the info_png. +If you need it to add a particular chunk that isn't known by LodePNG, you can +use lodepng_chunk_append or lodepng_chunk_create to the chunk data in +info_png.unknown_chunks_data[x]. + +Chunks that are known by LodePNG should not be added in that way. E.g. to make +LodePNG add a bKGD chunk, set background_defined to true and add the correct +parameters there instead. + + +9. compiler support +------------------- + +No libraries other than the current standard C library are needed to compile +LodePNG. For the C++ version, only the standard C++ library is needed on top. +Add the files lodepng.c(pp) and lodepng.h to your project, include +lodepng.h where needed, and your program can read/write PNG files. + +It is compatible with C90 and up, and C++03 and up. + +If performance is important, use optimization when compiling! For both the +encoder and decoder, this makes a large difference. + +Make sure that LodePNG is compiled with the same compiler of the same version +and with the same settings as the rest of the program, or the interfaces with +std::vectors and std::strings in C++ can be incompatible. + +CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. + +*) gcc and g++ + +LodePNG is developed in gcc so this compiler is natively supported. It gives no +warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ +version 4.7.1 on Linux, 32-bit and 64-bit. + +*) Clang + +Fully supported and warning-free. + +*) Mingw + +The Mingw compiler (a port of gcc for Windows) should be fully supported by +LodePNG. + +*) Visual Studio and Visual C++ Express Edition + +LodePNG should be warning-free with warning level W4. Two warnings were disabled +with pragmas though: warning 4244 about implicit conversions, and warning 4996 +where it wants to use a non-standard function fopen_s instead of the standard C +fopen. + +Visual Studio may want "stdafx.h" files to be included in each source file and +give an error "unexpected end of file while looking for precompiled header". +This is not standard C++ and will not be added to the stock LodePNG. You can +disable it for lodepng.cpp only by right clicking it, Properties, C/C++, +Precompiled Headers, and set it to Not Using Precompiled Headers there. + +NOTE: Modern versions of VS should be fully supported, but old versions, e.g. +VS6, are not guaranteed to work. + +*) Compilers on Macintosh + +LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for +C and C++. + +*) Other Compilers + +If you encounter problems on any compilers, feel free to let me know and I may +try to fix it if the compiler is modern and standards complient. + + +10. examples +------------ + +This decoder example shows the most basic usage of LodePNG. More complex +examples can be found on the LodePNG website. + +10.1. decoder C++ example +------------------------- + +#include "lodepng.h" +#include + +int main(int argc, char *argv[]) +{ + const char* filename = argc > 1 ? argv[1] : "test.png"; + + //load and decode + std::vector image; + unsigned width, height; + unsigned error = lodepng::decode(image, width, height, filename); + + //if there's an error, display it + if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; + + //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... +} + +10.2. decoder C example +----------------------- + +#include "lodepng.h" + +int main(int argc, char *argv[]) +{ + unsigned error; + unsigned char* image; + size_t width, height; + const char* filename = argc > 1 ? argv[1] : "test.png"; + + error = lodepng_decode32_file(&image, &width, &height, filename); + + if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); + + / * use image here * / + + free(image); + return 0; +} + + +11. changes +----------- + +The version number of LodePNG is the date of the change given in the format +yyyymmdd. + +Some changes aren't backwards compatible. Those are indicated with a (!) +symbol. + +*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. +*) 23 aug 2014: Reduced needless memory usage of decoder. +*) 28 jun 2014: Removed fix_png setting, always support palette OOB for + simplicity. Made ColorProfile public. +*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. +*) 22 dec 2013: Power of two windowsize required for optimization. +*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. +*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). +*) 11 mar 2013 (!): Bugfix with custom free. Changed from "my" to "lodepng_" + prefix for the custom allocators and made it possible with a new #define to + use custom ones in your project without needing to change lodepng's code. +*) 28 jan 2013: Bugfix with color key. +*) 27 okt 2012: Tweaks in text chunk keyword length error handling. +*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode. + (no palette). Better deflate tree encoding. New compression tweak settings. + Faster color conversions while decoding. Some internal cleanups. +*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. +*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions + and made it work with function pointers instead. +*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc + and free functions and toggle #defines from compiler flags. Small fixes. +*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible. +*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed + redundant C++ codec classes. Reduced amount of structs. Everything changed, + but it is cleaner now imho and functionality remains the same. Also fixed + several bugs and shrinked the implementation code. Made new samples. +*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best + PNG color model and bit depth, based on the amount and type of colors of the + raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. +*) 9 okt 2011: simpler hash chain implementation for the encoder. +*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. +*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. + A bug with the PNG filtertype heuristic was fixed, so that it chooses much + better ones (it's quite significant). A setting to do an experimental, slow, + brute force search for PNG filter types is added. +*) 17 aug 2011 (!): changed some C zlib related function names. +*) 16 aug 2011: made the code less wide (max 120 characters per line). +*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. +*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. +*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman + to optimize long sequences of zeros. +*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and + LodePNG_InfoColor_canHaveAlpha functions for convenience. +*) 7 nov 2010: added LodePNG_error_text function to get error code description. +*) 30 okt 2010: made decoding slightly faster +*) 26 okt 2010: (!) changed some C function and struct names (more consistent). + Reorganized the documentation and the declaration order in the header. +*) 08 aug 2010: only changed some comments and external samples. +*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. +*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. +*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could + read by ignoring the problem but windows apps couldn't. +*) 06 jun 2008: added more error checks for out of memory cases. +*) 26 apr 2008: added a few more checks here and there to ensure more safety. +*) 06 mar 2008: crash with encoding of strings fixed +*) 02 feb 2008: support for international text chunks added (iTXt) +*) 23 jan 2008: small cleanups, and #defines to divide code in sections +*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. +*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. +*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added + Also vareous fixes, such as in the deflate and the padding bits code. +*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved + filtering code of encoder. +*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A + C++ wrapper around this provides an interface almost identical to before. + Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code + are together in these files but it works both for C and C++ compilers. +*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks +*) 30 aug 2007: bug fixed which makes this Borland C++ compatible +*) 09 aug 2007: some VS2005 warnings removed again +*) 21 jul 2007: deflate code placed in new namespace separate from zlib code +*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images +*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing + invalid std::vector element [0] fixed, and level 3 and 4 warnings removed +*) 02 jun 2007: made the encoder add a tag with version by default +*) 27 may 2007: zlib and png code separated (but still in the same file), + simple encoder/decoder functions added for more simple usage cases +*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), + moved some examples from here to lodepng_examples.cpp +*) 12 may 2007: palette decoding bug fixed +*) 24 apr 2007: changed the license from BSD to the zlib license +*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. +*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding + palettized PNG images. Plus little interface change with palette and texts. +*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. + Fixed a bug where the end code of a block had length 0 in the Huffman tree. +*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented + and supported by the encoder, resulting in smaller PNGs at the output. +*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. +*) 24 jan 2007: gave encoder an error interface. Added color conversion from any + greyscale type to 8-bit greyscale with or without alpha. +*) 21 jan 2007: (!) Totally changed the interface. It allows more color types + to convert to and is more uniform. See the manual for how it works now. +*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: + encode/decode custom tEXt chunks, separate classes for zlib & deflate, and + at last made the decoder give errors for incorrect Adler32 or Crc. +*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. +*) 29 dec 2006: Added support for encoding images without alpha channel, and + cleaned out code as well as making certain parts faster. +*) 28 dec 2006: Added "Settings" to the encoder. +*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. + Removed some code duplication in the decoder. Fixed little bug in an example. +*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. + Fixed a bug of the decoder with 16-bit per color. +*) 15 okt 2006: Changed documentation structure +*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the + given image buffer, however for now it's not compressed. +*) 08 sep 2006: (!) Changed to interface with a Decoder class +*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different + way. Renamed decodePNG to decodePNGGeneric. +*) 29 jul 2006: (!) Changed the interface: image info is now returned as a + struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. +*) 28 jul 2006: Cleaned the code and added new error checks. + Corrected terminology "deflate" into "inflate". +*) 23 jun 2006: Added SDL example in the documentation in the header, this + example allows easy debugging by displaying the PNG and its transparency. +*) 22 jun 2006: (!) Changed way to obtain error value. Added + loadFile function for convenience. Made decodePNG32 faster. +*) 21 jun 2006: (!) Changed type of info vector to unsigned. + Changed position of palette in info vector. Fixed an important bug that + happened on PNGs with an uncompressed block. +*) 16 jun 2006: Internally changed unsigned into unsigned where + needed, and performed some optimizations. +*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them + in LodePNG namespace. Changed the order of the parameters. Rewrote the + documentation in the header. Renamed files to lodepng.cpp and lodepng.h +*) 22 apr 2006: Optimized and improved some code +*) 07 sep 2005: (!) Changed to std::vector interface +*) 12 aug 2005: Initial release (C++, decoder only) + + +12. contact information +----------------------- + +Feel free to contact me with suggestions, problems, comments, ... concerning +LodePNG. If you encounter a PNG image that doesn't work properly with this +decoder, feel free to send it and I'll use it to find and fix the problem. + +My email address is (puzzle the account and domain together with an @ symbol): +Domain: gmail dot com. +Account: lode dot vandevenne. + + +Copyright (c) 2005-2015 Lode Vandevenne +*/ diff --git a/util/obj.cpp b/util/obj.cpp index 6ae70f1..8d3127c 100644 --- a/util/obj.cpp +++ b/util/obj.cpp @@ -38,19 +38,29 @@ obj::~obj() { delete faceboxes[i]; } - + delete vbo; + delete tbo; + delete nbo; + delete ibo; } void obj::buildBufPoss() { recenter(); vector BufPosvec; vector BufNorvec; + vector BufTexvec; vector BufIdxvec; int index = 0; bool genNormals = false; if (faces.size() != facenormals.size() || facenormals[0].size() == 0) { genNormals = true; } + //MY + bool useTexture = false; + if (facetextures.size() > 0) { + useTexture = true; + } + for (int k = 0; k < (int) faces.size(); k++) { if (isConvex(faces[k]) == true) { @@ -99,6 +109,17 @@ void obj::buildBufPoss() { BufNorvec.push_back(n[2]); //BufNorvec.push_back(0.0f); } + if (useTexture) + { + vector facetex = facetextures[k]; + BufTexvec.push_back(texturecoords.at(facetex[0]).x); + BufTexvec.push_back(texturecoords.at(facetex[0]).y); + BufTexvec.push_back(texturecoords.at(facetex[i-1]).x); + BufTexvec.push_back(texturecoords.at(facetex[i-1]).y); + BufTexvec.push_back(texturecoords.at(facetex[i]).x); + BufTexvec.push_back(texturecoords.at(facetex[i]).y); + } + BufIdxvec.push_back(index + 0); BufIdxvec.push_back(index + 1); BufIdxvec.push_back(index + 2); @@ -110,10 +131,12 @@ void obj::buildBufPoss() { vbo = new float[BufPosvec.size()]; nbo = new float[BufNorvec.size()]; + tbo = new float[BufTexvec.size()]; ibo = new int[BufIdxvec.size()]; vbosize = (int)BufPosvec.size(); nbosize = (int)BufNorvec.size(); ibosize = (int)BufIdxvec.size(); + tbosize = (int)BufTexvec.size(); for (int i = 0; i < (int) BufPosvec.size(); i++) { vbo[i] = BufPosvec[i]; } @@ -123,6 +146,9 @@ void obj::buildBufPoss() { for (int i = 0; i < (int) BufIdxvec.size(); i++) { ibo[i] = BufIdxvec[i]; } + for (int i = 0; i < (int)BufTexvec.size(); i++) { + tbo[i] = BufTexvec[i]; + } setColor(glm::vec3(1, 1, 1)); printf("Mesh built: buffers contain %d faces & %d vertices\n", @@ -317,8 +343,28 @@ void obj::addNormal(glm::vec3 normal) { normals.push_back(glm::vec4(normal[0], normal[1], normal[2], 1)); } -void obj::addTextureCoord(glm::vec3 texcoord) { - texturecoords.push_back(glm::vec4(texcoord[0], texcoord[1], texcoord[2], 1)); +//void obj::addTextureCoord(glm::vec3 texcoord) { +// texturecoords.push_back(glm::vec4(texcoord[0], texcoord[1], texcoord[2], 1)); +//} +void obj::addTextureCoord(glm::vec2 texcoord) { + if (texcoord.x < 0.0f) + { + texcoord.x = 0.0f; + } + else if (texcoord.x > 1.0f) + { + texcoord.x = 1.0f; + } + + if (texcoord.y < 0.0f) + { + texcoord.y = 0.0f; + } + else if (texcoord.y > 1.0f) + { + texcoord.y = 1.0f; + } + texturecoords.push_back(texcoord); } float *obj::getBoundingBox() { @@ -443,7 +489,8 @@ vector *obj::getNormals() { return &normals; } -vector *obj::getTextureCoords() { +//vector *obj::getTextureCoords() { +vector *obj::getTextureCoords() { return &texturecoords; } @@ -467,6 +514,10 @@ float *obj::getBufNor() { return nbo; } +float *obj::getBufTex() { + return tbo; +} + int *obj::getBufIdx() { return ibo; } @@ -487,3 +538,5 @@ int obj::getBufColsize() { return cbosize; } + + diff --git a/util/obj.hpp b/util/obj.hpp index d81f5f6..192f62b 100644 --- a/util/obj.hpp +++ b/util/obj.hpp @@ -22,15 +22,19 @@ class obj { vector > facetextures; vector faceboxes; //bounding boxes for each face are stored in vbo-format! vector normals; - vector texturecoords; + //vector texturecoords; + vector texturecoords; int vbosize; int nbosize; int cbosize; int ibosize; + int tbosize; float *vbo; float *nbo; float *cbo; + float *tbo; int *ibo; + float *boundingbox; float top; glm::vec3 defaultColor; @@ -41,6 +45,22 @@ class obj { float zmax; float zmin; bool maxminSet; + +public: + glm::vec3 diffuse_color; + glm::vec3 ambient_color; + glm::vec3 specular_color; + float specular_exponent; + std::string diffuse_texture_file; + std::string specular_texture_file; + int mDiffTexID; + int mSpecTexID; + + int diffuse_width, diffuse_height; + int specular_width, specular_height; + std::vector diffuse_tex; + std::vector specular_tex; + public: obj(); ~obj(); @@ -52,7 +72,8 @@ class obj { void addPoint(glm::vec3); void addFace(vector); void addNormal(glm::vec3); - void addTextureCoord(glm::vec3); + //void addTextureCoord(glm::vec3); + void addTextureCoord(glm::vec2); void addFaceNormal(vector); void addFaceTexture(vector); void compareMaxMin(float, float, float); @@ -69,6 +90,7 @@ class obj { float *getBufPos(); float *getBufCol(); float *getBufNor(); + float *getBufTex(); int *getBufIdx(); int getBufPossize(); int getBufNorsize(); @@ -79,6 +101,11 @@ class obj { vector > *getFaceNormals(); vector > *getFaceTextures(); vector *getNormals(); - vector *getTextureCoords(); + //vector *getTextureCoords(); + vector *getTextureCoords(); vector *getFaceBoxes(); + + + + }; diff --git a/util/objloader.cpp b/util/objloader.cpp index 0b00e6c..56962db 100644 --- a/util/objloader.cpp +++ b/util/objloader.cpp @@ -13,6 +13,7 @@ #include #include #include "objloader.hpp" +#include "lodepng.h" using namespace std; @@ -39,8 +40,9 @@ objLoader::objLoader(string filename, obj *newMesh) { getline(liness, v, ' '); getline(liness, x, ' '); getline(liness, y, ' '); - getline(liness, z, ' '); - geomesh->addTextureCoord(glm::vec3(::atof(x.c_str()), ::atof(y.c_str()), ::atof(z.c_str()))); + //getline(liness, z, ' '); + //geomesh->addTextureCoord(glm::vec3(::atof(x.c_str()), ::atof(y.c_str()), ::atof(z.c_str()))); + geomesh->addTextureCoord(glm::vec2(::atof(x.c_str()), ::atof(y.c_str()))); } else if (line[0] == 'v' && line[1] == 'n') { string v; string x; @@ -115,6 +117,22 @@ objLoader::objLoader(string filename, obj *newMesh) { //std::cout << "Vertex Format" << std::endl; } } + //MY, material(texture) + else if (line[0] == 'm') + { + string linetype; + liness >> linetype; + if (linetype == "mtllib") + { + string matfile; + liness >> matfile; + //parse Material file + parseMaterial(matfile); + } + } + + + } printf("Loaded %d faces & %d vertices from %s\n", @@ -133,3 +151,117 @@ objLoader::~objLoader() { obj *objLoader::getMesh() { return geomesh; } + + + +void objLoader::parseMaterial(const string & materialfn) +{ + printf("Loaded material from %s \n", materialfn.c_str()); + ifstream matStream; + matStream.open(materialfn.c_str()); + if (matStream.fail()){ + cerr << "Unable to open file: " << materialfn << endl; + cin.get(); + exit(1); + } + + while (!matStream.fail()){ + string line; + string linetype; + + getline(matStream, line); + stringstream linestream; + linestream.str(line); + linestream >> linetype; + + if (linetype == "Kd" || + linetype == "Ka" || + linetype == "Ks"){ + + float c[3]; + linestream >> c[0] >> c[1] >> c[2]; + + //Normalize in case of file errors + //for(int i=0; i< 3; i++) + // if(c[i] > 1.0f) c[i] = 1.0f; + + glm::vec3 *color = NULL; + + if (linetype == "Kd") + color = &geomesh->diffuse_color; + if (linetype == "Ka") + color = &geomesh->ambient_color; + if (linetype == "Ks") + color = &geomesh->specular_color; + + if (color != NULL) { + (*color)[0] = c[0]; + (*color)[1] = c[1]; + (*color)[2] = c[2]; + } + } + + if (linetype == "map_Kd") + linestream >> geomesh->diffuse_texture_file; + + if (linetype == "map_Ks") + linestream >> geomesh->specular_texture_file; + + if (linetype == "Ns") + linestream >> geomesh->specular_exponent; + } + + //simple version + //int w, h; + if (geomesh->diffuse_texture_file != "") + { + getTexture(geomesh->diffuse_texture_file, + geomesh->diffuse_tex, geomesh->diffuse_width, geomesh->diffuse_height); + } + + if (geomesh->specular_texture_file != "") + { + getTexture(geomesh->specular_texture_file, + geomesh->specular_tex, geomesh->specular_width, geomesh->specular_height); + } +} + +#define MGL_GET_RED(P) (((P) & 0x000000ff)) +#define MGL_GET_GREEN(P) (((P) & 0x0000ff00) >> 8) +#define MGL_GET_BLUE(P) (((P) & 0x00ff0000) >> 16) + +void objLoader::getTexture(const string & filename, vector & data, int & width, int & height) +{ + std::vector image; + + unsigned w, h; + unsigned error = lodepng::decode(image, w, h, filename.c_str()); + + width = w; + height = h; + + + // If there's an error, display it. + if (error != 0) + { + std::cout << "error " << error << ": " << lodepng_error_text(error) << std::endl; + return; + } + + data.resize(w*h); + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { + int index = (i * w + j); + + int index_img = (h - 1 - i) * w + j; + + //no alpha + + data.at(index).r = (float)((int)image.at(4 * index_img + 0)) / 255.0f; + data.at(index).g = (float)((int)image.at(4 * index_img + 1)) / 255.0f; + data.at(index).b = (float)((int)image.at(4 * index_img + 2)) / 255.0f; + } + } +} \ No newline at end of file diff --git a/util/objloader.hpp b/util/objloader.hpp index 229d570..bfd93ee 100644 --- a/util/objloader.hpp +++ b/util/objloader.hpp @@ -25,4 +25,11 @@ class objLoader { //------------------------ obj *getMesh(); + + + //MY + void parseMaterial(const string & materialfn); + + + void getTexture(const string & filename, vector & data, int & width, int & height); };