diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cc5906..42b6770 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,26 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(metaball) +project(metaballs) set(CMAKE_C_STANDARD 99) -# set(CMAKE_C_STANDARD_REQUIRED TRUE) -# raylib -find_package(raylib QUIET) -if (NOT raylib_FOUND) - include(FetchContent) - FetchContent_Declare( - raylib - GIT_REPOSITORY https://github.com/raysan5/raylib.git - GIT_TAG 4.5.0 - ) - FetchContent_MakeAvailable(raylib) -endif() - -message(STATUS "PROJECT_NAME: ${PROJECT_NAME}") -add_executable(${PROJECT_NAME} main.c metaballs.h) -target_link_libraries(${PROJECT_NAME} PUBLIC raylib) - -add_custom_target(copy_assets - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets -) -add_dependencies(${PROJECT_NAME} copy_assets) \ No newline at end of file +add_subdirectory(examples) \ No newline at end of file diff --git a/README.md b/README.md index 3bd383e..83ef9bd 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ ![Thumbnail](./thumbnail.jpg) -Header only 3d metaballs generator in ANSI C +Header only 3d metaballs generator in C99 ## About [![Build Status](https://github.com/casensiom/metaballs/actions/workflows/cmake-multi-platform.yml/badge.svg)](https://github.com/casensiom/metaballs/actions) -This library computes 3d metaballs in pure ANSI C. +This library computes 3d metaballs in pure C99. ![Thumbnail](./thumbnail.gif) diff --git a/assets/texel_checker.png b/assets/texel_checker.png deleted file mode 100644 index 79d3832..0000000 Binary files a/assets/texel_checker.png and /dev/null differ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..4e5a6f2 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,34 @@ +# raylib +find_package(raylib QUIET) +if (NOT raylib_FOUND) + include(FetchContent) + FetchContent_Declare( + raylib + GIT_REPOSITORY https://github.com/raysan5/raylib.git + GIT_TAG 4.5.0 + ) + FetchContent_MakeAvailable(raylib) +endif() + +add_library(metaball_dependency + raylib_wrapper.h + raylib_wrapper.c + ball.h + ball.c +) +target_link_libraries(metaball_dependency PUBLIC raylib) + +add_custom_target(copy_assets + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets +) +add_dependencies(metaball_dependency copy_assets) + +add_executable(example0 example0.c) +target_link_libraries(example0 PUBLIC metaball_dependency) + +add_executable(example1 example1.c) +target_link_libraries(example1 PUBLIC metaball_dependency) + +add_executable(example2 example2.c) +target_link_libraries(example2 PUBLIC metaball_dependency) + diff --git a/examples/assets/uv.png b/examples/assets/uv.png new file mode 100644 index 0000000..ce90316 Binary files /dev/null and b/examples/assets/uv.png differ diff --git a/examples/ball.c b/examples/ball.c new file mode 100644 index 0000000..f35017d --- /dev/null +++ b/examples/ball.c @@ -0,0 +1,40 @@ +#include "ball.h" + +void ball_push(BallArray *balls, Ball ball) +{ + balls->items[balls->count] = ball; + balls->count++; +} + +Ball ball_create_random(Grid grid) +{ + float radius_x = (grid.count.x * grid.size.x) / 4; + float radius_y = (grid.count.y * grid.size.y) / 4; + float radius_z = (grid.count.z * grid.size.z) / 4; + + Vector3d speed = { + .x = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f), + .y = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f), + .z = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f)}; + + Vector3d initial = { + .x = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f), + .y = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f), + .z = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f)}; + + Vector3d p = (Vector3d){ + .x = grid.center.x + radius_x * cos(initial.x), + .y = grid.center.y + radius_y * sin(initial.y), + .z = grid.center.z + radius_z * cos(initial.z)}; + + Color4C color = (Color4C){ + .r = (unsigned char)(64 + (rand() % 192)), + .g = (unsigned char)(128 + (rand() % 128)), + .b = (unsigned char)(128 + (rand() % 128)), + .a = (unsigned char)(255) + }; + + float ball_mass = 50.0f + (float)(rand() % 200); + + return (Ball){.pos = p, .mass = ball_mass, .color = color}; +} diff --git a/examples/ball.h b/examples/ball.h new file mode 100644 index 0000000..c0dd13e --- /dev/null +++ b/examples/ball.h @@ -0,0 +1,9 @@ +#ifndef _BALL_H_ +#define _BALL_H_ + +#include "../metaballs.h" + +void ball_push(BallArray *balls, Ball ball); +Ball ball_create_random(Grid grid); + +#endif //_BALL_H_ \ No newline at end of file diff --git a/examples/example0.c b/examples/example0.c new file mode 100644 index 0000000..fd240f5 --- /dev/null +++ b/examples/example0.c @@ -0,0 +1,113 @@ +#include "ball.h" +#include "raylib_wrapper.h" + +int main(int argc, char *argv[]) +{ + const int screenWidth = 800; + const int screenHeight = 400; + InitWindow(screenWidth, screenHeight, "Metaballs"); + //DisableCursor(); + + Index3d count = {.x = 10, .y = 10, .z = 10}; + Vector3d size = {.x = 2, .y = 2, .z = 2}; + Vector3d pos = {.x = 0, .y = 0, .z = 0}; + Grid grid = grid_create(count, size, pos); + + BallArray balls = MB_CREATE_ARRAY(Ball, 3); + + Vector3d zero = { + .x = 0.0f, + .y = 0.0f, + .z = 0.0f}; + + Vector3d center = (Vector3d){ + .x = grid.center.x, + .y = grid.center.y, + .z = grid.center.z}; + + Color4C color = (Color4C){ + .r = 0xff, + .g = 0xff, + .b = 0xff, + .a = 0xff + }; + ball_push(&balls, (Ball){.pos = center, .mass = 15, .color = color}); + + // Define the camera to look into our 3d world + Camera camera = {0}; + camera.position = (Vector3){grid.center.x, grid.center.y, grid.center.z - grid.count.z * grid.size.z * 1.5}; // Camera position + camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; // Camera looking at point + camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera projection type + + + Material wired = LoadMaterialDefault(); + wired.maps[MATERIAL_MAP_DIFFUSE].color = GRAY; + wired.maps[MATERIAL_MAP_SPECULAR].color = GRAY; + + Texture2D text2d = LoadTexture("assets/uv.png"); + SetTextureWrap(text2d, TEXTURE_WRAP_CLAMP); + Material material = LoadMaterialDefault(); + material.maps[MATERIAL_MAP_DIFFUSE].texture = text2d; + material.maps[MATERIAL_MAP_SPECULAR].color = GRAY; + + Matrix transform = (Matrix){1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + + // RL upload mesh + Mesh rayMesh = raylib_upload_mesh(grid); + + while (!WindowShouldClose()) // Detect window close button or ESC key + { + + UpdateCamera(&camera, CAMERA_THIRD_PERSON); + camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; + + if(IsKeyPressed(KEY_U)) { + grid.config.wired = !grid.config.wired; + } + if(IsKeyPressed(KEY_P)) { + grid.config.mapping = MAPPING_PLANAR; + } + if(IsKeyPressed(KEY_L)) { + grid.config.mapping = MAPPING_SPHERIC; + } + + if(IsKeyPressed(KEY_H)) { + grid.config.threshold += 0.05f; + } + if(IsKeyPressed(KEY_J)) { + grid.config.threshold -= 0.05f; + } + + generate_mesh(&grid, balls); + + BeginDrawing(); + ClearBackground(RAYWHITE); + BeginMode3D(camera); + // RL render mesh + raylib_render_mesh(grid, &rayMesh, material, wired, transform); + EndMode3D(); + + char label_fps[256]; + sprintf(label_fps, "FPS: %d", GetFPS()); + DrawText(label_fps, 10, 10, 20, BLACK); + + // sprintf(label_fps, "CACHE HIT: %lu, MISS: %lu", cache_hit, cache_miss); + // DrawText(label_fps, 10, 50, 20, BLACK); + EndDrawing(); + } + + + // RL unload mesh + raylib_unload_mesh(&rayMesh); + MB_DESTROY_ARRAY(balls); + grid_destroy(&grid); + + CloseWindow(); + + return 0; +} diff --git a/examples/example1.c b/examples/example1.c new file mode 100644 index 0000000..befb0e2 --- /dev/null +++ b/examples/example1.c @@ -0,0 +1,128 @@ +#include "ball.h" +#include "raylib_wrapper.h" + + +void update_balls(BallArray balls, Vector3d pos, float radius) { + + float t = GetTime(); + + Vector3d movement[] = {{.x = 1.1, .y = 1.3, .z = 1.7}, + {.x = 0.7, .y = 1.9, .z = 2.3}, + {.x = 0.3, .y = 2.9, .z = 1.1}, + {.x = 1.3, .y = 1.7, .z = 0.7}, + {.x = 2.3, .y = 1.9, .z = 2.9}}; + const size_t count = sizeof(movement) / sizeof(movement[0]); + + + float ec = radius; + for (size_t i = 0; i < balls.count; i++) + { + Vector3d m = movement[i % count]; + balls.items[i].pos = (Vector3d){.x = pos.x - cos(t*m.x) * radius, + .y = pos.y - cos(t*m.y) * radius, + .z = pos.z - cos(t*m.z) * radius}; + + } +} + + +int main(int argc, char *argv[]) +{ + const int screenWidth = 800; + const int screenHeight = 400; + InitWindow(screenWidth, screenHeight, "Metaballs"); + DisableCursor(); + + Index3d count = {.x = 20 * 2, .y = 20 * 2, .z = 20 * 2}; + Vector3d size = {.x = 10 / 2, .y = 10 / 2, .z = 10 / 2}; + Vector3d pos = {.x = 0, .y = 0, .z = 0}; + Grid grid = grid_create(count, size, pos); + + BallArray balls = MB_CREATE_ARRAY(Ball, 5); + for (size_t i = 0; i < balls.capacity; i++) + { + ball_push(&balls, ball_create_random(grid)); + } + + // Define the camera to look into our 3d world + Camera camera = {0}; + camera.position = (Vector3){grid.center.x, grid.center.y, grid.center.z - grid.count.z * grid.size.z * 1.5}; // Camera position + camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; // Camera looking at point + camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera projection type + + + Material wired = LoadMaterialDefault(); + wired.maps[MATERIAL_MAP_DIFFUSE].color = GRAY; + wired.maps[MATERIAL_MAP_SPECULAR].color = GRAY; + + Texture2D text2d = LoadTexture("assets/uv.png"); + SetTextureWrap(text2d, TEXTURE_WRAP_MIRROR_REPEAT); + Material material = LoadMaterialDefault(); + material.maps[MATERIAL_MAP_DIFFUSE].texture = text2d; + material.maps[MATERIAL_MAP_SPECULAR].color = GRAY; + + Matrix transform = (Matrix){1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + + // RL upload mesh + Mesh rayMesh = raylib_upload_mesh(grid); + + while (!WindowShouldClose()) // Detect window close button or ESC key + { + + UpdateCamera(&camera, CAMERA_THIRD_PERSON); + camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; + + if (!IsKeyDown(KEY_SPACE)) + { + update_balls(balls, grid.center, grid.size.x * 10); + } + if(IsKeyPressed(KEY_U)) { + grid.config.wired = !grid.config.wired; + } + if(IsKeyPressed(KEY_P)) { + grid.config.mapping = MAPPING_PLANAR; + } + if(IsKeyPressed(KEY_L)) { + grid.config.mapping = MAPPING_SPHERIC; + } + + if(IsKeyPressed(KEY_H)) { + grid.config.threshold += 0.05f; + } + if(IsKeyPressed(KEY_J)) { + grid.config.threshold -= 0.05f; + } + + generate_mesh(&grid, balls); + + BeginDrawing(); + ClearBackground(RAYWHITE); + BeginMode3D(camera); + // RL render mesh + raylib_render_mesh(grid, &rayMesh, material, wired, transform); + EndMode3D(); + + char label_fps[256]; + sprintf(label_fps, "FPS: %d", GetFPS()); + DrawText(label_fps, 10, 10, 20, BLACK); + + // sprintf(label_fps, "CACHE HIT: %lu, MISS: %lu", cache_hit, cache_miss); + // DrawText(label_fps, 10, 50, 20, BLACK); + EndDrawing(); + } + + + // RL unload mesh + raylib_unload_mesh(&rayMesh); + MB_DESTROY_ARRAY(balls); + grid_destroy(&grid); + + CloseWindow(); + + return 0; +} diff --git a/examples/example2.c b/examples/example2.c new file mode 100644 index 0000000..dd34773 --- /dev/null +++ b/examples/example2.c @@ -0,0 +1,133 @@ +#include "ball.h" +#include "raylib_wrapper.h" + + +void update_balls(BallArray balls, size_t w, size_t d, Grid grid) +{ + size_t index = 0; + for (size_t x = 0; x < w; x++) + { + float u = (float)x / (float)w; + for (size_t z = 0; z < d; z++) + { + float wave = 10.0 + 12.0 * sin(32 * u + GetTime() * 4.0f); + balls.items[index++].pos.y = wave; + } + } + + float z = grid.pos.z + grid.size.z * (grid.count.z/2); + float wave = 12.0 * sin(GetTime() * 2.0f); + balls.items[balls.count-1].pos.z = z + wave; + balls.items[balls.count-2].pos.z = z - wave; + +} + +int main(int argc, char *argv[]) +{ + const int screenWidth = 800; + const int screenHeight = 400; + InitWindow(screenWidth, screenHeight, "Metaballs"); + // DisableCursor(); + + Index3d count = {.x = 40, .y = 10, .z = 20}; + Vector3d size = {.x = 10, .y = 10, .z = 10}; + Vector3d pos = {.x = 0, .y = 0, .z = 0}; + Grid grid = grid_create(count, size, pos); + grid.config.wired = true; + grid.config.threshold = 0.2; + + size_t w = 16; + size_t d = 4; + BallArray balls = MB_CREATE_ARRAY(Ball, w*d + 2); + + for (size_t x = 0; x < w; x++) + { + for (size_t z = 0; z < d; z++) + { + ball_push(&balls, (Ball){ + .pos = {.x = pos.x + size.x * (x * count.x/(w - 1)), + .y = pos.y + 2 * size.y, + .z = pos.z + size.z * (z * count.z/(d - 1))}, + .mass = 48, + .color = {.r = 0x80 , .g = 0x80, .b = (128) + ((64+64)*x)/w , .a = 0xff}}); + } + } + + Vector3d ball_pos = {.x = pos.x + 10 * size.x, .y = pos.y + 4 * size.y, .z = pos.z + 10 * size.z}; + ball_push(&balls, (Ball){.pos = ball_pos, .mass = -96, .color = {.r = 0xff, .g = 0xff, .b = 0xff, .a = 0xff}}); + + ball_pos = (Vector3d){.x = pos.x + 30 * size.x, .y = pos.y + 4 * size.y, .z = pos.z + 10 * size.z}; + ball_push(&balls, (Ball){.pos = ball_pos, .mass = -96, .color = {.r = 0xff, .g = 0xff, .b = 0xff, .a = 0xff}}); + + + // Define the camera to look into our 3d world + Camera camera = {0}; + camera.position = (Vector3){grid.center.x, grid.center.y, grid.center.z - grid.count.z * grid.size.z}; // Camera position + camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; // Camera looking at point + camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera projection type + + + Material wired = LoadMaterialDefault(); + wired.maps[MATERIAL_MAP_DIFFUSE].color = GRAY; + wired.maps[MATERIAL_MAP_SPECULAR].color = GRAY; + + Material material = LoadMaterialDefault(); + material.maps[MATERIAL_MAP_DIFFUSE].color = WHITE; + material.maps[MATERIAL_MAP_SPECULAR].color = GRAY; + + Matrix transform = (Matrix){1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + + // RL upload mesh + Mesh rayMesh = raylib_upload_mesh(grid); + + while (!WindowShouldClose()) // Detect window close button or ESC key + { + UpdateCamera(&camera, CAMERA_THIRD_PERSON); + camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; + + if (!IsKeyDown(KEY_SPACE)) + { + update_balls(balls, w, d, grid); + } + if(IsKeyPressed(KEY_U)) { + grid.config.wired = !grid.config.wired; + } + if(IsKeyPressed(KEY_P)) { + grid.config.mapping = MAPPING_PLANAR; + } + if(IsKeyPressed(KEY_L)) { + grid.config.mapping = MAPPING_SPHERIC; + } + + if(IsKeyPressed(KEY_H)) { + grid.config.threshold += 0.05f; + } + if(IsKeyPressed(KEY_J)) { + grid.config.threshold -= 0.05f; + } + generate_mesh(&grid, balls); + + BeginDrawing(); + ClearBackground(RAYWHITE); + BeginMode3D(camera); + // RL render mesh + raylib_render_mesh(grid, &rayMesh, material, wired, transform); + EndMode3D(); + EndDrawing(); + } + + + // RL unload mesh + raylib_unload_mesh(&rayMesh); + MB_DESTROY_ARRAY(balls); + grid_destroy(&grid); + + CloseWindow(); + + return 0; +} diff --git a/examples/raylib_wrapper.c b/examples/raylib_wrapper.c new file mode 100644 index 0000000..532c095 --- /dev/null +++ b/examples/raylib_wrapper.c @@ -0,0 +1,118 @@ +#include "raylib_wrapper.h" + +#define METABALLS_IMPLEMENTATION +#include "../metaballs.h" + +Mesh raylib_upload_mesh(Grid grid) +{ + Mesh mesh = {0}; + + mesh.vertexCount = grid.mesh.vertexCapacity; + mesh.triangleCount = grid.mesh.triangleCapacity; + mesh.vertices = grid.mesh.vertices; + mesh.texcoords = grid.mesh.texcoords; + mesh.colors = grid.mesh.colors; + mesh.normals = grid.mesh.normals; + mesh.indices = grid.mesh.indices; + + UploadMesh(&mesh, true); + + return mesh; +} + +void raylib_render_mesh(Grid grid, Mesh *mesh, Material material, Material wired, Matrix transform) +{ + mesh->vertexCount = grid.mesh.vertexCount; + mesh->triangleCount = grid.mesh.triangleCount; + + UpdateMeshBuffer(*mesh, 0, mesh->vertices, mesh->vertexCount * 3 * sizeof(float), 0); + UpdateMeshBuffer(*mesh, 1, mesh->texcoords, mesh->vertexCount * 2 * sizeof(float), 0); + UpdateMeshBuffer(*mesh, 2, mesh->normals, mesh->vertexCount * 3 * sizeof(float), 0); + UpdateMeshBuffer(*mesh, 3, mesh->colors, mesh->vertexCount * 4 * sizeof(unsigned char), 0); + UpdateMeshBuffer(*mesh, 6, mesh->indices, mesh->triangleCount * 3 * sizeof(unsigned short), 0); + + DrawMesh(*mesh, material, transform); + + if(grid.config.wired) { + rlEnableWireMode(); + DrawMesh(*mesh, wired, transform); + rlDisableWireMode(); + } + + Vector3 center = (Vector3){ + .x = grid.center.x - grid.size.x * 0.5f, + .y = grid.center.y - grid.size.y * 0.5f, + .z = grid.center.z - grid.size.z * 0.5f}; + Vector3 size = (Vector3){ + .x = (grid.count.x-1) * grid.size.x, + .y = (grid.count.y-1) * grid.size.y, + .z = (grid.count.z-1) * grid.size.z}; + DrawCubeWiresV(center, size, BLACK); + + Vector3 orig = (Vector3){ + .x = grid.pos.x, + .y = grid.pos.y, + .z = grid.pos.z}; + DrawSphere(orig, 2, BLACK); + DrawSphere(center, 2, BLACK); + + // for (size_t i = 0; i < (grid.mesh.vertexCount) * 3; i++) + // { + // Vector3 orig = {.x = 0, + // .y = 0, + // .z = 0}; + // Vector3 orig2 = {.x = grid.mesh.vertices[i + 0], + // .y = grid.mesh.vertices[i + 1], + // .z = grid.mesh.vertices[i + 2]}; + + // Vector3 normal = { .x = grid.mesh.normals[i + 0], + // .y = grid.mesh.normals[i + 1], + // .z = grid.mesh.normals[i + 2]}; + // Vector3 end = { .x = orig.x + normal.x * grid.size.x, + // .y = orig.y + normal.y * grid.size.y, + // .z = orig.z + normal.z * grid.size.z}; + + // DrawLine3D(orig, end, BLUE); + // } + + // for (size_t x = 0; x < grid.count.x; x++) + // { + // for (size_t z = 0; z < grid.count.z; z++) + // { + // Vector3 orig = (Vector3){ + // .x = grid.pos.x + x * grid.size.x, + // .y = grid.pos.y, + // .z = grid.pos.z + z * grid.size.z}; + // Vector3 end = (Vector3){ + // .x = grid.pos.x + x * grid.size.x, + // .y = grid.pos.y + (grid.count.y - 1) * grid.size.y, + // .z = grid.pos.z + z * grid.size.z}; + + // DrawLine3D(orig, end, PINK); + // } + // } +} + +void raylib_unload_mesh(Mesh *mesh) +{ + // Unload rlgl mesh vboId data + rlUnloadVertexArray(mesh->vaoId); + if (mesh->vboId != NULL) + { + for (int i = 0; i < 7; i++) + { + rlUnloadVertexBuffer(mesh->vboId[i]); + } + } + free(mesh->vboId); + + + mesh->vertices = 0x0; + mesh->texcoords = 0x0; + mesh->colors = 0x0; + mesh->normals = 0x0; + mesh->indices = 0x0; + + mesh->vertexCount = 0; + mesh->triangleCount = 0; +} diff --git a/examples/raylib_wrapper.h b/examples/raylib_wrapper.h new file mode 100644 index 0000000..c661e3a --- /dev/null +++ b/examples/raylib_wrapper.h @@ -0,0 +1,10 @@ + +#include "../metaballs.h" + +#include +#include + + +Mesh raylib_upload_mesh(Grid grid); +void raylib_render_mesh(Grid grid, Mesh *mesh, Material material, Material wired, Matrix transform); +void raylib_unload_mesh(Mesh *mesh); diff --git a/main.c b/main.c deleted file mode 100644 index 977ab46..0000000 --- a/main.c +++ /dev/null @@ -1,204 +0,0 @@ - -#define METABALLS_IMPLEMENTATION -#include "metaballs.h" - - -#include -#include - - -Mesh raylib_upload_mesh(Grid grid) -{ - Mesh mesh = {0}; - - mesh.vertexCount = grid.mesh.vertexCapacity; - mesh.triangleCount = grid.mesh.triangleCapacity; - mesh.vertices = grid.mesh.vertices; - mesh.texcoords = grid.mesh.texcoords; - mesh.colors = grid.mesh.colors; - mesh.normals = grid.mesh.normals; - mesh.indices = grid.mesh.indices; - - UploadMesh(&mesh, true); - - return mesh; -} - -void raylib_render_mesh(Grid grid, Mesh *mesh, Material material, Material wired, Matrix transform) -{ - mesh->vertexCount = grid.mesh.vertexCount; - mesh->triangleCount = grid.mesh.triangleCount; - - UpdateMeshBuffer(*mesh, 0, mesh->vertices, mesh->vertexCount * 3 * sizeof(float), 0); - UpdateMeshBuffer(*mesh, 1, mesh->texcoords, mesh->vertexCount * 2 * sizeof(float), 0); - UpdateMeshBuffer(*mesh, 2, mesh->normals, mesh->vertexCount * 3 * sizeof(float), 0); - UpdateMeshBuffer(*mesh, 3, mesh->colors, mesh->vertexCount * 4 * sizeof(unsigned char), 0); - UpdateMeshBuffer(*mesh, 6, mesh->indices, mesh->triangleCount * 3 * sizeof(unsigned short), 0); - - DrawMesh(*mesh, material, transform); - - if(grid.config.wired) { - rlEnableWireMode(); - DrawMesh(*mesh, wired, transform); - rlDisableWireMode(); - } - - Vector3 center = (Vector3){ - .x = grid.center.x - grid.size.x * 0.5f, - .y = grid.center.y - grid.size.y * 0.5f, - .z = grid.center.z - grid.size.z * 0.5f}; - Vector3 size = (Vector3){ - .x = (grid.count.x-1) * grid.size.x, - .y = (grid.count.y-1) * grid.size.y, - .z = (grid.count.z-1) * grid.size.z}; - DrawCubeWiresV(center, size, BLACK); - - Vector3 orig = (Vector3){ - .x = grid.pos.x, - .y = grid.pos.y, - .z = grid.pos.z}; - DrawSphere(orig, 2, BLACK); - - - // for (size_t x = 0; x < grid.count.x; x++) - // { - // for (size_t z = 0; z < grid.count.z; z++) - // { - // Vector3 orig = (Vector3){ - // .x = grid.pos.x + x * grid.size.x, - // .y = grid.pos.y, - // .z = grid.pos.z + z * grid.size.z}; - // Vector3 end = (Vector3){ - // .x = grid.pos.x + x * grid.size.x, - // .y = grid.pos.y + (grid.count.y - 1) * grid.size.y, - // .z = grid.pos.z + z * grid.size.z}; - - // DrawLine3D(orig, end, BLUE); - // } - // } -} - -void raylib_unload_mesh(Mesh *mesh) -{ - // Unload rlgl mesh vboId data - rlUnloadVertexArray(mesh->vaoId); - if (mesh->vboId != NULL) - { - for (int i = 0; i < 7; i++) - { - rlUnloadVertexBuffer(mesh->vboId[i]); - } - } - free(mesh->vboId); - - - mesh->vertices = 0x0; - mesh->texcoords = 0x0; - mesh->colors = 0x0; - mesh->normals = 0x0; - mesh->indices = 0x0; - - mesh->vertexCount = 0; - mesh->triangleCount = 0; -} - -int main(int argc, char *argv[]) -{ - const int screenWidth = 640; - const int screenHeight = 480; - InitWindow(screenWidth, screenHeight, "Metaballs"); - DisableCursor(); - - Index3d count = {.x = 20, .y = 20, .z = 20}; - Vector3d size = {.x = 10, .y = 10, .z = 10}; - Vector3d pos = {.x = 0, .y = 0, .z = 0}; - Grid grid = grid_create(count, size, pos); - - BallArray balls = MB_CREATE_ARRAY(Ball, 5); - for (size_t i = 0; i < balls.capacity; i++) - { - push_ball(&balls, random_ball(grid)); - } - - // Define the camera to look into our 3d world - Camera camera = {0}; - camera.position = (Vector3){grid.center.x, grid.center.y, grid.center.z - grid.count.z * grid.size.z * 2}; // Camera position - camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; // Camera looking at point - camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - camera.projection = CAMERA_PERSPECTIVE; // Camera projection type - - - Material wired = LoadMaterialDefault(); - wired.maps[MATERIAL_MAP_DIFFUSE].color = GRAY; - - Texture2D text2d = LoadTexture("assets/texel_checker.png"); - SetTextureWrap(text2d, TEXTURE_WRAP_MIRROR_REPEAT); - Material material = LoadMaterialDefault(); - material.maps[MATERIAL_MAP_DIFFUSE].texture = text2d; - - Matrix transform = (Matrix){1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f}; - - // RL upload mesh - Mesh rayMesh = raylib_upload_mesh(grid); - - while (!WindowShouldClose()) // Detect window close button or ESC key - { - cache_hit = 0; - cache_miss = 0; - - UpdateCamera(&camera, CAMERA_THIRD_PERSON); - camera.target = (Vector3){grid.center.x, grid.center.y, grid.center.z}; - - if (!IsKeyDown(KEY_SPACE)) - { - move_balls(grid, balls, GetTime()); - } - if(IsKeyPressed(KEY_U)) { - grid.config.wired = !grid.config.wired; - } - if(IsKeyPressed(KEY_P)) { - grid.config.mapping = MAPPING_PLANAR; - } - if(IsKeyPressed(KEY_L)) { - grid.config.mapping = MAPPING_SPHERIC; - } - - if(IsKeyPressed(KEY_H)) { - grid.config.threshold += 0.05f; - } - if(IsKeyPressed(KEY_J)) { - grid.config.threshold -= 0.05f; - } - - generate_mesh(&grid, balls); - - BeginDrawing(); - ClearBackground(RAYWHITE); - BeginMode3D(camera); - // RL render mesh - raylib_render_mesh(grid, &rayMesh, material, wired, transform); - EndMode3D(); - - char label_fps[256]; - sprintf(label_fps, "FPS: %d, THRESHOLD: %0.2f", GetFPS(), grid.config.threshold); - DrawText(label_fps, 10, 10, 20, BLACK); - - sprintf(label_fps, "CACHE HIT: %lu, MISS: %lu", cache_hit, cache_miss); - DrawText(label_fps, 10, 50, 20, BLACK); - EndDrawing(); - } - - - // RL unload mesh - raylib_unload_mesh(&rayMesh); - MB_DESTROY_ARRAY(balls); - grid_destroy(&grid); - - CloseWindow(); - - return 0; -} diff --git a/metaballs.h b/metaballs.h index a505e35..3c1ca48 100644 --- a/metaballs.h +++ b/metaballs.h @@ -2,7 +2,6 @@ // https://github.com/casensiom/metaballs // - #ifndef _METABALLS_H_ #define _METABALLS_H_ @@ -37,12 +36,12 @@ size_t count; \ } TYPE##Array##SIZE; -#define MB_CREATE_ARRAY(TYPE, CAPACITY) \ - (TYPE##Array) \ - { \ - .items = (TYPE *)malloc(CAPACITY * sizeof(TYPE)), \ - .count = 0, \ - .capacity = CAPACITY \ +#define MB_CREATE_ARRAY(TYPE, CAPACITY) \ + (TYPE##Array) \ + { \ + .items = (TYPE *)malloc((CAPACITY) * sizeof(TYPE)), \ + .count = 0, \ + .capacity = (CAPACITY) \ } #define MB_DESTROY_ARRAY(arr) \ @@ -103,10 +102,6 @@ typedef struct ball_struct Vector3d pos; float mass; Color4C color; - - // orbital params - Vector3d angular_speed; - Vector3d initial_pos; } Ball; MB_DEFINE_ARRAY(Ball); @@ -187,20 +182,21 @@ typedef struct grid_struct } Grid; #if defined(__cplusplus) -extern "C" { +extern "C" +{ #endif -Grid grid_create(Index3d count, Vector3d size, Vector3d pos); + Grid grid_create(Index3d count, Vector3d size, Vector3d pos); -void grid_destroy(Grid *grid); + void grid_destroy(Grid *grid); -void push_ball(BallArray *balls, Ball ball); + void push_ball(BallArray *balls, Ball ball); -void move_balls(Grid grid, BallArray balls, float t); + void move_balls(Grid grid, BallArray balls, float t); -Ball random_ball(Grid grid); + Ball random_ball(Grid grid); -void generate_mesh(Grid *grid, BallArray balls); + void generate_mesh(Grid *grid, BallArray balls); #if defined(__cplusplus) } @@ -210,7 +206,6 @@ void generate_mesh(Grid *grid, BallArray balls); #ifdef METABALLS_IMPLEMENTATION - static char marching_cube_triangles[256][16]; static char marching_cube_edges[12][2]; static int marching_cube_vertices[8][3]; @@ -219,7 +214,37 @@ static char marching_cube_neighbors[256]; static size_t cache_hit = 0; static size_t cache_miss = 0; -float vector3d_length(Vector3d start, Vector3d end) { +float clamp(float v, float min, float max) +{ + return (v < min) ? min : (v > max) ? max : v; +} + +Vector3d vector3d_add(Vector3d orig, Vector3d val) +{ + return (Vector3d){ + .x = orig.x + val.x, + .y = orig.y + val.y, + .z = orig.z + val.z}; +} + +Vector3d vector3d_substract(Vector3d orig, Vector3d val) +{ + return (Vector3d){ + .x = orig.x - val.x, + .y = orig.y - val.y, + .z = orig.z - val.z}; +} + +Vector3d vector3d_multiply(Vector3d v, float factor) +{ + return (Vector3d){ + .x = v.x * factor, + .y = v.y * factor, + .z = v.z * factor}; +} + +float vector3d_length(Vector3d start, Vector3d end) +{ float x = end.x - start.x; float y = end.y - start.y; float z = end.z - start.z; @@ -249,7 +274,6 @@ float vector3d_dot_product(Vector3d v1, Vector3d v2) return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } - Vector3d compute_grid_point_coordinates(Index3d pos, Grid grid) { Vector3d out; @@ -260,15 +284,16 @@ Vector3d compute_grid_point_coordinates(Index3d pos, Grid grid) } size_t compute_grid_point_index(Index3d pos, Grid grid) -{ +{ size_t ret = pos.x + - (pos.y * grid.count.x) + - (pos.z * grid.count.x * grid.count.y); + (pos.y * grid.count.x) + + (pos.z * grid.count.x * grid.count.y); assert(ret < grid.count.x * grid.count.y * grid.count.z); return ret; } -Index3d compute_grid_index(Vector3d pos, Grid grid) { +Index3d compute_grid_index(Vector3d pos, Grid grid) +{ Index3d out; out.x = (size_t)floor((pos.x - grid.pos.x) / grid.size.x); out.y = (size_t)floor((pos.y - grid.pos.y) / grid.size.y); @@ -380,33 +405,73 @@ float compute_energy(Vector3d world_pos, BallArray balls) return energy; } +Vector3d compute_normal_balls(Vector3d pos, BallArray balls) +{ + Vector3d nor = (Vector3d){.x = 0.0, .y = 0.0001, .z = 0.0}; + + for (size_t i = 0; i < balls.count; ++i) + { + Vector3d dir = vector3d_substract(pos, balls.items[i].pos); + Vector3d v = {0}; +#if 1 // simplification + float dist = dir.x * dir.x + dir.y * dir.y + dir.z * dir.z; + if (dist > 1e-6) + { + v.x = dir.x / dist; + v.y = dir.y / dist; + v.z = dir.z / dist; + } +#endif +#if 0 // derive energy over position => 2 * mass / distance^4 + float dist = dir.x * dir.x + dir.y * dir.y + dir.z * dir.z; + v.x = 2 * balls.items[i].mass * dir.x / (dist * dist); + v.y = 2 * balls.items[i].mass * dir.y / (dist * dist); + v.z = 2 * balls.items[i].mass * dir.z / (dist * dist); +#endif +#if 0 + float db = vector3d_length(balls.items[i].pos, pos); + float x = clamp(db/balls.items[i].mass, 0.0, 1.0); + float p = x*x*(30.0*x*x - 60.0*x + 30.0); + v = vector3d_normalize( dir ); + v = vector3d_multiply(v, p / balls.items[i].mass); +#endif + nor = vector3d_add(nor, v); + } + + return vector3d_normalize(nor); +} + Vertex3d compute_vertex(Vector3d vertex, Grid grid, BallArray balls) { Vertex3d v; v.pos = vertex; // Compute vertex normal - // n += 2 * mass * vector / distance^4 - Vector3d normal = {0}; + v.normal = compute_normal_balls(v.pos, balls); float total_energy = 0; for (size_t i = 0; i < balls.count; i++) { + if (balls.items[i].mass < 0) + { + continue; + } Vector3d dir = { .x = v.pos.x - balls.items[i].pos.x, .y = v.pos.y - balls.items[i].pos.y, .z = v.pos.z - balls.items[i].pos.z}; float dist = dir.x * dir.x + dir.y * dir.y + dir.z * dir.z; - total_energy += balls.items[i].mass / dist; - normal.x += 2 * balls.items[i].mass * dir.x / (dist * dist); - normal.y += 2 * balls.items[i].mass * dir.y / (dist * dist); - normal.z += 2 * balls.items[i].mass * dir.z / (dist * dist); + total_energy += balls.items[i].mass / dist; } Color4C color = {0}; for (size_t i = 0; i < balls.count; i++) { + if (balls.items[i].mass < 0) + { + continue; + } Vector3d dir = { .x = v.pos.x - balls.items[i].pos.x, .y = v.pos.y - balls.items[i].pos.y, @@ -422,19 +487,18 @@ Vertex3d compute_vertex(Vector3d vertex, Grid grid, BallArray balls) } color.a = 0xff; - normal = vector3d_normalize(normal); - if (grid.config.mapping == MAPPING_PLANAR) { - v.text_coord.x = (normal.x / 2.0) + 0.5; - v.text_coord.y = -(normal.y / 2.0) + 0.5; + v.text_coord.x = (v.normal.x / 2.0) + 0.5; + v.text_coord.y = -(v.normal.y / 2.0) + 0.5; } else { - float theta = atan2(normal.z, normal.x); - float phi = acos(normal.y); - v.text_coord.x = (theta + PI) / (2.0 * PI) + 0.5; - v.text_coord.y = phi / PI + 0.5; + + float theta = atan2(v.normal.x, v.normal.z); + float phi = acos(v.normal.y); + v.text_coord.x = (theta + PI) / (2.0 * PI); + v.text_coord.y = (phi / PI); } v.color = color; @@ -673,9 +737,9 @@ Grid grid_create(Index3d count, Vector3d size, Vector3d pos) Grid grid; Vector3d center = { - .x = pos.x + (count.x * size.x) / 2.0f, - .y = pos.y + (count.y * size.y) / 2.0f, - .z = pos.z + (count.z * size.z) / 2.0f}; + .x = pos.x + ((count.x - 1.0f) / 2.0f) * size.x, + .y = pos.y + ((count.y - 1.0f) / 2.0f) * size.y, + .z = pos.z + ((count.z - 1.0f) / 2.0f) * size.z}; grid.count = count; grid.size = size; @@ -684,7 +748,10 @@ Grid grid_create(Index3d count, Vector3d size, Vector3d pos) grid.nodes = MB_CREATE_ARRAY(Node, grid.count.x * grid.count.y * grid.count.z); grid.queue = MB_CREATE_ARRAY(Index3d, grid.count.x * grid.count.y * grid.count.z); grid.mesh = mesh_create(grid); + grid.config.threshold = 0.3; + grid.config.wired = true; + grid.config.mapping = MAPPING_SPHERIC; return grid; } @@ -701,65 +768,6 @@ void grid_destroy(Grid *grid) mesh_destroy(&(grid->mesh)); } -void push_ball(BallArray *balls, Ball ball) -{ - balls->items[balls->count] = ball; - balls->count++; -} - -void move_balls(Grid grid, BallArray balls, float t) -{ - float radius_x = (grid.count.x * grid.size.x) / 4; - float radius_y = (grid.count.y * grid.size.y) / 4; - float radius_z = (grid.count.z * grid.size.z) / 4; - - for (size_t i = 0; i < balls.count; i++) - { - balls.items[i].pos = (Vector3d){ - .x = grid.center.x + radius_x * cosf(balls.items[i].angular_speed.x * t + balls.items[i].initial_pos.x), - .y = grid.center.y + radius_y * sinf(balls.items[i].angular_speed.y * t + balls.items[i].initial_pos.y), - .z = grid.center.z + radius_z * cosf(balls.items[i].angular_speed.z * t + balls.items[i].initial_pos.z)}; - } -} - -Ball random_ball(Grid grid) -{ - float radius_x = (grid.count.x * grid.size.x) / 4; - float radius_y = (grid.count.y * grid.size.y) / 4; - float radius_z = (grid.count.z * grid.size.z) / 4; - - Vector3d speed = { - .x = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f), - .y = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f), - .z = 0.1f + (float)rand() / ((float)RAND_MAX / 2.0f)}; - - Vector3d initial = { - .x = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f), - .y = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f), - .z = 2.0f - (float)rand() / ((float)RAND_MAX / 4.0f)}; - - Vector3d p = (Vector3d){ - .x = grid.center.x + radius_x * cos(initial.x), - .y = grid.center.y + radius_y * sin(initial.y), - .z = grid.center.z + radius_z * cos(initial.z)}; - - Color4C color = (Color4C){ - .r = (unsigned char)(64 + (rand() % 192)), - .g = (unsigned char)(128 + (rand() % 128)), - .b = (unsigned char)(128 + (rand() % 128)), - .a = (unsigned char)(255) - }; - - float ball_mass = 50.0f + (float)(rand() % 200); - - return (Ball){.pos = p, .mass = ball_mass, .color = color, .angular_speed = speed, .initial_pos = initial}; -} - - - - - - //============================================================================= //============================================================================== @@ -774,7 +782,7 @@ Ball random_ball(Grid grid) // | / 3 | / 2 // |/ |/ // +----------+ -// 0 1 +// 0 1 // +----------+ // 7/| 6 /| @@ -787,7 +795,7 @@ Ball random_ball(Grid grid) // | / 2 | / // |/3 |/1 // +----------+ -// 0 +// 0 //============================================================================== //============================================================================== @@ -800,307 +808,302 @@ Ball random_ball(Grid grid) // bit 3 : y - 1 // bit 4 : z + 1 // bit 5 : z - 1 -static char marching_cube_neighbors[256] = -{ - 0, 42, 41, 43, 25, 59, 57, 59, 26, 58, 59, 59, 27, 59, 59, 51, - 38, 46, 47, 47, 63, 63, 63, 63, 62, 62, 63, 63, 63, 63, 63, 55, - 37, 47, 45, 47, 61, 63, 61, 63, 63, 63, 63, 63, 63, 63, 63, 55, - 39, 47, 47, 15, 63, 63, 63, 31, 63, 63, 63, 31, 63, 63, 63, 23, - 21, 63, 61, 63, 29, 63, 61, 63, 31, 63, 63, 63, 31, 63, 63, 55, - 55, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, - 53, 63, 61, 63, 61, 63, 60, 62, 63, 63, 63, 63, 63, 63, 62, 54, - 55, 63, 63, 31, 63, 63, 62, 30, 63, 63, 63, 31, 63, 63, 62, 22, - 22, 62, 63, 63, 31, 63, 63, 63, 30, 62, 63, 63, 31, 63, 63, 55, - 54, 62, 63, 63, 63, 63, 63, 63, 62, 60, 63, 61, 63, 61, 63, 53, - 55, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, - 55, 63, 63, 31, 63, 63, 63, 31, 63, 61, 63, 29, 63, 61, 63, 21, - 23, 63, 63, 63, 31, 63, 63, 63, 31, 63, 63, 63, 15, 47, 47, 39, - 55, 63, 63, 63, 63, 63, 63, 63, 63, 61, 63, 61, 47, 45, 47, 37, - 55, 63, 63, 63, 63, 63, 62, 62, 63, 63, 63, 63, 47, 47, 46, 38, - 51, 59, 59, 27, 59, 59, 58, 26, 59, 57, 59, 25, 43, 41, 42, 0 -}; +static char marching_cube_neighbors[256] = + { + 0, 42, 41, 43, 25, 59, 57, 59, 26, 58, 59, 59, 27, 59, 59, 51, + 38, 46, 47, 47, 63, 63, 63, 63, 62, 62, 63, 63, 63, 63, 63, 55, + 37, 47, 45, 47, 61, 63, 61, 63, 63, 63, 63, 63, 63, 63, 63, 55, + 39, 47, 47, 15, 63, 63, 63, 31, 63, 63, 63, 31, 63, 63, 63, 23, + 21, 63, 61, 63, 29, 63, 61, 63, 31, 63, 63, 63, 31, 63, 63, 55, + 55, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, + 53, 63, 61, 63, 61, 63, 60, 62, 63, 63, 63, 63, 63, 63, 62, 54, + 55, 63, 63, 31, 63, 63, 62, 30, 63, 63, 63, 31, 63, 63, 62, 22, + 22, 62, 63, 63, 31, 63, 63, 63, 30, 62, 63, 63, 31, 63, 63, 55, + 54, 62, 63, 63, 63, 63, 63, 63, 62, 60, 63, 61, 63, 61, 63, 53, + 55, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 55, + 55, 63, 63, 31, 63, 63, 63, 31, 63, 61, 63, 29, 63, 61, 63, 21, + 23, 63, 63, 63, 31, 63, 63, 63, 31, 63, 63, 63, 15, 47, 47, 39, + 55, 63, 63, 63, 63, 63, 63, 63, 63, 61, 63, 61, 47, 45, 47, 37, + 55, 63, 63, 63, 63, 63, 62, 62, 63, 63, 63, 63, 47, 47, 46, 38, + 51, 59, 59, 27, 59, 59, 58, 26, 59, 57, 59, 25, 43, 41, 42, 0}; // Cube vertices -static int marching_cube_vertices[8][3] = -{ - {0,0,0}, - {1,0,0}, - {1,0,1}, - {0,0,1}, - {0,1,0}, - {1,1,0}, - {1,1,1}, - {0,1,1} -}; +static int marching_cube_vertices[8][3] = + { + {0, 0, 0}, + {1, 0, 0}, + {1, 0, 1}, + {0, 0, 1}, + {0, 1, 0}, + {1, 1, 0}, + {1, 1, 1}, + {0, 1, 1}}; // This is the edges and the direction on them. They are designed so // that edges of neighboring cubes are in the same direction. -static char marching_cube_edges[12][2] = -{ - {0,1}, {1,2}, {3,2}, {0,3}, - {4,5}, {5,6}, {7,6}, {4,7}, - {0,4}, {1,5}, {3,7}, {2,6} -}; +static char marching_cube_edges[12][2] = + { + {0, 1}, {1, 2}, {3, 2}, {0, 3}, {4, 5}, {5, 6}, {7, 6}, {4, 7}, {0, 4}, {1, 5}, {3, 7}, {2, 6}}; // This list gives the edges that the triangles in each case intersect. -static char marching_cube_triangles[256][16] = -{ - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 0 - { 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 - { 9, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 2 - { 3, 1, 8, 1, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 3 - {11, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 4 - { 3, 0, 8, 11, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 5 - {11, 9, 2, 9, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 - { 3, 2, 8, 8, 2, 11, 8, 11, 9, -1, -1, -1, -1, -1, -1, -1}, // 7 - { 2, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 8 - { 2, 0, 10, 0, 8, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 9 - { 0, 1, 9, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 10 - { 2, 1, 10, 10, 1, 9, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, // 11 - { 1, 3, 11, 3, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 12 - { 1, 0, 11, 11, 0, 8, 11, 8, 10, -1, -1, -1, -1, -1, -1, -1}, // 13 - { 0, 3, 9, 9, 3, 10, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, // 14 - {11, 9, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 15 - { 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 16 - { 0, 4, 3, 4, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 17 - { 9, 0, 1, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 18 - { 9, 4, 1, 1, 4, 7, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, // 19 - {11, 1, 2, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 20 - { 7, 3, 4, 4, 3, 0, 11, 1, 2, -1, -1, -1, -1, -1, -1, -1}, // 21 - {11, 9, 2, 2, 9, 0, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, // 22 - { 9, 2, 11, 7, 2, 9, 3, 2, 7, 4, 7, 9, -1, -1, -1, -1}, // 23 - { 7, 8, 4, 2, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 24 - { 7, 10, 4, 4, 10, 2, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, // 25 - { 1, 9, 0, 7, 8, 4, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1}, // 26 - {10, 4, 7, 10, 9, 4, 2, 9, 10, 1, 9, 2, -1, -1, -1, -1}, // 27 - { 1, 3, 11, 11, 3, 10, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, // 28 - {11, 1, 10, 10, 1, 4, 4, 1, 0, 4, 7, 10, -1, -1, -1, -1}, // 29 - { 8, 4, 7, 10, 9, 0, 11, 9, 10, 3, 10, 0, -1, -1, -1, -1}, // 30 - {10, 4, 7, 9, 4, 10, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, // 31 - { 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 32 - { 4, 9, 5, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 33 - { 4, 0, 5, 0, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 34 - { 4, 8, 5, 5, 8, 3, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, // 35 - {11, 1, 2, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 36 - { 8, 3, 0, 11, 1, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, // 37 - {11, 5, 2, 2, 5, 4, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, // 38 - { 5, 2, 11, 5, 3, 2, 4, 3, 5, 8, 3, 4, -1, -1, -1, -1}, // 39 - { 4, 9, 5, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 40 - { 2, 0, 10, 10, 0, 8, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, // 41 - { 4, 0, 5, 5, 0, 1, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1}, // 42 - { 5, 2, 1, 8, 2, 5, 10, 2, 8, 5, 4, 8, -1, -1, -1, -1}, // 43 - {10, 11, 3, 3, 11, 1, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, // 44 - { 5, 4, 9, 1, 0, 8, 1, 8, 11, 11, 8, 10, -1, -1, -1, -1}, // 45 - { 0, 5, 4, 10, 5, 0, 11, 5, 10, 3, 10, 0, -1, -1, -1, -1}, // 46 - { 8, 5, 4, 11, 5, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, // 47 - { 8, 9, 7, 9, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 48 - { 0, 9, 3, 3, 9, 5, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, // 49 - { 8, 0, 7, 7, 0, 1, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, // 50 - { 3, 1, 5, 7, 3, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 51 - { 8, 9, 7, 7, 9, 5, 2, 11, 1, -1, -1, -1, -1, -1, -1, -1}, // 52 - { 2, 11, 1, 0, 9, 5, 0, 5, 3, 3, 5, 7, -1, -1, -1, -1}, // 53 - { 2, 8, 0, 5, 8, 2, 7, 8, 5, 2, 11, 5, -1, -1, -1, -1}, // 54 - { 5, 2, 11, 3, 2, 5, 7, 3, 5, -1, -1, -1, -1, -1, -1, -1}, // 55 - { 5, 7, 9, 9, 7, 8, 2, 3, 10, -1, -1, -1, -1, -1, -1, -1}, // 56 - { 7, 9, 5, 2, 9, 7, 0, 9, 2, 10, 2, 7, -1, -1, -1, -1}, // 57 - {10, 2, 3, 8, 0, 1, 8, 1, 7, 7, 1, 5, -1, -1, -1, -1}, // 58 - { 1, 10, 2, 7, 10, 1, 5, 7, 1, -1, -1, -1, -1, -1, -1, -1}, // 59 - { 8, 9, 5, 7, 8, 5, 3, 11, 1, 10, 11, 3, -1, -1, -1, -1}, // 60 - { 0, 5, 7, 9, 5, 0, 0, 7, 10, 11, 1, 0, 0, 10, 11, -1}, // 61 - { 0, 10, 11, 3, 10, 0, 0, 11, 5, 7, 8, 0, 0, 5, 7, -1}, // 62 - { 5, 10, 11, 5, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 63 - { 5, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 64 - { 3, 0, 8, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 65 - { 1, 9, 0, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 66 - { 3, 1, 8, 8, 1, 9, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1}, // 67 - { 5, 1, 6, 1, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 68 - { 5, 1, 6, 6, 1, 2, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, // 69 - { 5, 9, 6, 6, 9, 0, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, // 70 - { 8, 5, 9, 2, 5, 8, 6, 5, 2, 8, 3, 2, -1, -1, -1, -1}, // 71 - {10, 2, 3, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 72 - { 8, 10, 0, 0, 10, 2, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1}, // 73 - { 9, 0, 1, 10, 2, 3, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1}, // 74 - { 6, 5, 11, 2, 1, 9, 2, 9, 10, 10, 9, 8, -1, -1, -1, -1}, // 75 - {10, 6, 3, 3, 6, 5, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, // 76 - {10, 0, 8, 5, 0, 10, 1, 0, 5, 6, 5, 10, -1, -1, -1, -1}, // 77 - { 6, 3, 10, 6, 0, 3, 5, 0, 6, 9, 0, 5, -1, -1, -1, -1}, // 78 - { 9, 6, 5, 10, 6, 9, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, // 79 - { 6, 5, 11, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 80 - { 0, 4, 3, 3, 4, 7, 11, 6, 5, -1, -1, -1, -1, -1, -1, -1}, // 81 - { 0, 1, 9, 6, 5, 11, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, // 82 - { 5, 11, 6, 7, 1, 9, 3, 1, 7, 4, 7, 9, -1, -1, -1, -1}, // 83 - { 2, 6, 1, 1, 6, 5, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, // 84 - { 5, 1, 2, 6, 5, 2, 4, 3, 0, 7, 3, 4, -1, -1, -1, -1}, // 85 - { 7, 8, 4, 5, 9, 0, 5, 0, 6, 6, 0, 2, -1, -1, -1, -1}, // 86 - { 9, 7, 3, 4, 7, 9, 9, 3, 2, 6, 5, 9, 9, 2, 6, -1}, // 87 - { 2, 3, 10, 4, 7, 8, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1}, // 88 - { 6, 5, 11, 2, 4, 7, 0, 4, 2, 10, 2, 7, -1, -1, -1, -1}, // 89 - { 9, 0, 1, 8, 4, 7, 10, 2, 3, 6, 5, 11, -1, -1, -1, -1}, // 90 - { 1, 9, 2, 2, 9, 10, 10, 9, 4, 4, 7, 10, 6, 5, 11, -1}, // 91 - { 7, 8, 4, 5, 3, 10, 1, 3, 5, 6, 5, 10, -1, -1, -1, -1}, // 92 - {10, 5, 1, 6, 5, 10, 10, 1, 0, 4, 7, 10, 10, 0, 4, -1}, // 93 - { 9, 0, 5, 5, 0, 6, 6, 0, 3, 3, 10, 6, 7, 8, 4, -1}, // 94 - { 9, 6, 5, 10, 6, 9, 9, 4, 7, 9, 7, 10, -1, -1, -1, -1}, // 95 - { 9, 11, 4, 11, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 96 - { 6, 4, 11, 11, 4, 9, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, // 97 - { 1, 11, 0, 0, 11, 6, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, // 98 - { 1, 8, 3, 6, 8, 1, 4, 8, 6, 11, 6, 1, -1, -1, -1, -1}, // 99 - { 9, 1, 4, 4, 1, 2, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, // 100 - { 8, 3, 0, 9, 1, 2, 9, 2, 4, 4, 2, 6, -1, -1, -1, -1}, // 101 - { 4, 0, 2, 6, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 102 - { 2, 8, 3, 4, 8, 2, 6, 4, 2, -1, -1, -1, -1, -1, -1, -1}, // 103 - { 9, 11, 4, 4, 11, 6, 3, 10, 2, -1, -1, -1, -1, -1, -1, -1}, // 104 - { 2, 0, 8, 10, 2, 8, 11, 4, 9, 6, 4, 11, -1, -1, -1, -1}, // 105 - { 2, 3, 10, 6, 0, 1, 4, 0, 6, 11, 6, 1, -1, -1, -1, -1}, // 106 - { 1, 6, 4, 11, 6, 1, 1, 4, 8, 10, 2, 1, 1, 8, 10, -1}, // 107 - { 4, 9, 6, 6, 9, 3, 3, 9, 1, 3, 10, 6, -1, -1, -1, -1}, // 108 - { 1, 8, 10, 0, 8, 1, 1, 10, 6, 4, 9, 1, 1, 6, 4, -1}, // 109 - { 6, 3, 10, 0, 3, 6, 4, 0, 6, -1, -1, -1, -1, -1, -1, -1}, // 110 - { 8, 6, 4, 8, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 111 - { 6, 7, 11, 11, 7, 8, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, // 112 - { 3, 0, 7, 7, 0, 11, 11, 0, 9, 11, 6, 7, -1, -1, -1, -1}, // 113 - { 7, 11, 6, 7, 1, 11, 8, 1, 7, 0, 1, 8, -1, -1, -1, -1}, // 114 - { 7, 11, 6, 1, 11, 7, 3, 1, 7, -1, -1, -1, -1, -1, -1, -1}, // 115 - { 6, 1, 2, 8, 1, 6, 9, 1, 8, 7, 8, 6, -1, -1, -1, -1}, // 116 - { 9, 2, 6, 1, 2, 9, 9, 6, 7, 3, 0, 9, 9, 7, 3, -1}, // 117 - { 0, 7, 8, 6, 7, 0, 2, 6, 0, -1, -1, -1, -1, -1, -1, -1}, // 118 - { 2, 7, 3, 2, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 119 - {10, 2, 3, 8, 11, 6, 9, 11, 8, 7, 8, 6, -1, -1, -1, -1}, // 120 - { 7, 2, 0, 10, 2, 7, 7, 0, 9, 11, 6, 7, 7, 9, 11, -1}, // 121 - { 0, 1, 8, 8, 1, 7, 7, 1, 11, 11, 6, 7, 10, 2, 3, -1}, // 122 - { 1, 10, 2, 7, 10, 1, 1, 11, 6, 1, 6, 7, -1, -1, -1, -1}, // 123 - { 6, 8, 9, 7, 8, 6, 6, 9, 1, 3, 10, 6, 6, 1, 3, -1}, // 124 - { 1, 0, 9, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 125 - { 0, 7, 8, 6, 7, 0, 0, 3, 10, 0, 10, 6, -1, -1, -1, -1}, // 126 - { 6, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 127 - {10, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 128 - { 8, 3, 0, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 129 - { 9, 0, 1, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 130 - { 9, 8, 1, 1, 8, 3, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1}, // 131 - { 2, 11, 1, 7, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 132 - {11, 1, 2, 8, 3, 0, 7, 6, 10, -1, -1, -1, -1, -1, -1, -1}, // 133 - { 0, 2, 9, 9, 2, 11, 7, 6, 10, -1, -1, -1, -1, -1, -1, -1}, // 134 - { 7, 6, 10, 3, 2, 11, 3, 11, 8, 8, 11, 9, -1, -1, -1, -1}, // 135 - { 3, 7, 2, 7, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 136 - { 8, 7, 0, 0, 7, 6, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, // 137 - { 6, 2, 7, 7, 2, 3, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, // 138 - { 2, 1, 6, 6, 1, 8, 8, 1, 9, 6, 8, 7, -1, -1, -1, -1}, // 139 - { 6, 11, 7, 7, 11, 1, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, // 140 - { 6, 11, 7, 11, 1, 7, 7, 1, 8, 8, 1, 0, -1, -1, -1, -1}, // 141 - { 7, 0, 3, 11, 0, 7, 9, 0, 11, 7, 6, 11, -1, -1, -1, -1}, // 142 - {11, 7, 6, 8, 7, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, // 143 - { 4, 6, 8, 6, 10, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 144 - {10, 3, 6, 6, 3, 0, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, // 145 - {10, 8, 6, 6, 8, 4, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, // 146 - { 6, 9, 4, 3, 9, 6, 1, 9, 3, 6, 10, 3, -1, -1, -1, -1}, // 147 - { 4, 6, 8, 8, 6, 10, 1, 2, 11, -1, -1, -1, -1, -1, -1, -1}, // 148 - {11, 1, 2, 10, 3, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1}, // 149 - { 8, 4, 10, 10, 4, 6, 9, 0, 2, 9, 2, 11, -1, -1, -1, -1}, // 150 - { 3, 11, 9, 2, 11, 3, 3, 9, 4, 6, 10, 3, 3, 4, 6, -1}, // 151 - { 3, 8, 2, 2, 8, 4, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, // 152 - { 2, 0, 4, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 153 - { 0, 1, 9, 4, 2, 3, 6, 2, 4, 8, 4, 3, -1, -1, -1, -1}, // 154 - { 4, 1, 9, 2, 1, 4, 6, 2, 4, -1, -1, -1, -1, -1, -1, -1}, // 155 - { 3, 8, 1, 1, 8, 6, 6, 8, 4, 1, 6, 11, -1, -1, -1, -1}, // 156 - { 0, 11, 1, 6, 11, 0, 4, 6, 0, -1, -1, -1, -1, -1, -1, -1}, // 157 - { 3, 4, 6, 8, 4, 3, 3, 6, 11, 9, 0, 3, 3, 11, 9, -1}, // 158 - { 4, 11, 9, 4, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 159 - { 5, 4, 9, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 160 - { 3, 0, 8, 5, 4, 9, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1}, // 161 - { 1, 5, 0, 0, 5, 4, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1}, // 162 - { 6, 10, 7, 4, 8, 3, 4, 3, 5, 5, 3, 1, -1, -1, -1, -1}, // 163 - { 4, 9, 5, 2, 11, 1, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1}, // 164 - { 7, 6, 10, 11, 1, 2, 3, 0, 8, 5, 4, 9, -1, -1, -1, -1}, // 165 - {10, 7, 6, 11, 5, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1}, // 166 - { 8, 3, 4, 4, 3, 5, 5, 3, 2, 2, 11, 5, 6, 10, 7, -1}, // 167 - { 3, 7, 2, 2, 7, 6, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, // 168 - { 4, 9, 5, 6, 0, 8, 2, 0, 6, 7, 6, 8, -1, -1, -1, -1}, // 169 - { 2, 3, 6, 6, 3, 7, 0, 1, 5, 0, 5, 4, -1, -1, -1, -1}, // 170 - { 8, 6, 2, 7, 6, 8, 8, 2, 1, 5, 4, 8, 8, 1, 5, -1}, // 171 - { 4, 9, 5, 6, 11, 1, 6, 1, 7, 7, 1, 3, -1, -1, -1, -1}, // 172 - {11, 1, 6, 6, 1, 7, 7, 1, 0, 0, 8, 7, 4, 9, 5, -1}, // 173 - {11, 4, 0, 5, 4, 11, 11, 0, 3, 7, 6, 11, 11, 3, 7, -1}, // 174 - {11, 7, 6, 8, 7, 11, 11, 5, 4, 11, 4, 8, -1, -1, -1, -1}, // 175 - { 5, 6, 9, 9, 6, 10, 9, 10, 8, -1, -1, -1, -1, -1, -1, -1}, // 176 - {10, 3, 6, 3, 0, 6, 6, 0, 5, 5, 0, 9, -1, -1, -1, -1}, // 177 - { 8, 0, 10, 10, 0, 5, 5, 0, 1, 10, 5, 6, -1, -1, -1, -1}, // 178 - { 3, 6, 10, 5, 6, 3, 1, 5, 3, -1, -1, -1, -1, -1, -1, -1}, // 179 - {11, 1, 2, 10, 9, 5, 8, 9, 10, 6, 10, 5, -1, -1, -1, -1}, // 180 - { 3, 0, 10, 10, 0, 6, 6, 0, 9, 9, 5, 6, 11, 1, 2, -1}, // 181 - { 5, 10, 8, 6, 10, 5, 5, 8, 0, 2, 11, 5, 5, 0, 2, -1}, // 182 - { 3, 6, 10, 5, 6, 3, 3, 2, 11, 3, 11, 5, -1, -1, -1, -1}, // 183 - { 9, 5, 8, 8, 5, 2, 2, 5, 6, 2, 3, 8, -1, -1, -1, -1}, // 184 - { 6, 9, 5, 0, 9, 6, 2, 0, 6, -1, -1, -1, -1, -1, -1, -1}, // 185 - { 8, 1, 5, 0, 1, 8, 8, 5, 6, 2, 3, 8, 8, 6, 2, -1}, // 186 - { 6, 1, 5, 6, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 187 - { 6, 1, 3, 11, 1, 6, 6, 3, 8, 9, 5, 6, 6, 8, 9, -1}, // 188 - { 0, 11, 1, 6, 11, 0, 0, 9, 5, 0, 5, 6, -1, -1, -1, -1}, // 189 - { 8, 0, 3, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 190 - { 6, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 191 - {11, 10, 5, 10, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 192 - {11, 10, 5, 5, 10, 7, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, // 193 - { 7, 5, 10, 10, 5, 11, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, // 194 - { 5, 11, 7, 7, 11, 10, 1, 9, 8, 1, 8, 3, -1, -1, -1, -1}, // 195 - { 2, 10, 1, 1, 10, 7, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, // 196 - { 3, 0, 8, 7, 1, 2, 5, 1, 7, 10, 7, 2, -1, -1, -1, -1}, // 197 - { 5, 9, 7, 7, 9, 2, 2, 9, 0, 7, 2, 10, -1, -1, -1, -1}, // 198 - { 2, 7, 5, 10, 7, 2, 2, 5, 9, 8, 3, 2, 2, 9, 8, -1}, // 199 - {11, 2, 5, 5, 2, 3, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, // 200 - { 0, 8, 2, 2, 8, 5, 5, 8, 7, 5, 11, 2, -1, -1, -1, -1}, // 201 - { 1, 9, 0, 3, 5, 11, 7, 5, 3, 2, 3, 11, -1, -1, -1, -1}, // 202 - { 2, 9, 8, 1, 9, 2, 2, 8, 7, 5, 11, 2, 2, 7, 5, -1}, // 203 - { 5, 1, 3, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 204 - { 7, 0, 8, 1, 0, 7, 5, 1, 7, -1, -1, -1, -1, -1, -1, -1}, // 205 - { 3, 9, 0, 5, 9, 3, 7, 5, 3, -1, -1, -1, -1, -1, -1, -1}, // 206 - { 7, 9, 8, 7, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 207 - { 4, 5, 8, 8, 5, 11, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, // 208 - { 4, 5, 0, 0, 5, 10, 10, 5, 11, 0, 10, 3, -1, -1, -1, -1}, // 209 - { 9, 0, 1, 11, 8, 4, 10, 8, 11, 5, 11, 4, -1, -1, -1, -1}, // 210 - { 4, 11, 10, 5, 11, 4, 4, 10, 3, 1, 9, 4, 4, 3, 1, -1}, // 211 - { 1, 2, 5, 5, 2, 8, 8, 2, 10, 8, 4, 5, -1, -1, -1, -1}, // 212 - {10, 0, 4, 3, 0, 10, 10, 4, 5, 1, 2, 10, 10, 5, 1, -1}, // 213 - { 5, 0, 2, 9, 0, 5, 5, 2, 10, 8, 4, 5, 5, 10, 8, -1}, // 214 - { 5, 9, 4, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 215 - {11, 2, 5, 2, 3, 5, 5, 3, 4, 4, 3, 8, -1, -1, -1, -1}, // 216 - { 2, 5, 11, 4, 5, 2, 0, 4, 2, -1, -1, -1, -1, -1, -1, -1}, // 217 - { 2, 3, 11, 11, 3, 5, 5, 3, 8, 8, 4, 5, 9, 0, 1, -1}, // 218 - { 2, 5, 11, 4, 5, 2, 2, 1, 9, 2, 9, 4, -1, -1, -1, -1}, // 219 - { 5, 8, 4, 3, 8, 5, 1, 3, 5, -1, -1, -1, -1, -1, -1, -1}, // 220 - { 5, 0, 4, 5, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 221 - { 5, 8, 4, 3, 8, 5, 5, 9, 0, 5, 0, 3, -1, -1, -1, -1}, // 222 - { 5, 9, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 223 - { 7, 4, 10, 10, 4, 9, 10, 9, 11, -1, -1, -1, -1, -1, -1, -1}, // 224 - { 3, 0, 8, 7, 4, 9, 7, 9, 10, 10, 9, 11, -1, -1, -1, -1}, // 225 - {10, 1, 11, 4, 1, 10, 0, 1, 4, 10, 7, 4, -1, -1, -1, -1}, // 226 - { 4, 3, 1, 8, 3, 4, 4, 1, 11, 10, 7, 4, 4, 11, 10, -1}, // 227 - { 7, 4, 10, 4, 9, 10, 10, 9, 2, 2, 9, 1, -1, -1, -1, -1}, // 228 - { 4, 9, 7, 7, 9, 10, 10, 9, 1, 1, 2, 10, 3, 0, 8, -1}, // 229 - { 4, 10, 7, 2, 10, 4, 0, 2, 4, -1, -1, -1, -1, -1, -1, -1}, // 230 - { 4, 10, 7, 2, 10, 4, 4, 8, 3, 4, 3, 2, -1, -1, -1, -1}, // 231 - {11, 2, 9, 9, 2, 7, 7, 2, 3, 9, 7, 4, -1, -1, -1, -1}, // 232 - { 7, 9, 11, 4, 9, 7, 7, 11, 2, 0, 8, 7, 7, 2, 0, -1}, // 233 - {11, 3, 7, 2, 3, 11, 11, 7, 4, 0, 1, 11, 11, 4, 0, -1}, // 234 - { 2, 1, 11, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 235 - { 1, 4, 9, 7, 4, 1, 3, 7, 1, -1, -1, -1, -1, -1, -1, -1}, // 236 - { 1, 4, 9, 7, 4, 1, 1, 0, 8, 1, 8, 7, -1, -1, -1, -1}, // 237 - { 3, 4, 0, 3, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 238 - { 7, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 239 - { 8, 9, 11, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 240 - { 9, 3, 0, 10, 3, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, // 241 - {11, 0, 1, 8, 0, 11, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, // 242 - {11, 3, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 243 - {10, 1, 2, 9, 1, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, // 244 - { 9, 3, 0, 10, 3, 9, 9, 1, 2, 9, 2, 10, -1, -1, -1, -1}, // 245 - {10, 0, 2, 10, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 246 - {10, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 247 - { 8, 2, 3, 11, 2, 8, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, // 248 - { 2, 9, 11, 2, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 249 - { 8, 2, 3, 11, 2, 8, 8, 0, 1, 8, 1, 11, -1, -1, -1, -1}, // 250 - { 2, 1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 251 - { 8, 1, 3, 8, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 252 - { 1, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 253 - { 8, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 254 - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} // 255 +static char marching_cube_triangles[256][16] = + { + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 0 + {3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 + {9, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 2 + {3, 1, 8, 1, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 3 + {11, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 4 + {3, 0, 8, 11, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 5 + {11, 9, 2, 9, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 + {3, 2, 8, 8, 2, 11, 8, 11, 9, -1, -1, -1, -1, -1, -1, -1}, // 7 + {2, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 8 + {2, 0, 10, 0, 8, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 9 + {0, 1, 9, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 10 + {2, 1, 10, 10, 1, 9, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, // 11 + {1, 3, 11, 3, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 12 + {1, 0, 11, 11, 0, 8, 11, 8, 10, -1, -1, -1, -1, -1, -1, -1}, // 13 + {0, 3, 9, 9, 3, 10, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, // 14 + {11, 9, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 15 + {8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 16 + {0, 4, 3, 4, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 17 + {9, 0, 1, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 18 + {9, 4, 1, 1, 4, 7, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, // 19 + {11, 1, 2, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 20 + {7, 3, 4, 4, 3, 0, 11, 1, 2, -1, -1, -1, -1, -1, -1, -1}, // 21 + {11, 9, 2, 2, 9, 0, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, // 22 + {9, 2, 11, 7, 2, 9, 3, 2, 7, 4, 7, 9, -1, -1, -1, -1}, // 23 + {7, 8, 4, 2, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 24 + {7, 10, 4, 4, 10, 2, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, // 25 + {1, 9, 0, 7, 8, 4, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1}, // 26 + {10, 4, 7, 10, 9, 4, 2, 9, 10, 1, 9, 2, -1, -1, -1, -1}, // 27 + {1, 3, 11, 11, 3, 10, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, // 28 + {11, 1, 10, 10, 1, 4, 4, 1, 0, 4, 7, 10, -1, -1, -1, -1}, // 29 + {8, 4, 7, 10, 9, 0, 11, 9, 10, 3, 10, 0, -1, -1, -1, -1}, // 30 + {10, 4, 7, 9, 4, 10, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, // 31 + {4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 32 + {4, 9, 5, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 33 + {4, 0, 5, 0, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 34 + {4, 8, 5, 5, 8, 3, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, // 35 + {11, 1, 2, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 36 + {8, 3, 0, 11, 1, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, // 37 + {11, 5, 2, 2, 5, 4, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, // 38 + {5, 2, 11, 5, 3, 2, 4, 3, 5, 8, 3, 4, -1, -1, -1, -1}, // 39 + {4, 9, 5, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 40 + {2, 0, 10, 10, 0, 8, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, // 41 + {4, 0, 5, 5, 0, 1, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1}, // 42 + {5, 2, 1, 8, 2, 5, 10, 2, 8, 5, 4, 8, -1, -1, -1, -1}, // 43 + {10, 11, 3, 3, 11, 1, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, // 44 + {5, 4, 9, 1, 0, 8, 1, 8, 11, 11, 8, 10, -1, -1, -1, -1}, // 45 + {0, 5, 4, 10, 5, 0, 11, 5, 10, 3, 10, 0, -1, -1, -1, -1}, // 46 + {8, 5, 4, 11, 5, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, // 47 + {8, 9, 7, 9, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 48 + {0, 9, 3, 3, 9, 5, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, // 49 + {8, 0, 7, 7, 0, 1, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, // 50 + {3, 1, 5, 7, 3, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 51 + {8, 9, 7, 7, 9, 5, 2, 11, 1, -1, -1, -1, -1, -1, -1, -1}, // 52 + {2, 11, 1, 0, 9, 5, 0, 5, 3, 3, 5, 7, -1, -1, -1, -1}, // 53 + {2, 8, 0, 5, 8, 2, 7, 8, 5, 2, 11, 5, -1, -1, -1, -1}, // 54 + {5, 2, 11, 3, 2, 5, 7, 3, 5, -1, -1, -1, -1, -1, -1, -1}, // 55 + {5, 7, 9, 9, 7, 8, 2, 3, 10, -1, -1, -1, -1, -1, -1, -1}, // 56 + {7, 9, 5, 2, 9, 7, 0, 9, 2, 10, 2, 7, -1, -1, -1, -1}, // 57 + {10, 2, 3, 8, 0, 1, 8, 1, 7, 7, 1, 5, -1, -1, -1, -1}, // 58 + {1, 10, 2, 7, 10, 1, 5, 7, 1, -1, -1, -1, -1, -1, -1, -1}, // 59 + {8, 9, 5, 7, 8, 5, 3, 11, 1, 10, 11, 3, -1, -1, -1, -1}, // 60 + {0, 5, 7, 9, 5, 0, 0, 7, 10, 11, 1, 0, 0, 10, 11, -1}, // 61 + {0, 10, 11, 3, 10, 0, 0, 11, 5, 7, 8, 0, 0, 5, 7, -1}, // 62 + {5, 10, 11, 5, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 63 + {5, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 64 + {3, 0, 8, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 65 + {1, 9, 0, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 66 + {3, 1, 8, 8, 1, 9, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1}, // 67 + {5, 1, 6, 1, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 68 + {5, 1, 6, 6, 1, 2, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, // 69 + {5, 9, 6, 6, 9, 0, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, // 70 + {8, 5, 9, 2, 5, 8, 6, 5, 2, 8, 3, 2, -1, -1, -1, -1}, // 71 + {10, 2, 3, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 72 + {8, 10, 0, 0, 10, 2, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1}, // 73 + {9, 0, 1, 10, 2, 3, 6, 5, 11, -1, -1, -1, -1, -1, -1, -1}, // 74 + {6, 5, 11, 2, 1, 9, 2, 9, 10, 10, 9, 8, -1, -1, -1, -1}, // 75 + {10, 6, 3, 3, 6, 5, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, // 76 + {10, 0, 8, 5, 0, 10, 1, 0, 5, 6, 5, 10, -1, -1, -1, -1}, // 77 + {6, 3, 10, 6, 0, 3, 5, 0, 6, 9, 0, 5, -1, -1, -1, -1}, // 78 + {9, 6, 5, 10, 6, 9, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, // 79 + {6, 5, 11, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 80 + {0, 4, 3, 3, 4, 7, 11, 6, 5, -1, -1, -1, -1, -1, -1, -1}, // 81 + {0, 1, 9, 6, 5, 11, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, // 82 + {5, 11, 6, 7, 1, 9, 3, 1, 7, 4, 7, 9, -1, -1, -1, -1}, // 83 + {2, 6, 1, 1, 6, 5, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, // 84 + {5, 1, 2, 6, 5, 2, 4, 3, 0, 7, 3, 4, -1, -1, -1, -1}, // 85 + {7, 8, 4, 5, 9, 0, 5, 0, 6, 6, 0, 2, -1, -1, -1, -1}, // 86 + {9, 7, 3, 4, 7, 9, 9, 3, 2, 6, 5, 9, 9, 2, 6, -1}, // 87 + {2, 3, 10, 4, 7, 8, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1}, // 88 + {6, 5, 11, 2, 4, 7, 0, 4, 2, 10, 2, 7, -1, -1, -1, -1}, // 89 + {9, 0, 1, 8, 4, 7, 10, 2, 3, 6, 5, 11, -1, -1, -1, -1}, // 90 + {1, 9, 2, 2, 9, 10, 10, 9, 4, 4, 7, 10, 6, 5, 11, -1}, // 91 + {7, 8, 4, 5, 3, 10, 1, 3, 5, 6, 5, 10, -1, -1, -1, -1}, // 92 + {10, 5, 1, 6, 5, 10, 10, 1, 0, 4, 7, 10, 10, 0, 4, -1}, // 93 + {9, 0, 5, 5, 0, 6, 6, 0, 3, 3, 10, 6, 7, 8, 4, -1}, // 94 + {9, 6, 5, 10, 6, 9, 9, 4, 7, 9, 7, 10, -1, -1, -1, -1}, // 95 + {9, 11, 4, 11, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 96 + {6, 4, 11, 11, 4, 9, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, // 97 + {1, 11, 0, 0, 11, 6, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, // 98 + {1, 8, 3, 6, 8, 1, 4, 8, 6, 11, 6, 1, -1, -1, -1, -1}, // 99 + {9, 1, 4, 4, 1, 2, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, // 100 + {8, 3, 0, 9, 1, 2, 9, 2, 4, 4, 2, 6, -1, -1, -1, -1}, // 101 + {4, 0, 2, 6, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 102 + {2, 8, 3, 4, 8, 2, 6, 4, 2, -1, -1, -1, -1, -1, -1, -1}, // 103 + {9, 11, 4, 4, 11, 6, 3, 10, 2, -1, -1, -1, -1, -1, -1, -1}, // 104 + {2, 0, 8, 10, 2, 8, 11, 4, 9, 6, 4, 11, -1, -1, -1, -1}, // 105 + {2, 3, 10, 6, 0, 1, 4, 0, 6, 11, 6, 1, -1, -1, -1, -1}, // 106 + {1, 6, 4, 11, 6, 1, 1, 4, 8, 10, 2, 1, 1, 8, 10, -1}, // 107 + {4, 9, 6, 6, 9, 3, 3, 9, 1, 3, 10, 6, -1, -1, -1, -1}, // 108 + {1, 8, 10, 0, 8, 1, 1, 10, 6, 4, 9, 1, 1, 6, 4, -1}, // 109 + {6, 3, 10, 0, 3, 6, 4, 0, 6, -1, -1, -1, -1, -1, -1, -1}, // 110 + {8, 6, 4, 8, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 111 + {6, 7, 11, 11, 7, 8, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, // 112 + {3, 0, 7, 7, 0, 11, 11, 0, 9, 11, 6, 7, -1, -1, -1, -1}, // 113 + {7, 11, 6, 7, 1, 11, 8, 1, 7, 0, 1, 8, -1, -1, -1, -1}, // 114 + {7, 11, 6, 1, 11, 7, 3, 1, 7, -1, -1, -1, -1, -1, -1, -1}, // 115 + {6, 1, 2, 8, 1, 6, 9, 1, 8, 7, 8, 6, -1, -1, -1, -1}, // 116 + {9, 2, 6, 1, 2, 9, 9, 6, 7, 3, 0, 9, 9, 7, 3, -1}, // 117 + {0, 7, 8, 6, 7, 0, 2, 6, 0, -1, -1, -1, -1, -1, -1, -1}, // 118 + {2, 7, 3, 2, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 119 + {10, 2, 3, 8, 11, 6, 9, 11, 8, 7, 8, 6, -1, -1, -1, -1}, // 120 + {7, 2, 0, 10, 2, 7, 7, 0, 9, 11, 6, 7, 7, 9, 11, -1}, // 121 + {0, 1, 8, 8, 1, 7, 7, 1, 11, 11, 6, 7, 10, 2, 3, -1}, // 122 + {1, 10, 2, 7, 10, 1, 1, 11, 6, 1, 6, 7, -1, -1, -1, -1}, // 123 + {6, 8, 9, 7, 8, 6, 6, 9, 1, 3, 10, 6, 6, 1, 3, -1}, // 124 + {1, 0, 9, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 125 + {0, 7, 8, 6, 7, 0, 0, 3, 10, 0, 10, 6, -1, -1, -1, -1}, // 126 + {6, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 127 + {10, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 128 + {8, 3, 0, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 129 + {9, 0, 1, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 130 + {9, 8, 1, 1, 8, 3, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1}, // 131 + {2, 11, 1, 7, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 132 + {11, 1, 2, 8, 3, 0, 7, 6, 10, -1, -1, -1, -1, -1, -1, -1}, // 133 + {0, 2, 9, 9, 2, 11, 7, 6, 10, -1, -1, -1, -1, -1, -1, -1}, // 134 + {7, 6, 10, 3, 2, 11, 3, 11, 8, 8, 11, 9, -1, -1, -1, -1}, // 135 + {3, 7, 2, 7, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 136 + {8, 7, 0, 0, 7, 6, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, // 137 + {6, 2, 7, 7, 2, 3, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, // 138 + {2, 1, 6, 6, 1, 8, 8, 1, 9, 6, 8, 7, -1, -1, -1, -1}, // 139 + {6, 11, 7, 7, 11, 1, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, // 140 + {6, 11, 7, 11, 1, 7, 7, 1, 8, 8, 1, 0, -1, -1, -1, -1}, // 141 + {7, 0, 3, 11, 0, 7, 9, 0, 11, 7, 6, 11, -1, -1, -1, -1}, // 142 + {11, 7, 6, 8, 7, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, // 143 + {4, 6, 8, 6, 10, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 144 + {10, 3, 6, 6, 3, 0, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, // 145 + {10, 8, 6, 6, 8, 4, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, // 146 + {6, 9, 4, 3, 9, 6, 1, 9, 3, 6, 10, 3, -1, -1, -1, -1}, // 147 + {4, 6, 8, 8, 6, 10, 1, 2, 11, -1, -1, -1, -1, -1, -1, -1}, // 148 + {11, 1, 2, 10, 3, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1}, // 149 + {8, 4, 10, 10, 4, 6, 9, 0, 2, 9, 2, 11, -1, -1, -1, -1}, // 150 + {3, 11, 9, 2, 11, 3, 3, 9, 4, 6, 10, 3, 3, 4, 6, -1}, // 151 + {3, 8, 2, 2, 8, 4, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, // 152 + {2, 0, 4, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 153 + {0, 1, 9, 4, 2, 3, 6, 2, 4, 8, 4, 3, -1, -1, -1, -1}, // 154 + {4, 1, 9, 2, 1, 4, 6, 2, 4, -1, -1, -1, -1, -1, -1, -1}, // 155 + {3, 8, 1, 1, 8, 6, 6, 8, 4, 1, 6, 11, -1, -1, -1, -1}, // 156 + {0, 11, 1, 6, 11, 0, 4, 6, 0, -1, -1, -1, -1, -1, -1, -1}, // 157 + {3, 4, 6, 8, 4, 3, 3, 6, 11, 9, 0, 3, 3, 11, 9, -1}, // 158 + {4, 11, 9, 4, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 159 + {5, 4, 9, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 160 + {3, 0, 8, 5, 4, 9, 6, 10, 7, -1, -1, -1, -1, -1, -1, -1}, // 161 + {1, 5, 0, 0, 5, 4, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1}, // 162 + {6, 10, 7, 4, 8, 3, 4, 3, 5, 5, 3, 1, -1, -1, -1, -1}, // 163 + {4, 9, 5, 2, 11, 1, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1}, // 164 + {7, 6, 10, 11, 1, 2, 3, 0, 8, 5, 4, 9, -1, -1, -1, -1}, // 165 + {10, 7, 6, 11, 5, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1}, // 166 + {8, 3, 4, 4, 3, 5, 5, 3, 2, 2, 11, 5, 6, 10, 7, -1}, // 167 + {3, 7, 2, 2, 7, 6, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, // 168 + {4, 9, 5, 6, 0, 8, 2, 0, 6, 7, 6, 8, -1, -1, -1, -1}, // 169 + {2, 3, 6, 6, 3, 7, 0, 1, 5, 0, 5, 4, -1, -1, -1, -1}, // 170 + {8, 6, 2, 7, 6, 8, 8, 2, 1, 5, 4, 8, 8, 1, 5, -1}, // 171 + {4, 9, 5, 6, 11, 1, 6, 1, 7, 7, 1, 3, -1, -1, -1, -1}, // 172 + {11, 1, 6, 6, 1, 7, 7, 1, 0, 0, 8, 7, 4, 9, 5, -1}, // 173 + {11, 4, 0, 5, 4, 11, 11, 0, 3, 7, 6, 11, 11, 3, 7, -1}, // 174 + {11, 7, 6, 8, 7, 11, 11, 5, 4, 11, 4, 8, -1, -1, -1, -1}, // 175 + {5, 6, 9, 9, 6, 10, 9, 10, 8, -1, -1, -1, -1, -1, -1, -1}, // 176 + {10, 3, 6, 3, 0, 6, 6, 0, 5, 5, 0, 9, -1, -1, -1, -1}, // 177 + {8, 0, 10, 10, 0, 5, 5, 0, 1, 10, 5, 6, -1, -1, -1, -1}, // 178 + {3, 6, 10, 5, 6, 3, 1, 5, 3, -1, -1, -1, -1, -1, -1, -1}, // 179 + {11, 1, 2, 10, 9, 5, 8, 9, 10, 6, 10, 5, -1, -1, -1, -1}, // 180 + {3, 0, 10, 10, 0, 6, 6, 0, 9, 9, 5, 6, 11, 1, 2, -1}, // 181 + {5, 10, 8, 6, 10, 5, 5, 8, 0, 2, 11, 5, 5, 0, 2, -1}, // 182 + {3, 6, 10, 5, 6, 3, 3, 2, 11, 3, 11, 5, -1, -1, -1, -1}, // 183 + {9, 5, 8, 8, 5, 2, 2, 5, 6, 2, 3, 8, -1, -1, -1, -1}, // 184 + {6, 9, 5, 0, 9, 6, 2, 0, 6, -1, -1, -1, -1, -1, -1, -1}, // 185 + {8, 1, 5, 0, 1, 8, 8, 5, 6, 2, 3, 8, 8, 6, 2, -1}, // 186 + {6, 1, 5, 6, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 187 + {6, 1, 3, 11, 1, 6, 6, 3, 8, 9, 5, 6, 6, 8, 9, -1}, // 188 + {0, 11, 1, 6, 11, 0, 0, 9, 5, 0, 5, 6, -1, -1, -1, -1}, // 189 + {8, 0, 3, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 190 + {6, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 191 + {11, 10, 5, 10, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 192 + {11, 10, 5, 5, 10, 7, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, // 193 + {7, 5, 10, 10, 5, 11, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, // 194 + {5, 11, 7, 7, 11, 10, 1, 9, 8, 1, 8, 3, -1, -1, -1, -1}, // 195 + {2, 10, 1, 1, 10, 7, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, // 196 + {3, 0, 8, 7, 1, 2, 5, 1, 7, 10, 7, 2, -1, -1, -1, -1}, // 197 + {5, 9, 7, 7, 9, 2, 2, 9, 0, 7, 2, 10, -1, -1, -1, -1}, // 198 + {2, 7, 5, 10, 7, 2, 2, 5, 9, 8, 3, 2, 2, 9, 8, -1}, // 199 + {11, 2, 5, 5, 2, 3, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, // 200 + {0, 8, 2, 2, 8, 5, 5, 8, 7, 5, 11, 2, -1, -1, -1, -1}, // 201 + {1, 9, 0, 3, 5, 11, 7, 5, 3, 2, 3, 11, -1, -1, -1, -1}, // 202 + {2, 9, 8, 1, 9, 2, 2, 8, 7, 5, 11, 2, 2, 7, 5, -1}, // 203 + {5, 1, 3, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 204 + {7, 0, 8, 1, 0, 7, 5, 1, 7, -1, -1, -1, -1, -1, -1, -1}, // 205 + {3, 9, 0, 5, 9, 3, 7, 5, 3, -1, -1, -1, -1, -1, -1, -1}, // 206 + {7, 9, 8, 7, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 207 + {4, 5, 8, 8, 5, 11, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, // 208 + {4, 5, 0, 0, 5, 10, 10, 5, 11, 0, 10, 3, -1, -1, -1, -1}, // 209 + {9, 0, 1, 11, 8, 4, 10, 8, 11, 5, 11, 4, -1, -1, -1, -1}, // 210 + {4, 11, 10, 5, 11, 4, 4, 10, 3, 1, 9, 4, 4, 3, 1, -1}, // 211 + {1, 2, 5, 5, 2, 8, 8, 2, 10, 8, 4, 5, -1, -1, -1, -1}, // 212 + {10, 0, 4, 3, 0, 10, 10, 4, 5, 1, 2, 10, 10, 5, 1, -1}, // 213 + {5, 0, 2, 9, 0, 5, 5, 2, 10, 8, 4, 5, 5, 10, 8, -1}, // 214 + {5, 9, 4, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 215 + {11, 2, 5, 2, 3, 5, 5, 3, 4, 4, 3, 8, -1, -1, -1, -1}, // 216 + {2, 5, 11, 4, 5, 2, 0, 4, 2, -1, -1, -1, -1, -1, -1, -1}, // 217 + {2, 3, 11, 11, 3, 5, 5, 3, 8, 8, 4, 5, 9, 0, 1, -1}, // 218 + {2, 5, 11, 4, 5, 2, 2, 1, 9, 2, 9, 4, -1, -1, -1, -1}, // 219 + {5, 8, 4, 3, 8, 5, 1, 3, 5, -1, -1, -1, -1, -1, -1, -1}, // 220 + {5, 0, 4, 5, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 221 + {5, 8, 4, 3, 8, 5, 5, 9, 0, 5, 0, 3, -1, -1, -1, -1}, // 222 + {5, 9, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 223 + {7, 4, 10, 10, 4, 9, 10, 9, 11, -1, -1, -1, -1, -1, -1, -1}, // 224 + {3, 0, 8, 7, 4, 9, 7, 9, 10, 10, 9, 11, -1, -1, -1, -1}, // 225 + {10, 1, 11, 4, 1, 10, 0, 1, 4, 10, 7, 4, -1, -1, -1, -1}, // 226 + {4, 3, 1, 8, 3, 4, 4, 1, 11, 10, 7, 4, 4, 11, 10, -1}, // 227 + {7, 4, 10, 4, 9, 10, 10, 9, 2, 2, 9, 1, -1, -1, -1, -1}, // 228 + {4, 9, 7, 7, 9, 10, 10, 9, 1, 1, 2, 10, 3, 0, 8, -1}, // 229 + {4, 10, 7, 2, 10, 4, 0, 2, 4, -1, -1, -1, -1, -1, -1, -1}, // 230 + {4, 10, 7, 2, 10, 4, 4, 8, 3, 4, 3, 2, -1, -1, -1, -1}, // 231 + {11, 2, 9, 9, 2, 7, 7, 2, 3, 9, 7, 4, -1, -1, -1, -1}, // 232 + {7, 9, 11, 4, 9, 7, 7, 11, 2, 0, 8, 7, 7, 2, 0, -1}, // 233 + {11, 3, 7, 2, 3, 11, 11, 7, 4, 0, 1, 11, 11, 4, 0, -1}, // 234 + {2, 1, 11, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 235 + {1, 4, 9, 7, 4, 1, 3, 7, 1, -1, -1, -1, -1, -1, -1, -1}, // 236 + {1, 4, 9, 7, 4, 1, 1, 0, 8, 1, 8, 7, -1, -1, -1, -1}, // 237 + {3, 4, 0, 3, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 238 + {7, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 239 + {8, 9, 11, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 240 + {9, 3, 0, 10, 3, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, // 241 + {11, 0, 1, 8, 0, 11, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, // 242 + {11, 3, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 243 + {10, 1, 2, 9, 1, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, // 244 + {9, 3, 0, 10, 3, 9, 9, 1, 2, 9, 2, 10, -1, -1, -1, -1}, // 245 + {10, 0, 2, 10, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 246 + {10, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 247 + {8, 2, 3, 11, 2, 8, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, // 248 + {2, 9, 11, 2, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 249 + {8, 2, 3, 11, 2, 8, 8, 0, 1, 8, 1, 11, -1, -1, -1, -1}, // 250 + {2, 1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 251 + {8, 1, 3, 8, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 252 + {1, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 253 + {8, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 254 + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} // 255 }; #endif // METABALLS_IMPLEMENTATION