/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup bmesh * * Primitive shapes. */ #include "MEM_guardedalloc.h" #include "BLI_math_base_safe.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BKE_customdata.hh" #include "bmesh.hh" #include "intern/bmesh_operators_private.hh" /* ************************ primitives ******************* */ static const float icovert[12][3] = { {0.0f, 0.0f, -200.0f}, {144.72f, -105.144f, -89.443f}, {-55.277f, -170.128, -89.443f}, {-178.885f, 0.0f, -89.443f}, {-55.277f, 170.128f, -89.443f}, {144.72f, 105.144f, -89.443f}, {55.277f, -170.128f, 89.443f}, {-144.72f, -105.144f, 89.443f}, {-144.72f, 105.144f, 89.443f}, {55.277f, 170.128f, 89.443f}, {178.885f, 0.0f, 89.443f}, {0.0f, 0.0f, 200.0f}, }; static const short icoface[20][3] = { {0, 1, 2}, {1, 0, 5}, {0, 2, 3}, {0, 3, 4}, {0, 4, 5}, {1, 5, 10}, {2, 1, 6}, {3, 2, 7}, {4, 3, 8}, {5, 4, 9}, {1, 10, 6}, {2, 6, 7}, {3, 7, 8}, {4, 8, 9}, {5, 9, 10}, {6, 10, 11}, {7, 6, 11}, {8, 7, 11}, {9, 8, 11}, {10, 9, 11}, }; static const float icouvs[60][2] = { {0.181819f, 0.000000f}, {0.272728f, 0.157461f}, {0.090910f, 0.157461f}, {0.272728f, 0.157461f}, {0.363637f, 0.000000f}, {0.454546f, 0.157461f}, {0.909091f, 0.000000f}, {1.000000f, 0.157461f}, {0.818182f, 0.157461f}, {0.727273f, 0.000000f}, {0.818182f, 0.157461f}, {0.636364f, 0.157461f}, {0.545455f, 0.000000f}, {0.636364f, 0.157461f}, {0.454546f, 0.157461f}, {0.272728f, 0.157461f}, {0.454546f, 0.157461f}, {0.363637f, 0.314921f}, {0.090910f, 0.157461f}, {0.272728f, 0.157461f}, {0.181819f, 0.314921f}, {0.818182f, 0.157461f}, {1.000000f, 0.157461f}, {0.909091f, 0.314921f}, {0.636364f, 0.157461f}, {0.818182f, 0.157461f}, {0.727273f, 0.314921f}, {0.454546f, 0.157461f}, {0.636364f, 0.157461f}, {0.545455f, 0.314921f}, {0.272728f, 0.157461f}, {0.363637f, 0.314921f}, {0.181819f, 0.314921f}, {0.090910f, 0.157461f}, {0.181819f, 0.314921f}, {0.000000f, 0.314921f}, {0.818182f, 0.157461f}, {0.909091f, 0.314921f}, {0.727273f, 0.314921f}, {0.636364f, 0.157461f}, {0.727273f, 0.314921f}, {0.545455f, 0.314921f}, {0.454546f, 0.157461f}, {0.545455f, 0.314921f}, {0.363637f, 0.314921f}, {0.181819f, 0.314921f}, {0.363637f, 0.314921f}, {0.272728f, 0.472382f}, {0.000000f, 0.314921f}, {0.181819f, 0.314921f}, {0.090910f, 0.472382f}, {0.727273f, 0.314921f}, {0.909091f, 0.314921f}, {0.818182f, 0.472382f}, {0.545455f, 0.314921f}, {0.727273f, 0.314921f}, {0.636364f, 0.472382f}, {0.363637f, 0.314921f}, {0.545455f, 0.314921f}, {0.454546f, 0.472382f}, }; static const int monkeyo = 4; static const int monkeynv = 271; static const int monkeynf = 250; static const signed char monkeyv[271][3] = { {-71, 21, 98}, {-63, 12, 88}, {-57, 7, 74}, {-82, -3, 79}, {-82, 4, 92}, {-82, 17, 100}, {-92, 21, 102}, {-101, 12, 95}, {-107, 7, 83}, {-117, 31, 84}, {-109, 31, 95}, {-96, 31, 102}, {-92, 42, 102}, {-101, 50, 95}, {-107, 56, 83}, {-82, 66, 79}, {-82, 58, 92}, {-82, 46, 100}, {-71, 42, 98}, {-63, 50, 88}, {-57, 56, 74}, {-47, 31, 72}, {-55, 31, 86}, {-67, 31, 97}, {-66, 31, 99}, {-70, 43, 100}, {-82, 48, 103}, {-93, 43, 105}, {-98, 31, 105}, {-93, 20, 105}, {-82, 31, 106}, {-82, 15, 103}, {-70, 20, 100}, {-127, 55, 95}, {-127, 45, 105}, {-127, -87, 94}, {-127, -41, 100}, {-127, -24, 102}, {-127, -99, 92}, {-127, 52, 77}, {-127, 73, 73}, {-127, 115, -70}, {-127, 72, -109}, {-127, 9, -106}, {-127, -49, -45}, {-101, -24, 72}, {-87, -56, 73}, {-82, -89, 73}, {-80, -114, 68}, {-85, -121, 67}, {-104, -124, 71}, {-127, -126, 74}, {-71, -18, 68}, {-46, -5, 69}, {-21, 19, 57}, {-17, 55, 76}, {-36, 62, 80}, {-64, 77, 88}, {-86, 97, 94}, {-107, 92, 97}, {-119, 63, 96}, {-106, 53, 99}, {-111, 39, 98}, {-101, 12, 95}, {-79, 2, 90}, {-64, 8, 86}, {-47, 24, 83}, {-45, 38, 83}, {-50, 48, 85}, {-72, 56, 92}, {-95, 60, 97}, {-127, -98, 94}, {-113, -92, 94}, {-112, -107, 91}, {-119, -113, 89}, {-127, -114, 88}, {-127, -25, 96}, {-127, -18, 95}, {-114, -19, 95}, {-111, -29, 96}, {-116, -37, 95}, {-76, -6, 86}, {-48, 7, 80}, {-34, 26, 77}, {-32, 48, 84}, {-39, 53, 93}, {-71, 70, 102}, {-87, 82, 107}, {-101, 79, 109}, {-114, 55, 108}, {-111, -13, 104}, {-100, -57, 91}, {-95, -90, 88}, {-93, -105, 85}, {-97, -117, 81}, {-106, -119, 81}, {-127, -121, 82}, {-127, 6, 93}, {-127, 27, 98}, {-85, 61, 95}, {-106, 18, 96}, {-110, 27, 97}, {-112, -88, 94}, {-117, -57, 96}, {-127, -57, 96}, {-127, -42, 95}, {-115, -35, 100}, {-110, -29, 102}, {-113, -17, 100}, {-122, -16, 100}, {-127, -26, 106}, {-121, -19, 104}, {-115, -20, 104}, {-113, -29, 106}, {-117, -32, 103}, {-127, -37, 103}, {-94, -40, 71}, {-106, -31, 91}, {-104, -40, 91}, {-97, -32, 71}, {-127, -112, 88}, {-121, -111, 88}, {-115, -105, 91}, {-115, -95, 93}, {-127, -100, 84}, {-115, -96, 85}, {-115, -104, 82}, {-121, -109, 81}, {-127, -110, 81}, {-105, 28, 100}, {-103, 20, 99}, {-84, 55, 97}, {-92, 54, 99}, {-73, 51, 99}, {-55, 45, 89}, {-52, 37, 88}, {-53, 25, 87}, {-66, 13, 92}, {-79, 8, 95}, {-98, 14, 100}, {-104, 38, 100}, {-100, 48, 100}, {-97, 46, 97}, {-102, 38, 97}, {-96, 16, 97}, {-79, 11, 93}, {-68, 15, 90}, {-57, 27, 86}, {-56, 36, 86}, {-59, 43, 87}, {-74, 50, 96}, {-91, 51, 98}, {-84, 52, 96}, {-101, 22, 96}, {-102, 29, 96}, {-113, 59, 78}, {-102, 85, 79}, {-84, 88, 76}, {-65, 71, 71}, {-40, 58, 63}, {-25, 52, 59}, {-28, 21, 48}, {-50, 0, 53}, {-71, -12, 60}, {-127, 115, 37}, {-127, 126, -10}, {-127, -25, -86}, {-127, -59, 24}, {-127, -125, 59}, {-127, -103, 44}, {-127, -73, 41}, {-127, -62, 36}, {-18, 30, 7}, {-17, 41, -6}, {-28, 34, -56}, {-68, 56, -90}, {-33, -6, 9}, {-51, -16, -21}, {-45, -1, -55}, {-84, 7, -85}, {-97, -45, 52}, {-104, -53, 33}, {-90, -91, 49}, {-95, -64, 50}, {-85, -117, 51}, {-109, -97, 47}, {-111, -69, 46}, {-106, -121, 56}, {-99, -36, 55}, {-100, -29, 60}, {-101, -22, 64}, {-100, -50, 21}, {-89, -40, -34}, {-83, -19, -69}, {-69, 111, -49}, {-69, 119, -9}, {-69, 109, 30}, {-68, 67, 55}, {-34, 52, 43}, {-46, 58, 36}, {-45, 90, 7}, {-25, 72, 16}, {-25, 79, -15}, {-45, 96, -25}, {-45, 87, -57}, {-25, 69, -46}, {-48, 42, -75}, {-65, 3, -70}, {-22, 42, -26}, {-75, -22, 19}, {-72, -25, -27}, {-13, 52, -30}, {-28, -18, -16}, {6, -13, -42}, {37, 7, -55}, {46, 41, -54}, {31, 65, -54}, {4, 61, -40}, {3, 53, -37}, {25, 56, -50}, {35, 37, -52}, {28, 10, -52}, {5, -5, -39}, {-21, -9, -17}, {-9, 46, -28}, {-6, 39, -37}, {-14, -3, -27}, {6, 0, -47}, {25, 12, -57}, {31, 32, -57}, {23, 46, -56}, {4, 44, -46}, {-19, 37, -27}, {-20, 22, -35}, {-30, 12, -35}, {-22, 11, -35}, {-19, 2, -35}, {-23, -2, -35}, {-34, 0, -9}, {-35, -3, -22}, {-35, 5, -24}, {-25, 26, -27}, {-13, 31, -34}, {-13, 30, -41}, {-23, -2, -41}, {-18, 2, -41}, {-21, 10, -41}, {-29, 12, -41}, {-19, 22, -41}, {6, 42, -53}, {25, 44, -62}, {34, 31, -63}, {28, 11, -62}, {7, 0, -54}, {-14, -2, -34}, {-5, 37, -44}, {-13, 14, -42}, {-7, 8, -43}, {1, 16, -47}, {-4, 22, -45}, {3, 30, -48}, {8, 24, -49}, {15, 27, -50}, {12, 35, -50}, {4, 56, -62}, {33, 60, -70}, {48, 38, -64}, {41, 7, -68}, {6, -11, -63}, {-26, -16, -42}, {-17, 49, -49}, }; static signed char monkeyf[250][4] = { {27, 4, 5, 26}, {25, 4, 5, 24}, {3, 6, 5, 4}, {1, 6, 5, 2}, {5, 6, 7, 4}, {3, 6, 7, 2}, {5, 8, 7, 6}, {3, 8, 7, 4}, {7, 8, 9, 6}, {5, 8, 9, 4}, {7, 10, 9, 8}, {5, 10, 9, 6}, {9, 10, 11, 8}, {7, 10, 11, 6}, {9, 12, 11, 10}, {7, 12, 11, 8}, {11, 6, 13, 12}, {5, 4, 13, 12}, {3, -2, 13, 12}, {-3, -4, 13, 12}, {-5, -10, 13, 12}, {-11, -12, 14, 12}, {-13, -18, 14, 13}, {-19, 4, 5, 13}, {10, 12, 4, 4}, {10, 11, 9, 9}, {8, 7, 9, 9}, {7, 5, 6, 6}, {6, 3, 4, 4}, {5, 1, 2, 2}, {4, -1, 0, 0}, {3, -3, -2, -2}, {22, 67, 68, 23}, {20, 65, 66, 21}, {18, 63, 64, 19}, {16, 61, 62, 17}, {14, 59, 60, 15}, {12, 19, 48, 57}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, -9, -8, 47}, {18, 27, 45, 46}, {26, 55, 43, 44}, {24, 41, 42, 54}, {22, 39, 40, 23}, {20, 37, 38, 21}, {18, 35, 36, 19}, {16, 33, 34, 17}, {14, 31, 32, 15}, {12, 39, 30, 13}, {11, 48, 45, 38}, {8, 36, -19, 9}, {8, -20, 44, 47}, {42, 45, 46, 43}, {18, 19, 40, 39}, {16, 17, 38, 37}, {14, 15, 36, 35}, {32, 44, 43, 33}, {12, 33, 32, 42}, {19, 44, 43, 42}, {40, 41, 42, -27}, {8, 9, 39, -28}, {15, 43, 42, 16}, {13, 43, 42, 14}, {11, 43, 42, 12}, {9, -30, 42, 10}, {37, 12, 38, -32}, {-33, 37, 45, 46}, {-33, 40, 41, 39}, {38, 40, 41, 37}, {36, 40, 41, 35}, {34, 40, 41, 33}, {36, 39, 38, 37}, {35, 40, 39, 38}, {1, 2, 14, 21}, {1, 2, 40, 13}, {1, 2, 40, 39}, {1, 24, 12, 39}, {-34, 36, 38, 11}, {35, 38, 36, 37}, {-37, 8, 35, 37}, {-11, -12, -45, 40}, {-11, -12, 39, 38}, {-11, -12, 37, 36}, {-11, -12, 35, 34}, {33, 34, 40, 41}, {33, 34, 38, 39}, {33, 34, 36, 37}, {33, -52, 34, 35}, {33, 37, 36, 34}, {33, 35, 34, 34}, {8, 7, 37, 36}, {-32, 7, 35, 46}, {-34, -33, 45, 46}, {4, -33, 43, 34}, {-34, -33, 41, 42}, {-34, -33, 39, 40}, {-34, -33, 37, 38}, {-34, -33, 35, 36}, {-34, -33, 33, 34}, {-34, -33, 31, 32}, {-34, -4, 28, 30}, {-5, -34, 28, 27}, {-35, -44, 36, 27}, {26, 35, 36, 45}, {24, 25, 44, 45}, {25, 23, 44, 42}, {25, 24, 41, 40}, {25, 24, 39, 38}, {25, 24, 37, 36}, {25, 24, 35, 34}, {25, 24, 33, 32}, {25, 24, 31, 30}, {15, 24, 29, 38}, {25, 24, 27, 26}, {23, 12, 37, 26}, {11, 12, 35, 36}, {-86, -59, 36, -80}, {-60, -61, 36, 35}, {-62, -63, 36, 35}, {-64, -65, 36, 35}, {-66, -67, 36, 35}, {-68, -69, 36, 35}, {-70, -71, 36, 35}, {-72, -73, 36, 35}, {-74, -75, 36, 35}, {42, 43, 53, 58}, {40, 41, 57, 56}, {38, 39, 55, 57}, {-81, -80, 37, 56}, {-83, -82, 55, 52}, {-85, -84, 51, 49}, {-87, -86, 48, 49}, {47, 50, 51, 48}, {46, 48, 51, 49}, {43, 46, 49, 44}, {-92, -91, 45, 42}, {-23, 49, 50, -20}, {-94, 40, 48, -24}, {-96, -22, 48, 49}, {-97, 48, 21, -90}, {-100, 36, 50, 23}, {22, 49, 48, -100}, {-101, 47, 46, 22}, {21, 45, 35, 25}, {33, 34, 44, 41}, {13, 14, 28, 24}, {-107, 26, 30, -106}, {14, 46, 45, 15}, {14, 44, 43, -110}, {-111, 42, 23, -110}, {6, 7, 45, 46}, {45, 44, 47, 46}, {45, 46, 47, 48}, {47, 46, 49, 48}, {17, 49, 47, 48}, {17, 36, 46, 48}, {35, 36, 44, 45}, {35, 36, 40, 43}, {35, 36, 38, 39}, {-4, -3, 37, 35}, {-123, 34, 33, 1}, {-9, -8, -7, -6}, {-10, -7, 32, -125}, {-127, -11, -126, -126}, {-7, -6, 5, 31}, {4, 5, 33, 30}, {4, 39, 33, 32}, {4, 35, 32, 38}, {20, 21, 39, 38}, {4, 37, 38, 5}, {-11, -10, 36, 3}, {-11, 15, 14, 35}, {13, 16, 34, 34}, {-13, 14, 13, 13}, {-3, 1, 30, 29}, {-3, 28, 29, 1}, {-2, 31, 28, -1}, {12, 13, 27, 30}, {-2, 26, 12, 12}, {35, 29, 42, 36}, {34, 35, 36, 33}, {32, 35, 36, 31}, {30, 35, 36, 29}, {28, 35, 36, 27}, {26, 35, 36, 25}, {34, 39, 38, 35}, {32, 39, 38, 33}, {30, 39, 38, 31}, {28, 39, 38, 29}, {26, 39, 38, 27}, {25, 31, 32, 38}, {-18, -17, 45, 44}, {-18, 17, 28, 44}, {-24, -20, 42, -23}, {11, 35, 27, 14}, {25, 28, 39, 41}, {37, 41, 40, 38}, {34, 40, 36, 35}, {32, 40, 39, 33}, {30, 39, 31, 40}, {21, 29, 39, 22}, {-31, 37, 28, 4}, {-32, 33, 35, 36}, {32, 33, 34, 34}, {18, 35, 36, 48}, {34, 25, 40, 35}, {24, 25, 38, 39}, {24, 25, 36, 37}, {24, 25, 34, 35}, {24, 25, 32, 33}, {24, 13, 41, 31}, {17, 11, 41, 35}, {15, 16, 34, 35}, {13, 14, 34, 35}, {11, 12, 34, 35}, {9, 10, 34, 35}, {7, 8, 34, 35}, {26, 25, 37, 36}, {35, 36, 37, 38}, {37, 36, 39, 38}, {37, 38, 39, 40}, {25, 31, 36, 39}, {18, 34, 35, 30}, {17, 22, 30, 33}, {19, 29, 21, 20}, {16, 26, 29, 17}, {24, 29, 28, 25}, {22, 31, 28, 23}, {20, 31, 30, 21}, {18, 31, 30, 19}, {16, 30, 17, 17}, {-21, -22, 35, 34}, {-21, -22, 33, 32}, {-21, -22, 31, 30}, {-21, -22, 29, 28}, {-21, -22, 27, 26}, {-28, -22, 25, 31}, {24, 28, 29, 30}, {23, 24, 26, 27}, {23, 24, 25, 25}, {-69, -35, -32, 27}, {-70, 26, 25, -66}, {-68, -67, 24, -33}, }; static const float monkeyuvs[] = { 0.843250f, 0.588863f, 0.833697f, 0.611927f, 0.794218f, 0.611927f, 0.815334f, 0.560948f, 0.866314f, 0.937441f, 0.866314f, 0.897962f, 0.889378f, 0.888409f, 0.917293f, 0.916324f, 0.815334f, 0.560948f, 0.794218f, 0.611927f, 0.746541f, 0.611927f, 0.781622f, 0.527235f, 0.866314f, 0.985118f, 0.866314f, 0.937441f, 0.917293f, 0.916324f, 0.951006f, 0.950037f, 0.794218f, 0.611927f, 0.815334f, 0.662907f, 0.781622f, 0.696619f, 0.746541f, 0.611927f, 0.781622f, 0.950037f, 0.815334f, 0.916325f, 0.866314f, 0.937441f, 0.866314f, 0.985118f, 0.833697f, 0.611927f, 0.843250f, 0.634991f, 0.815334f, 0.662907f, 0.794218f, 0.611927f, 0.815334f, 0.916325f, 0.843250f, 0.888409f, 0.866314f, 0.897962f, 0.866314f, 0.937441f, 0.843250f, 0.634991f, 0.866314f, 0.644544f, 0.866314f, 0.684023f, 0.815334f, 0.662907f, 0.794218f, 0.865345f, 0.833697f, 0.865345f, 0.843250f, 0.888409f, 0.815334f, 0.916325f, 0.815334f, 0.662907f, 0.866314f, 0.684023f, 0.866314f, 0.731700f, 0.781622f, 0.696619f, 0.746541f, 0.865345f, 0.794218f, 0.865345f, 0.815334f, 0.916325f, 0.781622f, 0.950037f, 0.866314f, 0.684023f, 0.917293f, 0.662907f, 0.951006f, 0.696619f, 0.866314f, 0.731700f, 0.781622f, 0.780653f, 0.815334f, 0.814366f, 0.794218f, 0.865345f, 0.746541f, 0.865345f, 0.866314f, 0.644544f, 0.889378f, 0.634991f, 0.917293f, 0.662907f, 0.866314f, 0.684023f, 0.815334f, 0.814366f, 0.843250f, 0.842281f, 0.833697f, 0.865345f, 0.794218f, 0.865345f, 0.889378f, 0.634991f, 0.898931f, 0.611927f, 0.938410f, 0.611927f, 0.917293f, 0.662907f, 0.866314f, 0.793249f, 0.866314f, 0.832728f, 0.843250f, 0.842281f, 0.815334f, 0.814366f, 0.917293f, 0.662907f, 0.938410f, 0.611927f, 0.986087f, 0.611927f, 0.951006f, 0.696619f, 0.866314f, 0.745572f, 0.866314f, 0.793249f, 0.815334f, 0.814366f, 0.781622f, 0.780653f, 0.938410f, 0.611927f, 0.917294f, 0.560947f, 0.951006f, 0.527235f, 0.986087f, 0.611927f, 0.951006f, 0.780653f, 0.917294f, 0.814365f, 0.866314f, 0.793249f, 0.866314f, 0.745572f, 0.898931f, 0.611927f, 0.889378f, 0.588863f, 0.917294f, 0.560947f, 0.938410f, 0.611927f, 0.917294f, 0.814365f, 0.889378f, 0.842281f, 0.866314f, 0.832728f, 0.866314f, 0.793249f, 0.889378f, 0.588863f, 0.866314f, 0.579310f, 0.866314f, 0.539831f, 0.917294f, 0.560947f, 0.938410f, 0.865345f, 0.898931f, 0.865345f, 0.889378f, 0.842281f, 0.917294f, 0.814365f, 0.917294f, 0.560947f, 0.866314f, 0.539831f, 0.866314f, 0.492154f, 0.951006f, 0.527235f, 0.986087f, 0.865345f, 0.938410f, 0.865345f, 0.917294f, 0.814365f, 0.951006f, 0.780653f, 0.866314f, 0.539831f, 0.815334f, 0.560948f, 0.781622f, 0.527235f, 0.866314f, 0.492154f, 0.951006f, 0.950037f, 0.917293f, 0.916324f, 0.938410f, 0.865345f, 0.986087f, 0.865345f, 0.866314f, 0.579310f, 0.843250f, 0.588863f, 0.815334f, 0.560948f, 0.866314f, 0.539831f, 0.917293f, 0.916324f, 0.889378f, 0.888409f, 0.898931f, 0.865345f, 0.938410f, 0.865345f, 0.843250f, 0.588863f, 0.866314f, 0.579310f, 0.866314f, 0.585461f, 0.847600f, 0.593213f, 0.892780f, 0.865345f, 0.898931f, 0.865345f, 0.889378f, 0.888409f, 0.885028f, 0.884059f, 0.866314f, 0.579310f, 0.889378f, 0.588863f, 0.885028f, 0.593213f, 0.866314f, 0.585461f, 0.885028f, 0.846631f, 0.889378f, 0.842281f, 0.898931f, 0.865345f, 0.892780f, 0.865345f, 0.889378f, 0.588863f, 0.898931f, 0.611927f, 0.892780f, 0.611927f, 0.885028f, 0.593213f, 0.866314f, 0.838879f, 0.866314f, 0.832728f, 0.889378f, 0.842281f, 0.885028f, 0.846631f, 0.898931f, 0.611927f, 0.889378f, 0.634991f, 0.885028f, 0.630641f, 0.892780f, 0.611927f, 0.847600f, 0.846631f, 0.843250f, 0.842281f, 0.866314f, 0.832728f, 0.866314f, 0.838879f, 0.889378f, 0.634991f, 0.866314f, 0.644544f, 0.866314f, 0.638393f, 0.885028f, 0.630641f, 0.839848f, 0.865345f, 0.833697f, 0.865345f, 0.843250f, 0.842281f, 0.847600f, 0.846631f, 0.866314f, 0.644544f, 0.843250f, 0.634991f, 0.847600f, 0.630641f, 0.866314f, 0.638393f, 0.847600f, 0.884059f, 0.843250f, 0.888409f, 0.833697f, 0.865345f, 0.839848f, 0.865345f, 0.843250f, 0.634991f, 0.833697f, 0.611927f, 0.839848f, 0.611927f, 0.847600f, 0.630641f, 0.866314f, 0.891811f, 0.866314f, 0.897962f, 0.843250f, 0.888409f, 0.847600f, 0.884059f, 0.833697f, 0.611927f, 0.843250f, 0.588863f, 0.847600f, 0.593213f, 0.839848f, 0.611927f, 0.885028f, 0.884059f, 0.889378f, 0.888409f, 0.866314f, 0.897962f, 0.866314f, 0.891811f, 0.866314f, 0.611927f, 0.839848f, 0.611927f, 0.847600f, 0.593213f, 0.885028f, 0.884059f, 0.866314f, 0.891811f, 0.866314f, 0.865345f, 0.847600f, 0.630641f, 0.839848f, 0.611927f, 0.866314f, 0.611927f, 0.866314f, 0.865345f, 0.866314f, 0.891811f, 0.847600f, 0.884059f, 0.866314f, 0.611927f, 0.866314f, 0.638393f, 0.847600f, 0.630641f, 0.847600f, 0.884059f, 0.839848f, 0.865345f, 0.866314f, 0.865345f, 0.866314f, 0.611927f, 0.885028f, 0.630641f, 0.866314f, 0.638393f, 0.839848f, 0.865345f, 0.847600f, 0.846631f, 0.866314f, 0.865345f, 0.866314f, 0.611927f, 0.892780f, 0.611927f, 0.885028f, 0.630641f, 0.847600f, 0.846631f, 0.866314f, 0.838879f, 0.866314f, 0.865345f, 0.866314f, 0.611927f, 0.885028f, 0.593213f, 0.892780f, 0.611927f, 0.866314f, 0.838879f, 0.885028f, 0.846631f, 0.866314f, 0.865345f, 0.866314f, 0.611927f, 0.866314f, 0.585461f, 0.885028f, 0.593213f, 0.885028f, 0.846631f, 0.892780f, 0.865345f, 0.866314f, 0.865345f, 0.866314f, 0.611927f, 0.847600f, 0.593213f, 0.866314f, 0.585461f, 0.892780f, 0.865345f, 0.885028f, 0.884059f, 0.866314f, 0.865345f, 0.520711f, 0.060503f, 0.517028f, 0.068490f, 0.500000f, 0.064527f, 0.500000f, 0.054411f, 0.500000f, 0.064527f, 0.482972f, 0.068490f, 0.479289f, 0.060503f, 0.500000f, 0.054411f, 0.530457f, 0.065062f, 0.522612f, 0.070678f, 0.517028f, 0.068490f, 0.520711f, 0.060503f, 0.482972f, 0.068490f, 0.477388f, 0.070678f, 0.469543f, 0.065062f, 0.479289f, 0.060503f, 0.532878f, 0.067822f, 0.526301f, 0.079422f, 0.522612f, 0.070678f, 0.530457f, 0.065062f, 0.477388f, 0.070678f, 0.473699f, 0.079422f, 0.467122f, 0.067822f, 0.469543f, 0.065062f, 0.544695f, 0.083023f, 0.529228f, 0.091098f, 0.526301f, 0.079422f, 0.532878f, 0.067822f, 0.473699f, 0.079422f, 0.470772f, 0.091098f, 0.455305f, 0.083023f, 0.467122f, 0.067822f, 0.565647f, 0.115495f, 0.537536f, 0.127779f, 0.529228f, 0.091098f, 0.544695f, 0.083023f, 0.470772f, 0.091098f, 0.462464f, 0.127779f, 0.434353f, 0.115495f, 0.455305f, 0.083023f, 0.586916f, 0.172042f, 0.626605f, 0.208159f, 0.600470f, 0.238288f, 0.535885f, 0.215568f, 0.399530f, 0.238288f, 0.373395f, 0.208159f, 0.413084f, 0.172042f, 0.464115f, 0.215568f, 0.626605f, 0.208159f, 0.650908f, 0.240294f, 0.636962f, 0.261221f, 0.600470f, 0.238288f, 0.363038f, 0.261221f, 0.349092f, 0.240294f, 0.373395f, 0.208159f, 0.399530f, 0.238288f, 0.650908f, 0.240294f, 0.689501f, 0.268805f, 0.655896f, 0.284413f, 0.636962f, 0.261221f, 0.344104f, 0.284413f, 0.310499f, 0.268805f, 0.349092f, 0.240294f, 0.363038f, 0.261221f, 0.689501f, 0.268805f, 0.684517f, 0.317795f, 0.659507f, 0.313152f, 0.655896f, 0.284413f, 0.340493f, 0.313152f, 0.315483f, 0.317795f, 0.310499f, 0.268805f, 0.344104f, 0.284413f, 0.684517f, 0.317795f, 0.671357f, 0.334694f, 0.649107f, 0.322437f, 0.659507f, 0.313152f, 0.350893f, 0.322437f, 0.328643f, 0.334694f, 0.315483f, 0.317795f, 0.340493f, 0.313152f, 0.671357f, 0.334694f, 0.636775f, 0.370732f, 0.613636f, 0.353108f, 0.649107f, 0.322437f, 0.386364f, 0.353108f, 0.363225f, 0.370732f, 0.328643f, 0.334694f, 0.350893f, 0.322437f, 0.636775f, 0.370732f, 0.602261f, 0.395588f, 0.594178f, 0.371277f, 0.613636f, 0.353108f, 0.405822f, 0.371277f, 0.397739f, 0.395588f, 0.363225f, 0.370732f, 0.386364f, 0.353108f, 0.602261f, 0.395588f, 0.581044f, 0.398468f, 0.577351f, 0.373341f, 0.594178f, 0.371277f, 0.422649f, 0.373341f, 0.418956f, 0.398468f, 0.397739f, 0.395588f, 0.405822f, 0.371277f, 0.581044f, 0.398468f, 0.532016f, 0.387365f, 0.539817f, 0.354339f, 0.577351f, 0.373341f, 0.460183f, 0.354339f, 0.467984f, 0.387365f, 0.418956f, 0.398468f, 0.422649f, 0.373341f, 0.532016f, 0.387365f, 0.500000f, 0.382860f, 0.500000f, 0.340417f, 0.539817f, 0.354339f, 0.500000f, 0.340417f, 0.500000f, 0.382860f, 0.467984f, 0.387365f, 0.460183f, 0.354339f, 0.559135f, 0.334326f, 0.579057f, 0.335646f, 0.577351f, 0.373341f, 0.539817f, 0.354339f, 0.422649f, 0.373341f, 0.420943f, 0.335646f, 0.440865f, 0.334326f, 0.460183f, 0.354339f, 0.579057f, 0.335646f, 0.592090f, 0.332885f, 0.594178f, 0.371277f, 0.577351f, 0.373341f, 0.405822f, 0.371277f, 0.407910f, 0.332885f, 0.420943f, 0.335646f, 0.422649f, 0.373341f, 0.606163f, 0.325516f, 0.613636f, 0.353108f, 0.594178f, 0.371277f, 0.592090f, 0.332885f, 0.405822f, 0.371277f, 0.386364f, 0.353108f, 0.393837f, 0.325516f, 0.407910f, 0.332885f, 0.628251f, 0.311636f, 0.649107f, 0.322437f, 0.613636f, 0.353108f, 0.606163f, 0.325516f, 0.386364f, 0.353108f, 0.350893f, 0.322437f, 0.371749f, 0.311636f, 0.393837f, 0.325516f, 0.635551f, 0.300507f, 0.659507f, 0.313152f, 0.649107f, 0.322437f, 0.628251f, 0.311636f, 0.350893f, 0.322437f, 0.340493f, 0.313152f, 0.364449f, 0.300507f, 0.371749f, 0.311636f, 0.631484f, 0.283889f, 0.655896f, 0.284413f, 0.659507f, 0.313152f, 0.635551f, 0.300507f, 0.340493f, 0.313152f, 0.344104f, 0.284413f, 0.368516f, 0.283889f, 0.364449f, 0.300507f, 0.611331f, 0.264411f, 0.636962f, 0.261221f, 0.655896f, 0.284413f, 0.631484f, 0.283889f, 0.344104f, 0.284413f, 0.363038f, 0.261221f, 0.388669f, 0.264411f, 0.368516f, 0.283889f, 0.592372f, 0.254897f, 0.600470f, 0.238288f, 0.636962f, 0.261221f, 0.611331f, 0.264411f, 0.363038f, 0.261221f, 0.399530f, 0.238288f, 0.407628f, 0.254897f, 0.388669f, 0.264411f, 0.559669f, 0.267717f, 0.535885f, 0.215568f, 0.600470f, 0.238288f, 0.592372f, 0.254897f, 0.399530f, 0.238288f, 0.464115f, 0.215568f, 0.440331f, 0.267717f, 0.407628f, 0.254897f, 0.559669f, 0.267717f, 0.550878f, 0.277832f, 0.500000f, 0.252445f, 0.535885f, 0.215568f, 0.500000f, 0.252445f, 0.449122f, 0.277832f, 0.440331f, 0.267717f, 0.464115f, 0.215568f, 0.559135f, 0.334326f, 0.539817f, 0.354339f, 0.500000f, 0.340417f, 0.544001f, 0.314523f, 0.500000f, 0.340417f, 0.460183f, 0.354339f, 0.440865f, 0.334326f, 0.455999f, 0.314523f, 0.544001f, 0.314523f, 0.500000f, 0.340417f, 0.500000f, 0.295691f, 0.543637f, 0.293371f, 0.500000f, 0.295691f, 0.500000f, 0.340417f, 0.455999f, 0.314523f, 0.456363f, 0.293371f, 0.500000f, 0.252445f, 0.550878f, 0.277832f, 0.543637f, 0.293371f, 0.500000f, 0.295691f, 0.456363f, 0.293371f, 0.449122f, 0.277832f, 0.500000f, 0.252445f, 0.500000f, 0.295691f, 0.506819f, 0.075382f, 0.500000f, 0.073497f, 0.500000f, 0.064527f, 0.517028f, 0.068490f, 0.500000f, 0.064527f, 0.500000f, 0.073497f, 0.493181f, 0.075382f, 0.482972f, 0.068490f, 0.511782f, 0.080633f, 0.506819f, 0.075382f, 0.517028f, 0.068490f, 0.522612f, 0.070678f, 0.482972f, 0.068490f, 0.493181f, 0.075382f, 0.488218f, 0.080633f, 0.477388f, 0.070678f, 0.512172f, 0.093457f, 0.511782f, 0.080633f, 0.522612f, 0.070678f, 0.526301f, 0.079422f, 0.477388f, 0.070678f, 0.488218f, 0.080633f, 0.487828f, 0.093457f, 0.473699f, 0.079422f, 0.537536f, 0.127779f, 0.514257f, 0.133422f, 0.513874f, 0.097191f, 0.529228f, 0.091098f, 0.486126f, 0.097191f, 0.485743f, 0.133422f, 0.462464f, 0.127779f, 0.470772f, 0.091098f, 0.512172f, 0.093457f, 0.526301f, 0.079422f, 0.529228f, 0.091098f, 0.513874f, 0.097191f, 0.470772f, 0.091098f, 0.473699f, 0.079422f, 0.487828f, 0.093457f, 0.486126f, 0.097191f, 0.520226f, 0.164615f, 0.500000f, 0.157864f, 0.500000f, 0.134352f, 0.514257f, 0.133422f, 0.500000f, 0.134352f, 0.500000f, 0.157864f, 0.479774f, 0.164615f, 0.485743f, 0.133422f, 0.513874f, 0.097191f, 0.514257f, 0.133422f, 0.500000f, 0.134352f, 0.500000f, 0.100063f, 0.500000f, 0.134352f, 0.485743f, 0.133422f, 0.486126f, 0.097191f, 0.500000f, 0.100063f, 0.500000f, 0.091346f, 0.512172f, 0.093457f, 0.513874f, 0.097191f, 0.500000f, 0.100063f, 0.486126f, 0.097191f, 0.487828f, 0.093457f, 0.500000f, 0.091346f, 0.500000f, 0.100063f, 0.530258f, 0.180239f, 0.521901f, 0.181560f, 0.517666f, 0.172353f, 0.520226f, 0.164615f, 0.482334f, 0.172353f, 0.478099f, 0.181560f, 0.469742f, 0.180239f, 0.479774f, 0.164615f, 0.523673f, 0.198817f, 0.518957f, 0.194728f, 0.521901f, 0.181560f, 0.530258f, 0.180239f, 0.478099f, 0.181560f, 0.481043f, 0.194728f, 0.476327f, 0.198817f, 0.469742f, 0.180239f, 0.500000f, 0.203867f, 0.508211f, 0.197295f, 0.518957f, 0.194728f, 0.523673f, 0.198817f, 0.481043f, 0.194728f, 0.491789f, 0.197295f, 0.500000f, 0.203867f, 0.476327f, 0.198817f, 0.500000f, 0.197278f, 0.500000f, 0.192167f, 0.508211f, 0.197295f, 0.500000f, 0.203867f, 0.491789f, 0.197295f, 0.500000f, 0.192167f, 0.500000f, 0.197278f, 0.500000f, 0.203867f, 0.500000f, 0.157864f, 0.520226f, 0.164615f, 0.517666f, 0.172353f, 0.500000f, 0.165170f, 0.482334f, 0.172353f, 0.479774f, 0.164615f, 0.500000f, 0.157864f, 0.500000f, 0.165170f, 0.500000f, 0.165170f, 0.517666f, 0.172353f, 0.513538f, 0.176949f, 0.500000f, 0.171718f, 0.486462f, 0.176949f, 0.482334f, 0.172353f, 0.500000f, 0.165170f, 0.500000f, 0.171718f, 0.500000f, 0.192167f, 0.500000f, 0.186182f, 0.508818f, 0.192407f, 0.508211f, 0.197295f, 0.491182f, 0.192407f, 0.500000f, 0.186182f, 0.500000f, 0.192167f, 0.491789f, 0.197295f, 0.508211f, 0.197295f, 0.508818f, 0.192407f, 0.515232f, 0.190709f, 0.518957f, 0.194728f, 0.484768f, 0.190709f, 0.491182f, 0.192407f, 0.491789f, 0.197295f, 0.481043f, 0.194728f, 0.518957f, 0.194728f, 0.515232f, 0.190709f, 0.516908f, 0.181873f, 0.521901f, 0.181560f, 0.483092f, 0.181873f, 0.484768f, 0.190709f, 0.481043f, 0.194728f, 0.478099f, 0.181560f, 0.521901f, 0.181560f, 0.516908f, 0.181873f, 0.513538f, 0.176949f, 0.517666f, 0.172353f, 0.486462f, 0.176949f, 0.483092f, 0.181873f, 0.478099f, 0.181560f, 0.482334f, 0.172353f, 0.500000f, 0.186182f, 0.516908f, 0.181873f, 0.515232f, 0.190709f, 0.508818f, 0.192407f, 0.484768f, 0.190709f, 0.483092f, 0.181873f, 0.500000f, 0.186182f, 0.491182f, 0.192407f, 0.500000f, 0.186182f, 0.500000f, 0.171718f, 0.513538f, 0.176949f, 0.516908f, 0.181873f, 0.486462f, 0.176949f, 0.500000f, 0.171718f, 0.500000f, 0.186182f, 0.483092f, 0.181873f, 0.500000f, 0.203867f, 0.523673f, 0.198817f, 0.535885f, 0.215568f, 0.500000f, 0.252445f, 0.464115f, 0.215568f, 0.476327f, 0.198817f, 0.500000f, 0.203867f, 0.500000f, 0.252445f, 0.523673f, 0.198817f, 0.530258f, 0.180239f, 0.544209f, 0.172814f, 0.535885f, 0.215568f, 0.455791f, 0.172814f, 0.469742f, 0.180239f, 0.476327f, 0.198817f, 0.464115f, 0.215568f, 0.530258f, 0.180239f, 0.520226f, 0.164615f, 0.541327f, 0.154899f, 0.544209f, 0.172814f, 0.458673f, 0.154899f, 0.479774f, 0.164615f, 0.469742f, 0.180239f, 0.455791f, 0.172814f, 0.520226f, 0.164615f, 0.514257f, 0.133422f, 0.537536f, 0.127779f, 0.541327f, 0.154899f, 0.462464f, 0.127779f, 0.485743f, 0.133422f, 0.479774f, 0.164615f, 0.458673f, 0.154899f, 0.565647f, 0.115495f, 0.578661f, 0.139176f, 0.541327f, 0.154899f, 0.537536f, 0.127779f, 0.458673f, 0.154899f, 0.421339f, 0.139176f, 0.434353f, 0.115495f, 0.462464f, 0.127779f, 0.578661f, 0.139176f, 0.583245f, 0.154155f, 0.544209f, 0.172814f, 0.541327f, 0.154899f, 0.455791f, 0.172814f, 0.416755f, 0.154155f, 0.421339f, 0.139176f, 0.458673f, 0.154899f, 0.586916f, 0.172042f, 0.535885f, 0.215568f, 0.544209f, 0.172814f, 0.583245f, 0.154155f, 0.455791f, 0.172814f, 0.464115f, 0.215568f, 0.413084f, 0.172042f, 0.416755f, 0.154155f, 0.512172f, 0.093457f, 0.500000f, 0.091346f, 0.500000f, 0.089977f, 0.509911f, 0.090724f, 0.500000f, 0.089977f, 0.500000f, 0.091346f, 0.487828f, 0.093457f, 0.490089f, 0.090724f, 0.511782f, 0.080633f, 0.512172f, 0.093457f, 0.509911f, 0.090724f, 0.509713f, 0.082236f, 0.490089f, 0.090724f, 0.487828f, 0.093457f, 0.488218f, 0.080633f, 0.490287f, 0.082236f, 0.506819f, 0.075382f, 0.511782f, 0.080633f, 0.509713f, 0.082236f, 0.505196f, 0.077083f, 0.490287f, 0.082236f, 0.488218f, 0.080633f, 0.493181f, 0.075382f, 0.494804f, 0.077083f, 0.500000f, 0.073497f, 0.506819f, 0.075382f, 0.505196f, 0.077083f, 0.500000f, 0.075473f, 0.494804f, 0.077083f, 0.493181f, 0.075382f, 0.500000f, 0.073497f, 0.500000f, 0.075473f, 0.500000f, 0.075473f, 0.505196f, 0.077083f, 0.503445f, 0.080840f, 0.500000f, 0.080320f, 0.496555f, 0.080840f, 0.494804f, 0.077083f, 0.500000f, 0.075473f, 0.500000f, 0.080320f, 0.505196f, 0.077083f, 0.509713f, 0.082236f, 0.506660f, 0.083289f, 0.503445f, 0.080840f, 0.493340f, 0.083289f, 0.490287f, 0.082236f, 0.494804f, 0.077083f, 0.496555f, 0.080840f, 0.509713f, 0.082236f, 0.509911f, 0.090724f, 0.506822f, 0.086791f, 0.506660f, 0.083289f, 0.493178f, 0.086791f, 0.490089f, 0.090724f, 0.490287f, 0.082236f, 0.493340f, 0.083289f, 0.509911f, 0.090724f, 0.500000f, 0.089977f, 0.500000f, 0.085637f, 0.506822f, 0.086791f, 0.500000f, 0.085637f, 0.500000f, 0.089977f, 0.490089f, 0.090724f, 0.493178f, 0.086791f, 0.500000f, 0.085637f, 0.500000f, 0.080320f, 0.503445f, 0.080840f, 0.506822f, 0.086791f, 0.496555f, 0.080840f, 0.500000f, 0.080320f, 0.500000f, 0.085637f, 0.493178f, 0.086791f, 0.506822f, 0.086791f, 0.503445f, 0.080840f, 0.506660f, 0.083289f, 0.493340f, 0.083289f, 0.496555f, 0.080840f, 0.493178f, 0.086791f, 0.543637f, 0.293371f, 0.550878f, 0.277832f, 0.562361f, 0.284338f, 0.559190f, 0.294882f, 0.437639f, 0.284338f, 0.449122f, 0.277832f, 0.456363f, 0.293371f, 0.440810f, 0.294882f, 0.544001f, 0.314523f, 0.543637f, 0.293371f, 0.559190f, 0.294882f, 0.563180f, 0.307151f, 0.440810f, 0.294882f, 0.456363f, 0.293371f, 0.455999f, 0.314523f, 0.436820f, 0.307151f, 0.559135f, 0.334326f, 0.544001f, 0.314523f, 0.563180f, 0.307151f, 0.570458f, 0.318697f, 0.436820f, 0.307151f, 0.455999f, 0.314523f, 0.440865f, 0.334326f, 0.429542f, 0.318697f, 0.550878f, 0.277832f, 0.559669f, 0.267717f, 0.569243f, 0.278245f, 0.562361f, 0.284338f, 0.430757f, 0.278245f, 0.440331f, 0.267717f, 0.449122f, 0.277832f, 0.437639f, 0.284338f, 0.559669f, 0.267717f, 0.592372f, 0.254897f, 0.589914f, 0.271772f, 0.569243f, 0.278245f, 0.410086f, 0.271772f, 0.407628f, 0.254897f, 0.440331f, 0.267717f, 0.430757f, 0.278245f, 0.592372f, 0.254897f, 0.611331f, 0.264411f, 0.602190f, 0.277180f, 0.589914f, 0.271772f, 0.397810f, 0.277180f, 0.388669f, 0.264411f, 0.407628f, 0.254897f, 0.410086f, 0.271772f, 0.611331f, 0.264411f, 0.631484f, 0.283889f, 0.617110f, 0.287175f, 0.602190f, 0.277180f, 0.382890f, 0.287175f, 0.368516f, 0.283889f, 0.388669f, 0.264411f, 0.397810f, 0.277180f, 0.631484f, 0.283889f, 0.635551f, 0.300507f, 0.618074f, 0.299197f, 0.617110f, 0.287175f, 0.381926f, 0.299197f, 0.364449f, 0.300507f, 0.368516f, 0.283889f, 0.382890f, 0.287175f, 0.635551f, 0.300507f, 0.628251f, 0.311636f, 0.615871f, 0.307438f, 0.618074f, 0.299197f, 0.384129f, 0.307438f, 0.371749f, 0.311636f, 0.364449f, 0.300507f, 0.381926f, 0.299197f, 0.628251f, 0.311636f, 0.606163f, 0.325516f, 0.598424f, 0.313725f, 0.615871f, 0.307438f, 0.401576f, 0.313725f, 0.393837f, 0.325516f, 0.371749f, 0.311636f, 0.384129f, 0.307438f, 0.606163f, 0.325516f, 0.592090f, 0.332885f, 0.590828f, 0.319797f, 0.598424f, 0.313725f, 0.409172f, 0.319797f, 0.407910f, 0.332885f, 0.393837f, 0.325516f, 0.401576f, 0.313725f, 0.592090f, 0.332885f, 0.579057f, 0.335646f, 0.582130f, 0.320991f, 0.590828f, 0.319797f, 0.417870f, 0.320991f, 0.420943f, 0.335646f, 0.407910f, 0.332885f, 0.409172f, 0.319797f, 0.579057f, 0.335646f, 0.559135f, 0.334326f, 0.570458f, 0.318697f, 0.582130f, 0.320991f, 0.429542f, 0.318697f, 0.440865f, 0.334326f, 0.420943f, 0.335646f, 0.417870f, 0.320991f, 0.582130f, 0.320991f, 0.570458f, 0.318697f, 0.578615f, 0.309394f, 0.583998f, 0.312892f, 0.421385f, 0.309394f, 0.429542f, 0.318697f, 0.417870f, 0.320991f, 0.416002f, 0.312892f, 0.590828f, 0.319797f, 0.582130f, 0.320991f, 0.583998f, 0.312892f, 0.589656f, 0.312336f, 0.416002f, 0.312892f, 0.417870f, 0.320991f, 0.409172f, 0.319797f, 0.410344f, 0.312336f, 0.598424f, 0.313725f, 0.590828f, 0.319797f, 0.589656f, 0.312336f, 0.596347f, 0.309249f, 0.410344f, 0.312336f, 0.409172f, 0.319797f, 0.401576f, 0.313725f, 0.403653f, 0.309249f, 0.615871f, 0.307438f, 0.598424f, 0.313725f, 0.596347f, 0.309249f, 0.606014f, 0.302517f, 0.403653f, 0.309249f, 0.401576f, 0.313725f, 0.384129f, 0.307438f, 0.393986f, 0.302517f, 0.618074f, 0.299197f, 0.615871f, 0.307438f, 0.606014f, 0.302517f, 0.607735f, 0.297520f, 0.393986f, 0.302517f, 0.384129f, 0.307438f, 0.381926f, 0.299197f, 0.392265f, 0.297520f, 0.617110f, 0.287175f, 0.618074f, 0.299197f, 0.607735f, 0.297520f, 0.606985f, 0.291216f, 0.392265f, 0.297520f, 0.381926f, 0.299197f, 0.382890f, 0.287175f, 0.393015f, 0.291216f, 0.602190f, 0.277180f, 0.617110f, 0.287175f, 0.606985f, 0.291216f, 0.598275f, 0.283083f, 0.393015f, 0.291216f, 0.382890f, 0.287175f, 0.397810f, 0.277180f, 0.401725f, 0.283083f, 0.589914f, 0.271772f, 0.602190f, 0.277180f, 0.598275f, 0.283083f, 0.589866f, 0.280167f, 0.401725f, 0.283083f, 0.397810f, 0.277180f, 0.410086f, 0.271772f, 0.410134f, 0.280167f, 0.569243f, 0.278245f, 0.589914f, 0.271772f, 0.589866f, 0.280167f, 0.576352f, 0.284624f, 0.410134f, 0.280167f, 0.410086f, 0.271772f, 0.430757f, 0.278245f, 0.423648f, 0.284624f, 0.562361f, 0.284338f, 0.569243f, 0.278245f, 0.576352f, 0.284624f, 0.572831f, 0.289915f, 0.423648f, 0.284624f, 0.430757f, 0.278245f, 0.437639f, 0.284338f, 0.427169f, 0.289915f, 0.570458f, 0.318697f, 0.563180f, 0.307151f, 0.573307f, 0.303342f, 0.578615f, 0.309394f, 0.426693f, 0.303342f, 0.436820f, 0.307151f, 0.429542f, 0.318697f, 0.421385f, 0.309394f, 0.563180f, 0.307151f, 0.559190f, 0.294882f, 0.572447f, 0.295716f, 0.573307f, 0.303342f, 0.427553f, 0.295716f, 0.440810f, 0.294882f, 0.436820f, 0.307151f, 0.426693f, 0.303342f, 0.559190f, 0.294882f, 0.562361f, 0.284338f, 0.572831f, 0.289915f, 0.572447f, 0.295716f, 0.427169f, 0.289915f, 0.437639f, 0.284338f, 0.440810f, 0.294882f, 0.427553f, 0.295716f, 0.500000f, 0.382860f, 0.532016f, 0.387365f, 0.529647f, 0.428636f, 0.500000f, 0.428636f, 0.470353f, 0.428636f, 0.467984f, 0.387365f, 0.500000f, 0.382860f, 0.500000f, 0.428636f, 0.532016f, 0.387365f, 0.581044f, 0.398468f, 0.584616f, 0.428636f, 0.529647f, 0.428636f, 0.415384f, 0.428636f, 0.418956f, 0.398468f, 0.467984f, 0.387365f, 0.470353f, 0.428636f, 0.581044f, 0.398468f, 0.602261f, 0.395588f, 0.622301f, 0.417889f, 0.584616f, 0.428636f, 0.377699f, 0.417889f, 0.397739f, 0.395588f, 0.418956f, 0.398468f, 0.415384f, 0.428636f, 0.602261f, 0.395588f, 0.636775f, 0.370732f, 0.666214f, 0.388954f, 0.622301f, 0.417889f, 0.333786f, 0.388954f, 0.363225f, 0.370732f, 0.397739f, 0.395588f, 0.377699f, 0.417889f, 0.636775f, 0.370732f, 0.671357f, 0.334694f, 0.701481f, 0.344467f, 0.666214f, 0.388954f, 0.298519f, 0.344467f, 0.328643f, 0.334694f, 0.363225f, 0.370732f, 0.333786f, 0.388954f, 0.671357f, 0.334694f, 0.684517f, 0.317795f, 0.712163f, 0.315527f, 0.701481f, 0.344467f, 0.287837f, 0.315527f, 0.315483f, 0.317795f, 0.328643f, 0.334694f, 0.298519f, 0.344467f, 0.684517f, 0.317795f, 0.689501f, 0.268805f, 0.704305f, 0.260225f, 0.712163f, 0.315527f, 0.295695f, 0.260225f, 0.310499f, 0.268805f, 0.315483f, 0.317795f, 0.287837f, 0.315527f, 0.689501f, 0.268805f, 0.650908f, 0.240294f, 0.672947f, 0.224880f, 0.704305f, 0.260225f, 0.327053f, 0.224880f, 0.349092f, 0.240294f, 0.310499f, 0.268805f, 0.295695f, 0.260225f, 0.650908f, 0.240294f, 0.626605f, 0.208159f, 0.640497f, 0.198841f, 0.672947f, 0.224880f, 0.359503f, 0.198841f, 0.373395f, 0.208159f, 0.349092f, 0.240294f, 0.327053f, 0.224880f, 0.603553f, 0.023452f, 0.625128f, 0.029461f, 0.635753f, 0.082198f, 0.598617f, 0.056841f, 0.364247f, 0.082198f, 0.374872f, 0.029461f, 0.396447f, 0.023452f, 0.401383f, 0.056841f, 0.546781f, 0.009442f, 0.603553f, 0.023452f, 0.598617f, 0.056841f, 0.556354f, 0.040906f, 0.401383f, 0.056841f, 0.396447f, 0.023452f, 0.453219f, 0.009442f, 0.443646f, 0.040906f, 0.500000f, 0.033223f, 0.546781f, 0.009442f, 0.556354f, 0.040906f, 0.527159f, 0.049514f, 0.443646f, 0.040906f, 0.453219f, 0.009442f, 0.500000f, 0.033223f, 0.472841f, 0.049514f, 0.520711f, 0.060503f, 0.500000f, 0.054411f, 0.500000f, 0.033223f, 0.527159f, 0.049514f, 0.500000f, 0.033223f, 0.500000f, 0.054411f, 0.479289f, 0.060503f, 0.472841f, 0.049514f, 0.530457f, 0.065062f, 0.520711f, 0.060503f, 0.527159f, 0.049514f, 0.537222f, 0.060794f, 0.472841f, 0.049514f, 0.479289f, 0.060503f, 0.469543f, 0.065062f, 0.462778f, 0.060794f, 0.532878f, 0.067822f, 0.530457f, 0.065062f, 0.537222f, 0.060794f, 0.558499f, 0.065137f, 0.462778f, 0.060794f, 0.469543f, 0.065062f, 0.467122f, 0.067822f, 0.441501f, 0.065137f, 0.544695f, 0.083023f, 0.532878f, 0.067822f, 0.558499f, 0.065137f, 0.588127f, 0.085177f, 0.441501f, 0.065137f, 0.467122f, 0.067822f, 0.455305f, 0.083023f, 0.411873f, 0.085177f, 0.558499f, 0.065137f, 0.556354f, 0.040906f, 0.598617f, 0.056841f, 0.588127f, 0.085177f, 0.401383f, 0.056841f, 0.443646f, 0.040906f, 0.441501f, 0.065137f, 0.411873f, 0.085177f, 0.558499f, 0.065137f, 0.537222f, 0.060794f, 0.527159f, 0.049514f, 0.556354f, 0.040906f, 0.472841f, 0.049514f, 0.462778f, 0.060794f, 0.441501f, 0.065137f, 0.443646f, 0.040906f, 0.607239f, 0.113940f, 0.588127f, 0.085177f, 0.598617f, 0.056841f, 0.635753f, 0.082198f, 0.401383f, 0.056841f, 0.411873f, 0.085177f, 0.392761f, 0.113940f, 0.364247f, 0.082198f, 0.565647f, 0.115495f, 0.544695f, 0.083023f, 0.588127f, 0.085177f, 0.607239f, 0.113940f, 0.411873f, 0.085177f, 0.455305f, 0.083023f, 0.434353f, 0.115495f, 0.392761f, 0.113940f, 0.578661f, 0.139176f, 0.612663f, 0.133675f, 0.605467f, 0.151503f, 0.583245f, 0.154155f, 0.394533f, 0.151503f, 0.387337f, 0.133675f, 0.421339f, 0.139176f, 0.416755f, 0.154155f, 0.565647f, 0.115495f, 0.607239f, 0.113940f, 0.612663f, 0.133675f, 0.578661f, 0.139176f, 0.387337f, 0.133675f, 0.392761f, 0.113940f, 0.434353f, 0.115495f, 0.421339f, 0.139176f, 0.586916f, 0.172042f, 0.583245f, 0.154155f, 0.605467f, 0.151503f, 0.600708f, 0.162985f, 0.394533f, 0.151503f, 0.416755f, 0.154155f, 0.413084f, 0.172042f, 0.399292f, 0.162985f, 0.586916f, 0.172042f, 0.600708f, 0.162985f, 0.640497f, 0.198841f, 0.626605f, 0.208159f, 0.359503f, 0.198841f, 0.399292f, 0.162985f, 0.413084f, 0.172042f, 0.373395f, 0.208159f, 0.922374f, 0.064228f, 0.859647f, 0.117994f, 0.823287f, 0.101559f, 0.861342f, 0.027230f, 0.176713f, 0.101559f, 0.140353f, 0.117994f, 0.077626f, 0.064228f, 0.138658f, 0.027230f, 0.861342f, 0.027230f, 0.823287f, 0.101559f, 0.765863f, 0.087001f, 0.774604f, 0.010837f, 0.234137f, 0.087001f, 0.176713f, 0.101559f, 0.138658f, 0.027230f, 0.225396f, 0.010837f, 0.774604f, 0.010837f, 0.765863f, 0.087001f, 0.661952f, 0.087561f, 0.647010f, 0.028716f, 0.338048f, 0.087561f, 0.234137f, 0.087001f, 0.225396f, 0.010837f, 0.352990f, 0.028716f, 0.647010f, 0.028716f, 0.661952f, 0.087561f, 0.635753f, 0.082198f, 0.625128f, 0.029461f, 0.364247f, 0.082198f, 0.338048f, 0.087561f, 0.352990f, 0.028716f, 0.374872f, 0.029461f, 0.607239f, 0.113940f, 0.635753f, 0.082198f, 0.661952f, 0.087561f, 0.612663f, 0.133675f, 0.338048f, 0.087561f, 0.364247f, 0.082198f, 0.392761f, 0.113940f, 0.387337f, 0.133675f, 0.704305f, 0.260225f, 0.672947f, 0.224880f, 0.743592f, 0.198572f, 0.766410f, 0.233065f, 0.256408f, 0.198572f, 0.327053f, 0.224880f, 0.295695f, 0.260225f, 0.233590f, 0.233065f, 0.987633f, 0.154243f, 0.889478f, 0.177602f, 0.859647f, 0.117994f, 0.922374f, 0.064228f, 0.140353f, 0.117994f, 0.110522f, 0.177602f, 0.012367f, 0.154243f, 0.077626f, 0.064228f, 0.899807f, 0.420886f, 0.844317f, 0.347370f, 0.881169f, 0.309153f, 0.958963f, 0.357385f, 0.118831f, 0.309153f, 0.155683f, 0.347370f, 0.100193f, 0.420886f, 0.041037f, 0.357385f, 0.958963f, 0.357385f, 0.881169f, 0.309153f, 0.903302f, 0.261367f, 0.999860f, 0.253531f, 0.096698f, 0.261367f, 0.118831f, 0.309153f, 0.041037f, 0.357385f, 0.000140f, 0.253531f, 0.999860f, 0.253531f, 0.903302f, 0.261367f, 0.889478f, 0.177602f, 0.987633f, 0.154243f, 0.110522f, 0.177602f, 0.096698f, 0.261367f, 0.000140f, 0.253531f, 0.012367f, 0.154243f, 0.724763f, 0.340212f, 0.712163f, 0.315527f, 0.744725f, 0.304629f, 0.766113f, 0.319494f, 0.255275f, 0.304629f, 0.287837f, 0.315527f, 0.275237f, 0.340212f, 0.233887f, 0.319494f, 0.766113f, 0.319494f, 0.744725f, 0.304629f, 0.793427f, 0.280495f, 0.826663f, 0.297810f, 0.206573f, 0.280495f, 0.255275f, 0.304629f, 0.233887f, 0.319494f, 0.173337f, 0.297810f, 0.826663f, 0.297810f, 0.793427f, 0.280495f, 0.823620f, 0.254612f, 0.855331f, 0.267956f, 0.176380f, 0.254612f, 0.206573f, 0.280495f, 0.173337f, 0.297810f, 0.144669f, 0.267956f, 0.855331f, 0.267956f, 0.823620f, 0.254612f, 0.835860f, 0.225225f, 0.868309f, 0.233525f, 0.164140f, 0.225225f, 0.176380f, 0.254612f, 0.144669f, 0.267956f, 0.131691f, 0.233525f, 0.813499f, 0.190705f, 0.851288f, 0.181145f, 0.868309f, 0.233525f, 0.835860f, 0.225225f, 0.131691f, 0.233525f, 0.148712f, 0.181145f, 0.186501f, 0.190705f, 0.164140f, 0.225225f, 0.889478f, 0.177602f, 0.903302f, 0.261367f, 0.868309f, 0.233525f, 0.851288f, 0.181145f, 0.131691f, 0.233525f, 0.096698f, 0.261367f, 0.110522f, 0.177602f, 0.148712f, 0.181145f, 0.903302f, 0.261367f, 0.881169f, 0.309153f, 0.855331f, 0.267956f, 0.868309f, 0.233525f, 0.144669f, 0.267956f, 0.118831f, 0.309153f, 0.096698f, 0.261367f, 0.131691f, 0.233525f, 0.881169f, 0.309153f, 0.844317f, 0.347370f, 0.826663f, 0.297810f, 0.855331f, 0.267956f, 0.173337f, 0.297810f, 0.155683f, 0.347370f, 0.118831f, 0.309153f, 0.144669f, 0.267956f, 0.844317f, 0.347370f, 0.772263f, 0.374010f, 0.766113f, 0.319494f, 0.826663f, 0.297810f, 0.233887f, 0.319494f, 0.227737f, 0.374010f, 0.155683f, 0.347370f, 0.173337f, 0.297810f, 0.744519f, 0.390057f, 0.724763f, 0.340212f, 0.766113f, 0.319494f, 0.772263f, 0.374010f, 0.233887f, 0.319494f, 0.275237f, 0.340212f, 0.255481f, 0.390057f, 0.227737f, 0.374010f, 0.824765f, 0.470987f, 0.772263f, 0.374010f, 0.844317f, 0.347370f, 0.899807f, 0.420886f, 0.155683f, 0.347370f, 0.227737f, 0.374010f, 0.175235f, 0.470987f, 0.100193f, 0.420886f, 0.792141f, 0.464714f, 0.742181f, 0.461543f, 0.726855f, 0.432574f, 0.744519f, 0.390057f, 0.273145f, 0.432574f, 0.257819f, 0.461543f, 0.207859f, 0.464714f, 0.255481f, 0.390057f, 0.792141f, 0.464714f, 0.744519f, 0.390057f, 0.772263f, 0.374010f, 0.824765f, 0.470987f, 0.227737f, 0.374010f, 0.255481f, 0.390057f, 0.207859f, 0.464714f, 0.175235f, 0.470987f, 0.795638f, 0.489991f, 0.792141f, 0.464714f, 0.824765f, 0.470987f, 0.175235f, 0.470987f, 0.207859f, 0.464714f, 0.204362f, 0.489991f, 0.712163f, 0.315527f, 0.704305f, 0.260225f, 0.766410f, 0.233065f, 0.744725f, 0.304629f, 0.233590f, 0.233065f, 0.295695f, 0.260225f, 0.287837f, 0.315527f, 0.255275f, 0.304629f, 0.766410f, 0.233065f, 0.786137f, 0.227788f, 0.793427f, 0.280495f, 0.744725f, 0.304629f, 0.206573f, 0.280495f, 0.213863f, 0.227788f, 0.233590f, 0.233065f, 0.255275f, 0.304629f, 0.786137f, 0.227788f, 0.802950f, 0.203415f, 0.823620f, 0.254612f, 0.793427f, 0.280495f, 0.176380f, 0.254612f, 0.197050f, 0.203415f, 0.213863f, 0.227788f, 0.206573f, 0.280495f, 0.813499f, 0.190705f, 0.835860f, 0.225225f, 0.823620f, 0.254612f, 0.802950f, 0.203415f, 0.176380f, 0.254612f, 0.164140f, 0.225225f, 0.186501f, 0.190705f, 0.197050f, 0.203415f, 0.661952f, 0.087561f, 0.765863f, 0.087001f, 0.769334f, 0.128771f, 0.691484f, 0.146686f, 0.230666f, 0.128771f, 0.234137f, 0.087001f, 0.338048f, 0.087561f, 0.308516f, 0.146686f, 0.743592f, 0.198572f, 0.691484f, 0.146686f, 0.769334f, 0.128771f, 0.780113f, 0.169386f, 0.230666f, 0.128771f, 0.308516f, 0.146686f, 0.256408f, 0.198572f, 0.219887f, 0.169386f, 0.672947f, 0.224880f, 0.640497f, 0.198841f, 0.691484f, 0.146686f, 0.743592f, 0.198572f, 0.308516f, 0.146686f, 0.359503f, 0.198841f, 0.327053f, 0.224880f, 0.256408f, 0.198572f, 0.640497f, 0.198841f, 0.605467f, 0.151503f, 0.612663f, 0.133675f, 0.691484f, 0.146686f, 0.387337f, 0.133675f, 0.394533f, 0.151503f, 0.359503f, 0.198841f, 0.308516f, 0.146686f, 0.612663f, 0.133675f, 0.661952f, 0.087561f, 0.691484f, 0.146686f, 0.308516f, 0.146686f, 0.338048f, 0.087561f, 0.387337f, 0.133675f, 0.640497f, 0.198841f, 0.600708f, 0.162985f, 0.605467f, 0.151503f, 0.394533f, 0.151503f, 0.399292f, 0.162985f, 0.359503f, 0.198841f, 0.813499f, 0.190705f, 0.803789f, 0.171181f, 0.830917f, 0.139518f, 0.851288f, 0.181145f, 0.169083f, 0.139518f, 0.196211f, 0.171181f, 0.186501f, 0.190705f, 0.148712f, 0.181145f, 0.889478f, 0.177602f, 0.851288f, 0.181145f, 0.830917f, 0.139518f, 0.859647f, 0.117994f, 0.169083f, 0.139518f, 0.148712f, 0.181145f, 0.110522f, 0.177602f, 0.140353f, 0.117994f, 0.780113f, 0.169386f, 0.769334f, 0.128771f, 0.830917f, 0.139518f, 0.803789f, 0.171181f, 0.169083f, 0.139518f, 0.230666f, 0.128771f, 0.219887f, 0.169386f, 0.196211f, 0.171181f, 0.765863f, 0.087001f, 0.823287f, 0.101559f, 0.830917f, 0.139518f, 0.769334f, 0.128771f, 0.169083f, 0.139518f, 0.176713f, 0.101559f, 0.234137f, 0.087001f, 0.230666f, 0.128771f, 0.859647f, 0.117994f, 0.830917f, 0.139518f, 0.823287f, 0.101559f, 0.176713f, 0.101559f, 0.169083f, 0.139518f, 0.140353f, 0.117994f, 0.574628f, 0.959188f, 0.464516f, 0.959188f, 0.477326f, 0.891852f, 0.545439f, 0.884582f, 0.272900f, 0.891852f, 0.285710f, 0.959188f, 0.175598f, 0.959188f, 0.204787f, 0.884582f, 0.574628f, 0.959188f, 0.545439f, 0.884582f, 0.605134f, 0.846978f, 0.715894f, 0.897069f, 0.145092f, 0.846978f, 0.204787f, 0.884582f, 0.175598f, 0.959188f, 0.034332f, 0.897069f, 0.715894f, 0.897069f, 0.605134f, 0.846978f, 0.605360f, 0.784410f, 0.683874f, 0.757011f, 0.144866f, 0.784410f, 0.145092f, 0.846978f, 0.034332f, 0.897069f, 0.066352f, 0.757011f, 0.683874f, 0.757011f, 0.605360f, 0.784410f, 0.574835f, 0.744212f, 0.617867f, 0.719156f, 0.175391f, 0.744212f, 0.144866f, 0.784410f, 0.066352f, 0.757011f, 0.132359f, 0.719156f, 0.617867f, 0.719156f, 0.574835f, 0.744212f, 0.534996f, 0.712528f, 0.568728f, 0.682132f, 0.215230f, 0.712528f, 0.175391f, 0.744212f, 0.132359f, 0.719156f, 0.181498f, 0.682132f, 0.568728f, 0.682132f, 0.534996f, 0.712528f, 0.483006f, 0.686791f, 0.508539f, 0.641024f, 0.267220f, 0.686791f, 0.215230f, 0.712528f, 0.181498f, 0.682132f, 0.241687f, 0.641024f, 0.534996f, 0.712528f, 0.513415f, 0.736977f, 0.478880f, 0.719593f, 0.483006f, 0.686791f, 0.271346f, 0.719593f, 0.236811f, 0.736977f, 0.215230f, 0.712528f, 0.267220f, 0.686791f, 0.574835f, 0.744212f, 0.541117f, 0.760754f, 0.513415f, 0.736977f, 0.534996f, 0.712528f, 0.236811f, 0.736977f, 0.209109f, 0.760754f, 0.175391f, 0.744212f, 0.215230f, 0.712528f, 0.605360f, 0.784410f, 0.557599f, 0.789442f, 0.541117f, 0.760754f, 0.574835f, 0.744212f, 0.209109f, 0.760754f, 0.192627f, 0.789442f, 0.144866f, 0.784410f, 0.175391f, 0.744212f, 0.605134f, 0.846978f, 0.553841f, 0.821849f, 0.557599f, 0.789442f, 0.605360f, 0.784410f, 0.192627f, 0.789442f, 0.196385f, 0.821849f, 0.145092f, 0.846978f, 0.144866f, 0.784410f, 0.545439f, 0.884582f, 0.524671f, 0.842380f, 0.553841f, 0.821849f, 0.605134f, 0.846978f, 0.196385f, 0.821849f, 0.225555f, 0.842380f, 0.204787f, 0.884582f, 0.145092f, 0.846978f, 0.545439f, 0.884582f, 0.477326f, 0.891852f, 0.485193f, 0.845321f, 0.524671f, 0.842380f, 0.265033f, 0.845321f, 0.272900f, 0.891852f, 0.204787f, 0.884582f, 0.225555f, 0.842380f, 0.743592f, 0.198572f, 0.780113f, 0.169386f, 0.786150f, 0.181127f, 0.770208f, 0.191225f, 0.213850f, 0.181127f, 0.219887f, 0.169386f, 0.256408f, 0.198572f, 0.229792f, 0.191225f, 0.408153f, 0.587507f, 0.508539f, 0.641024f, 0.483006f, 0.686791f, 0.409610f, 0.674022f, 0.267220f, 0.686791f, 0.241687f, 0.641024f, 0.342073f, 0.587507f, 0.340616f, 0.674022f, 0.766410f, 0.233065f, 0.743592f, 0.198572f, 0.770208f, 0.191225f, 0.786137f, 0.227788f, 0.229792f, 0.191225f, 0.256408f, 0.198572f, 0.233590f, 0.233065f, 0.213863f, 0.227788f, 0.400301f, 0.910556f, 0.414155f, 0.878318f, 0.477326f, 0.891852f, 0.464516f, 0.959188f, 0.272900f, 0.891852f, 0.336071f, 0.878318f, 0.349925f, 0.910556f, 0.285710f, 0.959188f, 0.483006f, 0.686791f, 0.478880f, 0.719593f, 0.443630f, 0.713731f, 0.409610f, 0.674022f, 0.306596f, 0.713731f, 0.271346f, 0.719593f, 0.267220f, 0.686791f, 0.340616f, 0.674022f, 0.429725f, 0.728622f, 0.392812f, 0.710774f, 0.409610f, 0.674022f, 0.443630f, 0.713731f, 0.340616f, 0.674022f, 0.357414f, 0.710774f, 0.320501f, 0.728622f, 0.306596f, 0.713731f, 0.422979f, 0.754609f, 0.392812f, 0.710774f, 0.429725f, 0.728622f, 0.432640f, 0.746527f, 0.320501f, 0.728622f, 0.357414f, 0.710774f, 0.327247f, 0.754609f, 0.317586f, 0.746527f, 0.427719f, 0.796173f, 0.391578f, 0.815187f, 0.392812f, 0.710774f, 0.422979f, 0.754609f, 0.357414f, 0.710774f, 0.358648f, 0.815187f, 0.322507f, 0.796173f, 0.327247f, 0.754609f, 0.414155f, 0.878318f, 0.391578f, 0.815187f, 0.427719f, 0.796173f, 0.448277f, 0.830976f, 0.322507f, 0.796173f, 0.358648f, 0.815187f, 0.336071f, 0.878318f, 0.301949f, 0.830976f, 0.477326f, 0.891852f, 0.414155f, 0.878318f, 0.448277f, 0.830976f, 0.485193f, 0.845321f, 0.301949f, 0.830976f, 0.336071f, 0.878318f, 0.272900f, 0.891852f, 0.265033f, 0.845321f, 0.786137f, 0.227788f, 0.797710f, 0.195652f, 0.802580f, 0.199758f, 0.802950f, 0.203415f, 0.197420f, 0.199758f, 0.202290f, 0.195652f, 0.213863f, 0.227788f, 0.197050f, 0.203415f, 0.786137f, 0.227788f, 0.770208f, 0.191225f, 0.789609f, 0.184671f, 0.797710f, 0.195652f, 0.210391f, 0.184671f, 0.229792f, 0.191225f, 0.213863f, 0.227788f, 0.202290f, 0.195652f, 0.770208f, 0.191225f, 0.786150f, 0.181127f, 0.789609f, 0.184671f, 0.210391f, 0.184671f, 0.213850f, 0.181127f, 0.229792f, 0.191225f, 0.485193f, 0.845321f, 0.448277f, 0.830976f, 0.466042f, 0.804091f, 0.490498f, 0.816075f, 0.284184f, 0.804091f, 0.301949f, 0.830976f, 0.265033f, 0.845321f, 0.259728f, 0.816075f, 0.448277f, 0.830976f, 0.427719f, 0.796173f, 0.448042f, 0.783921f, 0.466042f, 0.804091f, 0.302184f, 0.783921f, 0.322507f, 0.796173f, 0.301949f, 0.830976f, 0.284184f, 0.804091f, 0.427719f, 0.796173f, 0.422979f, 0.754609f, 0.438745f, 0.764960f, 0.448042f, 0.783921f, 0.311481f, 0.764960f, 0.327247f, 0.754609f, 0.322507f, 0.796173f, 0.302184f, 0.783921f, 0.422979f, 0.754609f, 0.432640f, 0.746527f, 0.445216f, 0.756351f, 0.438745f, 0.764960f, 0.305010f, 0.756351f, 0.317586f, 0.746527f, 0.327247f, 0.754609f, 0.311481f, 0.764960f, 0.432640f, 0.746527f, 0.429725f, 0.728622f, 0.449819f, 0.743458f, 0.445216f, 0.756351f, 0.300407f, 0.743458f, 0.320501f, 0.728622f, 0.317586f, 0.746527f, 0.305010f, 0.756351f, 0.429725f, 0.728622f, 0.443630f, 0.713731f, 0.456307f, 0.732687f, 0.449819f, 0.743458f, 0.293919f, 0.732687f, 0.306596f, 0.713731f, 0.320501f, 0.728622f, 0.300407f, 0.743458f, 0.443630f, 0.713731f, 0.478880f, 0.719593f, 0.475471f, 0.740871f, 0.456307f, 0.732687f, 0.274755f, 0.740871f, 0.271346f, 0.719593f, 0.306596f, 0.713731f, 0.293919f, 0.732687f, 0.524671f, 0.842380f, 0.485193f, 0.845321f, 0.490498f, 0.816075f, 0.514211f, 0.817769f, 0.259728f, 0.816075f, 0.265033f, 0.845321f, 0.225555f, 0.842380f, 0.236015f, 0.817769f, 0.553841f, 0.821849f, 0.524671f, 0.842380f, 0.514211f, 0.817769f, 0.527961f, 0.808598f, 0.236015f, 0.817769f, 0.225555f, 0.842380f, 0.196385f, 0.821849f, 0.222265f, 0.808598f, 0.557599f, 0.789442f, 0.553841f, 0.821849f, 0.527961f, 0.808598f, 0.530079f, 0.790754f, 0.222265f, 0.808598f, 0.196385f, 0.821849f, 0.192627f, 0.789442f, 0.220147f, 0.790754f, 0.541117f, 0.760754f, 0.557599f, 0.789442f, 0.530079f, 0.790754f, 0.518620f, 0.772385f, 0.220147f, 0.790754f, 0.192627f, 0.789442f, 0.209109f, 0.760754f, 0.231606f, 0.772385f, 0.513415f, 0.736977f, 0.541117f, 0.760754f, 0.518620f, 0.772385f, 0.498668f, 0.755033f, 0.231606f, 0.772385f, 0.209109f, 0.760754f, 0.236811f, 0.736977f, 0.251558f, 0.755033f, 0.478880f, 0.719593f, 0.513415f, 0.736977f, 0.498668f, 0.755033f, 0.475471f, 0.740871f, 0.251558f, 0.755033f, 0.236811f, 0.736977f, 0.271346f, 0.719593f, 0.274755f, 0.740871f, 0.445216f, 0.756351f, 0.449819f, 0.743458f, 0.468029f, 0.756171f, 0.459660f, 0.770459f, 0.282197f, 0.756171f, 0.300407f, 0.743458f, 0.305010f, 0.756351f, 0.290566f, 0.770459f, 0.459660f, 0.770459f, 0.468029f, 0.756171f, 0.487167f, 0.769899f, 0.477354f, 0.785393f, 0.263059f, 0.769899f, 0.282197f, 0.756171f, 0.290566f, 0.770459f, 0.272872f, 0.785393f, 0.477354f, 0.785393f, 0.487167f, 0.769899f, 0.504617f, 0.782999f, 0.496545f, 0.797122f, 0.245609f, 0.782999f, 0.263059f, 0.769899f, 0.272872f, 0.785393f, 0.253681f, 0.797122f, 0.496545f, 0.797122f, 0.504617f, 0.782999f, 0.516137f, 0.792591f, 0.513713f, 0.804019f, 0.234089f, 0.792591f, 0.245609f, 0.782999f, 0.253681f, 0.797122f, 0.236513f, 0.804019f, 0.514211f, 0.817769f, 0.490498f, 0.816075f, 0.496545f, 0.797122f, 0.513713f, 0.804019f, 0.253681f, 0.797122f, 0.259728f, 0.816075f, 0.236015f, 0.817769f, 0.236513f, 0.804019f, 0.466042f, 0.804091f, 0.477354f, 0.785393f, 0.496545f, 0.797122f, 0.490498f, 0.816075f, 0.253681f, 0.797122f, 0.272872f, 0.785393f, 0.284184f, 0.804091f, 0.259728f, 0.816075f, 0.466042f, 0.804091f, 0.448042f, 0.783921f, 0.459660f, 0.770459f, 0.477354f, 0.785393f, 0.290566f, 0.770459f, 0.302184f, 0.783921f, 0.284184f, 0.804091f, 0.272872f, 0.785393f, 0.445216f, 0.756351f, 0.459660f, 0.770459f, 0.448042f, 0.783921f, 0.438745f, 0.764960f, 0.302184f, 0.783921f, 0.290566f, 0.770459f, 0.305010f, 0.756351f, 0.311481f, 0.764960f, 0.456307f, 0.732687f, 0.475471f, 0.740871f, 0.468029f, 0.756171f, 0.449819f, 0.743458f, 0.282197f, 0.756171f, 0.274755f, 0.740871f, 0.293919f, 0.732687f, 0.300407f, 0.743458f, 0.498668f, 0.755033f, 0.487167f, 0.769899f, 0.468029f, 0.756171f, 0.475471f, 0.740871f, 0.282197f, 0.756171f, 0.263059f, 0.769899f, 0.251558f, 0.755033f, 0.274755f, 0.740871f, 0.518620f, 0.772385f, 0.504617f, 0.782999f, 0.487167f, 0.769899f, 0.498668f, 0.755033f, 0.263059f, 0.769899f, 0.245609f, 0.782999f, 0.231606f, 0.772385f, 0.251558f, 0.755033f, 0.530079f, 0.790754f, 0.516137f, 0.792591f, 0.504617f, 0.782999f, 0.518620f, 0.772385f, 0.245609f, 0.782999f, 0.234089f, 0.792591f, 0.220147f, 0.790754f, 0.231606f, 0.772385f, 0.527961f, 0.808598f, 0.513713f, 0.804019f, 0.516137f, 0.792591f, 0.530079f, 0.790754f, 0.234089f, 0.792591f, 0.236513f, 0.804019f, 0.222265f, 0.808598f, 0.220147f, 0.790754f, 0.514211f, 0.817769f, 0.513713f, 0.804019f, 0.527961f, 0.808598f, 0.222265f, 0.808598f, 0.236513f, 0.804019f, 0.236015f, 0.817769f, 0.568728f, 0.682132f, 0.508539f, 0.641024f, 0.574269f, 0.607668f, 0.613510f, 0.655816f, 0.175957f, 0.607668f, 0.241687f, 0.641024f, 0.181498f, 0.682132f, 0.136716f, 0.655816f, 0.617867f, 0.719156f, 0.568728f, 0.682132f, 0.613510f, 0.655816f, 0.644031f, 0.693270f, 0.136716f, 0.655816f, 0.181498f, 0.682132f, 0.132359f, 0.719156f, 0.106195f, 0.693270f, 0.683874f, 0.757011f, 0.617867f, 0.719156f, 0.644031f, 0.693270f, 0.668163f, 0.712097f, 0.106195f, 0.693270f, 0.132359f, 0.719156f, 0.066352f, 0.757011f, 0.082063f, 0.712097f, 0.727131f, 0.698475f, 0.683874f, 0.757011f, 0.668163f, 0.712097f, 0.676584f, 0.686010f, 0.082063f, 0.712097f, 0.066352f, 0.757011f, 0.023095f, 0.698475f, 0.073642f, 0.686010f, 0.729804f, 0.624370f, 0.727131f, 0.698475f, 0.676584f, 0.686010f, 0.667013f, 0.640198f, 0.073642f, 0.686010f, 0.023095f, 0.698475f, 0.020422f, 0.624370f, 0.083213f, 0.640198f, 0.721292f, 0.572934f, 0.729804f, 0.624370f, 0.667013f, 0.640198f, 0.648152f, 0.594596f, 0.083213f, 0.640198f, 0.020422f, 0.624370f, 0.028934f, 0.572934f, 0.102074f, 0.594596f, 0.667013f, 0.640198f, 0.613510f, 0.655816f, 0.574269f, 0.607668f, 0.648152f, 0.594596f, 0.175957f, 0.607668f, 0.136716f, 0.655816f, 0.083213f, 0.640198f, 0.102074f, 0.594596f, 0.667013f, 0.640198f, 0.676584f, 0.686010f, 0.644031f, 0.693270f, 0.613510f, 0.655816f, 0.106195f, 0.693270f, 0.073642f, 0.686010f, 0.083213f, 0.640198f, 0.136716f, 0.655816f, 0.676584f, 0.686010f, 0.668163f, 0.712097f, 0.644031f, 0.693270f, 0.106195f, 0.693270f, 0.082063f, 0.712097f, 0.073642f, 0.686010f, 0.630034f, 0.557583f, 0.717709f, 0.538143f, 0.721292f, 0.572934f, 0.648152f, 0.594596f, 0.028934f, 0.572934f, 0.032517f, 0.538143f, 0.120192f, 0.557583f, 0.102074f, 0.594596f, 0.630034f, 0.557583f, 0.648152f, 0.594596f, 0.574269f, 0.607668f, 0.526877f, 0.539235f, 0.175957f, 0.607668f, 0.102074f, 0.594596f, 0.120192f, 0.557583f, 0.223349f, 0.539235f, 0.408153f, 0.587507f, 0.526877f, 0.539235f, 0.574269f, 0.607668f, 0.508539f, 0.641024f, 0.175957f, 0.607668f, 0.223349f, 0.539235f, 0.342073f, 0.587507f, 0.241687f, 0.641024f, }; #define VERT_MARK 1 #define EDGE_ORIG 1 #define EDGE_MARK 2 #define FACE_MARK 1 #define FACE_NEW 2 void bmo_create_grid_exec(BMesh *bm, BMOperator *op) { BMOpSlot *slot_verts_out = BMO_slot_get(op->slots_out, "verts.out"); const float dia = BMO_slot_float_get(op->slots_in, "size"); const uint xtot = max_ii(1, BMO_slot_int_get(op->slots_in, "x_segments")); const uint ytot = max_ii(1, BMO_slot_int_get(op->slots_in, "y_segments")); const float xtot_inv2 = 2.0f / (xtot); const float ytot_inv2 = 2.0f / (ytot); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMVert **varr; BMVert *vquad[4]; float mat[4][4]; float vec[3], tvec[3]; uint x, y, i; BMO_slot_mat4_get(op->slots_in, "matrix", mat); BMO_slot_buffer_alloc(op, op->slots_out, "verts.out", (xtot + 1) * (ytot + 1)); varr = (BMVert **)slot_verts_out->data.buf; i = 0; vec[2] = 0.0f; for (y = 0; y <= ytot; y++) { vec[1] = ((y * ytot_inv2) - 1.0f) * dia; for (x = 0; x <= xtot; x++) { vec[0] = ((x * xtot_inv2) - 1.0f) * dia; mul_v3_m4v3(tvec, mat, vec); varr[i] = BM_vert_create(bm, tvec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, varr[i], VERT_MARK); i++; } } #define XY(_x, _y) ((_x) + ((_y) * (xtot + 1))) for (y = 1; y <= ytot; y++) { for (x = 1; x <= xtot; x++) { BMFace *f; vquad[0] = varr[XY(x - 1, y - 1)]; vquad[1] = varr[XY(x, y - 1)]; vquad[2] = varr[XY(x, y)]; vquad[3] = varr[XY(x - 1, y)]; f = BM_face_create_verts(bm, vquad, 4, nullptr, BM_CREATE_NOP, true); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } } } #undef XY if (calc_uvs) { BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK, cd_loop_uv_offset); } } void BM_mesh_calc_uvs_grid(BMesh *bm, const uint x_segments, const uint y_segments, const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMLoop *l; BMIter iter, liter; const float dx = 1.0f / float(x_segments); const float dy = 1.0f / float(y_segments); const float dx_wrap = 1.0 - (dx / 2.0f); float x = 0.0f; float y = dy; int loop_index; BLI_assert(cd_loop_uv_offset != -1); BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); switch (loop_index) { case 0: y -= dy; break; case 1: x += dx; break; case 2: y += dy; break; case 3: x -= dx; break; default: break; } luv[0] = x; luv[1] = y; } x += dx; if (x >= dx_wrap) { x = 0.0f; y += dy; } } } void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) { const float rad = BMO_slot_float_get(op->slots_in, "radius"); const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; BMIter iter; const float axis[3] = {0, 0, 1}; float vec[3], mat[4][4], cmat[3][3]; int a; BMO_slot_mat4_get(op->slots_in, "matrix", mat); const float phid = float(M_PI) / tot; // const float phi = 0.25f * float(M_PI); /* UNUSED. */ /* one segment first */ for (a = 0; a <= tot; a++) { /* Going in this direction, then edge extruding, makes normals face outward */ float sin_phi, cos_phi; sin_cos_from_fraction(a, 2 * tot, &sin_phi, &cos_phi); vec[0] = 0.0f; vec[1] = rad * sin_phi; vec[2] = rad * cos_phi; eve = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, eve, VERT_MARK); if (a != 0) { e = BM_edge_create(bm, preveve, eve, nullptr, BM_CREATE_NOP); BMO_edge_flag_enable(bm, e, EDGE_ORIG); } preveve = eve; } /* extrude and rotate; negative phi to make normals face outward */ axis_angle_to_mat3(cmat, axis, -(M_PI * 2) / seg); for (a = 0; a < seg; a++) { if (a) { BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); } else { BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG); BMO_op_exec(bm, &bmop); } BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); BMO_op_callf(bm, op->flag, "rotate cent=%v matrix=%m3 verts=%S", vec, cmat, &bmop, "geom.out"); prevop = bmop; } if (a) { BMO_op_finish(bm, &bmop); } { float len, len2, vec2[3]; len = 2 * rad * sinf(phid / 2.0f); /* Length of one segment in shortest parallel. */ vec[0] = rad * sinf(phid); vec[1] = 0.0f; vec[2] = rad * cosf(phid); mul_v3_m3v3(vec2, cmat, vec); len2 = len_v3v3(vec, vec2); /* use shortest segment length divided by 3 as merge threshold */ BMO_op_callf( bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f); } if (calc_uvs) { BMFace *f; BMLoop *l; BMIter fiter, liter; /* We cannot tag faces for UVs computing above, * so we have to do it now, based on all its vertices being tagged. */ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { bool valid = true; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { if (!BMO_vert_flag_test(bm, l->v, VERT_MARK)) { valid = false; break; } } if (valid) { BMO_face_flag_enable(bm, f, FACE_MARK); } } BM_mesh_calc_uvs_sphere(bm, FACE_MARK, cd_loop_uv_offset); } /* Now apply the inverse matrix. */ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_vert_flag_test(bm, eve, VERT_MARK)) { mul_m4_v3(mat, eve->co); } } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) { const float rad = BMO_slot_float_get(op->slots_in, "radius"); const float rad_div = rad / 200.0f; const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMVert *eva[12]; BMVert *v; BMIter liter; BMIter viter; BMLoop *l; float vec[3], mat[4][4] /* , phi, phid */; int a; BMO_slot_mat4_get(op->slots_in, "matrix", mat); // phid = 2.0f * float(M_PI) / subdiv; /* UNUSED. */ // phi = 0.25f * float(M_PI); /* UNUSED. */ for (a = 0; a < 12; a++) { vec[0] = rad_div * icovert[a][0]; vec[1] = rad_div * icovert[a][1]; vec[2] = rad_div * icovert[a][2]; eva[a] = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, eva[a], VERT_MARK); } int uvi = 0; for (a = 0; a < 20; a++) { BMFace *f; BMVert *v1, *v2, *v3; v1 = eva[icoface[a][0]]; v2 = eva[icoface[a][1]]; v3 = eva[icoface[a][2]]; f = BM_face_create_quad_tri(bm, v1, v2, v3, nullptr, nullptr, BM_CREATE_NOP); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BMO_edge_flag_enable(bm, l->e, EDGE_MARK); } /* Set the UVs here, the iteration order of the faces is not guaranteed, * so it's best to set the UVs right after the face is created. */ if (calc_uvs) { int loop_index; BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); luv[0] = icouvs[uvi][0]; luv[1] = icouvs[uvi][1]; uvi++; } } } if (subdiv > 1) { BMOperator bmop; BMO_op_initf(bm, &bmop, op->flag, "subdivide_edges edges=%fe " "smooth=%f " "cuts=%i " "use_grid_fill=%b use_sphere=%b", EDGE_MARK, rad, (1 << (subdiv - 1)) - 1, true, true); BMO_op_exec(bm, &bmop); BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_EDGE, EDGE_MARK); BMO_op_finish(bm, &bmop); } /* must transform after because of sphere subdivision */ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (BMO_vert_flag_test(bm, v, VERT_MARK)) { mul_m4_v3(mat, v->co); } } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset) { float *uvs[4]; BMLoop *l; BMIter iter; float dx; int loop_index, loop_index_max_x; BLI_assert(f->len <= 4); /* If face has 3 vertices, it's a polar face, in which case we need to * compute a nearby to determine its latitude. */ float avgx = 0.0f, avgy = 0.0f; BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) { if (f->len == 3) { avgx += l->v->co[0]; avgy += l->v->co[1]; } } avgx /= 3.0f; avgy /= 3.0f; BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); float x = l->v->co[0]; float y = l->v->co[1]; float z = l->v->co[2]; float len = len_v3(l->v->co); /* Use neighboring point to compute angle for poles. */ float theta; if (f->len == 3 && fabsf(x) < 0.0001f && fabsf(y) < 0.0001f) { theta = atan2f(avgy, avgx); } else { theta = atan2f(y, x); } /* Shift borderline coordinates to the left. */ if (fabsf(theta - float(M_PI)) < 0.0001f) { theta = -M_PI; } float phi = safe_acosf(z / len); luv[0] = 0.5f + theta / (float(M_PI) * 2); luv[1] = 1.0f - phi / float(M_PI); uvs[loop_index] = luv; } /* Fix awkwardly-wrapping UVs */ loop_index_max_x = 0; for (loop_index = 1; loop_index < f->len; loop_index++) { if (uvs[loop_index][0] > uvs[loop_index_max_x][0]) { loop_index_max_x = loop_index; } } for (loop_index = 0; loop_index < f->len; loop_index++) { if (loop_index != loop_index_max_x) { dx = uvs[loop_index_max_x][0] - uvs[loop_index][0]; if (dx > 0.5f) { uvs[loop_index][0] += 1.0f; } } } } void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMIter iter; BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } bm_mesh_calc_uvs_sphere_face(f, cd_loop_uv_offset); } BMIter iter2; BMLoop *l; int loop_index; float minx = 1.0f; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); if (luv[0] < minx) { minx = luv[0]; } } } BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); luv[0] -= minx; } } } void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) { BMVert **tv = static_cast(MEM_mallocN(sizeof(*tv) * monkeynv * 2, "tv")); float mat[4][4]; int i; BMO_slot_mat4_get(op->slots_in, "matrix", mat); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); for (i = 0; i < monkeynv; i++) { float v[3]; /* rotate to face in the -Y axis */ v[0] = (monkeyv[i][0] + 127) / 128.0; v[2] = monkeyv[i][1] / 128.0; v[1] = monkeyv[i][2] / -128.0; tv[i] = BM_vert_create(bm, v, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, tv[i], VERT_MARK); if (fabsf(v[0] = -v[0]) < 0.001f) { tv[monkeynv + i] = tv[i]; } else { BMVert *eve = BM_vert_create(bm, v, nullptr, BM_CREATE_NOP); mul_m4_v3(mat, eve->co); tv[monkeynv + i] = eve; } BMO_vert_flag_enable(bm, tv[monkeynv + i], VERT_MARK); mul_m4_v3(mat, tv[i]->co); } int uvi = 0; for (i = 0; i < monkeynf; i++) { BMFace *f_new_a = BM_face_create_quad_tri( bm, tv[monkeyf[i][0] + i - monkeyo], tv[monkeyf[i][1] + i - monkeyo], tv[monkeyf[i][2] + i - monkeyo], (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : nullptr, nullptr, BM_CREATE_NOP); BMFace *f_new_b = BM_face_create_quad_tri( bm, tv[monkeynv + monkeyf[i][2] + i - monkeyo], tv[monkeynv + monkeyf[i][1] + i - monkeyo], tv[monkeynv + monkeyf[i][0] + i - monkeyo], (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : nullptr, nullptr, BM_CREATE_NOP); /* Set the UVs here, the iteration order of the faces is not guaranteed, * so it's best to set the UVs right after the face is created. */ if (calc_uvs) { BMLoop *l; BMIter liter; BM_ITER_ELEM (l, &liter, f_new_a, BM_LOOPS_OF_FACE) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); luv[0] = monkeyuvs[uvi * 2 + 0]; luv[1] = monkeyuvs[uvi * 2 + 1]; uvi++; } BM_ITER_ELEM (l, &liter, f_new_b, BM_LOOPS_OF_FACE) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); luv[0] = monkeyuvs[uvi * 2 + 0]; luv[1] = monkeyuvs[uvi * 2 + 1]; uvi++; } } } MEM_freeN(tv); BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_circle_exec(BMesh *bm, BMOperator *op) { const float radius = BMO_slot_float_get(op->slots_in, "radius"); const int segs = BMO_slot_int_get(op->slots_in, "segments"); const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMVert *v1, *lastv1 = nullptr, *cent1, *firstv1 = nullptr; float vec[3], mat[4][4]; int a; if (!segs) { return; } BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (cap_ends) { zero_v3(vec); mul_m4_v3(mat, vec); cent1 = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, cent1, VERT_MARK); } for (a = 0; a < segs; a++) { /* Going this way ends up with normal(s) upward */ sin_cos_from_fraction(a, segs, &vec[0], &vec[1]); vec[0] *= -radius; vec[1] *= radius; vec[2] = 0.0f; mul_m4_v3(mat, vec); v1 = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, v1, VERT_MARK); if (lastv1) { BM_edge_create(bm, v1, lastv1, nullptr, BM_CREATE_NOP); } if (a && cap_ends) { BMFace *f; f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, nullptr, nullptr, BM_CREATE_NOP); BMO_face_flag_enable(bm, f, FACE_NEW); } if (!firstv1) { firstv1 = v1; } lastv1 = v1; } if (!a) { return; } BM_edge_create(bm, firstv1, lastv1, nullptr, eBMCreateFlag(0)); if (cap_ends) { BMFace *f; f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, nullptr, nullptr, BM_CREATE_NOP); BMO_face_flag_enable(bm, f, FACE_NEW); if (calc_uvs) { BM_mesh_calc_uvs_circle(bm, mat, radius, FACE_NEW, cd_loop_uv_offset); } } if (!cap_tris) { BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void BM_mesh_calc_uvs_circle( BMesh *bm, float mat[4][4], const float radius, const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMLoop *l; BMIter fiter, liter; const float uv_scale = 0.5f / radius; const float uv_center = 0.5f; float inv_mat[4][4]; BLI_assert(cd_loop_uv_offset != -1); /* caller must ensure we have UVs already */ invert_m4_m4(inv_mat, mat); BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); float uv_vco[3]; copy_v3_v3(uv_vco, l->v->co); /* transform back into the unit circle flat on the Z-axis */ mul_m4_v3(inv_mat, uv_vco); /* then just take those coords for UVs */ luv[0] = uv_center + uv_scale * uv_vco[0]; luv[1] = uv_center + uv_scale * uv_vco[1]; } } } void bmo_create_cone_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *lastv1 = nullptr, *lastv2 = nullptr, *cent1, *cent2, *firstv1, *firstv2; BMFace *f; float vec[3], mat[4][4]; const float rad1 = BMO_slot_float_get(op->slots_in, "radius1"); const float rad2 = BMO_slot_float_get(op->slots_in, "radius2"); const float depth_half = 0.5f * BMO_slot_float_get(op->slots_in, "depth"); int segs = BMO_slot_int_get(op->slots_in, "segments"); const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); if (!segs) { return; } BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (cap_ends) { vec[0] = vec[1] = 0.0f; vec[2] = -depth_half; mul_m4_v3(mat, vec); cent1 = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); vec[0] = vec[1] = 0.0f; vec[2] = depth_half; mul_m4_v3(mat, vec); cent2 = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, cent1, VERT_MARK); BMO_vert_flag_enable(bm, cent2, VERT_MARK); } const int side_faces_len = segs - 1; BMFace **side_faces = static_cast( MEM_mallocN(sizeof(*side_faces) * side_faces_len, __func__)); for (int i = 0; i < segs; i++) { /* Calculate with higher precision, see: #87779. */ float sin_phi, cos_phi; sin_cos_from_fraction(i, segs, &sin_phi, &cos_phi); vec[0] = rad1 * sin_phi; vec[1] = rad1 * cos_phi; vec[2] = -depth_half; mul_m4_v3(mat, vec); v1 = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); vec[0] = rad2 * sin_phi; vec[1] = rad2 * cos_phi; vec[2] = depth_half; mul_m4_v3(mat, vec); v2 = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, v1, VERT_MARK); BMO_vert_flag_enable(bm, v2, VERT_MARK); if (i) { if (cap_ends) { f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, nullptr, nullptr, BM_CREATE_NOP); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } BMO_face_flag_enable(bm, f, FACE_NEW); f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, nullptr, nullptr, BM_CREATE_NOP); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } BMO_face_flag_enable(bm, f, FACE_NEW); } f = BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, nullptr, BM_CREATE_NOP); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } side_faces[i - 1] = f; } else { firstv1 = v1; firstv2 = v2; } lastv1 = v1; lastv2 = v2; } if (cap_ends) { f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, nullptr, nullptr, BM_CREATE_NOP); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } BMO_face_flag_enable(bm, f, FACE_NEW); f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, nullptr, nullptr, BM_CREATE_NOP); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } BMO_face_flag_enable(bm, f, FACE_NEW); } f = BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, nullptr, BM_CREATE_NOP); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } if (calc_uvs) { BM_mesh_calc_uvs_cone(bm, mat, rad2, rad1, segs, cap_ends, FACE_MARK, cd_loop_uv_offset); } /* Collapse vertices at the first end. */ if (rad1 == 0.0f) { if (cap_ends) { BM_vert_kill(bm, cent1); } for (int i = 0; i < side_faces_len; i++) { f = side_faces[i]; BMLoop *l = BM_FACE_FIRST_LOOP(f); BM_edge_collapse(bm, l->prev->e, l->prev->v, true, true); } } /* Collapse vertices at the second end. */ if (rad2 == 0.0f) { if (cap_ends) { BM_vert_kill(bm, cent2); } for (int i = 0; i < side_faces_len; i++) { f = side_faces[i]; BMLoop *l = BM_FACE_FIRST_LOOP(f); BM_edge_collapse(bm, l->next->e, l->next->v, true, true); } } if (!cap_tris) { BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); } if (side_faces != nullptr) { MEM_freeN(side_faces); } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void BM_mesh_calc_uvs_cone(BMesh *bm, float mat[4][4], const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMLoop *l; BMIter fiter, liter; const float uv_width = 1.0f / float(segments); const float uv_height = cap_ends ? 0.5f : 1.0f; /* Note that all this allows us to handle all cases * (real cone, truncated cone, with or without ends capped) * with a single common code. */ const float uv_center_y = cap_ends ? 0.25f : 0.5f; const float uv_center_x_top = cap_ends ? 0.25f : 0.5f; const float uv_center_x_bottom = cap_ends ? 0.75f : 0.5f; const float uv_radius = cap_ends ? 0.24f : 0.5f; /* Using the opposite's end uv_scale as fallback allows us to handle 'real cone' case. */ const float uv_scale_top = (radius_top != 0.0f) ? (uv_radius / radius_top) : ((radius_bottom != 0.0f) ? (uv_radius / radius_bottom) : uv_radius); const float uv_scale_bottom = (radius_bottom != 0.0f) ? (uv_radius / radius_bottom) : uv_scale_top; float local_up[3] = {0.0f, 0.0f, 1.0f}; float x, y; float inv_mat[4][4]; int loop_index; /* Transform the up-vector like we did the cone itself, without location. */ mul_mat3_m4_v3(mat, local_up); /* Remove global scaling. */ normalize_v3(local_up); invert_m4_m4(inv_mat, mat); BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */ x = 1.0f; y = 1.0f - uv_height; BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } if (f->len == 4 && radius_top && radius_bottom) { /* side face - so unwrap it in a rectangle */ BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); switch (loop_index) { case 0: /* Continue in the last position */ break; case 1: y += uv_height; break; case 2: x -= uv_width; break; case 3: y -= uv_height; break; default: break; } luv[0] = x; luv[1] = y; } } else { /* Top or bottom face - so unwrap it by transforming * back to a circle and using the X/Y coords. */ BM_face_normal_update(f); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); float uv_vco[3]; mul_v3_m4v3(uv_vco, inv_mat, l->v->co); if (dot_v3v3(f->no, local_up) > 0.0f) { /* if this is a top face of the cone */ luv[0] = uv_center_x_top + uv_vco[0] * uv_scale_top; luv[1] = uv_center_y + uv_vco[1] * uv_scale_top; } else { luv[0] = uv_center_x_bottom + uv_vco[0] * uv_scale_bottom; luv[1] = uv_center_y + uv_vco[1] * uv_scale_bottom; } } } } } void bmo_create_cube_exec(BMesh *bm, BMOperator *op) { BMVert *verts[8]; float mat[4][4]; float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); /* rotation order set to match 'BM_mesh_calc_uvs_cube' */ const char faces[6][4] = { {0, 1, 3, 2}, {2, 3, 7, 6}, {6, 7, 5, 4}, {4, 5, 1, 0}, {2, 6, 4, 0}, {7, 3, 1, 5}, }; BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (!off) { off = 0.5f; } int i = 0; for (int x = -1; x < 2; x += 2) { for (int y = -1; y < 2; y += 2) { for (int z = -1; z < 2; z += 2) { float vec[3] = {float(x) * off, float(y) * off, float(z) * off}; mul_m4_v3(mat, vec); verts[i] = BM_vert_create(bm, vec, nullptr, BM_CREATE_NOP); BMO_vert_flag_enable(bm, verts[i], VERT_MARK); i++; } } } for (i = 0; i < ARRAY_SIZE(faces); i++) { BMFace *f; BMVert *quad[4] = { verts[faces[i][0]], verts[faces[i][1]], verts[faces[i][2]], verts[faces[i][3]], }; f = BM_face_create_verts(bm, quad, 4, nullptr, BM_CREATE_NOP, true); if (calc_uvs) { BMO_face_flag_enable(bm, f, FACE_MARK); } } if (calc_uvs) { BM_mesh_calc_uvs_cube(bm, FACE_MARK); } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag) { BMFace *f; BMLoop *l; BMIter fiter, liter; const float width = 0.25f; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); float x = 0.375f; float y = 0.0f; int loop_index; BLI_assert(cd_loop_uv_offset != -1); /* the caller can ensure that we have UVs */ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { if (!BMO_face_flag_test(bm, f, oflag)) { continue; } BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) { float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); luv[0] = x; luv[1] = y; switch (loop_index) { case 0: x += width; break; case 1: y += width; break; case 2: x -= width; break; case 3: y -= width; break; default: break; } } if (y >= 0.75f && x > 0.125f) { x = 0.125f; y = 0.5f; } else if (x <= 0.125f) { x = 0.625f; y = 0.5f; } else { y += 0.25f; } } }