diff options
| author | Ethan Morgan <ethan@gweithio.com> | 2026-02-14 16:44:06 +0000 |
|---|---|---|
| committer | Ethan Morgan <ethan@gweithio.com> | 2026-02-14 16:44:06 +0000 |
| commit | 54409423f767d8b1cf30cb7d0efca6b4ca138823 (patch) | |
| tree | d915ac7828703ce4b963efdd9728a1777ba18c1e /apps | |
Diffstat (limited to 'apps')
105 files changed, 33206 insertions, 0 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 0000000..27e581d --- /dev/null +++ b/apps/CMakeLists.txt @@ -0,0 +1,2 @@ +# OpenMB Applications +add_subdirectory(openmb) diff --git a/apps/openmb/CMakeLists.txt b/apps/openmb/CMakeLists.txt new file mode 100644 index 0000000..7ca6f15 --- /dev/null +++ b/apps/openmb/CMakeLists.txt @@ -0,0 +1,45 @@ +set(OPENMB_SOURCES + main.cpp + renderer/GLHelpers.cpp + renderer/Shader.cpp + renderer/SSAORenderer.cpp + renderer/DirectionalLight.cpp + renderer/Mesh.cpp + renderer/Model.cpp + renderer/primitives.cpp + renderer/EditorHelpers.cpp + renderer/Skybox.cpp + scene/Camera.cpp + scene/GridSystem.cpp + scene/VoxelEditor.cpp + renderer/Texture.cpp + renderer/TextureManager.cpp +) + +add_executable(OpenMB ${OPENMB_SOURCES}) + +target_compile_features(OpenMB PRIVATE cxx_std_20) + +target_link_libraries(OpenMB PRIVATE + spdlog::spdlog + nlohmann_json::nlohmann_json + imgui::imgui + glfw + + # OpenGL linking handled below per-platform + glm::glm + OpenAL::OpenAL + assimp::assimp + Jolt::Jolt +) + +target_include_directories(OpenMB PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${Stb_INCLUDE_DIR} +) + +if(APPLE) + target_link_libraries(OpenMB PRIVATE "-framework OpenGL") +else() + target_link_libraries(OpenMB PRIVATE OpenGL::GL) +endif() diff --git a/apps/openmb/ImguiStyle.hpp b/apps/openmb/ImguiStyle.hpp new file mode 100644 index 0000000..3409281 --- /dev/null +++ b/apps/openmb/ImguiStyle.hpp @@ -0,0 +1,80 @@ +#ifndef IMGUI_STYLE_H +#define IMGUI_STYLE_H + +#include "imgui.h" + +inline void ApplyDebugTheme () { + auto& style = ImGui::GetStyle(); + style.WindowRounding = 8.0f; + style.WindowPadding = ImVec2( 12.0f, 12.0f ); + style.DisabledAlpha = 1.0f; + style.Alpha = 1.0f; +} + +inline void ApplyImguiTheme () { + ImGui::StyleColorsDark(); + ImGuiStyle& style = ImGui::GetStyle(); + style.DisabledAlpha = 1.0f; + style.Alpha = 1.0f; + style.WindowRounding = 4.0f; + style.FrameRounding = 4.0f; + style.GrabRounding = 4.0f; + style.WindowBorderSize = 0.0f; + style.FrameBorderSize = 0.0f; + style.ItemSpacing = ImVec2( 8.0f, 6.0f ); + + const float accentR = 0.95f; + const float accentG = 0.95f; + const float accentB = 0.95f; + + ImVec4* colors = style.Colors; + + colors[ImGuiCol_Text] = ImVec4( 0.95f, 0.95f, 0.95f, 1.00f ); + colors[ImGuiCol_TextDisabled] = ImVec4( 0.60f, 0.60f, 0.60f, 1.00f ); + colors[ImGuiCol_WindowBg] = ImVec4( 0.06f, 0.06f, 0.06f, 0.95f ); + colors[ImGuiCol_ChildBg] = ImVec4( 0.06f, 0.06f, 0.06f, 0.95f ); + + colors[ImGuiCol_PopupBg] = ImVec4( 0.06f, 0.06f, 0.08f, 0.95f ); + colors[ImGuiCol_Border] = ImVec4( 0.15f, 0.15f, 0.15f, 0.50f ); + colors[ImGuiCol_BorderShadow] = ImVec4( 0.00f, 0.00f, 0.00f, 0.00f ); + + colors[ImGuiCol_FrameBg] = ImVec4( 0.10f, 0.10f, 0.12f, 0.90f ); + colors[ImGuiCol_FrameBgHovered] = ImVec4( 0.20f, 0.20f, 0.20f, 0.95f ); + colors[ImGuiCol_FrameBgActive] = ImVec4( 0.24f, 0.24f, 0.24f, 0.95f ); + + colors[ImGuiCol_TitleBg] = ImVec4( 0.08f, 0.08f, 0.08f, 0.95f ); + colors[ImGuiCol_TitleBgActive] = ImVec4( 0.06f, 0.06f, 0.06f, 0.95f ); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4( 0.00f, 0.00f, 0.00f, 0.51f ); + colors[ImGuiCol_MenuBarBg] = ImVec4( 0.08f, 0.08f, 0.08f, 0.95f ); + + colors[ImGuiCol_Button] = ImVec4( 0.12f, 0.12f, 0.14f, 0.95f ); + colors[ImGuiCol_ButtonHovered] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_ButtonActive] = ImVec4( 0.08f, 0.08f, 0.08f, 0.95f ); + + colors[ImGuiCol_Header] = ImVec4( 0.08f, 0.08f, 0.08f, 0.95f ); + colors[ImGuiCol_HeaderHovered] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_HeaderActive] = ImVec4( accentR * 0.75f, accentG * 0.75f, accentB * 0.75f, 0.95f ); + + colors[ImGuiCol_Separator] = ImVec4( 0.12f, 0.12f, 0.14f, 1.00f ); + colors[ImGuiCol_SeparatorHovered] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_SeparatorActive] = ImVec4( accentR * 0.75f, accentG * 0.75f, accentB * 0.75f, 1.00f ); + + colors[ImGuiCol_Tab] = ImVec4( 0.10f, 0.10f, 0.12f, 0.95f ); + colors[ImGuiCol_TabHovered] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_TabActive] = ImVec4( accentR * 0.75f, accentG * 0.75f, accentB * 0.75f, 0.95f ); + + colors[ImGuiCol_CheckMark] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_SliderGrab] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_SliderGrabActive] = ImVec4( accentR * 0.75f, accentG * 0.75f, accentB * 0.75f, 0.95f ); + + colors[ImGuiCol_ScrollbarBg] = ImVec4( 0.05f, 0.05f, 0.06f, 0.90f ); + colors[ImGuiCol_ScrollbarGrab] = ImVec4( 0.12f, 0.12f, 0.14f, 0.95f ); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4( accentR * 0.85f, accentG * 0.85f, accentB * 0.85f, 0.95f ); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4( accentR * 0.75f, accentG * 0.75f, accentB * 0.75f, 0.95f ); + + colors[ImGuiCol_ResizeGrip] = ImVec4( 0.12f, 0.12f, 0.14f, 0.95f ); + colors[ImGuiCol_ResizeGripActive] = ImVec4( 0.12f, 0.12f, 0.14f, 0.95f ); + colors[ImGuiCol_ResizeGripHovered] = ImVec4( 0.12f, 0.12f, 0.14f, 0.95f ); +} + +#endif diff --git a/apps/openmb/main.cpp b/apps/openmb/main.cpp new file mode 100644 index 0000000..54027b9 --- /dev/null +++ b/apps/openmb/main.cpp @@ -0,0 +1,1753 @@ +#if defined( __APPLE__ ) +#define GL_SILENCE_DEPRECATION +#endif +#if defined( __APPLE__ ) +#define GL_SILENCE_DEPRECATION +#endif + +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif + +#include <chrono> +#include <glm/glm.hpp> +#include <glm/gtc/matrix_transform.hpp> +#include <glm/gtc/type_ptr.hpp> +#include <iostream> +#include <vector> + +#include "ImguiStyle.hpp" +#include <imgui.h> +#include <imgui_impl_glfw.h> +#include <imgui_impl_opengl3.h> + +#include "renderer/DirectionalLight.hpp" +#include "renderer/EditorHelpers.hpp" +#include "renderer/GLHelpers.hpp" +#include "renderer/Model.hpp" +#include "renderer/SSAORenderer.hpp" +#include "renderer/Shader.hpp" +#include "renderer/Skybox.hpp" +#include "renderer/Texture.hpp" +#include "renderer/TextureManager.hpp" +#include "renderer/primitives.hpp" +#include "scene/Camera.hpp" + +#include "scene/GridSystem.hpp" +#include "scene/VoxelEditor.hpp" +#include <algorithm> +#include <assimp/Importer.hpp> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <filesystem> +#include <fstream> +#include <nlohmann/json.hpp> + +void keyCallback ( GLFWwindow* window, int key, int scancode, int action, int mods ) {} + +int main () { + if( !glfwInit() ) { + std::cerr << "Failed to initialize GLFW!" << std::endl; + return -1; + } + + glfwWindowHint( GLFW_DEPTH_BITS, 24 ); + + glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); + glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 ); + glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); + +#ifdef __APPLE__ + glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); +#endif + + int width = 1280; + int height = 720; + GLFWwindow* window = glfwCreateWindow( width, height, "oh yeah, thats hotsauce alright", nullptr, nullptr ); + if( !window ) { + std::cerr << "Failed to create GLFW window!" << std::endl; + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent( window ); + glfwSwapInterval( 1 ); + + glfwMaximizeWindow( window ); + int fbWidth = 0, fbHeight = 0; + glfwGetFramebufferSize( window, &fbWidth, &fbHeight ); + if( fbWidth == 0 || fbHeight == 0 ) { + fbWidth = width; + fbHeight = height; + } + bool ePrev = false; + bool mouseCaptured = true; + + glViewport( 0, 0, fbWidth, fbHeight ); + glfwSetFramebufferSizeCallback( window, [] ( GLFWwindow* /*w*/, int w, int h ) { glViewport( 0, 0, w, h ); } ); + glfwSetKeyCallback( window, keyCallback ); + + if( !renderer::initGL() ) { + std::cerr << "Failed to initialize OpenGL" << std::endl; + glfwDestroyWindow( window ); + glfwTerminate(); + return -1; + } + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + (void)io; + ImGui::StyleColorsDark(); + ApplyImguiTheme(); + ImGui_ImplGlfw_InitForOpenGL( window, true ); + ImGui_ImplOpenGL3_Init( "#version 330 core" ); + + renderer::Shader shader; + const std::string vertPath = "apps/openmb/resources/shaders/cube.vert"; + const std::string fragPath = "apps/openmb/resources/shaders/cube.frag"; + if( !shader.fromFiles( vertPath, fragPath ) ) { + std::cerr << "Failed to load/compile shader files: " << vertPath << " and " << fragPath << std::endl; + glfwDestroyWindow( window ); + glfwTerminate(); + return -1; + } + + scene::GridSystem gridSystem; + + renderer::Mesh cube = renderer::primitives::makeCube(); + renderer::Mesh texturedCube = renderer::primitives::makeTexturedCubeWithNormals(); + renderer::Mesh grid = renderer::primitives::makeGrid( 100, gridSystem.getCellSize() ); + + renderer::Skybox skybox; + if( !skybox.loadFromDirectory( "apps/openmb/resources/skybox" ) ) { + std::cerr << "Warning: failed to load skybox from resources/skybox" << std::endl; + } + + renderer::Shader texShader; + const std::string tVert = "apps/openmb/resources/shaders/textured.vert"; + const std::string tFrag = "apps/openmb/resources/shaders/textured_lit.frag"; + if( !texShader.fromFiles( tVert, tFrag ) ) { + std::cerr << "Failed to load textured shader files: " << tVert << " and " << tFrag << std::endl; + } else { + texShader.use(); + texShader.setInt( "radialEnabled", 0 ); + texShader.setFloat( "radialInner", 0.38f ); + texShader.setFloat( "radialOuter", 0.5f ); + texShader.setInt( "albedo", 0 ); + texShader.setInt( "normalMap", 1 ); + texShader.setInt( "normalEnabled", 0 ); + texShader.setFloat( "normalStrength", 1.0f ); + texShader.setInt( "shadowMap", 2 ); + texShader.setInt( "ssao", 3 ); + texShader.setFloat( "aoStrength", 1.0f ); + } + + glm::vec3 loadedSunDir( 0.3f, 1.0f, 0.5f ); + glm::vec3 loadedSunColor( 1.0f, 0.98f, 0.9f ); + float loadedSunIntensity = 1.0f; + bool loadedSunAvailable = false; + + renderer::DirectionalLight sun; + sun.setDirection( glm::normalize( glm::vec3( 0.3f, 1.0f, 0.5f ) ) ); + sun.setColor( glm::vec3( 1.0f, 0.98f, 0.9f ) ); + sun.setIntensity( 1.0f ); + static bool lightingEnabled = true; + + static float shadowBiasMinGui = 0.00200f; + static float shadowBiasScaleGui = 0.005f; + static int pcfRadiusGui = 0; + static bool snapToTexels = true; + + // Fog parameters (world-space exponential fog) + static glm::vec3 fogColor = glm::vec3( 0.6f, 0.65f, 0.7f ); + static float fogDensity = 0.0741f; + static float fogAmount = 1.f; + + // God-rays parameters + static bool godraysEnabled = false; + // overall multiplier applied to the god-rays composite (keeps defaults conservative) + static float godraysIntensity = 0.08f; + static int godraysSamples = 30; + static float godraysDensity = 0.8f; + static float godraysWeight = 0.4f; + static float godraysDecay = 0.95f; + static int godraysDownscale = 4; // occlusion texture downscale factor + + texShader.use(); + texShader.setFloat( "shadowBiasMin", shadowBiasMinGui ); + texShader.setFloat( "shadowBiasScale", shadowBiasScaleGui ); + texShader.setInt( "pcfRadius", pcfRadiusGui ); + + const unsigned int shadowWidth = 4096, shadowHeight = 4096; + renderer::Shader depthShader; + const std::string dVert = "apps/openmb/resources/shaders/depth.vert"; + const std::string dFrag = "apps/openmb/resources/shaders/depth.frag"; + if( !depthShader.fromFiles( dVert, dFrag ) ) { + std::cerr << "Warning: failed to load depth shader for shadow mapping" << std::endl; + } + + unsigned int depthMapFBO = 0; + unsigned int depthMap = 0; + glGenFramebuffers( 1, &depthMapFBO ); + glGenTextures( 1, &depthMap ); + glBindTexture( GL_TEXTURE_2D, depthMap ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowWidth, shadowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, + nullptr ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER ); + float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor ); + + // We'll perform manual depth comparisons in the shader, so disable sampler compare mode. + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL ); // ignored when compare mode is NONE + + glBindFramebuffer( GL_FRAMEBUFFER, depthMapFBO ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0 ); + glDrawBuffer( GL_NONE ); + glReadBuffer( GL_NONE ); + if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) { + std::cerr << "Warning: Shadow framebuffer not complete" << std::endl; + } + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + + // --- God rays / occlusion resources --- + renderer::Shader occlusionShader; + const std::string occVert = "apps/openmb/resources/shaders/occlusion.vert"; + const std::string occFrag = "apps/openmb/resources/shaders/occlusion.frag"; + if( !occlusionShader.fromFiles( occVert, occFrag ) ) { + std::cerr << "Warning: failed to load occlusion shader" << std::endl; + } + + renderer::Shader godraysShader; + const std::string grVert = "apps/openmb/resources/shaders/godrays_quad.vert"; + const std::string grFrag = "apps/openmb/resources/shaders/godrays_radial.frag"; + if( !godraysShader.fromFiles( grVert, grFrag ) ) { + std::cerr << "Warning: failed to load godrays shader" << std::endl; + } + + // fullscreen quad (NDC coords) + renderer::Mesh quadMesh; + { + std::vector<float> q = { + // pos.x, pos.y, pos.z, u, v + -1.0f, + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + -1.0f, + 0.0f, + 1.0f, + 0.0f, + 1.0f, + 1.0f, + 0.0f, + 1.0f, + 1.0f, + -1.0f, + -1.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + 1.0f, + 0.0f, + 1.0f, + 1.0f, + -1.0f, + 1.0f, + 0.0f, + 0.0f, + 1.0f, + }; + quadMesh.createFromPosTex( q ); + } + + // occlusion FBO (low-res) + unsigned int occlusionFBO = 0; + unsigned int occlusionTex = 0; + unsigned int occlusionDepthRBO = 0; + glGenFramebuffers( 1, &occlusionFBO ); + glGenTextures( 1, &occlusionTex ); + int occlusionW = 0; + int occlusionH = 0; + // we'll allocate size at first frame (when framebuffer size is known) + + glm::mat4 dirLightSpace( 1.0f ); + + renderer::TextureManager textureManager; + textureManager.scanDirectory( "apps/openmb/resources/textures" ); + + std::vector<std::unique_ptr<renderer::Model>> models; + std::vector<std::string> modelNames; + { + std::string modelsDir = "apps/openmb/resources/models/rocks"; + if( std::filesystem::exists( modelsDir ) ) { + for( const auto& entry : std::filesystem::directory_iterator( modelsDir ) ) { + if( entry.path().extension() == ".obj" ) { + auto mptr = std::make_unique<renderer::Model>(); + if( mptr->loadFromFile( entry.path().string() ) ) { + modelNames.push_back( entry.path().stem().string() ); + models.push_back( std::move( mptr ) ); + } else { + std::cerr << "Warning: failed to load model: " << entry.path().string() << std::endl; + } + } + } + } + } + + renderer::Texture rocksAlbedo; + renderer::Texture rocksNormal; + bool rocksAlbedoLoaded = + rocksAlbedo.loadFromFile( "apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_BaseMap.png" ); + bool rocksNormalLoaded = + rocksNormal.loadFromFile( "apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_Normal.png" ); + if( !rocksAlbedoLoaded ) { + std::cerr << "Warning: failed to load rocks albedo at resources/models/rocks/Rocks_lp_SM_Rock_01_BaseMap.png" + << std::endl; + } + if( !rocksNormalLoaded ) { + std::cerr << "Warning: failed to load rocks normal at resources/models/rocks/Rocks_lp_SM_Rock_01_Normal.png" + << std::endl; + } + + std::filesystem::path bluePath = std::filesystem::path( "apps/openmb/resources/textures/brush/basic/blue.tga" ); + if( !std::filesystem::exists( bluePath ) ) { + std::filesystem::create_directories( bluePath.parent_path() ); + std::ofstream out( bluePath, std::ios::binary ); + if( out ) { + unsigned char header[18] = { 0 }; + header[2] = 2; + header[12] = 1; + header[13] = 0; + header[14] = 1; + header[15] = 0; + header[16] = 32; + out.write( reinterpret_cast<char*>( header ), 18 ); + unsigned char pixel[4] = { 255, 0, 0, 200 }; + out.write( reinterpret_cast<char*>( pixel ), 4 ); + out.close(); + std::cout << "Wrote blue texture to " << bluePath.string() << std::endl; + } + textureManager.scanDirectory( "apps/openmb/resources/textures" ); + } + textureManager.setCurrentTexture( "brush", "basic", "blue.tga" ); + + auto categories = textureManager.getCategories(); + if( !categories.empty() ) { + auto subcategories = textureManager.getSubcategories( categories[0] ); + if( !subcategories.empty() ) { + auto textures = textureManager.getTextureNames( categories[0], subcategories[0] ); + if( !textures.empty() ) { + textureManager.setCurrentTexture( categories[0], subcategories[0], textures[0] ); + } + } + } + + const float tileSize = gridSystem.getCellSize(); + + static float brushRadius = 1.5f; + static float prevBrushRadius = -1.0f; + + static float brushHeight = gridSystem.getCellSize(); + enum class PlacementBrush { + Brush = 0, + Cube = 1, + Model = 2, + }; + + static PlacementBrush placementBrush = PlacementBrush::Model; + static bool useCircleBrush = ( placementBrush == PlacementBrush::Brush ); + static int selectedModelIndex = 0; + static float selectedModelScale = 0.017f; + static float selectedModelYaw = 0.0f; + static bool placeCollidable = true; + + renderer::Mesh circleWire = renderer::editor::makeCircleWire( brushRadius, 64 ); + + renderer::Mesh filledCircle = renderer::editor::makeCircleFilled( 1.0f, 64 ); + + struct PaintedCircle { + glm::vec3 mCenter; + float mRadius; + int mTextureId; + }; + + std::vector<PaintedCircle> paintedCircles; + + static double lastPaintTime = 0.0; + const double paintInterval = 0.08; + + std::vector<std::pair<glm::vec3, glm::vec3>> worldBoxes; + std::vector<std::pair<glm::vec3, glm::vec3>> baseWorldBoxes; + + scene::VoxelEditor voxelEditor( gridSystem ); + + const std::string defaultLevelPath = "apps/openmb/resources/levels/default.json"; + if( std::filesystem::exists( defaultLevelPath ) ) { + if( voxelEditor.loadFromFile( defaultLevelPath ) ) { + std::cout << "Loaded default level (voxels) from " << defaultLevelPath << std::endl; + } else { + std::cerr << "Failed to load default level voxels" << std::endl; + } + + try { + std::ifstream in( defaultLevelPath ); + if( in ) { + nlohmann::json j; + in >> j; + if( j.contains( "paintedCircles" ) && j["paintedCircles"].is_array() ) { + for( const auto& pcj : j["paintedCircles"] ) { + PaintedCircle pc; + pc.mCenter.x = pcj.value( "x", 0.0f ); + pc.mCenter.y = pcj.value( "y", 0.0f ); + pc.mCenter.z = pcj.value( "z", 0.0f ); + pc.mRadius = pcj.value( "radius", 1.0f ); + pc.mTextureId = pcj.value( "textureId", 0 ); + paintedCircles.push_back( pc ); + } + std::cout << "Loaded " << paintedCircles.size() << " painted circles from " << defaultLevelPath + << std::endl; + } + if( j.contains( "sun" ) && j["sun"].is_object() ) { + try { + const auto& sj = j["sun"]; + if( sj.contains( "direction" ) && sj["direction"].is_array() && sj["direction"].size() >= 3 ) { + loadedSunDir.x = sj["direction"][0].get<float>(); + loadedSunDir.y = sj["direction"][1].get<float>(); + loadedSunDir.z = sj["direction"][2].get<float>(); + } + if( sj.contains( "color" ) && sj["color"].is_array() && sj["color"].size() >= 3 ) { + loadedSunColor.r = sj["color"][0].get<float>(); + loadedSunColor.g = sj["color"][1].get<float>(); + loadedSunColor.b = sj["color"][2].get<float>(); + } + if( sj.contains( "intensity" ) ) + loadedSunIntensity = sj["intensity"].get<float>(); + loadedSunAvailable = true; + } catch( ... ) { + } + } + } + } catch( ... ) { + } + } + + if( loadedSunAvailable ) { + sun.setDirection( glm::normalize( loadedSunDir ) ); + sun.setColor( loadedSunColor ); + sun.setIntensity( loadedSunIntensity ); + } + + renderer::Mesh wireCube = renderer::editor::makeWireCube( tileSize ); + + auto rayAABBIntersect = [&] ( const glm::vec3& ro, const glm::vec3& rd, const glm::vec3& bmin, const glm::vec3& bmax, + float& outT ) -> bool { + float tmin = -FLT_MAX; + float tmax = FLT_MAX; + for( int i = 0; i < 3; ++i ) { + float origin = ro[i]; + float dir = rd[i]; + float minB = bmin[i]; + float maxB = bmax[i]; + if( std::abs( dir ) < 1e-6f ) { + if( origin < minB || origin > maxB ) + return false; + } else { + float t1 = ( minB - origin ) / dir; + float t2 = ( maxB - origin ) / dir; + if( t1 > t2 ) + std::swap( t1, t2 ); + tmin = std::max( tmin, t1 ); + tmax = std::min( tmax, t2 ); + if( tmin > tmax ) + return false; + } + } + if( tmax < 0.0f ) + return false; + outT = tmin >= 0.0f ? tmin : tmax; + return true; + }; + + bool editorActive = false; + glm::vec3 lastRayOrigin( 0.0f ); + glm::vec3 lastRayDir( 0.0f ); + + int initialFBW = 0, initialFBH = 0; + glfwGetFramebufferSize( window, &initialFBW, &initialFBH ); + if( initialFBW == 0 || initialFBH == 0 ) { + initialFBW = width; + initialFBH = height; + } + glViewport( 0, 0, initialFBW, initialFBH ); + + scene::Camera camera( glm::vec3( 0.0f, 4.0f, 6.0f ), glm::vec3( 0.0f, 4.0f, 0.0f ), -90.0f, 0.0f ); + glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_DISABLED ); + double lastX = width / 2.0, lastY = height / 2.0; + bool firstMouse = true; + float lastFrame = 0.0f; + bool fPrev = false; + bool spacePrev = false; + bool zPrev = false; + bool yPrev = false; + bool lPrev = false; + bool placementEditorEnabled = true; + double lastTime = 0.0; + double deltaTime = 0.0; + double fps = 0.0; + + using Clock = std::chrono::high_resolution_clock; + auto instLastReport = Clock::now(); + double instAccumShadow = 0.0; + double instAccumSSAO = 0.0; + double instAccumDraw = 0.0; + double instAccumUI = 0.0; + double instAccumFrame = 0.0; + int instFrames = 0; + + while( !glfwWindowShouldClose( window ) ) { + auto instFrameStart = Clock::now(); + auto instSegStart = instFrameStart; + float currentFrame = static_cast<float>( glfwGetTime() ); + float deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + + bool fCur = glfwGetKey( window, GLFW_KEY_F ) == GLFW_PRESS; + if( fCur && !fPrev ) + camera.toggleFly(); + fPrev = fCur; + + bool spaceCur = glfwGetKey( window, GLFW_KEY_SPACE ) == GLFW_PRESS; + if( spaceCur && !spacePrev ) + camera.jump(); + spacePrev = spaceCur; + + bool eCur = glfwGetKey( window, GLFW_KEY_E ) == GLFW_PRESS; + if( eCur && !ePrev ) { + mouseCaptured = !mouseCaptured; + if( mouseCaptured ) { + glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_DISABLED ); + } else { + glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_NORMAL ); + } + } + ePrev = eCur; + + bool ctrl = ( glfwGetKey( window, GLFW_KEY_LEFT_CONTROL ) == GLFW_PRESS ) || + ( glfwGetKey( window, GLFW_KEY_RIGHT_CONTROL ) == GLFW_PRESS ); + bool zCur = glfwGetKey( window, GLFW_KEY_Z ) == GLFW_PRESS; + bool yCur = glfwGetKey( window, GLFW_KEY_Y ) == GLFW_PRESS; + bool lCur = glfwGetKey( window, GLFW_KEY_L ) == GLFW_PRESS; + + if( ctrl && zCur && !zPrev ) { + voxelEditor.undo(); + } else if( ctrl && yCur && !yPrev ) { + voxelEditor.redo(); + } + + zPrev = zCur; + yPrev = yCur; + if( lCur && !lPrev ) { + placementEditorEnabled = !placementEditorEnabled; + } + lPrev = lCur; + + double now = glfwGetTime(); + deltaTime = now - lastTime; + lastTime = now; + fps = 1.0 / deltaTime; + + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + if( mouseCaptured ) { + ImGuiIO& io = ImGui::GetIO(); + + for( int i = 0; i < IM_ARRAYSIZE( io.MouseDown ); ++i ) + io.MouseDown[i] = false; + io.WantCaptureMouse = false; + io.WantCaptureKeyboard = false; + } + + { + static bool requireFlyForEditing = true; + + editorActive = ( !requireFlyForEditing || camera.isFlying() ) && placementEditorEnabled; + ImGui::Begin( "Player" ); + ImGui::Text( "Flying: %s", camera.isFlying() ? "Yes" : "No" ); + ImGui::Text( "Grounded: %s", camera.isGrounded() ? "Yes" : "No" ); + float sm = camera.getSpeedMultiplier(); + ImGui::Text( "Speed x%.2f", sm ); + if( ImGui::Button( "Toggle Fly" ) ) + camera.toggleFly(); + if( ImGui::Button( "Jump" ) ) + camera.jump(); + ImGui::Separator(); + ImGui::Separator(); + ImGui::Text( "Edit: Ctrl+Z undo, Ctrl+Y redo" ); + ImGui::Text( "Undo stack: %zu", voxelEditor.getUndoStackSize() ); + ImGui::Text( "Redo stack: %zu", voxelEditor.getRedoStackSize() ); + + ImGui::Separator(); + ImGui::Text( "Level Management:" ); + + static char levelName[128] = "my_level"; + ImGui::InputText( "Level Name", levelName, IM_ARRAYSIZE( levelName ) ); + + if( ImGui::Button( "Save Level" ) ) { + std::filesystem::create_directories( "apps/openmb/resources/levels" ); + std::string filepath = std::string( "apps/openmb/resources/levels/" ) + levelName + ".json"; + try { + nlohmann::json j; + j["version"] = 1; + + nlohmann::json voxels = nlohmann::json::array(); + for( const auto& cell : voxelEditor.getPlacedCells() ) { + nlohmann::json v; + v["x"] = cell.x; + v["y"] = cell.y; + v["z"] = cell.z; + v["textureId"] = voxelEditor.getTextureIdForCell( cell ); + voxels.push_back( v ); + } + j["voxels"] = voxels; + + nlohmann::json pcs = nlohmann::json::array(); + for( const auto& pc : paintedCircles ) { + nlohmann::json p; + p["x"] = pc.mCenter.x; + p["y"] = pc.mCenter.y; + p["z"] = pc.mCenter.z; + p["radius"] = pc.mRadius; + p["textureId"] = pc.mTextureId; + pcs.push_back( p ); + } + j["paintedCircles"] = pcs; + + nlohmann::json modelsJson = nlohmann::json::array(); + for( const auto& mi : voxelEditor.getPlacedModels() ) { + nlohmann::json mj; + mj["modelIndex"] = mi.modelIndex; + mj["x"] = mi.pos.x; + mj["y"] = mi.pos.y; + mj["z"] = mi.pos.z; + mj["yaw"] = mi.yaw; + mj["scale"] = mi.scale; + modelsJson.push_back( mj ); + } + j["models"] = modelsJson; + + try { + nlohmann::json sj; + auto sd = sun.getDirection(); + sj["direction"] = { sd.x, sd.y, sd.z }; + auto sc = sun.getColor(); + sj["color"] = { sc.r, sc.g, sc.b }; + sj["intensity"] = sun.getIntensity(); + j["sun"] = sj; + } catch( ... ) { + } + + std::ofstream out( filepath ); + if( !out ) { + throw std::runtime_error( "failed to open file for writing" ); + } + out << j.dump( 2 ); + out.close(); + std::cout << "Level saved to " << filepath << std::endl; + } catch( const std::exception& e ) { + std::cerr << "Failed to save level: " << e.what() << std::endl; + } + } + + static int selectedLevel = 0; + static std::vector<std::string> levelFiles; + static bool levelsScanned = false; + + if( !levelsScanned || ImGui::Button( "Refresh Levels" ) ) { + levelFiles.clear(); + std::string levelsDir = "apps/openmb/resources/levels"; + if( std::filesystem::exists( levelsDir ) ) { + for( const auto& entry : std::filesystem::directory_iterator( levelsDir ) ) { + if( entry.path().extension() == ".json" ) { + levelFiles.push_back( entry.path().stem().string() ); + } + } + } + std::sort( levelFiles.begin(), levelFiles.end() ); + levelsScanned = true; + selectedLevel = 0; + } + + if( !levelFiles.empty() ) { + if( ImGui::BeginCombo( "Available Levels", levelFiles[selectedLevel].c_str() ) ) { + for( int i = 0; i < levelFiles.size(); ++i ) { + bool isSelected = ( selectedLevel == i ); + if( ImGui::Selectable( levelFiles[i].c_str(), isSelected ) ) { + selectedLevel = i; + } + if( isSelected ) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if( ImGui::Button( "Load Selected" ) ) { + std::string filepath = + std::string( "apps/openmb/resources/levels/" ) + levelFiles[selectedLevel] + ".json"; + + if( voxelEditor.loadFromFile( filepath ) ) { + std::cout << "Level loaded (voxels) from " << filepath << std::endl; + } else { + std::cerr << "Failed to load level voxels" << std::endl; + } + + paintedCircles.clear(); + try { + std::ifstream in( filepath ); + if( in ) { + nlohmann::json j; + in >> j; + if( j.contains( "paintedCircles" ) && j["paintedCircles"].is_array() ) { + for( const auto& pcj : j["paintedCircles"] ) { + PaintedCircle pc; + pc.mCenter.x = pcj.value( "x", 0.0f ); + pc.mCenter.y = pcj.value( "y", 0.0f ); + pc.mCenter.z = pcj.value( "z", 0.0f ); + pc.mRadius = pcj.value( "radius", 1.0f ); + pc.mTextureId = pcj.value( "textureId", 0 ); + paintedCircles.push_back( pc ); + } + std::cout << "Loaded " << paintedCircles.size() << " painted circles from " << filepath + << std::endl; + } + if( j.contains( "sun" ) && j["sun"].is_object() ) { + try { + const auto& sj = j["sun"]; + if( sj.contains( "direction" ) && sj["direction"].is_array() && + sj["direction"].size() >= 3 ) { + glm::vec3 sd; + sd.x = sj["direction"][0].get<float>(); + sd.y = sj["direction"][1].get<float>(); + sd.z = sj["direction"][2].get<float>(); + sun.setDirection( glm::normalize( sd ) ); + } + if( sj.contains( "color" ) && sj["color"].is_array() && sj["color"].size() >= 3 ) { + glm::vec3 sc; + sc.r = sj["color"][0].get<float>(); + sc.g = sj["color"][1].get<float>(); + sc.b = sj["color"][2].get<float>(); + sun.setColor( sc ); + } + if( sj.contains( "intensity" ) ) + sun.setIntensity( sj["intensity"].get<float>() ); + } catch( ... ) { + } + } + } + } catch( ... ) { + } + } + } else { + ImGui::Text( "No levels found" ); + } + + if( ImGui::Button( "Clear All" ) ) { + voxelEditor.clear(); + } + + ImGui::Separator(); + ImGui::Text( "Cube Texture:" ); + + auto categories = textureManager.getCategories(); + if( !categories.empty() ) { + static int selectedCategory = 0; + static int selectedSubcategory = 0; + static int selectedTexture = 0; + static std::string lastCategory; + static std::string lastSubcategory; + + std::string currentCat = textureManager.getCurrentCategory(); + if( !currentCat.empty() ) { + auto it = std::find( categories.begin(), categories.end(), currentCat ); + if( it != categories.end() ) + selectedCategory = std::distance( categories.begin(), it ); + } + + if( ImGui::BeginCombo( "Category", categories[selectedCategory].c_str() ) ) { + for( int i = 0; i < categories.size(); ++i ) { + bool isSelected = ( selectedCategory == i ); + if( ImGui::Selectable( categories[i].c_str(), isSelected ) ) { + selectedCategory = i; + selectedSubcategory = 0; + selectedTexture = 0; + lastCategory = categories[selectedCategory]; + + auto newSubcats = textureManager.getSubcategories( categories[selectedCategory] ); + if( !newSubcats.empty() ) { + auto newTextures = + textureManager.getTextureNames( categories[selectedCategory], newSubcats[0] ); + if( !newTextures.empty() ) { + textureManager.setCurrentTexture( categories[selectedCategory], newSubcats[0], + newTextures[0] ); + } + } + } + if( isSelected ) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + auto subcategories = textureManager.getSubcategories( categories[selectedCategory] ); + if( !subcategories.empty() ) { + + if( selectedSubcategory >= subcategories.size() ) + selectedSubcategory = 0; + + std::string currentSub = textureManager.getCurrentSubcategory(); + if( !currentSub.empty() && textureManager.getCurrentCategory() == categories[selectedCategory] ) { + auto it = std::find( subcategories.begin(), subcategories.end(), currentSub ); + if( it != subcategories.end() ) + selectedSubcategory = std::distance( subcategories.begin(), it ); + } + + if( ImGui::BeginCombo( "Style", subcategories[selectedSubcategory].c_str() ) ) { + for( int i = 0; i < subcategories.size(); ++i ) { + bool isSelected = ( selectedSubcategory == i ); + if( ImGui::Selectable( subcategories[i].c_str(), isSelected ) ) { + selectedSubcategory = i; + selectedTexture = 0; + lastSubcategory = subcategories[selectedSubcategory]; + + auto newTextures = textureManager.getTextureNames( categories[selectedCategory], + subcategories[selectedSubcategory] ); + if( !newTextures.empty() ) { + textureManager.setCurrentTexture( categories[selectedCategory], + subcategories[selectedSubcategory], + newTextures[0] ); + } + } + if( isSelected ) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + auto textures = textureManager.getTextureNames( categories[selectedCategory], + subcategories[selectedSubcategory] ); + if( !textures.empty() ) { + + if( selectedTexture >= textures.size() ) + selectedTexture = 0; + + std::string currentTex = textureManager.getCurrentTextureName(); + if( !currentTex.empty() && + textureManager.getCurrentCategory() == categories[selectedCategory] && + textureManager.getCurrentSubcategory() == subcategories[selectedSubcategory] ) { + auto it = std::find( textures.begin(), textures.end(), currentTex ); + if( it != textures.end() ) + selectedTexture = std::distance( textures.begin(), it ); + } + + if( ImGui::BeginCombo( "Texture", textures[selectedTexture].c_str() ) ) { + for( int i = 0; i < textures.size(); ++i ) { + bool isSelected = ( selectedTexture == i ); + if( ImGui::Selectable( textures[i].c_str(), isSelected ) ) { + selectedTexture = i; + textureManager.setCurrentTexture( categories[selectedCategory], + subcategories[selectedSubcategory], + textures[selectedTexture] ); + } + if( isSelected ) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + } + } + } + + ImGui::Separator(); + ImGui::Text( "Placement Mode:" ); + + const char* brushLabels[] = { "Brush", "Cube", "Model" }; + int brushIdx = static_cast<int>( placementBrush ); + if( ImGui::Combo( "Mode", &brushIdx, brushLabels, IM_ARRAYSIZE( brushLabels ) ) ) { + placementBrush = static_cast<PlacementBrush>( brushIdx ); + useCircleBrush = ( placementBrush == PlacementBrush::Brush ); + } + + if( placementBrush == PlacementBrush::Brush ) { + ImGui::Text( "Circle Brush:" ); + ImGui::SliderFloat( "Brush Radius (m)", &brushRadius, 0.1f, 20.0f ); + { + float minH = gridSystem.getFloorY(); + float maxH = gridSystem.getFloorY() + gridSystem.getWallHeight() * gridSystem.getCellSize(); + ImGui::SliderFloat( "Brush Height", &brushHeight, minH, maxH ); + } + } else if( placementBrush == PlacementBrush::Model ) { + ImGui::Text( "Model Placement:" ); + if( modelNames.empty() ) { + ImGui::Text( "No models found in resources/models/rocks" ); + } else { + if( selectedModelIndex >= modelNames.size() ) + selectedModelIndex = 0; + if( ImGui::BeginCombo( "Model", modelNames[selectedModelIndex].c_str() ) ) { + for( int i = 0; i < modelNames.size(); ++i ) { + bool sel = ( i == selectedModelIndex ); + if( ImGui::Selectable( modelNames[i].c_str(), sel ) ) + selectedModelIndex = i; + if( sel ) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + ImGui::SliderFloat( "Scale", &selectedModelScale, 0.01f, 2.0f ); + ImGui::SliderFloat( "Yaw (deg)", &selectedModelYaw, -180.0f, 180.0f ); + ImGui::Checkbox( "Place Collidable", &placeCollidable ); + ImGui::Text( "Left-click to place selected model at cursor height" ); + } + } else { + } + ImGui::Separator(); + ImGui::Checkbox( "Enable Lighting", &lightingEnabled ); + + ImGui::Text( "Sun / Directional Light" ); + glm::vec3 sunDir = sun.getDirection(); + float dirVals[3] = { sunDir.x, sunDir.y, sunDir.z }; + if( ImGui::SliderFloat3( "Direction", dirVals, -1.0f, 1.0f ) ) { + glm::vec3 nd = glm::normalize( glm::vec3( dirVals[0], dirVals[1], dirVals[2] ) ); + if( glm::length( nd ) > 0.0f ) + sun.setDirection( nd ); + } + + glm::vec3 sunCol = sun.getColor(); + float colVals[3] = { sunCol.r, sunCol.g, sunCol.b }; + if( ImGui::ColorEdit3( "Color", colVals ) ) { + sun.setColor( glm::vec3( colVals[0], colVals[1], colVals[2] ) ); + } + + float intensity = sun.getIntensity(); + if( ImGui::SliderFloat( "Intensity", &intensity, 0.0f, 5.0f ) ) { + sun.setIntensity( intensity ); + } + + ImGui::Separator(); + ImGui::Text( "Shadows" ); + ImGui::Checkbox( "Snap Shadow Texels", &snapToTexels ); + ImGui::SliderFloat( "Shadow Bias Min", &shadowBiasMinGui, 0.0f, 0.01f, "%.6f" ); + ImGui::SliderFloat( "Shadow Bias Scale", &shadowBiasScaleGui, 0.0f, 0.05f, "%.5f" ); + ImGui::SliderInt( "PCF Radius", &pcfRadiusGui, 0, 4 ); + + ImGui::Separator(); + ImGui::Text( "Fog" ); + float fogColVals[3] = { fogColor.r, fogColor.g, fogColor.b }; + if( ImGui::ColorEdit3( "Fog Color", fogColVals ) ) { + fogColor = glm::vec3( fogColVals[0], fogColVals[1], fogColVals[2] ); + } + ImGui::SliderFloat( "Fog Density", &fogDensity, 0.0f, 0.1f, "%.4f" ); + ImGui::SliderFloat( "Fog Amount", &fogAmount, 0.0f, 1.0f ); + + ImGui::Separator(); + ImGui::Text( "God Rays" ); + ImGui::Checkbox( "Enable God Rays", &godraysEnabled ); + ImGui::SliderFloat( "God Rays Intensity", &godraysIntensity, 0.0f, 2.0f ); + ImGui::SliderInt( "Samples", &godraysSamples, 4, 256 ); + ImGui::SliderFloat( "Density", &godraysDensity, 0.0f, 2.0f ); + ImGui::SliderFloat( "Weight", &godraysWeight, 0.0f, 2.0f ); + ImGui::SliderFloat( "Decay", &godraysDecay, 0.0f, 1.0f ); + ImGui::SliderInt( "Downscale", &godraysDownscale, 1, 8 ); + + if( !lightingEnabled ) { + + texShader.use(); + texShader.setFloat( "dirLight.intensity", 0.0f ); + } + + ImGui::End(); + } + + ImGui::SetNextWindowPos( ImVec2( io.DisplaySize.x - 10.0f, 10.0f ), ImGuiCond_Always, ImVec2( 1.0f, 0.0f ) ); + + ImGui::SetNextWindowSize( ImVec2( 180.0f, 0.0f ), ImGuiCond_Once ); + + ImGuiWindowFlags perfFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoBringToFrontOnFocus; + + ImGui::PushStyleVar( ImGuiStyleVar_WindowRounding, 6.0f ); + ImGui::PushStyleVar( ImGuiStyleVar_WindowPadding, ImVec2( 10, 6 ) ); + if( ImGui::Begin( "Performance", nullptr, perfFlags ) ) { + ImGui::Text( "FPS: %1.0f", fps ); + ImGui::Separator(); + ImGui::Text( "Resolution: %dx%d", fbWidth, fbHeight ); + } + ImGui::End(); + ImGui::PopStyleVar( 2 ); + + bool shift = ( glfwGetKey( window, GLFW_KEY_LEFT_SHIFT ) == GLFW_PRESS ) || + ( glfwGetKey( window, GLFW_KEY_RIGHT_SHIFT ) == GLFW_PRESS ); + camera.setSpeedMultiplier( shift ? 3.0f : 1.0f ); + + if( mouseCaptured ) { + if( glfwGetKey( window, GLFW_KEY_W ) == GLFW_PRESS ) + camera.processKeyboard( scene::Movement::Forward, deltaTime ); + if( glfwGetKey( window, GLFW_KEY_S ) == GLFW_PRESS ) + camera.processKeyboard( scene::Movement::Backward, deltaTime ); + if( glfwGetKey( window, GLFW_KEY_A ) == GLFW_PRESS ) + camera.processKeyboard( scene::Movement::Left, deltaTime ); + if( glfwGetKey( window, GLFW_KEY_D ) == GLFW_PRESS ) + camera.processKeyboard( scene::Movement::Right, deltaTime ); + } + + worldBoxes = voxelEditor.getAllCollisionBoxes( baseWorldBoxes ); + + if( !models.empty() ) { + const auto& placed = voxelEditor.getPlacedModels(); + for( const auto& mi : placed ) { + if( !mi.mCollidable ) + continue; + if( mi.modelIndex < 0 || mi.modelIndex >= static_cast<int>( models.size() ) ) + continue; + renderer::Model* mdl = models[mi.modelIndex].get(); + glm::vec3 bmin = mdl->getBoundsMin(); + glm::vec3 bmax = mdl->getBoundsMax(); + + glm::mat4 modelMat = glm::translate( glm::mat4( 1.0f ), mi.pos ); + modelMat = glm::rotate( modelMat, glm::radians( mi.yaw ), glm::vec3( 0.0f, 1.0f, 0.0f ) ); + modelMat = glm::scale( modelMat, glm::vec3( mi.scale ) ); + + glm::vec3 corners[8]; + corners[0] = glm::vec3( bmin.x, bmin.y, bmin.z ); + corners[1] = glm::vec3( bmax.x, bmin.y, bmin.z ); + corners[2] = glm::vec3( bmin.x, bmax.y, bmin.z ); + corners[3] = glm::vec3( bmin.x, bmin.y, bmax.z ); + corners[4] = glm::vec3( bmax.x, bmax.y, bmin.z ); + corners[5] = glm::vec3( bmax.x, bmin.y, bmax.z ); + corners[6] = glm::vec3( bmin.x, bmax.y, bmax.z ); + corners[7] = glm::vec3( bmax.x, bmax.y, bmax.z ); + + glm::vec3 wmin( FLT_MAX ); + glm::vec3 wmax( -FLT_MAX ); + for( int i = 0; i < 8; ++i ) { + glm::vec4 wc = modelMat * glm::vec4( corners[i], 1.0f ); + wmin = glm::min( wmin, glm::vec3( wc ) ); + wmax = glm::max( wmax, glm::vec3( wc ) ); + } + worldBoxes.emplace_back( wmin, wmax ); + } + } + + camera.updatePhysics( deltaTime, worldBoxes, 0.0f ); + + double xpos, ypos; + glfwGetCursorPos( window, &xpos, &ypos ); + if( firstMouse ) { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } + float xoffset = static_cast<float>( xpos - lastX ); + float yoffset = static_cast<float>( lastY - ypos ); + lastX = xpos; + lastY = ypos; + if( mouseCaptured ) + camera.processMouseMovement( xoffset, yoffset ); + + glm::vec3 sceneCenter( 0.0f, 5.0f, 0.0f ); + float sceneRadius = 50.0f; + for( const auto& c : voxelEditor.getPlacedCells() ) { + glm::mat4 model = glm::translate( glm::mat4( 1.0f ), voxelEditor.cellToWorldCenter( c ) ); + texturedCube.draw(); + } + int fbw = 0, fbh = 0; + glfwGetFramebufferSize( window, &fbw, &fbh ); + glViewport( 0, 0, fbw, fbh ); + glEnable( GL_DEPTH_TEST ); + glClearColor( 0.1f, 0.12f, 0.15f, 1.0f ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + float aspect = ( fbw > 0 && fbh > 0 ) ? (float)fbw / (float)fbh : (float)width / (float)height; + glm::mat4 proj = camera.getProjectionMatrix( aspect ); + glm::mat4 view = camera.getViewMatrix(); + + { + float nearPlane = 1.0f; + float farPlane = 200.0f; + glm::mat4 lightProj = + glm::ortho( -sceneRadius, sceneRadius, -sceneRadius, sceneRadius, nearPlane, farPlane ); + glm::vec3 lightDir = sun.getDirection(); + + glm::vec3 initialLightPos = sceneCenter - lightDir * 50.0f; + glm::mat4 initialLightView = glm::lookAt( initialLightPos, sceneCenter, glm::vec3( 0.0f, 1.0f, 0.0f ) ); + + glm::vec4 centerLS = initialLightView * glm::vec4( sceneCenter, 1.0f ); + + float worldTexelSize = ( 2.0f * sceneRadius ) / static_cast<float>( shadowWidth ); + + if( snapToTexels ) { + centerLS.x = std::floor( centerLS.x / worldTexelSize + 0.5f ) * worldTexelSize; + centerLS.y = std::floor( centerLS.y / worldTexelSize + 0.5f ) * worldTexelSize; + } + + glm::mat4 invInitialLightView = glm::inverse( initialLightView ); + glm::vec4 snappedCenterWorld4 = invInitialLightView * centerLS; + glm::vec3 snappedCenterWorld = glm::vec3( snappedCenterWorld4 ); + + static bool shadeSmoothInit = false; + static glm::vec3 smoothedCenter( 0.0f ); + if( !shadeSmoothInit ) { + smoothedCenter = snappedCenterWorld; + shadeSmoothInit = true; + } + + float smoothAlpha = ( shadowWidth > 4096 ) ? 0.20f : 0.08f; + smoothedCenter = glm::mix( smoothedCenter, snappedCenterWorld, smoothAlpha ); + + glm::vec3 lightPos = smoothedCenter - lightDir * 50.0f; + glm::mat4 lightView = glm::lookAt( lightPos, smoothedCenter, glm::vec3( 0.0f, 1.0f, 0.0f ) ); + glm::mat4 lightSpace = lightProj * lightView; + + dirLightSpace = lightSpace; + + glViewport( 0, 0, shadowWidth, shadowHeight ); + glBindFramebuffer( GL_FRAMEBUFFER, depthMapFBO ); + glClear( GL_DEPTH_BUFFER_BIT ); + if( depthShader.id() != 0 ) { + depthShader.use(); + depthShader.setMat4( "lightSpace", lightSpace ); + + glm::mat4 model = glm::mat4( 1.0f ); + depthShader.setMat4( "model", model ); + grid.draw(); + + for( const auto& c : voxelEditor.getPlacedCells() ) { + glm::mat4 m = glm::translate( glm::mat4( 1.0f ), voxelEditor.cellToWorldCenter( c ) ); + depthShader.setMat4( "model", m ); + texturedCube.draw(); + } + + if( !models.empty() ) { + const auto& placed = voxelEditor.getPlacedModels(); + for( const auto& mi : placed ) { + if( mi.modelIndex < 0 || mi.modelIndex >= static_cast<int>( models.size() ) ) + continue; + renderer::Model* mdl = models[mi.modelIndex].get(); + glm::mat4 modelMat = glm::translate( glm::mat4( 1.0f ), mi.pos ); + modelMat = glm::rotate( modelMat, glm::radians( mi.yaw ), glm::vec3( 0.0f, 1.0f, 0.0f ) ); + modelMat = glm::scale( modelMat, glm::vec3( mi.scale ) ); + + const auto& meshList = mdl->getMeshes(); + for( size_t miIdx = 0; miIdx < meshList.size(); ++miIdx ) { + depthShader.setMat4( "model", modelMat ); + meshList[miIdx]->draw(); + } + } + } + } + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + + { + auto instAfterShadow = Clock::now(); + double shadowMs = std::chrono::duration<double, std::milli>( instAfterShadow - instSegStart ).count(); + instAccumShadow += shadowMs; + + instSegStart = Clock::now(); + } + + glViewport( 0, 0, fbw, fbh ); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, depthMap ); + glActiveTexture( GL_TEXTURE0 ); + + texShader.use(); + texShader.setMat4( "lightSpace", lightSpace ); + + static renderer::SSAORenderer ssaoRenderer; + static bool ssaoInit = false; + if( !ssaoInit ) { + int initW = fbw > 0 ? fbw : width; + int initH = fbh > 0 ? fbh : height; + if( !ssaoRenderer.init( initW, initH, true ) ) + std::cerr << "Warning: failed to init SSAORenderer" << std::endl; + ssaoInit = true; + } + + ssaoRenderer.resize( fbw, fbh ); + + ssaoRenderer.bindGBuffer(); + { + renderer::Shader& gs = ssaoRenderer.getGBufferShader(); + gs.use(); + gs.setMat4( "view", view ); + gs.setMat4( "proj", proj ); + + glm::mat4 gridModel = glm::translate( glm::mat4( 1.0f ), glm::vec3( 0.0f, 0.0f, 0.0f ) ); + gs.setMat4( "model", gridModel ); + grid.draw(); + + for( const auto& c : voxelEditor.getPlacedCells() ) { + glm::mat4 model = glm::translate( glm::mat4( 1.0f ), voxelEditor.cellToWorldCenter( c ) ); + gs.setMat4( "model", model ); + texturedCube.draw(); + } + + if( !models.empty() ) { + const auto& placed = voxelEditor.getPlacedModels(); + for( const auto& mi : placed ) { + if( mi.modelIndex < 0 || mi.modelIndex >= static_cast<int>( models.size() ) ) + continue; + + renderer::Model* mdl = models[mi.modelIndex].get(); + glm::mat4 modelMat = glm::translate( glm::mat4( 1.0f ), mi.pos ); + modelMat = glm::rotate( modelMat, glm::radians( mi.yaw ), glm::vec3( 0.0f, 1.0f, 0.0f ) ); + modelMat = glm::scale( modelMat, glm::vec3( mi.scale ) ); + + const auto& meshList = mdl->getMeshes(); + for( size_t miIdx = 0; miIdx < meshList.size(); ++miIdx ) { + gs.setMat4( "model", modelMat ); + meshList[miIdx]->draw(); + } + } + } + } + ssaoRenderer.unbind(); + + glm::mat4 invProj = glm::inverse( proj ); + float aoRadius = 1.0f; + float aoBias = 0.025f; + float aoPower = 1.0f; + ssaoRenderer.computeSSAO( proj, invProj, aoRadius, aoBias, aoPower ); + ssaoRenderer.blurSSAO(); + + ssaoRenderer.bindSSAOTextureToUnit( 3, texShader, "ssao" ); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, depthMap ); + glActiveTexture( GL_TEXTURE0 ); + + { + auto instAfterSSAO = Clock::now(); + double ssaoMs = std::chrono::duration<double, std::milli>( instAfterSSAO - instSegStart ).count(); + instAccumSSAO += ssaoMs; + + instSegStart = Clock::now(); + } + } + + if( editorActive && !io.WantCaptureMouse ) { + glm::vec2 mouseFb( io.MousePos.x * io.DisplayFramebufferScale.x, + io.MousePos.y * io.DisplayFramebufferScale.y ); + glm::vec3 rayOrigin, rayDir; + renderer::editor::makeRayFromMouse( mouseFb, fbw, fbh, view, proj, camera.position(), rayOrigin, rayDir ); + + lastRayOrigin = rayOrigin; + lastRayDir = rayDir; + + bool leftDown = ( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_LEFT ) == GLFW_PRESS ) || io.MouseDown[0]; + bool rightDown = ( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_RIGHT ) == GLFW_PRESS ) || io.MouseDown[1]; + + if( placementBrush == PlacementBrush::Brush ) { + static bool prevLeftDownLocal = false; + + if( std::abs( rayDir.y ) > 1e-6f ) { + float t = ( brushHeight - rayOrigin.y ) / rayDir.y; + if( t > 0.0f ) { + glm::vec3 centerWorld = rayOrigin + rayDir * t; + + double now = glfwGetTime(); + if( leftDown ) { + if( !prevLeftDownLocal || ( now - lastPaintTime ) >= paintInterval ) { + PaintedCircle pc; + pc.mCenter = centerWorld; + pc.mRadius = brushRadius; + pc.mTextureId = textureManager.getCurrentTextureId(); + paintedCircles.push_back( pc ); + lastPaintTime = now; + } + } else { + } + } + } + + prevLeftDownLocal = leftDown; + } else if( placementBrush == PlacementBrush::Cube ) { + voxelEditor.processInput( rayOrigin, rayDir, leftDown, rightDown, shift, baseWorldBoxes, + textureManager.getCurrentTextureId(), placeCollidable ); + } else if( placementBrush == PlacementBrush::Model ) { + static bool prevLeftDownModel = false; + + if( std::abs( rayDir.y ) > 1e-6f ) { + float t = ( brushHeight - rayOrigin.y ) / rayDir.y; + if( t > 0.0f ) { + glm::vec3 centerWorld = rayOrigin + rayDir * t; + + double now = glfwGetTime(); + if( leftDown ) { + if( !prevLeftDownModel ) { + if( !models.empty() ) { + scene::VoxelEditor::ModelInstance mi; + mi.modelIndex = selectedModelIndex; + mi.pos = centerWorld; + mi.yaw = selectedModelYaw; + mi.scale = selectedModelScale; + mi.mCollidable = placeCollidable; + voxelEditor.addModelInstance( mi ); + } + } + } else { + } + } + } + + prevLeftDownModel = leftDown; + } + } + + glViewport( 0, 0, fbw, fbh ); + + skybox.draw( view, proj ); + + shader.use(); + glm::mat4 lineModel = glm::mat4( 1.0f ); + shader.setMat4( "model", lineModel ); + shader.setMat4( "view", view ); + shader.setMat4( "proj", proj ); + // Provide camera position and fog parameters to simple shader + shader.setVec3( "cameraPos", camera.position() ); + shader.setVec3( "fogColor", fogColor ); + shader.setFloat( "fogDensity", fogDensity ); + shader.setFloat( "fogAmount", fogAmount ); + + glm::mat4 gridModel = glm::translate( glm::mat4( 1.0f ), glm::vec3( 0.0f, 0.0f, 0.0f ) ); + shader.setMat4( "model", gridModel ); + shader.setVec3( "color", glm::vec3( 0.25f, 0.5f, 0.25f ) ); + grid.draw(); + + texShader.use(); + shader.use(); + shader.setMat4( "view", view ); + shader.setMat4( "proj", proj ); + + texShader.use(); + texShader.setMat4( "view", view ); + texShader.setMat4( "proj", proj ); + + // Provide camera position and fog parameters to textured shader + texShader.setVec3( "cameraPos", camera.position() ); + texShader.setVec3( "fogColor", fogColor ); + texShader.setFloat( "fogDensity", fogDensity ); + texShader.setFloat( "fogAmount", fogAmount ); + + texShader.setFloat( "shadowBiasMin", shadowBiasMinGui ); + texShader.setFloat( "shadowBiasScale", shadowBiasScaleGui ); + texShader.setInt( "pcfRadius", pcfRadiusGui ); + + if( lightingEnabled ) + sun.applyToShader( texShader ); + else { + texShader.setVec3( "dirLight.direction", glm::vec3( 0.0f, 1.0f, 0.0f ) ); + texShader.setVec3( "dirLight.color", glm::vec3( 0.0f ) ); + texShader.setFloat( "dirLight.intensity", 0.0f ); + } + + texShader.setMat4( "lightSpace", dirLightSpace ); + texShader.setFloat( "aoStrength", 1.0f ); + texShader.setFloat( "screenWidth", static_cast<float>( fbw ) ); + texShader.setFloat( "screenHeight", static_cast<float>( fbh ) ); + texShader.setVec3( "tint", glm::vec3( 1.0f, 1.0f, 1.0f ) ); + texShader.setInt( "albedo", 0 ); + + for( const auto& c : voxelEditor.getPlacedCells() ) { + int textureId = voxelEditor.getTextureIdForCell( c ); + auto* cellTexture = textureManager.getTextureById( textureId ); + + if( cellTexture ) { + cellTexture->bind( 0 ); + glm::mat4 model = glm::translate( glm::mat4( 1.0f ), voxelEditor.cellToWorldCenter( c ) ); + texShader.setMat4( "model", model ); + texShader.setVec3( "tint", glm::vec3( 1.0f, 1.0f, 1.0f ) ); + + texShader.setInt( "normalEnabled", 0 ); + texturedCube.draw(); + } + } + + if( !models.empty() ) { + texShader.use(); + texShader.setMat4( "view", view ); + texShader.setMat4( "proj", proj ); + texShader.setMat4( "lightSpace", dirLightSpace ); + const auto& placed = voxelEditor.getPlacedModels(); + for( const auto& mi : placed ) { + if( mi.modelIndex < 0 || mi.modelIndex >= static_cast<int>( models.size() ) ) + continue; + + renderer::Model* mdl = models[mi.modelIndex].get(); + glm::mat4 modelMat = glm::translate( glm::mat4( 1.0f ), mi.pos ); + modelMat = glm::rotate( modelMat, glm::radians( mi.yaw ), glm::vec3( 0.0f, 1.0f, 0.0f ) ); + modelMat = glm::scale( modelMat, glm::vec3( mi.scale ) ); + + const auto& meshList = mdl->getMeshes(); + const auto& texList = mdl->getTextures(); + const auto& normalList = mdl->getNormalTextures(); + const auto& meshToTex = mdl->getMeshTextureIndex(); + const auto& meshToNormal = mdl->getMeshNormalIndex(); + + for( size_t miIdx = 0; miIdx < meshList.size(); ++miIdx ) { + texShader.setMat4( "model", modelMat ); + int tidx = -1; + if( miIdx < meshToTex.size() ) + tidx = meshToTex[miIdx]; + bool hasNormal = false; + if( tidx >= 0 && tidx < static_cast<int>( texList.size() ) ) { + texList[tidx].bind( 0 ); + } + int nidx = -1; + if( miIdx < meshToNormal.size() ) + nidx = meshToNormal[miIdx]; + if( nidx >= 0 && nidx < static_cast<int>( normalList.size() ) ) { + normalList[nidx].bind( 1 ); + texShader.setInt( "normalEnabled", 1 ); + hasNormal = true; + } else { + texShader.setInt( "normalEnabled", 0 ); + } + + texShader.setVec3( "tint", glm::vec3( 1.0f, 1.0f, 1.0f ) ); + meshList[miIdx]->draw(); + if( hasNormal ) { + + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, 0 ); + glActiveTexture( GL_TEXTURE0 ); + } + } + } + } + + shader.use(); + + const auto& previewCells = voxelEditor.getPreviewCells(); + if( !previewCells.empty() && placementEditorEnabled ) { + if( previewCells.size() > 1 ) { + glm::ivec3 minC = previewCells.front(); + glm::ivec3 maxC = previewCells.front(); + for( const auto& c : previewCells ) { + minC.x = std::min( minC.x, c.x ); + minC.y = std::min( minC.y, c.y ); + minC.z = std::min( minC.z, c.z ); + maxC.x = std::max( maxC.x, c.x ); + maxC.y = std::max( maxC.y, c.y ); + maxC.z = std::max( maxC.z, c.z ); + } + + glm::vec3 aabbMin = voxelEditor.cellToAABB( minC ).first; + glm::vec3 aabbMax = voxelEditor.cellToAABB( maxC ).second; + + glm::vec3 center = ( aabbMin + aabbMax ) * 0.5f; + glm::vec3 size = aabbMax - aabbMin; + + glm::vec3 scaleVec = size / tileSize; + + glm::mat4 model = + glm::translate( glm::mat4( 1.0f ), center ) * glm::scale( glm::mat4( 1.0f ), scaleVec ); + + shader.setVec3( "color", glm::vec3( 0.2f, 0.9f, 0.9f ) ); + shader.setMat4( "model", model ); + wireCube.draw(); + } else { + const float previewScale = 0.995f; + glm::mat4 scaleMat = glm::scale( glm::mat4( 1.0f ), glm::vec3( previewScale ) ); + + shader.setVec3( "color", glm::vec3( 0.2f, 0.9f, 0.9f ) ); + + for( const auto& c : previewCells ) { + glm::mat4 model = glm::translate( glm::mat4( 1.0f ), voxelEditor.cellToWorldCenter( c ) ); + model = model * scaleMat; + shader.setMat4( "model", model ); + wireCube.draw(); + } + } + } + + if( useCircleBrush && editorActive ) { + if( std::abs( brushRadius - prevBrushRadius ) > 1e-6f ) { + circleWire = renderer::editor::makeCircleWire( brushRadius, 64 ); + prevBrushRadius = brushRadius; + } + + if( std::abs( lastRayDir.y ) > 1e-6f ) { + float t = ( brushHeight - lastRayOrigin.y ) / lastRayDir.y; + if( t > 0.0f ) { + glm::vec3 centerWorld = lastRayOrigin + lastRayDir * t; + + const float previewOffset = 0.01f; + glm::mat4 model = glm::translate( + glm::mat4( 1.0f ), glm::vec3( centerWorld.x, brushHeight + previewOffset, centerWorld.z ) ); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glDepthMask( GL_FALSE ); + texShader.use(); + texShader.setMat4( "view", view ); + texShader.setMat4( "proj", proj ); + if( lightingEnabled ) + sun.applyToShader( texShader ); + else + texShader.setFloat( "dirLight.intensity", 0.0f ); + texShader.setMat4( "lightSpace", dirLightSpace ); + texShader.setMat4( "model", glm::scale( model, glm::vec3( brushRadius, 1.0f, brushRadius ) ) ); + texShader.setVec3( "tint", glm::vec3( 1.0f, 1.0f, 1.0f ) ); + + auto* previewTex = textureManager.getTextureById( textureManager.getCurrentTextureId() ); + if( previewTex ) + previewTex->bind( 0 ); + + texShader.setInt( "radialEnabled", 1 ); + texShader.setFloat( "radialInner", 0.38f ); + texShader.setFloat( "radialOuter", 0.5f ); + filledCircle.draw(); + + texShader.setInt( "radialEnabled", 0 ); + glDepthMask( GL_TRUE ); + glDisable( GL_BLEND ); + + shader.setVec3( "color", glm::vec3( 0.0f, 0.5f, 1.0f ) ); + shader.setMat4( "model", model ); + glLineWidth( 2.5f ); + circleWire.draw(); + glLineWidth( 1.0f ); + } + } + } + + if( !paintedCircles.empty() ) { + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + texShader.use(); + texShader.setMat4( "view", view ); + texShader.setMat4( "proj", proj ); + if( lightingEnabled ) + sun.applyToShader( texShader ); + else + texShader.setFloat( "dirLight.intensity", 0.0f ); + + texShader.setInt( "radialEnabled", 1 ); + texShader.setFloat( "radialInner", 0.38f ); + texShader.setFloat( "radialOuter", 0.5f ); + + std::vector<std::pair<float, size_t>> distIndex; + distIndex.reserve( paintedCircles.size() ); + for( size_t i = 0; i < paintedCircles.size(); ++i ) { + const auto& pc = paintedCircles[i]; + float d2 = glm::length( camera.position() - pc.mCenter ); + distIndex.emplace_back( d2, i ); + } + std::sort( distIndex.begin(), distIndex.end(), + [] ( const auto& a, const auto& b ) { return a.first > b.first; } ); + + glDepthMask( GL_FALSE ); + for( const auto& di : distIndex ) { + const auto& pc = paintedCircles[di.second]; + auto* tex = textureManager.getTextureById( pc.mTextureId ); + if( !tex ) + continue; + tex->bind( 0 ); + glm::mat4 model = + glm::translate( glm::mat4( 1.0f ), glm::vec3( pc.mCenter.x, pc.mCenter.y + 0.02f, pc.mCenter.z ) ); + model = glm::scale( model, glm::vec3( pc.mRadius, 1.0f, pc.mRadius ) ); + texShader.setMat4( "model", model ); + texShader.setVec3( "tint", glm::vec3( 1.0f, 1.0f, 1.0f ) ); + filledCircle.draw(); + } + + glDepthMask( GL_TRUE ); + + texShader.setInt( "radialEnabled", 0 ); + + glDisable( GL_BLEND ); + } + + { + auto instAfterDraw = Clock::now(); + double drawMs = std::chrono::duration<double, std::milli>( instAfterDraw - instSegStart ).count(); + instAccumDraw += drawMs; + + instSegStart = Clock::now(); + } + + // --- Occlusion pass for god rays --- + { + int occW = std::max( 1, fbw / godraysDownscale ); + int occH = std::max( 1, fbh / godraysDownscale ); + if( occlusionW != occW || occlusionH != occH ) { + occlusionW = occW; + occlusionH = occH; + + glBindTexture( GL_TEXTURE_2D, occlusionTex ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, occlusionW, occlusionH, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + if( occlusionDepthRBO == 0 ) + glGenRenderbuffers( 1, &occlusionDepthRBO ); + glBindRenderbuffer( GL_RENDERBUFFER, occlusionDepthRBO ); + glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, occlusionW, occlusionH ); + + glBindFramebuffer( GL_FRAMEBUFFER, occlusionFBO ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, occlusionTex, 0 ); + glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, occlusionDepthRBO ); + GLenum drawbuf = GL_COLOR_ATTACHMENT0; + glDrawBuffers( 1, &drawbuf ); + if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) { + std::cerr << "Warning: occlusion framebuffer not complete" << std::endl; + } + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + } + + // Render occluders to low-res occlusion texture + glViewport( 0, 0, occlusionW, occlusionH ); + glBindFramebuffer( GL_FRAMEBUFFER, occlusionFBO ); + glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glEnable( GL_DEPTH_TEST ); + + occlusionShader.use(); + occlusionShader.setMat4( "view", view ); + occlusionShader.setMat4( "proj", proj ); + + // draw grid + { + glm::mat4 model = glm::mat4( 1.0f ); + occlusionShader.setMat4( "model", model ); + grid.draw(); + } + + // draw voxel cells + for( const auto& c : voxelEditor.getPlacedCells() ) { + glm::mat4 model = glm::translate( glm::mat4( 1.0f ), voxelEditor.cellToWorldCenter( c ) ); + occlusionShader.setMat4( "model", model ); + texturedCube.draw(); + } + + // draw placed models + if( !models.empty() ) { + const auto& placed = voxelEditor.getPlacedModels(); + for( const auto& mi : placed ) { + if( mi.modelIndex < 0 || mi.modelIndex >= static_cast<int>( models.size() ) ) + continue; + renderer::Model* mdl = models[mi.modelIndex].get(); + glm::mat4 modelMat = glm::translate( glm::mat4( 1.0f ), mi.pos ); + modelMat = glm::rotate( modelMat, glm::radians( mi.yaw ), glm::vec3( 0.0f, 1.0f, 0.0f ) ); + modelMat = glm::scale( modelMat, glm::vec3( mi.scale ) ); + + const auto& meshList = mdl->getMeshes(); + for( size_t miIdx = 0; miIdx < meshList.size(); ++miIdx ) { + occlusionShader.setMat4( "model", modelMat ); + meshList[miIdx]->draw(); + } + } + } + + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + glViewport( 0, 0, fbw, fbh ); + + // Compute light screen position + glm::vec3 lightWorldPos = sceneCenter - sun.getDirection() * 50.0f; + glm::vec4 clip = proj * view * glm::vec4( lightWorldPos, 1.0f ); + glm::vec3 ndc = glm::vec3( clip ) / clip.w; + glm::vec2 lightScreen = glm::vec2( ndc.x, ndc.y ) * 0.5f + glm::vec2( 0.5f ); + + // Composite god rays using alpha so it's less likely to blow out the scene + glEnable( GL_BLEND ); + glBlendFuncSeparate( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); + glDisable( GL_DEPTH_TEST ); + + if( godraysEnabled ) { + godraysShader.use(); + godraysShader.setInt( "occlusionTex", 4 ); + godraysShader.setVec2( "lightScreenPos", lightScreen ); + godraysShader.setVec3( "sunColor", sun.getColor() ); + godraysShader.setFloat( "sunIntensity", sun.getIntensity() ); + godraysShader.setFloat( "globalIntensity", godraysIntensity ); + godraysShader.setInt( "samples", godraysSamples ); + godraysShader.setFloat( "density", godraysDensity ); + godraysShader.setFloat( "weight", godraysWeight ); + godraysShader.setFloat( "decay", godraysDecay ); + + glActiveTexture( GL_TEXTURE4 ); + glBindTexture( GL_TEXTURE_2D, occlusionTex ); + glActiveTexture( GL_TEXTURE0 ); + + quadMesh.draw(); + } + + glActiveTexture( GL_TEXTURE4 ); + glBindTexture( GL_TEXTURE_2D, occlusionTex ); + glActiveTexture( GL_TEXTURE0 ); + + quadMesh.draw(); + + glDisable( GL_BLEND ); + glEnable( GL_DEPTH_TEST ); + } + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData( ImGui::GetDrawData() ); + + { + auto instAfterUI = Clock::now(); + double uiMs = std::chrono::duration<double, std::milli>( instAfterUI - instSegStart ).count(); + instAccumUI += uiMs; + + auto instFrameEnd = Clock::now(); + double frameMs = std::chrono::duration<double, std::milli>( instFrameEnd - instFrameStart ).count(); + instAccumFrame += frameMs; + ++instFrames; + + if( std::chrono::duration<double>( instFrameEnd - instLastReport ).count() >= 1.0 ) { + double avgShadow = instAccumShadow / double( instFrames ); + double avgSSAO = instAccumSSAO / double( instFrames ); + double avgDraw = instAccumDraw / double( instFrames ); + double avgUI = instAccumUI / double( instFrames ); + double avgFrame = instAccumFrame / double( instFrames ); + std::cout << "[TIMING] frames=" << instFrames << " frame(ms)=" << avgFrame << " shadow=" << avgShadow + << " ssao=" << avgSSAO << " draw=" << avgDraw << " ui=" << avgUI << std::endl; + + instLastReport = instFrameEnd; + instAccumShadow = 0.0; + instAccumSSAO = 0.0; + instAccumDraw = 0.0; + instAccumUI = 0.0; + instAccumFrame = 0.0; + instFrames = 0; + } + } + + glfwSwapBuffers( window ); + glfwPollEvents(); + } + + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow( window ); + glfwTerminate(); + + return 0; +} diff --git a/apps/openmb/renderer/DirectionalLight.cpp b/apps/openmb/renderer/DirectionalLight.cpp new file mode 100644 index 0000000..28fe281 --- /dev/null +++ b/apps/openmb/renderer/DirectionalLight.cpp @@ -0,0 +1,39 @@ +#include "DirectionalLight.hpp" + +namespace renderer { +DirectionalLight::DirectionalLight () + : mDirection( 0.3f, 1.0f, 0.5f ), mColor( 1.0f, 1.0f, 1.0f ), mIntensity( 1.0f ) { +} + +void DirectionalLight::setDirection ( const glm::vec3& dir ) { + mDirection = dir; +} + +void DirectionalLight::setColor ( const glm::vec3& c ) { + mColor = c; +} + +void DirectionalLight::setIntensity ( float i ) { + mIntensity = i; +} + +const glm::vec3& DirectionalLight::getDirection () const { + return mDirection; +} + +const glm::vec3& DirectionalLight::getColor () const { + return mColor; +} + +float DirectionalLight::getIntensity () const { + return mIntensity; +} + +void DirectionalLight::applyToShader ( const Shader& shader, const std::string& uniformName ) const { + + shader.setVec3( uniformName + ".direction", mDirection ); + shader.setVec3( uniformName + ".color", mColor ); + shader.setFloat( uniformName + ".intensity", mIntensity ); +} + +} // namespace renderer diff --git a/apps/openmb/renderer/DirectionalLight.hpp b/apps/openmb/renderer/DirectionalLight.hpp new file mode 100644 index 0000000..31e914e --- /dev/null +++ b/apps/openmb/renderer/DirectionalLight.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "Shader.hpp" +#include <glm/glm.hpp> + +namespace renderer { + +class DirectionalLight { + public: + DirectionalLight(); + + void setDirection( const glm::vec3& dir ); + void setColor( const glm::vec3& c ); + void setIntensity( float i ); + + const glm::vec3& getDirection() const; + const glm::vec3& getColor() const; + float getIntensity() const; + + void applyToShader( const Shader& shader, const std::string& uniformName = "dirLight" ) const; + + private: + glm::vec3 mDirection; + glm::vec3 mColor; + float mIntensity; +}; + +} // namespace renderer diff --git a/apps/openmb/renderer/EditorHelpers.cpp b/apps/openmb/renderer/EditorHelpers.cpp new file mode 100644 index 0000000..9531fb0 --- /dev/null +++ b/apps/openmb/renderer/EditorHelpers.cpp @@ -0,0 +1,148 @@ +#include "EditorHelpers.hpp" +#include <cmath> + +#include <glm/gtc/matrix_inverse.hpp> +#include <vector> + +namespace renderer { +namespace editor { +Mesh makeWireCube ( float size ) { + float h = size * 0.5f; + std::vector<float> verts = { + -h, -h, -h, h, -h, -h, h, -h, -h, h, -h, h, h, -h, h, -h, -h, h, -h, -h, h, -h, -h, -h, + + -h, h, -h, h, h, -h, h, h, -h, h, h, h, h, h, h, -h, h, h, -h, h, h, -h, h, -h, + + -h, -h, -h, -h, h, -h, h, -h, -h, h, h, -h, h, -h, h, h, h, h, -h, -h, h, -h, h, h }; + + Mesh m; + m.createFromPositions( verts, true ); + return m; +} + +Mesh makeCircleWire ( float radius, int segments ) { + if( segments < 3 ) + segments = 3; + + std::vector<float> verts; + verts.reserve( segments * 3 ); + + const float twoPi = 6.28318530717958647692f; + + for( int i = 0; i < segments; ++i ) { + int ni = ( i + 1 ) % segments; + float ti = (float)i / (float)segments; + float angi = ti * twoPi; + float xi = cosf( angi ) * radius; + float zi = sinf( angi ) * radius; + + float tni = (float)ni / (float)segments; + float angni = tni * twoPi; + float xni = cosf( angni ) * radius; + float zni = sinf( angni ) * radius; + + verts.push_back( xi ); + verts.push_back( 0.0f ); + verts.push_back( zi ); + + verts.push_back( xni ); + verts.push_back( 0.0f ); + verts.push_back( zni ); + } + + Mesh m; + m.createFromPositions( verts, true ); + return m; +} + +Mesh makeCircleFilled ( float radius, int segments ) { + if( segments < 3 ) + segments = 3; + + std::vector<float> data; + data.reserve( ( segments + 2 ) * 5 ); + + const float twoPi = 6.28318530717958647692f; + + float cx = 0.0f, cz = 0.0f; + float cu = 0.5f, cv = 0.5f; + + for( int i = 0; i < segments; ++i ) { + int i1 = i; + int i2 = ( i + 1 ) % segments; + + float t1 = (float)i1 / (float)segments; + float ang1 = t1 * twoPi; + float x1 = cosf( ang1 ) * radius; + float z1 = sinf( ang1 ) * radius; + float u1 = ( x1 / ( radius * 2.0f ) ) + 0.5f; + float v1 = ( z1 / ( radius * 2.0f ) ) + 0.5f; + + float t2 = (float)i2 / (float)segments; + float ang2 = t2 * twoPi; + float x2 = cosf( ang2 ) * radius; + float z2 = sinf( ang2 ) * radius; + float u2 = ( x2 / ( radius * 2.0f ) ) + 0.5f; + float v2 = ( z2 / ( radius * 2.0f ) ) + 0.5f; + + data.push_back( cx ); + data.push_back( 0.0f ); + data.push_back( cz ); + data.push_back( cu ); + data.push_back( cv ); + + data.push_back( x1 ); + data.push_back( 0.0f ); + data.push_back( z1 ); + data.push_back( u1 ); + data.push_back( v1 ); + + data.push_back( x2 ); + data.push_back( 0.0f ); + data.push_back( z2 ); + data.push_back( u2 ); + data.push_back( v2 ); + } + + Mesh m; + m.createFromPosTex( data ); + return m; +} + +bool makeRayFromMouse ( const glm::vec2& mousePx, int fbw, int fbh, const glm::mat4& view, + const glm::mat4& proj, const glm::vec3& camPos, glm::vec3& outOrigin, + glm::vec3& outDir ) { + if( fbw <= 0 || fbh <= 0 ) + return false; + + float ndcX = ( mousePx.x / (float)fbw ) * 2.0f - 1.0f; + float ndcY = 1.0f - ( mousePx.y / (float)fbh ) * 2.0f; + + glm::vec4 nearPointNDC( ndcX, ndcY, -1.0f, 1.0f ); + glm::vec4 farPointNDC( ndcX, ndcY, 1.0f, 1.0f ); + + glm::mat4 invPV = glm::inverse( proj * view ); + + glm::vec4 nearWorld = invPV * nearPointNDC; + glm::vec4 farWorld = invPV * farPointNDC; + if( nearWorld.w == 0.0f || farWorld.w == 0.0f ) + return false; + + nearWorld /= nearWorld.w; + farWorld /= farWorld.w; + + glm::vec3 nearPos = glm::vec3( nearWorld ); + glm::vec3 farPos = glm::vec3( farWorld ); + + outOrigin = nearPos; + outDir = glm::normalize( farPos - nearPos ); + + if( !isfinite( outDir.x ) || !isfinite( outDir.y ) || !isfinite( outDir.z ) ) { + outOrigin = camPos; + outDir = glm::normalize( glm::vec3( 0.0f, 0.0f, -1.0f ) ); + } + + return true; +} +} // namespace editor +} // namespace renderer diff --git a/apps/openmb/renderer/EditorHelpers.hpp b/apps/openmb/renderer/EditorHelpers.hpp new file mode 100644 index 0000000..8156675 --- /dev/null +++ b/apps/openmb/renderer/EditorHelpers.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "Mesh.hpp" +#include <glm/glm.hpp> + +namespace renderer { +namespace editor { + +Mesh makeWireCube ( float size = 1.0f ); + +Mesh makeCircleWire ( float radius = 1.0f, int segments = 64 ); + +Mesh makeCircleFilled ( float radius = 1.0f, int segments = 64 ); + +bool makeRayFromMouse ( const glm::vec2& mousePx, int fbw, int fbh, + const glm::mat4& view, const glm::mat4& proj, + const glm::vec3& camPos, glm::vec3& outOrigin, + glm::vec3& outDir ); +} // namespace editor +} // namespace renderer diff --git a/apps/openmb/renderer/GLHelpers.cpp b/apps/openmb/renderer/GLHelpers.cpp new file mode 100644 index 0000000..892fec0 --- /dev/null +++ b/apps/openmb/renderer/GLHelpers.cpp @@ -0,0 +1,30 @@ +#include "GLHelpers.hpp" + +#include <iostream> + +namespace renderer { +static void glDebugOutput ( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, + const GLchar* message, const void* userParam ) { + (void)source; + (void)type; + (void)id; + (void)severity; + (void)length; + (void)userParam; + + std::cerr << "GL Debug: " << message << std::endl; +} + +bool initGL () { + + glEnable( GL_DEPTH_TEST ); + glDepthFunc( GL_LESS ); + + setupDebugCallback(); + + return true; +} + +void setupDebugCallback () {} + +} // namespace renderer diff --git a/apps/openmb/renderer/GLHelpers.hpp b/apps/openmb/renderer/GLHelpers.hpp new file mode 100644 index 0000000..a566f51 --- /dev/null +++ b/apps/openmb/renderer/GLHelpers.hpp @@ -0,0 +1,14 @@ +#pragma once + +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif + +namespace renderer { + +bool initGL(); + +void setupDebugCallback(); +} // namespace renderer diff --git a/apps/openmb/renderer/Mesh.cpp b/apps/openmb/renderer/Mesh.cpp new file mode 100644 index 0000000..4fb34ee --- /dev/null +++ b/apps/openmb/renderer/Mesh.cpp @@ -0,0 +1,147 @@ +#include "Mesh.hpp" + +namespace renderer { +Mesh::Mesh () : mVAO( 0 ), mVBO( 0 ), mEBO( 0 ), mVertexCount( 0 ), mIndexCount( 0 ), mMode( GL_TRIANGLES ) {} + +Mesh::~Mesh () { + if( mVBO ) { + glDeleteBuffers( 1, &mVBO ); + } + if( mEBO ) { + glDeleteBuffers( 1, &mEBO ); + } + if( mVAO ) { + glDeleteVertexArrays( 1, &mVAO ); + } +} + +bool Mesh::createFromPositions ( const std::vector<float>& positions, bool lines ) { + if( positions.empty() ) { + return false; + } + + mMode = lines ? GL_LINES : GL_TRIANGLES; + mVertexCount = static_cast<GLsizei>( positions.size() / 3 ); + + glGenVertexArrays( 1, &mVAO ); + glGenBuffers( 1, &mVBO ); + + glBindVertexArray( mVAO ); + glBindBuffer( GL_ARRAY_BUFFER, mVBO ); + glBufferData( GL_ARRAY_BUFFER, positions.size() * sizeof( float ), positions.data(), GL_STATIC_DRAW ); + + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ), (void*)0 ); + + glBindVertexArray( 0 ); + + return true; +} + +bool Mesh::createFromPosTex ( const std::vector<float>& data ) { + if( data.empty() ) + return false; + + const size_t strideFloats = 5; + mMode = GL_TRIANGLES; + mVertexCount = static_cast<GLsizei>( data.size() / strideFloats ); + + glGenVertexArrays( 1, &mVAO ); + glGenBuffers( 1, &mVBO ); + + glBindVertexArray( mVAO ); + glBindBuffer( GL_ARRAY_BUFFER, mVBO ); + glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof( float ), data.data(), GL_STATIC_DRAW ); + + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), (void*)0 ); + + glEnableVertexAttribArray( 1 ); + glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), + (void*)( 3 * sizeof( float ) ) ); + + glBindVertexArray( 0 ); + return true; +} + +bool Mesh::createFromPosTexNormal ( const std::vector<float>& data ) { + if( data.empty() ) + return false; + + const size_t strideFloats = 8; + mMode = GL_TRIANGLES; + mVertexCount = static_cast<GLsizei>( data.size() / strideFloats ); + + glGenVertexArrays( 1, &mVAO ); + glGenBuffers( 1, &mVBO ); + + glBindVertexArray( mVAO ); + glBindBuffer( GL_ARRAY_BUFFER, mVBO ); + glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof( float ), data.data(), GL_STATIC_DRAW ); + + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), (void*)0 ); + + glEnableVertexAttribArray( 1 ); + glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), + (void*)( 3 * sizeof( float ) ) ); + + glEnableVertexAttribArray( 2 ); + glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), + (void*)( 5 * sizeof( float ) ) ); + + glBindVertexArray( 0 ); + return true; +} + +bool Mesh::createFromPosTexNormalIndexed ( const std::vector<float>& data, + const std::vector<unsigned int>& indices ) { + if( data.empty() || indices.empty() ) + return false; + + const size_t strideFloats = 8; + mMode = GL_TRIANGLES; + mVertexCount = static_cast<GLsizei>( data.size() / strideFloats ); + mIndexCount = static_cast<GLsizei>( indices.size() ); + + glGenVertexArrays( 1, &mVAO ); + glGenBuffers( 1, &mVBO ); + glGenBuffers( 1, &mEBO ); + + glBindVertexArray( mVAO ); + glBindBuffer( GL_ARRAY_BUFFER, mVBO ); + glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof( float ), data.data(), GL_STATIC_DRAW ); + + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mEBO ); + glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof( unsigned int ), indices.data(), + GL_STATIC_DRAW ); + + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), (void*)0 ); + + glEnableVertexAttribArray( 1 ); + glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), + (void*)( 3 * sizeof( float ) ) ); + + glEnableVertexAttribArray( 2 ); + glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, strideFloats * sizeof( float ), + (void*)( 5 * sizeof( float ) ) ); + + glBindVertexArray( 0 ); + return true; +} + +void Mesh::draw () const { + if( mVAO == 0 ) + return; + + glBindVertexArray( mVAO ); + if( mEBO && mIndexCount > 0 ) { + glDrawElements( mMode, mIndexCount, GL_UNSIGNED_INT, 0 ); + } else { + glDrawArrays( mMode, 0, mVertexCount ); + } + glBindVertexArray( 0 ); +} + +} // namespace renderer diff --git a/apps/openmb/renderer/Mesh.hpp b/apps/openmb/renderer/Mesh.hpp new file mode 100644 index 0000000..de0a8fa --- /dev/null +++ b/apps/openmb/renderer/Mesh.hpp @@ -0,0 +1,41 @@ +#pragma once + +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#else +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif +#endif +#include <vector> + +namespace renderer +{ + class Mesh + { + public: + Mesh(); + ~Mesh(); + + bool createFromPositions( const std::vector< float > &positions, bool lines = false ); + + bool createFromPosTex( const std::vector< float > &data ); + + bool createFromPosTexNormal( const std::vector< float > &data ); + bool createFromPosTexNormalIndexed( const std::vector< float > &data, + const std::vector< unsigned int > &indices ); + + void draw() const; + + private: + GLuint mVAO; + GLuint mVBO; + GLuint mEBO; + GLsizei mVertexCount; + GLsizei mIndexCount; + GLenum mMode; + }; + +} // namespace renderer diff --git a/apps/openmb/renderer/Model.cpp b/apps/openmb/renderer/Model.cpp new file mode 100644 index 0000000..d183bbc --- /dev/null +++ b/apps/openmb/renderer/Model.cpp @@ -0,0 +1,227 @@ +#include "Model.hpp" + +#include <algorithm> +#include <assimp/Importer.hpp> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <cctype> +#include <cfloat> +#include <filesystem> +#include <glm/glm.hpp> +#include <iostream> + +namespace renderer +{ + Model::Model() {} + + static glm::vec3 vecMin( const glm::vec3 &a, const glm::vec3 &b ) + { + return glm::vec3( std::min( a.x, b.x ), std::min( a.y, b.y ), std::min( a.z, b.z ) ); + } + + static glm::vec3 vecMax( const glm::vec3 &a, const glm::vec3 &b ) + { + return glm::vec3( std::max( a.x, b.x ), std::max( a.y, b.y ), std::max( a.z, b.z ) ); + } + + bool Model::loadFromFile( const std::string &path ) + { + Assimp::Importer importer; + const aiScene *scene = + importer.ReadFile( path, aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_ImproveCacheLocality | + aiProcess_JoinIdenticalVertices ); + if ( !scene || !scene->mRootNode ) + { + std::cerr << "Failed to load model: " << path << " (" << importer.GetErrorString() << ")" << std::endl; + return false; + } + + std::filesystem::path p( path ); + std::string baseDir = p.parent_path().string(); + + mMeshes.clear(); + mTextures.clear(); + mNormalTextures.clear(); + mMeshToTex.clear(); + mMeshToNormal.clear(); + mFallbackAlbedoIndex = -1; + mFallbackNormalIndex = -1; + mBoundsMin = glm::vec3( FLT_MAX ); + mBoundsMax = glm::vec3( -FLT_MAX ); + + if ( std::filesystem::exists( baseDir ) && std::filesystem::is_directory( baseDir ) ) + { + for ( const auto &e : std::filesystem::directory_iterator( baseDir ) ) + { + if ( !e.is_regular_file() ) + continue; + auto ext = e.path().extension().string(); + std::string extLower = ext; + std::transform( extLower.begin(), extLower.end(), extLower.begin(), + []( unsigned char c ) { return std::tolower( c ); } ); + if ( extLower != ".png" && extLower != ".jpg" && extLower != ".jpeg" && extLower != ".tga" ) + continue; + + std::string fname = e.path().filename().string(); + std::string fnameLower = fname; + std::transform( fnameLower.begin(), fnameLower.end(), fnameLower.begin(), + []( unsigned char c ) { return std::tolower( c ); } ); + + if ( fnameLower.find( "base" ) != std::string::npos || + fnameLower.find( "albedo" ) != std::string::npos || + fnameLower.find( "diff" ) != std::string::npos ) + { + Texture t; + if ( t.loadFromFile( e.path().string() ) ) + { + mFallbackAlbedoIndex = static_cast< int >( mTextures.size() ); + mTextures.push_back( std::move( t ) ); + std::cerr << "Model: found fallback albedo: " << e.path().string() << " (index " + << mFallbackAlbedoIndex << ")\n"; + } + } + else if ( fnameLower.find( "normal" ) != std::string::npos || + fnameLower.find( "nrm" ) != std::string::npos || + fnameLower.find( "bump" ) != std::string::npos ) + { + Texture tn; + if ( tn.loadFromFile( e.path().string() ) ) + { + mFallbackNormalIndex = static_cast< int >( mNormalTextures.size() ); + mNormalTextures.push_back( std::move( tn ) ); + std::cerr << "Model: found fallback normal: " << e.path().string() << " (index " + << mFallbackNormalIndex << ")\n"; + } + } + } + } + + return processNode( scene->mRootNode, scene, baseDir ); + } + + bool Model::processNode( aiNode *node, const aiScene *scene, const std::string &baseDir ) + { + for ( unsigned int i = 0; i < node->mNumMeshes; ++i ) + { + aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; + int texIndex = -1; + int normalIndex = -1; + if ( !processMesh( mesh, scene, baseDir, texIndex, normalIndex ) ) + return false; + + if ( texIndex == -1 && mFallbackAlbedoIndex != -1 ) + texIndex = mFallbackAlbedoIndex; + if ( normalIndex == -1 && mFallbackNormalIndex != -1 ) + normalIndex = mFallbackNormalIndex; + mMeshToTex.push_back( texIndex ); + mMeshToNormal.push_back( normalIndex ); + std::cerr << "Model: mesh " << i << " -> albedo index " << texIndex << ", normal index " << normalIndex + << "\n"; + } + + for ( unsigned int i = 0; i < node->mNumChildren; ++i ) + { + if ( !processNode( node->mChildren[i], scene, baseDir ) ) + return false; + } + + return true; + } + + bool Model::processMesh( aiMesh *mesh, const aiScene *scene, const std::string &baseDir, int &outTexIndex, + int &outNormalIndex ) + { + std::vector< float > data; + data.reserve( mesh->mNumFaces * 3 * 8 ); + + glm::vec3 localMin( FLT_MAX ); + glm::vec3 localMax( -FLT_MAX ); + + for ( unsigned int f = 0; f < mesh->mNumFaces; ++f ) + { + aiFace &face = mesh->mFaces[f]; + for ( unsigned int vi = 0; vi < face.mNumIndices; ++vi ) + { + unsigned int idx = face.mIndices[vi]; + aiVector3D pos = mesh->mVertices[idx]; + aiVector3D normal = mesh->HasNormals() ? mesh->mNormals[idx] : aiVector3D( 0.0f, 1.0f, 0.0f ); + aiVector3D texcoord = + mesh->HasTextureCoords( 0 ) ? mesh->mTextureCoords[0][idx] : aiVector3D( 0.0f, 0.0f, 0.0f ); + + data.push_back( pos.x ); + data.push_back( pos.y ); + data.push_back( pos.z ); + + data.push_back( texcoord.x ); + data.push_back( texcoord.y ); + + data.push_back( normal.x ); + data.push_back( normal.y ); + data.push_back( normal.z ); + } + } + + for ( size_t i = 0; i + 7 < data.size(); i += 8 ) + { + glm::vec3 p( data[i + 0], data[i + 1], data[i + 2] ); + localMin = vecMin( localMin, p ); + localMax = vecMax( localMax, p ); + } + if ( localMin.x <= localMax.x ) + { + mBoundsMin = vecMin( mBoundsMin, localMin ); + mBoundsMax = vecMax( mBoundsMax, localMax ); + } + auto m = std::make_unique< Mesh >(); + if ( !m->createFromPosTexNormal( data ) ) + { + std::cerr << "Failed to create mesh for model" << std::endl; + return false; + } + + mMeshes.push_back( std::move( m ) ); + + outTexIndex = -1; + outNormalIndex = -1; + if ( mesh->mMaterialIndex >= 0 && scene->mMaterials && mesh->mMaterialIndex < scene->mNumMaterials ) + { + aiMaterial *mat = scene->mMaterials[mesh->mMaterialIndex]; + aiString texPath; + if ( AI_SUCCESS == mat->GetTexture( aiTextureType_DIFFUSE, 0, &texPath ) ) + { + std::string texStr = texPath.C_Str(); + std::filesystem::path full = std::filesystem::path( baseDir ) / texStr; + Texture t; + if ( t.loadFromFile( full.string() ) ) + { + outTexIndex = static_cast< int >( mTextures.size() ); + mTextures.push_back( std::move( t ) ); + } + else + { + std::cerr << "Warning: failed to load texture: " << full.string() << std::endl; + } + } + + if ( AI_SUCCESS == mat->GetTexture( aiTextureType_NORMALS, 0, &texPath ) || + AI_SUCCESS == mat->GetTexture( aiTextureType_HEIGHT, 0, &texPath ) ) + { + std::string texStrN = texPath.C_Str(); + std::filesystem::path fullN = std::filesystem::path( baseDir ) / texStrN; + Texture tn; + if ( tn.loadFromFile( fullN.string() ) ) + { + outNormalIndex = static_cast< int >( mNormalTextures.size() ); + mNormalTextures.push_back( std::move( tn ) ); + } + else + { + std::cerr << "Warning: failed to load normal map: " << fullN.string() << std::endl; + } + } + } + + return true; + } + +} // namespace renderer diff --git a/apps/openmb/renderer/Model.hpp b/apps/openmb/renderer/Model.hpp new file mode 100644 index 0000000..e20c523 --- /dev/null +++ b/apps/openmb/renderer/Model.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "Mesh.hpp" +#include "Shader.hpp" +#include "Texture.hpp" + +#include <assimp/scene.h> +#include <glm/glm.hpp> +#include <memory> +#include <string> +#include <vector> + +namespace renderer +{ + class Model + { + public: + Model(); + ~Model() = default; + + bool loadFromFile( const std::string &path ); + + size_t meshCount() const { return mMeshes.size(); } + + const glm::vec3 &getBoundsMin() const { return mBoundsMin; } + const glm::vec3 &getBoundsMax() const { return mBoundsMax; } + + const std::vector< std::unique_ptr< Mesh > > &getMeshes() const { return mMeshes; } + const std::vector< Texture > &getTextures() const { return mTextures; } + const std::vector< Texture > &getNormalTextures() const { return mNormalTextures; } + const std::vector< int > &getMeshTextureIndex() const { return mMeshToTex; } + const std::vector< int > &getMeshNormalIndex() const { return mMeshToNormal; } + + private: + bool processNode( aiNode *node, const aiScene *scene, const std::string &baseDir ); + bool processMesh( aiMesh *mesh, const aiScene *scene, const std::string &baseDir, int &outTexIndex, + int &outNormalIndex ); + + std::vector< std::unique_ptr< Mesh > > mMeshes; + std::vector< Texture > mTextures; + std::vector< Texture > mNormalTextures; + + std::vector< int > mMeshToTex; + std::vector< int > mMeshToNormal; + int mFallbackAlbedoIndex; + int mFallbackNormalIndex; + glm::vec3 mBoundsMin; + glm::vec3 mBoundsMax; + }; + +} // namespace renderer diff --git a/apps/openmb/renderer/SSAORenderer.cpp b/apps/openmb/renderer/SSAORenderer.cpp new file mode 100644 index 0000000..8493529 --- /dev/null +++ b/apps/openmb/renderer/SSAORenderer.cpp @@ -0,0 +1,319 @@ +#include "SSAORenderer.hpp" + +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif +#include <glm/gtc/type_ptr.hpp> +#include <iostream> +#include <random> + +namespace renderer { + +SSAORenderer::SSAORenderer () + : mWidth( 0 ), mHeight( 0 ), mHalfRes( true ), mKernelSize( 32 ), mGBufferFBO( 0 ), mGNormal( 0 ), mGDepth( 0 ), + mSSAOFBO( 0 ), mSSAOTexture( 0 ), mSSAOBlurFBO( 0 ), mSSAOBlurTexture( 0 ), mNoiseTexture( 0 ), mQuadVAO( 0 ), + mQuadVBO( 0 ) { +} + +SSAORenderer::~SSAORenderer () { + if( mGNormal ) + glDeleteTextures( 1, &mGNormal ); + if( mGDepth ) + glDeleteTextures( 1, &mGDepth ); + if( mGBufferFBO ) + glDeleteFramebuffers( 1, &mGBufferFBO ); + if( mSSAOTexture ) + glDeleteTextures( 1, &mSSAOTexture ); + if( mSSAOBlurTexture ) + glDeleteTextures( 1, &mSSAOBlurTexture ); + if( mSSAOFBO ) + glDeleteFramebuffers( 1, &mSSAOFBO ); + if( mSSAOBlurFBO ) + glDeleteFramebuffers( 1, &mSSAOBlurFBO ); + if( mNoiseTexture ) + glDeleteTextures( 1, &mNoiseTexture ); + if( mQuadVBO ) + glDeleteBuffers( 1, &mQuadVBO ); + if( mQuadVAO ) + glDeleteVertexArrays( 1, &mQuadVAO ); +} + +bool SSAORenderer::init ( int width, int height, bool halfRes ) { + mWidth = width; + mHeight = height; + mHalfRes = halfRes; + + if( !mGBufferShader.fromFiles( "apps/openmb/resources/shaders/gbuffer.vert", + "apps/openmb/resources/shaders/gbuffer.frag" ) ) { + std::cerr << "Failed to load gbuffer shader" << std::endl; + return false; + } + if( !mSSAOShader.fromFiles( "apps/openmb/resources/shaders/ssao.vert", + "apps/openmb/resources/shaders/ssao.frag" ) ) { + std::cerr << "Failed to load ssao shader" << std::endl; + return false; + } + if( !mBlurShader.fromFiles( "apps/openmb/resources/shaders/ssao.vert", + "apps/openmb/resources/shaders/ssao_blur.frag" ) ) { + std::cerr << "Failed to load ssao blur shader" << std::endl; + return false; + } + + initBuffers(); + initKernelAndNoise(); + + float quadVertices[] = { + + -1.0f, + -1.0f, + 0.0f, + 0.0f, + 1.0f, + -1.0f, + 1.0f, + 0.0f, + -1.0f, + 1.0f, + 0.0f, + 1.0f, + -1.0f, + 1.0f, + 0.0f, + 1.0f, + 1.0f, + -1.0f, + 1.0f, + 0.0f, + 1.0f, + 1.0f, + 1.0f, + 1.0f, + }; + + glGenVertexArrays( 1, &mQuadVAO ); + glGenBuffers( 1, &mQuadVBO ); + glBindVertexArray( mQuadVAO ); + glBindBuffer( GL_ARRAY_BUFFER, mQuadVBO ); + glBufferData( GL_ARRAY_BUFFER, sizeof( quadVertices ), quadVertices, GL_STATIC_DRAW ); + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof( float ), (void*)0 ); + glEnableVertexAttribArray( 1 ); + glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof( float ), (void*)( 2 * sizeof( float ) ) ); + glBindVertexArray( 0 ); + + return true; +} + +void SSAORenderer::initBuffers () { + + if( mGBufferFBO == 0 ) + glGenFramebuffers( 1, &mGBufferFBO ); + glBindFramebuffer( GL_FRAMEBUFFER, mGBufferFBO ); + + if( mGNormal ) + glDeleteTextures( 1, &mGNormal ); + glGenTextures( 1, &mGNormal ); + glBindTexture( GL_TEXTURE_2D, mGNormal ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB16F, mWidth, mHeight, 0, GL_RGB, GL_FLOAT, nullptr ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mGNormal, 0 ); + + if( mGDepth ) + glDeleteTextures( 1, &mGDepth ); + glGenTextures( 1, &mGDepth ); + glBindTexture( GL_TEXTURE_2D, mGDepth ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, mWidth, mHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mGDepth, 0 ); + + GLenum attachments[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers( 1, attachments ); + + if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) + std::cerr << "GBuffer not complete" << std::endl; + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + + if( mSSAOFBO == 0 ) + glGenFramebuffers( 1, &mSSAOFBO ); + glBindFramebuffer( GL_FRAMEBUFFER, mSSAOFBO ); + if( mSSAOTexture ) + glDeleteTextures( 1, &mSSAOTexture ); + glGenTextures( 1, &mSSAOTexture ); + glBindTexture( GL_TEXTURE_2D, mSSAOTexture ); + int w = mHalfRes ? std::max( 1, mWidth / 2 ) : mWidth; + int h = mHalfRes ? std::max( 1, mHeight / 2 ) : mHeight; + glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mSSAOTexture, 0 ); + if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) + std::cerr << "SSAO FBO not complete" << std::endl; + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + + if( mSSAOBlurFBO == 0 ) + glGenFramebuffers( 1, &mSSAOBlurFBO ); + glBindFramebuffer( GL_FRAMEBUFFER, mSSAOBlurFBO ); + if( mSSAOBlurTexture ) + glDeleteTextures( 1, &mSSAOBlurTexture ); + glGenTextures( 1, &mSSAOBlurTexture ); + glBindTexture( GL_TEXTURE_2D, mSSAOBlurTexture ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mSSAOBlurTexture, 0 ); + if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) + std::cerr << "SSAO Blur FBO not complete" << std::endl; + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); +} + +void SSAORenderer::initKernelAndNoise () { + mKernel.clear(); + std::uniform_real_distribution<float> randomFloats( 0.0f, 1.0f ); + std::mt19937 gen; + + for( int i = 0; i < mKernelSize; ++i ) { + glm::vec3 sample( randomFloats( gen ) * 2.0f - 1.0f, randomFloats( gen ) * 2.0f - 1.0f, + randomFloats( gen ) ); + sample = glm::normalize( sample ); + sample *= randomFloats( gen ); + float scale = float( i ) / float( mKernelSize ); + scale = glm::mix( 0.1f, 1.0f, scale * scale ); + sample *= scale; + mKernel.push_back( sample ); + } + + mSSAOShader.use(); + for( int i = 0; i < mKernelSize; ++i ) { + mSSAOShader.setVec3( std::string( "samples[" ) + std::to_string( i ) + std::string( "]" ), mKernel[i] ); + } + mSSAOShader.setInt( "kernelSize", mKernelSize ); + + std::vector<float> noise; + for( int i = 0; i < 16; ++i ) { + float x = randomFloats( gen ) * 2.0f - 1.0f; + float y = randomFloats( gen ) * 2.0f - 1.0f; + noise.push_back( x ); + noise.push_back( y ); + noise.push_back( 0.0f ); + } + if( mNoiseTexture ) + glDeleteTextures( 1, &mNoiseTexture ); + glGenTextures( 1, &mNoiseTexture ); + glBindTexture( GL_TEXTURE_2D, mNoiseTexture ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F, 4, 4, 0, GL_RGB, GL_FLOAT, noise.data() ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glBindTexture( GL_TEXTURE_2D, 0 ); +} + +void SSAORenderer::resize ( int width, int height ) { + if( width == mWidth && height == mHeight ) + return; + mWidth = width; + mHeight = height; + initBuffers(); +} + +void SSAORenderer::bindGBuffer () { + glBindFramebuffer( GL_FRAMEBUFFER, mGBufferFBO ); + glViewport( 0, 0, mWidth, mHeight ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); +} + +void SSAORenderer::unbind () { + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); +} + +void SSAORenderer::computeSSAO ( const glm::mat4& proj, const glm::mat4& invProj, float radius, float bias, + float power ) { + int w = mHalfRes ? std::max( 1, mWidth / 2 ) : mWidth; + int h = mHalfRes ? std::max( 1, mHeight / 2 ) : mHeight; + + glBindFramebuffer( GL_FRAMEBUFFER, mSSAOFBO ); + glViewport( 0, 0, w, h ); + glClear( GL_COLOR_BUFFER_BIT ); + + mSSAOShader.use(); + mSSAOShader.setMat4( "proj", proj ); + mSSAOShader.setMat4( "invProj", invProj ); + mSSAOShader.setFloat( "radius", radius ); + mSSAOShader.setFloat( "bias", bias ); + mSSAOShader.setFloat( "power", power ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, mGDepth ); + mSSAOShader.setInt( "gDepth", 0 ); + + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, mGNormal ); + mSSAOShader.setInt( "gNormal", 1 ); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, mNoiseTexture ); + mSSAOShader.setInt( "texNoise", 2 ); + + float noiseScaleVal = float( w ) / 4.0f; + mSSAOShader.setInt( "gDepth", 0 ); + mSSAOShader.setInt( "gNormal", 1 ); + mSSAOShader.setInt( "texNoise", 2 ); + mSSAOShader.setFloat( "noiseScale", noiseScaleVal ); + glBindVertexArray( mQuadVAO ); + glDrawArrays( GL_TRIANGLES, 0, 6 ); + glBindVertexArray( 0 ); + + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); +} + +void SSAORenderer::blurSSAO () { + int w = mHalfRes ? std::max( 1, mWidth / 2 ) : mWidth; + int h = mHalfRes ? std::max( 1, mHeight / 2 ) : mHeight; + + glBindFramebuffer( GL_FRAMEBUFFER, mSSAOBlurFBO ); + glViewport( 0, 0, w, h ); + glClear( GL_COLOR_BUFFER_BIT ); + + mBlurShader.use(); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, mSSAOTexture ); + mBlurShader.setInt( "ssaoInput", 0 ); + mBlurShader.setInt( "horizontal", 1 ); + mBlurShader.setVec2( "texelSize", glm::vec2( 1.0f / float( w ), 1.0f / float( h ) ) ); + glBindVertexArray( mQuadVAO ); + glDrawArrays( GL_TRIANGLES, 0, 6 ); + glBindVertexArray( 0 ); + + glBindFramebuffer( GL_FRAMEBUFFER, mSSAOFBO ); + glViewport( 0, 0, w, h ); + glClear( GL_COLOR_BUFFER_BIT ); + + mBlurShader.use(); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, mSSAOBlurTexture ); + mBlurShader.setInt( "ssaoInput", 0 ); + mBlurShader.setInt( "horizontal", 0 ); + mBlurShader.setVec2( "texelSize", glm::vec2( 1.0f / float( w ), 1.0f / float( h ) ) ); + glBindVertexArray( mQuadVAO ); + glDrawArrays( GL_TRIANGLES, 0, 6 ); + glBindVertexArray( 0 ); + + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); +} + +unsigned int SSAORenderer::getSSAOTextureID () const { + return mSSAOTexture; +} + +void SSAORenderer::bindSSAOTextureToUnit ( int unit, renderer::Shader& shader, const std::string& uniformName ) const { + glActiveTexture( GL_TEXTURE0 + unit ); + glBindTexture( GL_TEXTURE_2D, getSSAOTextureID() ); + shader.setInt( uniformName, unit ); +} + +} // namespace renderer diff --git a/apps/openmb/renderer/SSAORenderer.hpp b/apps/openmb/renderer/SSAORenderer.hpp new file mode 100644 index 0000000..3075252 --- /dev/null +++ b/apps/openmb/renderer/SSAORenderer.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "Shader.hpp" +#include <glm/glm.hpp> +#include <vector> + +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif + +namespace renderer { +class SSAORenderer { + public: + SSAORenderer(); + ~SSAORenderer(); + + bool init( int width, int height, bool halfRes = true ); + void resize( int width, int height ); + + void bindGBuffer(); + void unbind(); + + void computeSSAO( const glm::mat4& proj, const glm::mat4& invProj, float radius, float bias, float power ); + void blurSSAO(); + + unsigned int getSSAOTextureID() const; + void bindSSAOTextureToUnit( int unit, renderer::Shader& shader, const std::string& uniformName = "ssao" ) const; + + renderer::Shader& getGBufferShader () { return mGBufferShader; } + + private: + void initBuffers(); + void initKernelAndNoise(); + + int mWidth; + int mHeight; + bool mHalfRes; + + GLuint mGBufferFBO; + GLuint mGNormal; + GLuint mGDepth; + + GLuint mSSAOFBO; + GLuint mSSAOTexture; + + GLuint mSSAOBlurFBO; + GLuint mSSAOBlurTexture; + + GLuint mNoiseTexture; + + GLuint mQuadVAO; + GLuint mQuadVBO; + + std::vector<glm::vec3> mKernel; + int mKernelSize; + + renderer::Shader mGBufferShader; + renderer::Shader mSSAOShader; + renderer::Shader mBlurShader; +}; + +} // namespace renderer diff --git a/apps/openmb/renderer/Shader.cpp b/apps/openmb/renderer/Shader.cpp new file mode 100644 index 0000000..a7c94e6 --- /dev/null +++ b/apps/openmb/renderer/Shader.cpp @@ -0,0 +1,137 @@ +#include "Shader.hpp" + +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif +#include <fstream> +#include <iostream> +#include <sstream> + +namespace renderer { +Shader::Shader () : mID( 0 ) {} + +Shader::~Shader () { + if( mID ) { + glDeleteProgram( mID ); + } +} + +bool Shader::fromSource ( const std::string& vertexSrc, const std::string& fragmentSrc ) { + return compileShader( vertexSrc.c_str(), fragmentSrc.c_str() ); +} + +bool Shader::fromFiles ( const std::string& vertexPath, const std::string& fragmentPath ) { + std::string vs = readFile( vertexPath ); + std::string fs = readFile( fragmentPath ); + if( vs.empty() || fs.empty() ) { + return false; + } + return compileShader( vs.c_str(), fs.c_str() ); +} + +void Shader::use () const { + glUseProgram( mID ); +} + +unsigned int Shader::id () const { + return mID; +} + +void Shader::setInt ( const std::string& name, int value ) const { + glUniform1i( glGetUniformLocation( mID, name.c_str() ), value ); +} + +void Shader::setFloat ( const std::string& name, float value ) const { + glUniform1f( glGetUniformLocation( mID, name.c_str() ), value ); +} + +void Shader::setVec3 ( const std::string& name, const glm::vec3& v ) const { + glUniform3f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y, v.z ); +} + +void Shader::setVec2 ( const std::string& name, const glm::vec2& v ) const { + glUniform2f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y ); +} + +void Shader::setMat4 ( const std::string& name, const glm::mat4& m ) const { + glUniformMatrix4fv( glGetUniformLocation( mID, name.c_str() ), 1, GL_FALSE, &m[0][0] ); +} + +bool Shader::compileShader ( const char* vSrc, const char* fSrc ) { + GLuint vert = glCreateShader( GL_VERTEX_SHADER ); + glShaderSource( vert, 1, &vSrc, nullptr ); + glCompileShader( vert ); + + GLint success = 0; + glGetShaderiv( vert, GL_COMPILE_STATUS, &success ); + if( success == GL_FALSE ) { + GLint len = 0; + glGetShaderiv( vert, GL_INFO_LOG_LENGTH, &len ); + std::string log( len, '\0' ); + glGetShaderInfoLog( vert, len, &len, &log[0] ); + std::cerr << "Vertex shader compile error:\n" + << log << std::endl; + std::cerr << "[Shader] Vertex shader ID = " << vert << std::endl; + glDeleteShader( vert ); + return false; + } + + GLuint frag = glCreateShader( GL_FRAGMENT_SHADER ); + + glShaderSource( frag, 1, &fSrc, nullptr ); + glCompileShader( frag ); + + glGetShaderiv( frag, GL_COMPILE_STATUS, &success ); + if( success == GL_FALSE ) { + GLint len = 0; + glGetShaderiv( frag, GL_INFO_LOG_LENGTH, &len ); + std::string log( len, '\0' ); + glGetShaderInfoLog( frag, len, &len, &log[0] ); + std::cerr << "Fragment shader compile error:\n" + << log << std::endl; + glDeleteShader( frag ); + glDeleteShader( vert ); + return false; + } + + mID = glCreateProgram(); + glAttachShader( mID, vert ); + glAttachShader( mID, frag ); + glLinkProgram( mID ); + + glGetProgramiv( mID, GL_LINK_STATUS, &success ); + if( success == GL_FALSE ) { + GLint len = 0; + glGetProgramiv( mID, GL_INFO_LOG_LENGTH, &len ); + std::string log( len, '\0' ); + glGetProgramInfoLog( mID, len, &len, &log[0] ); + std::cerr << "Shader link error:\n" + << log << std::endl; + glDeleteProgram( mID ); + mID = 0; + glDeleteShader( vert ); + glDeleteShader( frag ); + return false; + } + + glDetachShader( mID, vert ); + glDetachShader( mID, frag ); + glDeleteShader( vert ); + glDeleteShader( frag ); + + return true; +} + +std::string Shader::readFile ( const std::string& path ) const { + std::ifstream in( path ); + if( !in ) { + return std::string(); + } + std::stringstream ss; + ss << in.rdbuf(); + return ss.str(); +} + +} // namespace renderer diff --git a/apps/openmb/renderer/Shader.hpp b/apps/openmb/renderer/Shader.hpp new file mode 100644 index 0000000..260e67e --- /dev/null +++ b/apps/openmb/renderer/Shader.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <glm/glm.hpp> +#include <string> + +namespace renderer { +class Shader { + public: + Shader(); + ~Shader(); + + bool fromSource( const std::string& vertexSrc, const std::string& fragmentSrc ); + bool fromFiles( const std::string& vertexPath, const std::string& fragmentPath ); + + void use() const; + + unsigned int id() const; + + void setInt( const std::string& name, int value ) const; + void setFloat( const std::string& name, float value ) const; + void setVec3( const std::string& name, const glm::vec3& v ) const; + void setVec2( const std::string& name, const glm::vec2& v ) const; + void setMat4( const std::string& name, const glm::mat4& m ) const; + + private: + unsigned int mID; + bool compileShader( const char* vSrc, const char* fSrc ); + std::string readFile( const std::string& path ) const; +}; + +} // namespace renderer diff --git a/apps/openmb/renderer/Skybox.cpp b/apps/openmb/renderer/Skybox.cpp new file mode 100644 index 0000000..fea0021 --- /dev/null +++ b/apps/openmb/renderer/Skybox.cpp @@ -0,0 +1,155 @@ +#include "Skybox.hpp" + +#include "Shader.hpp" +#include <stb_image.h> + +#include <algorithm> +#include <filesystem> +#include <iostream> + +namespace Fs = std::filesystem; + +namespace renderer { +Skybox::Skybox () : mTexID( 0 ), mVAO( 0 ), mVBO( 0 ), mInitialized( false ) {} + +Skybox::~Skybox () { + if( mVBO ) + glDeleteBuffers( 1, &mVBO ); + if( mVAO ) + glDeleteVertexArrays( 1, &mVAO ); + if( mTexID ) + glDeleteTextures( 1, &mTexID ); +} + +static std::string toLower ( const std::string& s ) { + std::string out = s; + std::transform( out.begin(), out.end(), out.begin(), [] ( unsigned char c ) { return std::tolower( c ); } ); + return out; +} + +bool Skybox::loadFromDirectory ( const std::string& dirPath ) { + + std::vector<std::string> faceTokens = { "right", "left", "top", "bottom", "front", "back" }; + std::vector<std::string> faces( 6 ); + + if( !Fs::exists( dirPath ) || !Fs::is_directory( dirPath ) ) { + std::cerr << "Skybox directory does not exist: " << dirPath << std::endl; + return false; + } + + for( auto& entry : Fs::directory_iterator( dirPath ) ) { + if( !entry.is_regular_file() ) + continue; + auto name = entry.path().filename().string(); + std::string lname = toLower( name ); + for( size_t i = 0; i < faceTokens.size(); ++i ) { + if( lname.find( faceTokens[i] ) != std::string::npos ) { + faces[i] = entry.path().string(); + } + } + } + + for( size_t i = 0; i < faces.size(); ++i ) { + if( faces[i].empty() ) { + std::cerr << "Missing skybox face for token: " << faceTokens[i] << std::endl; + return false; + } + } + + return loadFaces( faces ); +} + +bool Skybox::loadFaces ( const std::vector<std::string>& faces ) { + glGenTextures( 1, &mTexID ); + glBindTexture( GL_TEXTURE_CUBE_MAP, mTexID ); + + stbi_set_flip_vertically_on_load( false ); + for( unsigned i = 0; i < faces.size(); ++i ) { + int w, h, ch; + unsigned char* data = stbi_load( faces[i].c_str(), &w, &h, &ch, 0 ); + if( !data ) { + std::cerr << "Failed to load skybox face: " << faces[i] << std::endl; + glBindTexture( GL_TEXTURE_CUBE_MAP, 0 ); + return false; + } + GLenum format = ( ch == 4 ) ? GL_RGBA : GL_RGB; + glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, data ); + stbi_image_free( data ); + } + + glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); + + glBindTexture( GL_TEXTURE_CUBE_MAP, 0 ); + + initMesh(); + mInitialized = true; + return true; +} + +void Skybox::initMesh () { + + float skyboxVertices[] = { -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, + + 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, + + -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; + + glGenVertexArrays( 1, &mVAO ); + glGenBuffers( 1, &mVBO ); + glBindVertexArray( mVAO ); + glBindBuffer( GL_ARRAY_BUFFER, mVBO ); + glBufferData( GL_ARRAY_BUFFER, sizeof( skyboxVertices ), &skyboxVertices, GL_STATIC_DRAW ); + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ), (void*)0 ); + glBindVertexArray( 0 ); +} + +void Skybox::draw ( const glm::mat4& view, const glm::mat4& proj ) { + if( !mInitialized ) + return; + + static Shader s; + static bool shaderLoaded = false; + if( !shaderLoaded ) { + s.fromFiles( "apps/openmb/resources/shaders/skybox.vert", "apps/openmb/resources/shaders/skybox.frag" ); + shaderLoaded = true; + } + + glDepthFunc( GL_LEQUAL ); + glDepthMask( GL_FALSE ); + + s.use(); + + glm::mat4 viewNoTrans = glm::mat4( glm::mat3( view ) ); + s.setMat4( "view", viewNoTrans ); + s.setMat4( "proj", proj ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_CUBE_MAP, mTexID ); + s.setInt( "skybox", 0 ); + + glBindVertexArray( mVAO ); + glDrawArrays( GL_TRIANGLES, 0, 36 ); + glBindVertexArray( 0 ); + + glDepthMask( GL_TRUE ); + glDepthFunc( GL_LESS ); +} + +} // namespace renderer diff --git a/apps/openmb/renderer/Skybox.hpp b/apps/openmb/renderer/Skybox.hpp new file mode 100644 index 0000000..656494f --- /dev/null +++ b/apps/openmb/renderer/Skybox.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <glm/glm.hpp> +#include <string> +#include <vector> + +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#else +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#endif + +namespace renderer { +class Skybox { + public: + Skybox(); + ~Skybox(); + + bool loadFromDirectory( const std::string& dirPath ); + + void draw( const glm::mat4& view, const glm::mat4& proj ); + + private: + bool loadFaces( const std::vector<std::string>& faces ); + void initMesh(); + + GLuint mTexID; + GLuint mVAO; + GLuint mVBO; + bool mInitialized; +}; + +} // namespace renderer diff --git a/apps/openmb/renderer/Texture.cpp b/apps/openmb/renderer/Texture.cpp new file mode 100644 index 0000000..e551f86 --- /dev/null +++ b/apps/openmb/renderer/Texture.cpp @@ -0,0 +1,53 @@ +#define STB_IMAGE_IMPLEMENTATION +#include <stb_image.h> + +#include "Texture.hpp" + +#include <iostream> + +namespace renderer { +Texture::Texture () : mID( 0 ) {} + +Texture::~Texture () { + if( mID ) + glDeleteTextures( 1, &mID ); +} + +bool Texture::loadFromFile ( const std::string& path, bool flip ) { + stbi_set_flip_vertically_on_load( flip ); + int w, h, channels; + unsigned char* data = stbi_load( path.c_str(), &w, &h, &channels, 0 ); + if( !data ) { + std::cerr << "Failed to load texture: " << path << std::endl; + return false; + } + + GLenum format = GL_RGB; + if( channels == 1 ) + format = GL_RED; + else if( channels == 3 ) + format = GL_RGB; + else if( channels == 4 ) + format = GL_RGBA; + + glGenTextures( 1, &mID ); + glBindTexture( GL_TEXTURE_2D, mID ); + glTexImage2D( GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, data ); + glGenerateMipmap( GL_TEXTURE_2D ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + stbi_image_free( data ); + glBindTexture( GL_TEXTURE_2D, 0 ); + return true; +} + +void Texture::bind ( unsigned unit ) const { + glActiveTexture( GL_TEXTURE0 + unit ); + glBindTexture( GL_TEXTURE_2D, mID ); +} + +} // namespace renderer diff --git a/apps/openmb/renderer/Texture.hpp b/apps/openmb/renderer/Texture.hpp new file mode 100644 index 0000000..9acb5cd --- /dev/null +++ b/apps/openmb/renderer/Texture.hpp @@ -0,0 +1,28 @@ +#pragma once + +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#else +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif +#endif +#include <string> + +namespace renderer { +class Texture { + public: + Texture(); + ~Texture(); + + bool loadFromFile( const std::string& path, bool flip = true ); + void bind( unsigned unit = 0 ) const; + GLuint id () const { return mID; } + + private: + GLuint mID; +}; + +} // namespace renderer diff --git a/apps/openmb/renderer/TextureManager.cpp b/apps/openmb/renderer/TextureManager.cpp new file mode 100644 index 0000000..bfd7e15 --- /dev/null +++ b/apps/openmb/renderer/TextureManager.cpp @@ -0,0 +1,163 @@ +#include "TextureManager.hpp" + +#include <algorithm> +#include <iostream> + +namespace renderer { +TextureManager::TextureManager () + : mBasePath(), mTextures(), mCurrentCategory(), mCurrentSubcategory(), mCurrentTextureName(), + mCurrentTexture( nullptr ), mCurrentTextureId( 0 ), mTextureIdToPath(), mNextTextureId( 1 ) { +} + +void TextureManager::scanDirectory ( const std::string& basePath ) { + mBasePath = basePath; + mTextures.clear(); + + if( !std::filesystem::exists( basePath ) ) { + std::cerr << "TextureManager: Base path does not exist: " << basePath << std::endl; + return; + } + + for( const auto& categoryEntry : std::filesystem::directory_iterator( basePath ) ) { + if( !categoryEntry.is_directory() ) + continue; + + std::string categoryName = categoryEntry.path().filename().string(); + + for( const auto& subcategoryEntry : std::filesystem::directory_iterator( categoryEntry.path() ) ) { + if( !subcategoryEntry.is_directory() ) + continue; + + std::string subcategoryName = subcategoryEntry.path().filename().string(); + + for( const auto& fileEntry : std::filesystem::directory_iterator( subcategoryEntry.path() ) ) { + if( !fileEntry.is_regular_file() ) + continue; + + std::string fileName = fileEntry.path().filename().string(); + std::string extension = fileEntry.path().extension().string(); + + if( extension != ".png" && extension != ".jpg" && extension != ".jpeg" && extension != ".bmp" && + extension != ".tga" ) + continue; + + TextureEntry entry; + entry.mFullPath = fileEntry.path().string(); + entry.mLoaded = false; + + mTextures[categoryName][subcategoryName][fileName] = entry; + + int textureId = mNextTextureId++; + mTextureIdToPath[textureId] = std::make_tuple( categoryName, subcategoryName, fileName ); + } + } + } + + std::cout << "TextureManager: Scanned " << mTextures.size() << " categories" << std::endl; +} + +std::vector<std::string> TextureManager::getCategories () const { + std::vector<std::string> categories; + for( const auto& [category, _] : mTextures ) { + categories.push_back( category ); + } + std::sort( categories.begin(), categories.end() ); + return categories; +} + +std::vector<std::string> TextureManager::getSubcategories ( const std::string& category ) const { + std::vector<std::string> subcategories; + auto catIt = mTextures.find( category ); + if( catIt != mTextures.end() ) { + for( const auto& [subcategory, _] : catIt->second ) { + subcategories.push_back( subcategory ); + } + std::sort( subcategories.begin(), subcategories.end() ); + } + return subcategories; +} + +std::vector<std::string> TextureManager::getTextureNames ( const std::string& category, + const std::string& subcategory ) const { + std::vector<std::string> textureNames; + auto catIt = mTextures.find( category ); + if( catIt != mTextures.end() ) { + auto subIt = catIt->second.find( subcategory ); + if( subIt != catIt->second.end() ) { + for( const auto& [textureName, _] : subIt->second ) { + textureNames.push_back( textureName ); + } + std::sort( textureNames.begin(), textureNames.end() ); + } + } + return textureNames; +} + +Texture* TextureManager::getTexture ( const std::string& category, const std::string& subcategory, + const std::string& textureName ) { + auto catIt = mTextures.find( category ); + if( catIt == mTextures.end() ) + return nullptr; + + auto subIt = catIt->second.find( subcategory ); + if( subIt == catIt->second.end() ) + return nullptr; + + auto texIt = subIt->second.find( textureName ); + if( texIt == subIt->second.end() ) + return nullptr; + + TextureEntry& entry = texIt->second; + + if( !entry.mLoaded ) { + if( entry.mTexture.loadFromFile( entry.mFullPath ) ) { + entry.mLoaded = true; + } else { + std::cerr << "TextureManager: Failed to load texture: " << entry.mFullPath << std::endl; + return nullptr; + } + } + + return &entry.mTexture; +} + +Texture* TextureManager::getCurrentTexture () { + if( mCurrentTexture ) + return mCurrentTexture; + + if( !mCurrentCategory.empty() && !mCurrentSubcategory.empty() && !mCurrentTextureName.empty() ) { + mCurrentTexture = getTexture( mCurrentCategory, mCurrentSubcategory, mCurrentTextureName ); + } + + return mCurrentTexture; +} + +void TextureManager::setCurrentTexture ( const std::string& category, const std::string& subcategory, + const std::string& textureName ) { + mCurrentCategory = category; + mCurrentSubcategory = subcategory; + mCurrentTextureName = textureName; + mCurrentTexture = getTexture( category, subcategory, textureName ); + + for( const auto& [id, path] : mTextureIdToPath ) { + if( std::get<0>( path ) == category && std::get<1>( path ) == subcategory && + std::get<2>( path ) == textureName ) { + mCurrentTextureId = id; + break; + } + } +} + +int TextureManager::getCurrentTextureId () const { + return mCurrentTextureId; +} + +Texture* TextureManager::getTextureById ( int textureId ) { + auto it = mTextureIdToPath.find( textureId ); + if( it == mTextureIdToPath.end() ) + return nullptr; + + const auto& [category, subcategory, textureName] = it->second; + return getTexture( category, subcategory, textureName ); +} +} // namespace renderer diff --git a/apps/openmb/renderer/TextureManager.hpp b/apps/openmb/renderer/TextureManager.hpp new file mode 100644 index 0000000..f3e183f --- /dev/null +++ b/apps/openmb/renderer/TextureManager.hpp @@ -0,0 +1,64 @@ +#ifndef OPENMB_APPS_OPENMB_RENDERER_TEXTUREMANAGER_H +#define OPENMB_APPS_OPENMB_RENDERER_TEXTUREMANAGER_H + +#include "Texture.hpp" + +#include <filesystem> +#include <map> +#include <string> +#include <vector> + +namespace renderer { + +class TextureManager { + public: + TextureManager(); + ~TextureManager() = default; + + void scanDirectory( const std::string& basePath ); + + std::vector<std::string> getCategories() const; + + std::vector<std::string> getSubcategories( const std::string& category ) const; + + std::vector<std::string> getTextureNames( const std::string& category, const std::string& subcategory ) const; + + Texture* getTexture( const std::string& category, const std::string& subcategory, + const std::string& textureName ); + + Texture* getCurrentTexture(); + + void setCurrentTexture( const std::string& category, const std::string& subcategory, + const std::string& textureName ); + + const std::string& getCurrentCategory () const { return mCurrentCategory; } + const std::string& getCurrentSubcategory () const { return mCurrentSubcategory; } + const std::string& getCurrentTextureName () const { return mCurrentTextureName; } + + int getCurrentTextureId() const; + + Texture* getTextureById( int textureId ); + + private: + struct TextureEntry { + std::string mFullPath; + Texture mTexture; + bool mLoaded; + }; + + std::string mBasePath; + + std::map<std::string, std::map<std::string, std::map<std::string, TextureEntry>>> mTextures; + + std::string mCurrentCategory; + std::string mCurrentSubcategory; + std::string mCurrentTextureName; + Texture* mCurrentTexture; + int mCurrentTextureId; + + std::map<int, std::tuple<std::string, std::string, std::string>> mTextureIdToPath; + int mNextTextureId; +}; +} // namespace renderer + +#endif diff --git a/apps/openmb/renderer/primitives.cpp b/apps/openmb/renderer/primitives.cpp new file mode 100644 index 0000000..245f7e1 --- /dev/null +++ b/apps/openmb/renderer/primitives.cpp @@ -0,0 +1,595 @@ +#include "primitives.hpp" + +#include <vector> + +#include <glm/glm.hpp> + +namespace renderer +{ + namespace primitives + { + Mesh makeCube() + { + + std::vector< float > verts = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, + + -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, + + -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, + + 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, + + -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, + + -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f }; + + Mesh m; + m.createFromPositions( verts, false ); + return m; + } + + Mesh makeTexturedCube() + { + std::vector< float > verts; + + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 1.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f } ); + + Mesh m; + m.createFromPosTex( verts ); + return m; + } + + Mesh makeGrid( int halfSize, float spacing ) + { + std::vector< float > verts; + for ( int i = -halfSize; i <= halfSize; ++i ) + { + float x = i * spacing; + verts.push_back( x ); + verts.push_back( 0.0f ); + verts.push_back( -halfSize * spacing ); + verts.push_back( x ); + verts.push_back( 0.0f ); + verts.push_back( halfSize * spacing ); + } + + for ( int j = -halfSize; j <= halfSize; ++j ) + { + float z = j * spacing; + verts.push_back( -halfSize * spacing ); + verts.push_back( 0.0f ); + verts.push_back( z ); + verts.push_back( halfSize * spacing ); + verts.push_back( 0.0f ); + verts.push_back( z ); + } + + Mesh m; + m.createFromPositions( verts, true ); + return m; + } + + Mesh makeTexturedGrid( int width, int depth, float tileSize ) + { + std::vector< float > verts; + + for ( int z = 0; z < depth; ++z ) + { + for ( int x = 0; x < width; ++x ) + { + float x0 = ( x - width * 0.5f ) * tileSize; + float z0 = ( z - depth * 0.5f ) * tileSize; + float x1 = x0 + tileSize; + float z1 = z0 + tileSize; + + verts.push_back( x0 ); + verts.push_back( 0.0f ); + verts.push_back( z0 ); + verts.push_back( 0.0f ); + verts.push_back( 0.0f ); + + verts.push_back( x1 ); + verts.push_back( 0.0f ); + verts.push_back( z0 ); + verts.push_back( 1.0f ); + verts.push_back( 0.0f ); + + verts.push_back( x0 ); + verts.push_back( 0.0f ); + verts.push_back( z1 ); + verts.push_back( 0.0f ); + verts.push_back( 1.0f ); + + verts.push_back( x0 ); + verts.push_back( 0.0f ); + verts.push_back( z1 ); + verts.push_back( 0.0f ); + verts.push_back( 1.0f ); + + verts.push_back( x1 ); + verts.push_back( 0.0f ); + verts.push_back( z0 ); + verts.push_back( 1.0f ); + verts.push_back( 0.0f ); + + verts.push_back( x1 ); + verts.push_back( 0.0f ); + verts.push_back( z1 ); + verts.push_back( 1.0f ); + verts.push_back( 1.0f ); + } + } + + Mesh m; + m.createFromPosTex( verts ); + return m; + } + + Mesh makeTexturedCubeGrid( int width, int depth, float tileSize ) + { + std::vector< float > verts; + + auto pushFace = [&]( const std::array< float, 18 > &pos, const std::array< float, 12 > &uv, float cx, + float cy, float cz, float scale ) + { + for ( int i = 0; i < 6; ++i ) + { + int pi = i * 3; + int ui = i * 2; + verts.push_back( cx + pos[pi + 0] * scale ); + verts.push_back( cy + pos[pi + 1] * scale ); + verts.push_back( cz + pos[pi + 2] * scale ); + verts.push_back( uv[ui + 0] ); + verts.push_back( uv[ui + 1] ); + } + }; + + const std::array< float, 18 > topPos = { -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f }; + const std::array< float, 12 > topUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > bottomPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > bottomUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > frontPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > frontUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > backPos = { 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > backUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > leftPos = { -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > leftUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > rightPos = { 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > rightUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + for ( int z = 0; z < depth; ++z ) + { + for ( int x = 0; x < width; ++x ) + { + float cx = ( x - width * 0.5f ) * tileSize + tileSize * 0.5f; + float cz = ( z - depth * 0.5f ) * tileSize + tileSize * 0.5f; + + float cy = -0.5f * tileSize; + float scale = tileSize; + + pushFace( topPos, topUV, cx, cy, cz, scale ); + pushFace( bottomPos, bottomUV, cx, cy, cz, scale ); + pushFace( frontPos, frontUV, cx, cy, cz, scale ); + pushFace( backPos, backUV, cx, cy, cz, scale ); + pushFace( leftPos, leftUV, cx, cy, cz, scale ); + pushFace( rightPos, rightUV, cx, cy, cz, scale ); + } + } + + Mesh m; + m.createFromPosTex( verts ); + return m; + } + + Mesh makeTexturedWall( int length, int height, float tileSize, bool alongX, float fixedCoord ) + { + std::vector< float > verts; + + auto pushFace = [&]( const std::array< float, 18 > &pos, const std::array< float, 12 > &uv, float cx, + float cy, float cz, float scale ) + { + for ( int i = 0; i < 6; ++i ) + { + int pi = i * 3; + int ui = i * 2; + verts.push_back( cx + pos[pi + 0] * scale ); + verts.push_back( cy + pos[pi + 1] * scale ); + verts.push_back( cz + pos[pi + 2] * scale ); + verts.push_back( uv[ui + 0] ); + verts.push_back( uv[ui + 1] ); + } + }; + + const std::array< float, 18 > topPos = { -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f }; + const std::array< float, 12 > topUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > bottomPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > bottomUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > frontPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > frontUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > backPos = { 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > backUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > leftPos = { -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > leftUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > rightPos = { 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > rightUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + if ( alongX ) + { + + for ( int lx = 0; lx < length; ++lx ) + { + float cx = ( lx - length * 0.5f ) * tileSize + tileSize * 0.5f; + float cz = fixedCoord; + for ( int hy = 0; hy < height; ++hy ) + { + float cy = 0.02f * tileSize + hy * tileSize; + float scale = tileSize; + pushFace( topPos, topUV, cx, cy, cz, scale ); + pushFace( bottomPos, bottomUV, cx, cy, cz, scale ); + pushFace( frontPos, frontUV, cx, cy, cz, scale ); + pushFace( backPos, backUV, cx, cy, cz, scale ); + pushFace( leftPos, leftUV, cx, cy, cz, scale ); + pushFace( rightPos, rightUV, cx, cy, cz, scale ); + } + } + } + else + { + + for ( int lz = 0; lz < length; ++lz ) + { + float cz = ( lz - length * 0.5f ) * tileSize + tileSize * 0.5f; + float cx = fixedCoord; + for ( int hy = 0; hy < height; ++hy ) + { + float cy = 0.02f * tileSize + hy * tileSize; + float scale = tileSize; + pushFace( topPos, topUV, cx, cy, cz, scale ); + pushFace( bottomPos, bottomUV, cx, cy, cz, scale ); + pushFace( frontPos, frontUV, cx, cy, cz, scale ); + pushFace( backPos, backUV, cx, cy, cz, scale ); + pushFace( leftPos, leftUV, cx, cy, cz, scale ); + pushFace( rightPos, rightUV, cx, cy, cz, scale ); + } + } + } + + Mesh m; + m.createFromPosTex( verts ); + return m; + } + + Mesh makeTexturedCubeWithNormals() + { + std::vector< float > verts; + + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } ); + + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f } ); + + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f } ); + + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f } ); + + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f } ); + verts.insert( verts.end(), { 0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } ); + verts.insert( verts.end(), { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f } ); + + Mesh m; + m.createFromPosTexNormal( verts ); + return m; + } + + Mesh makeTexturedGridWithNormals( int width, int depth, float tileSize ) + { + std::vector< float > verts; + + for ( int z = 0; z < depth; ++z ) + { + for ( int x = 0; x < width; ++x ) + { + float x0 = ( x - width * 0.5f ) * tileSize; + float z0 = ( z - depth * 0.5f ) * tileSize; + float x1 = x0 + tileSize; + float z1 = z0 + tileSize; + + verts.insert( verts.end(), { x0, 0.0f, z0, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { x1, 0.0f, z0, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { x0, 0.0f, z1, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f } ); + + verts.insert( verts.end(), { x0, 0.0f, z1, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { x1, 0.0f, z0, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f } ); + verts.insert( verts.end(), { x1, 0.0f, z1, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f } ); + } + } + + Mesh m; + m.createFromPosTexNormal( verts ); + return m; + } + + Mesh makeTexturedCubeGridWithNormals( int width, int depth, float tileSize ) + { + std::vector< float > verts; + + auto pushFaceWithNormal = [&]( const std::array< float, 18 > &pos, const std::array< float, 12 > &uv, + const glm::vec3 &normal, float cx, float cy, float cz, float scale ) + { + for ( int i = 0; i < 6; ++i ) + { + int pi = i * 3; + int ui = i * 2; + verts.push_back( cx + pos[pi + 0] * scale ); + verts.push_back( cy + pos[pi + 1] * scale ); + verts.push_back( cz + pos[pi + 2] * scale ); + verts.push_back( uv[ui + 0] ); + verts.push_back( uv[ui + 1] ); + verts.push_back( normal.x ); + verts.push_back( normal.y ); + verts.push_back( normal.z ); + } + }; + + const std::array< float, 18 > topPos = { -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f }; + const std::array< float, 12 > topUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > bottomPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > bottomUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > frontPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > frontUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > backPos = { 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > backUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > leftPos = { -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > leftUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > rightPos = { 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > rightUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + for ( int z = 0; z < depth; ++z ) + { + for ( int x = 0; x < width; ++x ) + { + float cx = ( x - width * 0.5f ) * tileSize + tileSize * 0.5f; + float cz = ( z - depth * 0.5f ) * tileSize + tileSize * 0.5f; + + float cy = -0.5f * tileSize; + float scale = tileSize; + + pushFaceWithNormal( topPos, topUV, glm::vec3( 0.0f, 1.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( bottomPos, bottomUV, glm::vec3( 0.0f, -1.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( frontPos, frontUV, glm::vec3( 0.0f, 0.0f, 1.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( backPos, backUV, glm::vec3( 0.0f, 0.0f, -1.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( leftPos, leftUV, glm::vec3( -1.0f, 0.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( rightPos, rightUV, glm::vec3( 1.0f, 0.0f, 0.0f ), cx, cy, cz, scale ); + } + } + + Mesh m; + m.createFromPosTexNormal( verts ); + return m; + } + + Mesh makeTexturedWallWithNormals( int length, int height, float tileSize, bool alongX, float fixedCoord ) + { + std::vector< float > verts; + + auto pushFaceWithNormal = [&]( const std::array< float, 18 > &pos, const std::array< float, 12 > &uv, + const glm::vec3 &normal, float cx, float cy, float cz, float scale ) + { + for ( int i = 0; i < 6; ++i ) + { + int pi = i * 3; + int ui = i * 2; + verts.push_back( cx + pos[pi + 0] * scale ); + verts.push_back( cy + pos[pi + 1] * scale ); + verts.push_back( cz + pos[pi + 2] * scale ); + verts.push_back( uv[ui + 0] ); + verts.push_back( uv[ui + 1] ); + verts.push_back( normal.x ); + verts.push_back( normal.y ); + verts.push_back( normal.z ); + } + }; + + const std::array< float, 18 > topPos = { -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f }; + const std::array< float, 12 > topUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > bottomPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > bottomUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > frontPos = { -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > frontUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > backPos = { 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > backUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > leftPos = { -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f }; + const std::array< float, 12 > leftUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + const std::array< float, 18 > rightPos = { 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f }; + const std::array< float, 12 > rightUV = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + if ( alongX ) + { + for ( int lx = 0; lx < length; ++lx ) + { + float cx = ( lx - length * 0.5f ) * tileSize + tileSize * 0.5f; + float cz = fixedCoord; + for ( int hy = 0; hy < height; ++hy ) + { + float cy = hy * tileSize + tileSize * 0.5f; + float scale = tileSize; + pushFaceWithNormal( topPos, topUV, glm::vec3( 0.0f, 1.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( bottomPos, bottomUV, glm::vec3( 0.0f, -1.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( frontPos, frontUV, glm::vec3( 0.0f, 0.0f, 1.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( backPos, backUV, glm::vec3( 0.0f, 0.0f, -1.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( leftPos, leftUV, glm::vec3( -1.0f, 0.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( rightPos, rightUV, glm::vec3( 1.0f, 0.0f, 0.0f ), cx, cy, cz, scale ); + } + } + } + else + { + for ( int lz = 0; lz < length; ++lz ) + { + float cz = ( lz - length * 0.5f ) * tileSize + tileSize * 0.5f; + float cx = fixedCoord; + for ( int hy = 0; hy < height; ++hy ) + { + float cy = hy * tileSize + tileSize * 0.5f; + float scale = tileSize; + pushFaceWithNormal( topPos, topUV, glm::vec3( 0.0f, 1.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( bottomPos, bottomUV, glm::vec3( 0.0f, -1.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( frontPos, frontUV, glm::vec3( 0.0f, 0.0f, 1.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( backPos, backUV, glm::vec3( 0.0f, 0.0f, -1.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( leftPos, leftUV, glm::vec3( -1.0f, 0.0f, 0.0f ), cx, cy, cz, scale ); + pushFaceWithNormal( rightPos, rightUV, glm::vec3( 1.0f, 0.0f, 0.0f ), cx, cy, cz, scale ); + } + } + } + + Mesh m; + m.createFromPosTexNormal( verts ); + return m; + } + + } // namespace primitives + +} // namespace renderer diff --git a/apps/openmb/renderer/primitives.hpp b/apps/openmb/renderer/primitives.hpp new file mode 100644 index 0000000..bd07c02 --- /dev/null +++ b/apps/openmb/renderer/primitives.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "Mesh.hpp" + +namespace renderer +{ + namespace primitives + { + Mesh makeCube(); + Mesh makeTexturedCube(); + Mesh makeTexturedCubeWithNormals(); + Mesh makeGrid( int halfSize, float spacing ); + Mesh makeTexturedGrid( int width, int depth, float tileSize ); + Mesh makeTexturedGridWithNormals( int width, int depth, float tileSize ); + Mesh makeTexturedCubeGrid( int width, int depth, float tileSize ); + Mesh makeTexturedCubeGridWithNormals( int width, int depth, float tileSize ); + Mesh makeTexturedWall( int length, int height, float tileSize, bool alongX = true, float fixedCoord = 0.0f ); + Mesh makeTexturedWallWithNormals( int length, int height, float tileSize, bool alongX = true, + float fixedCoord = 0.0f ); + } // namespace primitives + +} // namespace renderer diff --git a/apps/openmb/resources/levels/default.json b/apps/openmb/resources/levels/default.json new file mode 100644 index 0000000..47322c3 --- /dev/null +++ b/apps/openmb/resources/levels/default.json @@ -0,0 +1,24701 @@ +{ + "models": [ + { + "modelIndex": 3, + "scale": 0.017000000923871994, + "x": -8.920812606811523, + "y": 1.0, + "yaw": 0.0, + "z": -5.858656883239746 + }, + { + "modelIndex": 3, + "scale": 0.017000000923871994, + "x": -6.891270160675049, + "y": 1.0, + "yaw": 0.0, + "z": -4.801188945770264 + }, + { + "modelIndex": 4, + "scale": 0.017000000923871994, + "x": -10.715228080749512, + "y": 1.0, + "yaw": 0.0, + "z": -7.831607818603516 + }, + { + "modelIndex": 4, + "scale": 0.017000000923871994, + "x": -11.074238777160645, + "y": 1.0, + "yaw": 0.0, + "z": -3.105196475982666 + }, + { + "modelIndex": 4, + "scale": 0.017000000923871994, + "x": -2.7807230949401855, + "y": 1.0, + "yaw": 0.0, + "z": -3.1151580810546875 + }, + { + "modelIndex": 1, + "scale": 0.017000000923871994, + "x": -4.819826126098633, + "y": 1.0, + "yaw": 0.0, + "z": 0.524317741394043 + }, + { + "modelIndex": 1, + "scale": 0.017000000923871994, + "x": -6.733904838562012, + "y": 1.0000004768371582, + "yaw": 0.0, + "z": 0.9215221405029297 + }, + { + "modelIndex": 1, + "scale": 0.017000000923871994, + "x": -8.02570629119873, + "y": 1.0, + "yaw": 0.0, + "z": 1.3742852210998535 + }, + { + "modelIndex": 0, + "scale": 0.017000000923871994, + "x": -9.27149772644043, + "y": 1.0, + "yaw": 0.0, + "z": 0.7743282318115234 + }, + { + "modelIndex": 0, + "scale": 0.017000000923871994, + "x": -10.817995071411133, + "y": 0.9999995231628418, + "yaw": 0.0, + "z": -0.1147160530090332 + }, + { + "modelIndex": 0, + "scale": 0.017000000923871994, + "x": 8.604547500610352, + "y": 1.0, + "yaw": 0.0, + "z": 1.912936806678772 + }, + { + "modelIndex": 3, + "scale": 0.017000000923871994, + "x": 2.3309972286224365, + "y": 1.0, + "yaw": 0.0, + "z": 12.099968910217285 + }, + { + "modelIndex": 3, + "scale": 0.017000000923871994, + "x": 6.445761680603027, + "y": 0.9999995231628418, + "yaw": 0.0, + "z": 12.606679916381836 + }, + { + "modelIndex": 0, + "scale": 0.017000000923871994, + "x": 5.363408088684082, + "y": 1.0, + "yaw": 0.0, + "z": 2.2424755096435547 + }, + { + "modelIndex": 0, + "scale": 0.017000000923871994, + "x": 4.560368061065674, + "y": 1.0, + "yaw": 0.0, + "z": 8.449825286865234 + }, + { + "modelIndex": 0, + "scale": 0.017000000923871994, + "x": 2.835254192352295, + "y": 1.0, + "yaw": 0.0, + "z": 1.8184318542480469 + } + ], + "paintedCircles": [], + "sun": { + "color": [ + 1.0, + 0.9800000190734863, + 0.8999999761581421 + ], + "direction": [ + 0.03500000014901161, + -0.30804863572120667, + 0.9507266283035278 + ], + "intensity": 0.8019999861717224 + }, + "version": 1, + "voxels": [ + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 0, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 1, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 2, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 3, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 4, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 5, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 18, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 19, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 20, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 21, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 22, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 0 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 1 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 2 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 3 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 4 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 5 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 6 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 7 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 8 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 9 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 23, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 6, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 7, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 8, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 9, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 10, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 11, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 12, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 13, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 14, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 15, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 16, + "y": 0, + "z": 23 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 10 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 11 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 12 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 13 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 14 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 15 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 16 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 17 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 18 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 19 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 20 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 21 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 22 + }, + { + "textureId": 11, + "x": 17, + "y": 0, + "z": 23 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 487, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 488, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 489, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 490, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 491, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 492, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 493, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 494, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 495, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 496, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 497, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 498, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 499, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 500, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 501, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 502, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 503, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 504, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 505, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 506, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 507, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 508, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 509, + "y": 0, + "z": 517 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 488, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 489, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 490, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 491, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 492, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 493, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 494, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 495, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 496, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 497, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 498, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 499, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 501, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 502, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 503, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 504, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 505, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 506, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 507, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 508, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 484 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 485 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 486 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 487 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 489 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 490 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 491 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 492 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 493 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 494 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 495 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 496 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 497 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 498 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 499 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 500 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 501 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 504 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 505 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 507 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 508 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 510 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 511 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 512 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 514 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 515 + }, + { + "textureId": 37, + "x": 509, + "y": 1, + "z": 516 + }, + { + "textureId": 37, + "x": 488, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 489, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 490, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 491, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 492, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 493, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 494, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 495, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 496, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 497, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 498, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 499, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 501, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 502, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 503, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 504, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 505, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 506, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 507, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 508, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 494 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 495 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 496 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 497 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 498 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 499 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 500 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 501 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 504 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 505 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 507 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 508 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 510 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 511 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 512 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 514 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 515 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 516 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 494 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 495 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 496 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 497 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 498 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 499 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 500 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 501 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 502 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 504 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 505 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 507 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 508 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 510 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 511 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 512 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 514 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 515 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 516 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 484 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 485 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 486 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 487 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 489 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 490 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 491 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 492 + }, + { + "textureId": 37, + "x": 487, + "y": 1, + "z": 493 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 484 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 485 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 486 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 487 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 489 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 490 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 491 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 492 + }, + { + "textureId": 37, + "x": 487, + "y": 2, + "z": 493 + }, + { + "textureId": 37, + "x": 493, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 493, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 494, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 494, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 495, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 495, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 496, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 496, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 497, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 497, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 498, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 498, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 499, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 499, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 501, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 501, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 502, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 502, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 503, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 503, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 504, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 504, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 505, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 505, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 506, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 506, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 507, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 507, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 508, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 508, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 488, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 488, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 489, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 489, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 490, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 490, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 491, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 491, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 492, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 492, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 484 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 485 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 502 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 504 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 505 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 507 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 508 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 510 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 511 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 512 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 514 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 515 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 516 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 486 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 487 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 489 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 490 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 491 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 492 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 493 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 494 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 495 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 496 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 497 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 498 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 499 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 500 + }, + { + "textureId": 37, + "x": 509, + "y": 2, + "z": 501 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 511 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 512 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 514 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 515 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 516 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 511 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 512 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 514 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 515 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 516 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 510 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 510 + }, + { + "textureId": 37, + "x": 500, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 500, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 488, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 488, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 489, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 489, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 490, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 490, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 491, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 491, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 492, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 492, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 493, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 493, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 494, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 494, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 495, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 495, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 496, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 496, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 497, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 497, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 498, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 498, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 497, + "y": 1, + "z": 507 + }, + { + "textureId": 37, + "x": 497, + "y": 1, + "z": 508 + }, + { + "textureId": 37, + "x": 497, + "y": 2, + "z": 507 + }, + { + "textureId": 37, + "x": 497, + "y": 2, + "z": 508 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 507 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 508 + }, + { + "textureId": 37, + "x": 498, + "y": 1, + "z": 507 + }, + { + "textureId": 37, + "x": 498, + "y": 1, + "z": 508 + }, + { + "textureId": 37, + "x": 498, + "y": 2, + "z": 507 + }, + { + "textureId": 37, + "x": 498, + "y": 2, + "z": 508 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 507 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 508 + }, + { + "textureId": 37, + "x": 490, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 491, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 492, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 493, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 494, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 495, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 496, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 497, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 498, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 490, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 491, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 492, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 493, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 494, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 495, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 496, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 497, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 498, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 501, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 502, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 503, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 504, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 505, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 506, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 507, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 508, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 491 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 492 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 493 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 494 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 495 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 496 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 497 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 498 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 499 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 500 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 501 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 502 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 503 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 504 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 505 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 506 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 507 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 508 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 484 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 485 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 486 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 487 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 489 + }, + { + "textureId": 37, + "x": 509, + "y": 3, + "z": 490 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 488, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 489, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 490, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 491, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 492, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 493, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 494, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 495, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 496, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 497, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 498, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 499, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 500, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 501, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 502, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 503, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 504, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 505, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 506, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 507, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 508, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 484 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 485 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 486 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 487 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 489 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 490 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 491 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 492 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 493 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 494 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 495 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 496 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 497 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 498 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 499 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 500 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 501 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 502 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 503 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 504 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 505 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 506 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 507 + }, + { + "textureId": 37, + "x": 487, + "y": 3, + "z": 508 + }, + { + "textureId": 2, + "x": 500, + "y": 1, + "z": 491 + }, + { + "textureId": 2, + "x": 499, + "y": 1, + "z": 492 + }, + { + "textureId": 6, + "x": 497, + "y": 1, + "z": 492 + }, + { + "textureId": 6, + "x": 499, + "y": 1, + "z": 493 + }, + { + "textureId": 6, + "x": 499, + "y": 2, + "z": 492 + }, + { + "textureId": 21, + "x": 497, + "y": 2, + "z": 492 + }, + { + "textureId": 21, + "x": 499, + "y": 2, + "z": 493 + }, + { + "textureId": 21, + "x": 499, + "y": 3, + "z": 492 + }, + { + "textureId": 21, + "x": 498, + "y": 1, + "z": 493 + }, + { + "textureId": 8, + "x": 497, + "y": 1, + "z": 491 + }, + { + "textureId": 8, + "x": 496, + "y": 1, + "z": 491 + }, + { + "textureId": 8, + "x": 497, + "y": 1, + "z": 493 + }, + { + "textureId": 8, + "x": 499, + "y": 1, + "z": 494 + }, + { + "textureId": 8, + "x": 503, + "y": 1, + "z": 493 + }, + { + "textureId": 8, + "x": 502, + "y": 1, + "z": 493 + }, + { + "textureId": 8, + "x": 501, + "y": 1, + "z": 493 + }, + { + "textureId": 8, + "x": 501, + "y": 2, + "z": 493 + }, + { + "textureId": 8, + "x": 502, + "y": 2, + "z": 493 + }, + { + "textureId": 8, + "x": 498, + "y": 2, + "z": 493 + }, + { + "textureId": 8, + "x": 498, + "y": 3, + "z": 493 + }, + { + "textureId": 8, + "x": 499, + "y": 3, + "z": 493 + }, + { + "textureId": 8, + "x": 500, + "y": 2, + "z": 493 + }, + { + "textureId": 8, + "x": 500, + "y": 3, + "z": 493 + }, + { + "textureId": 8, + "x": 501, + "y": 3, + "z": 493 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 510, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 511, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 512, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 513, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 514, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 515, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 516, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 517, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 518, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 519, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 520, + "y": 0, + "z": 517 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 483 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 484 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 485 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 486 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 487 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 488 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 489 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 490 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 491 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 492 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 493 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 494 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 495 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 496 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 497 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 498 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 499 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 500 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 501 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 502 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 514 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 515 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 516 + }, + { + "textureId": 24, + "x": 521, + "y": 0, + "z": 517 + }, + { + "textureId": 37, + "x": 510, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 511, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 512, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 513, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 514, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 515, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 516, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 517, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 518, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 519, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 520, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 517 + }, + { + "textureId": 37, + "x": 510, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 510, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 511, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 511, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 512, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 512, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 513, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 513, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 514, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 514, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 515, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 515, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 516, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 516, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 517, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 517, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 518, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 518, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 519, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 519, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 520, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 520, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 517 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 517 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 493 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 494 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 495 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 496 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 497 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 498 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 499 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 500 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 501 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 504 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 505 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 507 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 508 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 510 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 511 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 512 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 514 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 515 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 516 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 493 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 494 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 495 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 496 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 497 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 498 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 499 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 500 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 501 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 502 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 504 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 505 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 507 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 508 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 510 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 511 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 512 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 514 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 515 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 516 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 493 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 494 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 495 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 496 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 497 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 498 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 499 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 500 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 501 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 502 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 503 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 504 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 505 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 506 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 507 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 508 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 514 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 515 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 516 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 484 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 485 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 486 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 487 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 489 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 490 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 491 + }, + { + "textureId": 37, + "x": 521, + "y": 1, + "z": 492 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 484 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 485 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 486 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 487 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 489 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 490 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 491 + }, + { + "textureId": 37, + "x": 521, + "y": 2, + "z": 492 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 484 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 485 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 486 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 487 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 489 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 490 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 491 + }, + { + "textureId": 37, + "x": 521, + "y": 3, + "z": 492 + }, + { + "textureId": 37, + "x": 510, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 510, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 510, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 511, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 511, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 511, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 512, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 512, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 512, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 513, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 513, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 513, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 514, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 514, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 514, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 515, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 515, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 515, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 516, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 516, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 516, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 517, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 517, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 517, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 518, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 518, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 518, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 519, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 519, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 519, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 520, + "y": 1, + "z": 483 + }, + { + "textureId": 37, + "x": 520, + "y": 2, + "z": 483 + }, + { + "textureId": 37, + "x": 520, + "y": 3, + "z": 483 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 521, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 517 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 483 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 509, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 512, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 513, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 514, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 515, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 516, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 517, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 518, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 519, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 515 + }, + { + "textureId": 37, + "x": 520, + "y": 4, + "z": 516 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 484 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 485 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 486 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 487 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 488 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 489 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 490 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 491 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 492 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 493 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 494 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 495 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 496 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 497 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 498 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 499 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 500 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 501 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 502 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 503 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 511, + "y": 4, + "z": 514 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 510, + "y": 4, + "z": 514 + }, + { + "textureId": 11, + "x": 512, + "y": 5, + "z": 516 + }, + { + "textureId": 11, + "x": 512, + "y": 5, + "z": 515 + }, + { + "textureId": 11, + "x": 511, + "y": 5, + "z": 514 + }, + { + "textureId": 11, + "x": 510, + "y": 5, + "z": 514 + }, + { + "textureId": 11, + "x": 509, + "y": 5, + "z": 515 + }, + { + "textureId": 11, + "x": 509, + "y": 5, + "z": 517 + }, + { + "textureId": 11, + "x": 509, + "y": 5, + "z": 516 + }, + { + "textureId": 11, + "x": 509, + "y": 5, + "z": 514 + }, + { + "textureId": 11, + "x": 512, + "y": 5, + "z": 514 + }, + { + "textureId": 11, + "x": 510, + "y": 5, + "z": 517 + }, + { + "textureId": 11, + "x": 511, + "y": 5, + "z": 517 + }, + { + "textureId": 11, + "x": 512, + "y": 5, + "z": 517 + }, + { + "textureId": 11, + "x": 509, + "y": 6, + "z": 517 + }, + { + "textureId": 11, + "x": 510, + "y": 6, + "z": 517 + }, + { + "textureId": 11, + "x": 511, + "y": 6, + "z": 517 + }, + { + "textureId": 11, + "x": 512, + "y": 6, + "z": 517 + }, + { + "textureId": 11, + "x": 509, + "y": 6, + "z": 514 + }, + { + "textureId": 11, + "x": 509, + "y": 6, + "z": 515 + }, + { + "textureId": 11, + "x": 509, + "y": 6, + "z": 516 + }, + { + "textureId": 11, + "x": 511, + "y": 6, + "z": 514 + }, + { + "textureId": 11, + "x": 512, + "y": 6, + "z": 514 + }, + { + "textureId": 11, + "x": 512, + "y": 6, + "z": 515 + }, + { + "textureId": 11, + "x": 512, + "y": 6, + "z": 516 + }, + { + "textureId": 11, + "x": 510, + "y": 6, + "z": 514 + }, + { + "textureId": 29, + "x": 510, + "y": 1, + "z": 499 + }, + { + "textureId": 29, + "x": 511, + "y": 1, + "z": 499 + }, + { + "textureId": 29, + "x": 512, + "y": 1, + "z": 499 + }, + { + "textureId": 29, + "x": 513, + "y": 1, + "z": 499 + }, + { + "textureId": 29, + "x": 514, + "y": 1, + "z": 499 + }, + { + "textureId": 29, + "x": 510, + "y": 2, + "z": 499 + }, + { + "textureId": 29, + "x": 510, + "y": 3, + "z": 499 + }, + { + "textureId": 29, + "x": 511, + "y": 2, + "z": 499 + }, + { + "textureId": 29, + "x": 511, + "y": 3, + "z": 499 + }, + { + "textureId": 29, + "x": 512, + "y": 2, + "z": 499 + }, + { + "textureId": 29, + "x": 512, + "y": 3, + "z": 499 + }, + { + "textureId": 29, + "x": 520, + "y": 1, + "z": 495 + }, + { + "textureId": 29, + "x": 520, + "y": 2, + "z": 495 + }, + { + "textureId": 29, + "x": 520, + "y": 3, + "z": 495 + }, + { + "textureId": 29, + "x": 516, + "y": 3, + "z": 495 + }, + { + "textureId": 29, + "x": 517, + "y": 3, + "z": 495 + }, + { + "textureId": 29, + "x": 518, + "y": 3, + "z": 495 + }, + { + "textureId": 29, + "x": 519, + "y": 3, + "z": 495 + }, + { + "textureId": 29, + "x": 516, + "y": 2, + "z": 495 + }, + { + "textureId": 29, + "x": 516, + "y": 1, + "z": 495 + }, + { + "textureId": 38, + "x": 510, + "y": 1, + "z": 495 + }, + { + "textureId": 38, + "x": 510, + "y": 1, + "z": 496 + }, + { + "textureId": 38, + "x": 511, + "y": 1, + "z": 495 + }, + { + "textureId": 38, + "x": 511, + "y": 1, + "z": 496 + }, + { + "textureId": 38, + "x": 512, + "y": 1, + "z": 495 + }, + { + "textureId": 38, + "x": 512, + "y": 1, + "z": 496 + }, + { + "textureId": 38, + "x": 513, + "y": 1, + "z": 495 + }, + { + "textureId": 38, + "x": 513, + "y": 1, + "z": 496 + }, + { + "textureId": 38, + "x": 510, + "y": 2, + "z": 495 + }, + { + "textureId": 38, + "x": 511, + "y": 2, + "z": 495 + }, + { + "textureId": 38, + "x": 512, + "y": 2, + "z": 495 + }, + { + "textureId": 38, + "x": 513, + "y": 2, + "z": 495 + }, + { + "textureId": 38, + "x": 510, + "y": 3, + "z": 495 + }, + { + "textureId": 38, + "x": 511, + "y": 3, + "z": 495 + }, + { + "textureId": 38, + "x": 512, + "y": 3, + "z": 495 + }, + { + "textureId": 38, + "x": 513, + "y": 3, + "z": 495 + }, + { + "textureId": 33, + "x": 515, + "y": 1, + "z": 488 + }, + { + "textureId": 32, + "x": 515, + "y": 1, + "z": 489 + }, + { + "textureId": 27, + "x": 515, + "y": 1, + "z": 490 + }, + { + "textureId": 30, + "x": 515, + "y": 1, + "z": 491 + }, + { + "textureId": 38, + "x": 515, + "y": 1, + "z": 492 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 453, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 454, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 455, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 456, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 457, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 458, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 459, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 460, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 461, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 462, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 463, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 464, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 465, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 466, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 467, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 468, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 469, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 470, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 471, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 472, + "y": 0, + "z": 513 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 488 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 489 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 490 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 491 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 492 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 493 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 494 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 495 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 496 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 497 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 498 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 499 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 500 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 501 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 502 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 503 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 504 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 505 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 506 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 507 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 508 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 509 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 510 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 511 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 512 + }, + { + "textureId": 18, + "x": 473, + "y": 0, + "z": 513 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 489 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 490 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 491 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 492 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 493 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 494 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 495 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 496 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 497 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 498 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 499 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 500 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 501 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 504 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 505 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 506 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 507 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 508 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 509 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 510 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 511 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 512 + }, + { + "textureId": 37, + "x": 453, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 489 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 490 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 491 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 492 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 493 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 494 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 495 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 496 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 497 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 498 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 499 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 500 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 501 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 502 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 504 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 505 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 506 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 507 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 508 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 509 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 510 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 511 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 512 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 453, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 489 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 490 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 491 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 492 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 493 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 494 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 495 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 496 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 497 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 498 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 499 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 500 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 501 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 502 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 503 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 504 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 505 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 506 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 507 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 508 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 509 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 510 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 511 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 512 + }, + { + "textureId": 37, + "x": 453, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 454, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 454, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 454, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 455, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 455, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 455, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 456, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 456, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 456, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 457, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 457, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 457, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 458, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 458, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 458, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 459, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 459, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 459, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 460, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 460, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 460, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 461, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 461, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 461, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 462, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 462, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 462, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 463, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 463, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 463, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 464, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 464, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 464, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 465, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 465, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 465, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 466, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 466, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 466, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 467, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 467, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 467, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 468, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 468, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 468, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 469, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 469, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 469, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 470, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 470, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 470, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 471, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 471, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 471, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 472, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 472, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 472, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 513 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 513 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 513 + }, + { + "textureId": 37, + "x": 454, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 454, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 454, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 455, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 455, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 455, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 456, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 456, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 456, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 457, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 457, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 457, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 458, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 458, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 458, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 459, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 459, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 459, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 460, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 460, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 460, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 461, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 461, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 461, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 462, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 462, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 462, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 463, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 463, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 463, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 464, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 464, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 464, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 465, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 465, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 465, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 466, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 466, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 466, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 467, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 467, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 467, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 468, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 468, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 468, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 469, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 469, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 469, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 470, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 470, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 470, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 471, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 471, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 471, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 472, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 472, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 472, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 488 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 488 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 488 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 489 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 490 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 491 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 492 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 493 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 494 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 495 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 496 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 497 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 498 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 499 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 500 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 501 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 473, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 489 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 490 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 491 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 492 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 493 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 494 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 495 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 496 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 497 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 498 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 499 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 500 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 501 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 502 + }, + { + "textureId": 37, + "x": 473, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 489 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 490 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 491 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 492 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 493 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 494 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 495 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 496 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 497 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 498 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 499 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 500 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 501 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 502 + }, + { + "textureId": 37, + "x": 473, + "y": 3, + "z": 503 + }, + { + "textureId": 37, + "x": 467, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 468, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 469, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 470, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 471, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 472, + "y": 1, + "z": 503 + }, + { + "textureId": 37, + "x": 467, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 468, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 469, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 470, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 471, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 472, + "y": 2, + "z": 503 + }, + { + "textureId": 37, + "x": 467, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 465, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 466, + "y": 1, + "z": 502 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 504 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 505 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 506 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 507 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 453, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 454, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 455, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 456, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 457, + "y": 4, + "z": 513 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 508 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 509 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 510 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 511 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 512 + }, + { + "textureId": 37, + "x": 458, + "y": 4, + "z": 513 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 474, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 475, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 476, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 477, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 478, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 479, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 480, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 481, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 482, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 483, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 484, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 485, + "y": 0, + "z": 513 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 503 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 504 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 505 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 506 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 507 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 508 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 509 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 510 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 511 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 512 + }, + { + "textureId": 24, + "x": 486, + "y": 0, + "z": 513 + }, + { + "textureId": 28, + "x": 474, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 475, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 476, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 477, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 478, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 479, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 480, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 481, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 482, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 483, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 513 + }, + { + "textureId": 28, + "x": 474, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 475, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 476, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 477, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 478, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 479, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 480, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 481, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 482, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 483, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 503 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 504 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 505 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 506 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 507 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 508 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 509 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 510 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 511 + }, + { + "textureId": 28, + "x": 486, + "y": 1, + "z": 512 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 504 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 505 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 506 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 507 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 508 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 509 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 510 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 511 + }, + { + "textureId": 28, + "x": 485, + "y": 1, + "z": 512 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 504 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 505 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 506 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 507 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 508 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 509 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 510 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 511 + }, + { + "textureId": 28, + "x": 484, + "y": 1, + "z": 512 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 504 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 505 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 506 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 507 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 508 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 509 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 510 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 511 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 512 + }, + { + "textureId": 28, + "x": 486, + "y": 2, + "z": 503 + }, + { + "textureId": 28, + "x": 486, + "y": 3, + "z": 503 + }, + { + "textureId": 28, + "x": 485, + "y": 2, + "z": 503 + } + ] +}
\ No newline at end of file diff --git a/apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_BaseMap.png b/apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_BaseMap.png Binary files differnew file mode 100644 index 0000000..df63233 --- /dev/null +++ b/apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_BaseMap.png diff --git a/apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_Normal.png b/apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_Normal.png Binary files differnew file mode 100644 index 0000000..0d053e9 --- /dev/null +++ b/apps/openmb/resources/models/rocks/Rocks_lp_SM_Rock_01_Normal.png diff --git a/apps/openmb/resources/models/rocks/SM_Rocks_01.obj b/apps/openmb/resources/models/rocks/SM_Rocks_01.obj new file mode 100644 index 0000000..7ce69a3 --- /dev/null +++ b/apps/openmb/resources/models/rocks/SM_Rocks_01.obj @@ -0,0 +1,143 @@ +mtllib SM_Rocks_01.mtl +o SM_Rock_01 +usemtl SM_Rock_01 +v 25.26092529296875 -2.9519944190979004 -22.238948822021484 1 1 1 +v 17.55608558654785 28.462902069091797 -14.90195369720459 1 1 1 +v 25.384950637817383 -3.000762462615967 26.61064910888672 1 1 1 +v 25.384950637817383 -3.000762462615967 26.61064910888672 1 1 1 +v 18.888885498046875 22.837478637695312 17.41868782043457 1 1 1 +v -23.75592041015625 19.70545196533203 15.467035293579102 1 1 1 +v 25.384950637817383 -3.000762462615967 26.61064910888672 1 1 1 +v -23.75592041015625 19.70545196533203 15.467035293579102 1 1 1 +v -29.990339279174805 -3.1008284091949463 24.58433723449707 1 1 1 +v -29.990339279174805 -3.1008284091949463 24.58433723449707 1 1 1 +v -23.75592041015625 19.70545196533203 15.467035293579102 1 1 1 +v -16.769838333129883 34.94828796386719 -13.60036563873291 1 1 1 +v -29.990339279174805 -3.1008284091949463 24.58433723449707 1 1 1 +v -16.769838333129883 34.94828796386719 -13.60036563873291 1 1 1 +v -23.316240310668945 -2.7831718921661377 -22.27688217163086 1 1 1 +v -23.316240310668945 -2.7831718921661377 -22.27688217163086 1 1 1 +v 17.55608558654785 28.462902069091797 -14.90195369720459 1 1 1 +v 25.26092529296875 -2.9519944190979004 -22.238948822021484 1 1 1 +v 16.510061264038086 32.85257339477539 -5.287999629974365 1 1 1 +v 17.55608558654785 28.462902069091797 -14.90195369720459 1 1 1 +v 7.284137725830078 35.79560470581055 -13.225668907165527 1 1 1 +v 18.888885498046875 22.837478637695312 17.41868782043457 1 1 1 +v 16.510061264038086 32.85257339477539 -5.287999629974365 1 1 1 +v -23.75592041015625 19.70545196533203 15.467035293579102 1 1 1 +v 25.384950637817383 -3.000762462615967 26.61064910888672 1 1 1 +v 17.55608558654785 28.462902069091797 -14.90195369720459 1 1 1 +v 16.510061264038086 32.85257339477539 -5.287999629974365 1 1 1 +v 25.384950637817383 -3.000762462615967 26.61064910888672 1 1 1 +v 16.510061264038086 32.85257339477539 -5.287999629974365 1 1 1 +v 18.888885498046875 22.837478637695312 17.41868782043457 1 1 1 +v -23.75592041015625 19.70545196533203 15.467035293579102 1 1 1 +v 16.510061264038086 32.85257339477539 -5.287999629974365 1 1 1 +v 7.284137725830078 35.79560470581055 -13.225668907165527 1 1 1 +v -23.75592041015625 19.70545196533203 15.467035293579102 1 1 1 +v 7.284137725830078 35.79560470581055 -13.225668907165527 1 1 1 +v -16.769838333129883 34.94828796386719 -13.60036563873291 1 1 1 +v 17.55608558654785 28.462902069091797 -14.90195369720459 1 1 1 +v -23.316240310668945 -2.7831718921661377 -22.27688217163086 1 1 1 +v -16.769838333129883 34.94828796386719 -13.60036563873291 1 1 1 +v 17.55608558654785 28.462902069091797 -14.90195369720459 1 1 1 +v -16.769838333129883 34.94828796386719 -13.60036563873291 1 1 1 +v 7.284137725830078 35.79560470581055 -13.225668907165527 1 1 1 +vt 0.9151540398597717 0.6638060212135315 +vt 0.8233218789100647 0.6420246958732605 +vt 0.9151540994644165 0.525446355342865 +vt 0.6432810425758362 0.7442019581794739 +vt 0.7207525372505188 0.7599366903305054 +vt 0.7089783549308777 0.8796431422233582 +vt 0.6432810425758362 0.7442019581794739 +vt 0.7089783549308777 0.8796431422233582 +vt 0.643281102180481 0.9011420607566833 +vt 0.9023555517196655 0.2807621955871582 +vt 0.8462424278259277 0.2405529022216797 +vt 0.8163553476333618 0.14913451671600342 +vt 0.9023555517196655 0.2807621955871582 +vt 0.8163553476333618 0.14913451671600342 +vt 0.9274819493293762 0.14913451671600342 +vt 0.8163553476333618 0.003841996192932129 +vt 0.9079443216323853 0.1185804009437561 +vt 0.8163553476333618 0.14145052433013916 +vt 0.8106706142425537 0.61598140001297 +vt 0.8233218789100647 0.6420246958732605 +vt 0.7966386675834656 0.6379318237304688 +vt 0.7207525372505188 0.7599366903305054 +vt 0.7705004215240479 0.7734178900718689 +vt 0.7089783549308777 0.8796431422233582 +vt 0.9151540994644165 0.525446355342865 +vt 0.8233218789100647 0.6420246958732605 +vt 0.8106706142425537 0.61598140001297 +vt 0.9151540994644165 0.525446355342865 +vt 0.8106706142425537 0.61598140001297 +vt 0.8405073881149292 0.551552414894104 +vt 0.7089783549308777 0.8796431422233582 +vt 0.7705004215240479 0.7734178900718689 +vt 0.7857733368873596 0.800637423992157 +vt 0.7089783549308777 0.8796431422233582 +vt 0.7857733368873596 0.800637423992157 +vt 0.7835135459899902 0.8688094019889832 +vt 0.9079443216323853 0.1185804009437561 +vt 0.8163553476333618 0.003841996192932129 +vt 0.9260876178741455 0.02202659845352173 +vt 0.9079443216323853 0.1185804009437561 +vt 0.9260876178741455 0.02202659845352173 +vt 0.9291304349899292 0.09016966819763184 +vn 0.6726377770794297 0.32071716377217097 -0.6668574973017682 +vn 0.6339659239284751 0.4552281602650777 -0.6251835965531946 +vn 0.6144392709305254 0.41362667525230684 0.6718462293249006 +vn 0.6144392709305254 0.41362667525230684 0.6718462293249006 +vn 0.5201511502918131 0.6370423582962276 0.5688759219605662 +vn -0.6344013988511402 0.5915086435673553 0.4976468524172781 +vn 0.6144392709305254 0.41362667525230684 0.6718462293249006 +vn -0.6344013988511402 0.5915086435673553 0.4976468524172781 +vn -0.676035904620863 0.39984581723878665 0.6189497379433149 +vn -0.676035904620863 0.39984581723878665 0.6189497379433149 +vn -0.6344013988511402 0.5915086435673553 0.4976468524172781 +vn -0.4690241375337951 0.7922316552647998 -0.39036567831595415 +vn -0.676035904620863 0.39984581723878665 0.6189497379433149 +vn -0.4690241375337951 0.7922316552647998 -0.39036567831595415 +vn -0.6253659710280434 0.2808616452673895 -0.7280344349670883 +vn -0.6253659710280434 0.2808616452673895 -0.7280344349670883 +vn 0.6339659239284751 0.4552281602650777 -0.6251835965531946 +vn 0.6726377770794297 0.32071716377217097 -0.6668574973017682 +vn 0.5808586579053835 0.8002336535071202 0.1490950010262017 +vn 0.6339659239284751 0.4552281602650777 -0.6251835965531946 +vn 0.08841150891547786 0.8997927794700963 -0.42726614551678077 +vn 0.5201511502918131 0.6370423582962276 0.5688759219605662 +vn 0.5808586579053835 0.8002336535071202 0.1490950010262017 +vn -0.6344013988511402 0.5915086435673553 0.4976468524172781 +vn 0.6144392709305254 0.41362667525230684 0.6718462293249006 +vn 0.6339659239284751 0.4552281602650777 -0.6251835965531946 +vn 0.5808586579053835 0.8002336535071202 0.1490950010262017 +vn 0.6144392709305254 0.41362667525230684 0.6718462293249006 +vn 0.5808586579053835 0.8002336535071202 0.1490950010262017 +vn 0.5201511502918131 0.6370423582962276 0.5688759219605662 +vn -0.6344013988511402 0.5915086435673553 0.4976468524172781 +vn 0.5808586579053835 0.8002336535071202 0.1490950010262017 +vn 0.08841150891547786 0.8997927794700963 -0.42726614551678077 +vn -0.6344013988511402 0.5915086435673553 0.4976468524172781 +vn 0.08841150891547786 0.8997927794700963 -0.42726614551678077 +vn -0.4690241375337951 0.7922316552647998 -0.39036567831595415 +vn 0.6339659239284751 0.4552281602650777 -0.6251835965531946 +vn -0.6253659710280434 0.2808616452673895 -0.7280344349670883 +vn -0.4690241375337951 0.7922316552647998 -0.39036567831595415 +vn 0.6339659239284751 0.4552281602650777 -0.6251835965531946 +vn -0.4690241375337951 0.7922316552647998 -0.39036567831595415 +vn 0.08841150891547786 0.8997927794700963 -0.42726614551678077 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 8/8/8 9/9/9 +f 10/10/10 11/11/11 12/12/12 +f 13/13/13 14/14/14 15/15/15 +f 16/16/16 17/17/17 18/18/18 +f 19/19/19 20/20/20 21/21/21 +f 22/22/22 23/23/23 24/24/24 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 29/29/29 30/30/30 +f 31/31/31 32/32/32 33/33/33 +f 34/34/34 35/35/35 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 40/40/40 41/41/41 42/42/42 diff --git a/apps/openmb/resources/models/rocks/SM_Rocks_02.obj b/apps/openmb/resources/models/rocks/SM_Rocks_02.obj new file mode 100644 index 0000000..286e946 --- /dev/null +++ b/apps/openmb/resources/models/rocks/SM_Rocks_02.obj @@ -0,0 +1,723 @@ +mtllib SM_Rocks_02.mtl +o SM_Rock_02 +usemtl SM_Rock_01 +v -24.055938720703125 -2.7198753356933594 21.76458168029785 1 1 1 +v -23.67823028564453 5.3347392082214355 23.636808395385742 1 1 1 +v -23.61898422241211 5.268172740936279 -0.3714485168457031 1 1 1 +v -24.055938720703125 -2.7198753356933594 21.76458168029785 1 1 1 +v -23.61898422241211 5.268172740936279 -0.3714485168457031 1 1 1 +v -24.176836013793945 -2.7240138053894043 -0.34766215085983276 1 1 1 +v -23.67823028564453 5.3347392082214355 23.636808395385742 1 1 1 +v -22.744583129882812 13.409550666809082 23.675697326660156 1 1 1 +v -22.13628387451172 13.480212211608887 -0.4199879765510559 1 1 1 +v -23.67823028564453 5.3347392082214355 23.636808395385742 1 1 1 +v -22.13628387451172 13.480212211608887 -0.4199879765510559 1 1 1 +v -23.61898422241211 5.268172740936279 -0.3714485168457031 1 1 1 +v -23.61898422241211 5.268172740936279 -0.3714485168457031 1 1 1 +v -22.13628387451172 13.480212211608887 -0.4199879765510559 1 1 1 +v -18.710731506347656 12.634712219238281 -22.355607986450195 1 1 1 +v -23.61898422241211 5.268172740936279 -0.3714485168457031 1 1 1 +v -18.710731506347656 12.634712219238281 -22.355607986450195 1 1 1 +v -20.693063735961914 4.721319198608398 -21.627622604370117 1 1 1 +v -24.176836013793945 -2.7240138053894043 -0.34766215085983276 1 1 1 +v -23.61898422241211 5.268172740936279 -0.3714485168457031 1 1 1 +v -20.693063735961914 4.721319198608398 -21.627622604370117 1 1 1 +v -24.176836013793945 -2.7240138053894043 -0.34766215085983276 1 1 1 +v -20.693063735961914 4.721319198608398 -21.627622604370117 1 1 1 +v -22.415781021118164 -2.731252431869507 -20.6809024810791 1 1 1 +v -22.415781021118164 -2.731252431869507 -20.6809024810791 1 1 1 +v -20.693063735961914 4.721319198608398 -21.627622604370117 1 1 1 +v -0.5668163299560547 7.3641357421875 -23.636262893676758 1 1 1 +v -22.415781021118164 -2.731252431869507 -20.6809024810791 1 1 1 +v -0.5668163299560547 7.3641357421875 -23.636262893676758 1 1 1 +v -1.9873559474945068 -2.724776029586792 -22.56745147705078 1 1 1 +v -20.693063735961914 4.721319198608398 -21.627622604370117 1 1 1 +v -18.710731506347656 12.634712219238281 -22.355607986450195 1 1 1 +v 0.5532503128051758 17.697351455688477 -23.990585327148438 1 1 1 +v -20.693063735961914 4.721319198608398 -21.627622604370117 1 1 1 +v 0.5532503128051758 17.697351455688477 -23.990585327148438 1 1 1 +v -0.5668163299560547 7.3641357421875 -23.636262893676758 1 1 1 +v -0.5668163299560547 7.3641357421875 -23.636262893676758 1 1 1 +v 0.5532503128051758 17.697351455688477 -23.990585327148438 1 1 1 +v 22.11053466796875 21.398813247680664 -23.82655906677246 1 1 1 +v -0.5668163299560547 7.3641357421875 -23.636262893676758 1 1 1 +v 22.11053466796875 21.398813247680664 -23.82655906677246 1 1 1 +v 21.990467071533203 9.517776489257812 -23.895198822021484 1 1 1 +v -1.9873559474945068 -2.724776029586792 -22.56745147705078 1 1 1 +v -0.5668163299560547 7.3641357421875 -23.636262893676758 1 1 1 +v 21.990467071533203 9.517776489257812 -23.895198822021484 1 1 1 +v -1.9873559474945068 -2.724776029586792 -22.56745147705078 1 1 1 +v 21.990467071533203 9.517776489257812 -23.895198822021484 1 1 1 +v 19.872539520263672 -2.7096211910247803 -22.1872615814209 1 1 1 +v 19.872539520263672 -2.7096211910247803 -22.1872615814209 1 1 1 +v 21.990467071533203 9.517776489257812 -23.895198822021484 1 1 1 +v 22.783470153808594 9.66994571685791 0.16245421767234802 1 1 1 +v 19.872539520263672 -2.7096211910247803 -22.1872615814209 1 1 1 +v 22.783470153808594 9.66994571685791 0.16245421767234802 1 1 1 +v 20.263948440551758 -2.715498685836792 -0.35254400968551636 1 1 1 +v 21.990467071533203 9.517776489257812 -23.895198822021484 1 1 1 +v 22.11053466796875 21.398813247680664 -23.82655906677246 1 1 1 +v 24.008560180664062 22.104433059692383 -0.38888269662857056 1 1 1 +v 21.990467071533203 9.517776489257812 -23.895198822021484 1 1 1 +v 24.008560180664062 22.104433059692383 -0.38888269662857056 1 1 1 +v 22.783470153808594 9.66994571685791 0.16245421767234802 1 1 1 +v 22.783470153808594 9.66994571685791 0.16245421767234802 1 1 1 +v 24.008560180664062 22.104433059692383 -0.38888269662857056 1 1 1 +v 20.42901611328125 21.42203712463379 21.506250381469727 1 1 1 +v 22.783470153808594 9.66994571685791 0.16245421767234802 1 1 1 +v 20.42901611328125 21.42203712463379 21.506250381469727 1 1 1 +v 21.26266860961914 9.389525413513184 22.756641387939453 1 1 1 +v 20.263948440551758 -2.715498685836792 -0.35254400968551636 1 1 1 +v 22.783470153808594 9.66994571685791 0.16245421767234802 1 1 1 +v 21.26266860961914 9.389525413513184 22.756641387939453 1 1 1 +v 20.263948440551758 -2.715498685836792 -0.35254400968551636 1 1 1 +v 21.26266860961914 9.389525413513184 22.756641387939453 1 1 1 +v 18.593219757080078 -2.662442207336426 20.46881103515625 1 1 1 +v 18.593219757080078 -2.662442207336426 20.46881103515625 1 1 1 +v 21.26266860961914 9.389525413513184 22.756641387939453 1 1 1 +v -0.6047964096069336 7.412437915802002 23.94782066345215 1 1 1 +v 18.593219757080078 -2.662442207336426 20.46881103515625 1 1 1 +v -0.6047964096069336 7.412437915802002 23.94782066345215 1 1 1 +v -2.012502670288086 -2.720414876937866 21.87948226928711 1 1 1 +v 21.26266860961914 9.389525413513184 22.756641387939453 1 1 1 +v 20.42901611328125 21.42203712463379 21.506250381469727 1 1 1 +v 0.5940914154052734 17.66459846496582 24.32925796508789 1 1 1 +v 21.26266860961914 9.389525413513184 22.756641387939453 1 1 1 +v 0.5940914154052734 17.66459846496582 24.32925796508789 1 1 1 +v -0.6047964096069336 7.412437915802002 23.94782066345215 1 1 1 +v -0.6047964096069336 7.412437915802002 23.94782066345215 1 1 1 +v 0.5940914154052734 17.66459846496582 24.32925796508789 1 1 1 +v -22.744583129882812 13.409550666809082 23.675697326660156 1 1 1 +v -0.6047964096069336 7.412437915802002 23.94782066345215 1 1 1 +v -22.744583129882812 13.409550666809082 23.675697326660156 1 1 1 +v -23.67823028564453 5.3347392082214355 23.636808395385742 1 1 1 +v -2.012502670288086 -2.720414876937866 21.87948226928711 1 1 1 +v -0.6047964096069336 7.412437915802002 23.94782066345215 1 1 1 +v -23.67823028564453 5.3347392082214355 23.636808395385742 1 1 1 +v -2.012502670288086 -2.720414876937866 21.87948226928711 1 1 1 +v -23.67823028564453 5.3347392082214355 23.636808395385742 1 1 1 +v -24.055938720703125 -2.7198753356933594 21.76458168029785 1 1 1 +v -18.710731506347656 12.634712219238281 -22.355607986450195 1 1 1 +v -22.13628387451172 13.480212211608887 -0.4199879765510559 1 1 1 +v -19.28179168701172 23.09201431274414 -0.40094390511512756 1 1 1 +v -18.710731506347656 12.634712219238281 -22.355607986450195 1 1 1 +v -19.28179168701172 23.09201431274414 -0.40094390511512756 1 1 1 +v -16.962766647338867 21.690853118896484 -20.4646053314209 1 1 1 +v -22.13628387451172 13.480212211608887 -0.4199879765510559 1 1 1 +v -22.744583129882812 13.409550666809082 23.675697326660156 1 1 1 +v -18.88330078125 22.80573844909668 20.25123405456543 1 1 1 +v -22.13628387451172 13.480212211608887 -0.4199879765510559 1 1 1 +v -18.88330078125 22.80573844909668 20.25123405456543 1 1 1 +v -19.28179168701172 23.09201431274414 -0.40094390511512756 1 1 1 +v -19.28179168701172 23.09201431274414 -0.40094390511512756 1 1 1 +v -18.88330078125 22.80573844909668 20.25123405456543 1 1 1 +v -15.017461776733398 32.02982711791992 16.262922286987305 1 1 1 +v -19.28179168701172 23.09201431274414 -0.40094390511512756 1 1 1 +v -15.017461776733398 32.02982711791992 16.262922286987305 1 1 1 +v -15.003299713134766 32.14637756347656 -0.40167802572250366 1 1 1 +v -16.962766647338867 21.690853118896484 -20.4646053314209 1 1 1 +v -19.28179168701172 23.09201431274414 -0.40094390511512756 1 1 1 +v -15.003299713134766 32.14637756347656 -0.40167802572250366 1 1 1 +v -16.962766647338867 21.690853118896484 -20.4646053314209 1 1 1 +v -15.003299713134766 32.14637756347656 -0.40167802572250366 1 1 1 +v -13.85345458984375 31.184247970581055 -16.449951171875 1 1 1 +v 0.0286102294921875 41.531524658203125 -16.41400146484375 1 1 1 +v -7.422924041748047 37.50237274169922 -17.331745147705078 1 1 1 +v -7.4855804443359375 37.742950439453125 -0.46993908286094666 1 1 1 +v 0.0286102294921875 41.531524658203125 -16.41400146484375 1 1 1 +v -7.4855804443359375 37.742950439453125 -0.46993908286094666 1 1 1 +v 0.22161006927490234 42.54776382446289 -0.5730391144752502 1 1 1 +v -7.422924041748047 37.50237274169922 -17.331745147705078 1 1 1 +v -13.85345458984375 31.184247970581055 -16.449951171875 1 1 1 +v -15.003299713134766 32.14637756347656 -0.40167802572250366 1 1 1 +v -7.422924041748047 37.50237274169922 -17.331745147705078 1 1 1 +v -15.003299713134766 32.14637756347656 -0.40167802572250366 1 1 1 +v -7.4855804443359375 37.742950439453125 -0.46993908286094666 1 1 1 +v -7.4855804443359375 37.742950439453125 -0.46993908286094666 1 1 1 +v -15.003299713134766 32.14637756347656 -0.40167802572250366 1 1 1 +v -15.017461776733398 32.02982711791992 16.262922286987305 1 1 1 +v -7.4855804443359375 37.742950439453125 -0.46993908286094666 1 1 1 +v -15.017461776733398 32.02982711791992 16.262922286987305 1 1 1 +v -7.476067543029785 37.67071533203125 16.48223304748535 1 1 1 +v 0.22161006927490234 42.54776382446289 -0.5730391144752502 1 1 1 +v -7.4855804443359375 37.742950439453125 -0.46993908286094666 1 1 1 +v -7.476067543029785 37.67071533203125 16.48223304748535 1 1 1 +v 0.22161006927490234 42.54776382446289 -0.5730391144752502 1 1 1 +v -7.476067543029785 37.67071533203125 16.48223304748535 1 1 1 +v 0.3472328186035156 42.346988677978516 16.059913635253906 1 1 1 +v -22.744583129882812 13.409550666809082 23.675697326660156 1 1 1 +v 0.5940914154052734 17.66459846496582 24.32925796508789 1 1 1 +v -3.412318229675293 27.7247314453125 20.515581130981445 1 1 1 +v -22.744583129882812 13.409550666809082 23.675697326660156 1 1 1 +v -3.412318229675293 27.7247314453125 20.515581130981445 1 1 1 +v -18.88330078125 22.80573844909668 20.25123405456543 1 1 1 +v 0.5940914154052734 17.66459846496582 24.32925796508789 1 1 1 +v 20.42901611328125 21.42203712463379 21.506250381469727 1 1 1 +v 12.146782875061035 32.61277770996094 20.98918342590332 1 1 1 +v 0.5940914154052734 17.66459846496582 24.32925796508789 1 1 1 +v 12.146782875061035 32.61277770996094 20.98918342590332 1 1 1 +v -3.412318229675293 27.7247314453125 20.515581130981445 1 1 1 +v -3.412318229675293 27.7247314453125 20.515581130981445 1 1 1 +v 12.146782875061035 32.61277770996094 20.98918342590332 1 1 1 +v 0.3472328186035156 42.346988677978516 16.059913635253906 1 1 1 +v -3.412318229675293 27.7247314453125 20.515581130981445 1 1 1 +v 0.3472328186035156 42.346988677978516 16.059913635253906 1 1 1 +v -7.476067543029785 37.67071533203125 16.48223304748535 1 1 1 +v -18.88330078125 22.80573844909668 20.25123405456543 1 1 1 +v -3.412318229675293 27.7247314453125 20.515581130981445 1 1 1 +v -7.476067543029785 37.67071533203125 16.48223304748535 1 1 1 +v -18.88330078125 22.80573844909668 20.25123405456543 1 1 1 +v -7.476067543029785 37.67071533203125 16.48223304748535 1 1 1 +v -15.017461776733398 32.02982711791992 16.262922286987305 1 1 1 +v 22.11053466796875 21.398813247680664 -23.82655906677246 1 1 1 +v 0.5532503128051758 17.697351455688477 -23.990585327148438 1 1 1 +v -3.47137451171875 27.784055709838867 -22.0271053314209 1 1 1 +v 22.11053466796875 21.398813247680664 -23.82655906677246 1 1 1 +v -3.47137451171875 27.784055709838867 -22.0271053314209 1 1 1 +v 12.162232398986816 32.550628662109375 -21.80869483947754 1 1 1 +v 0.5532503128051758 17.697351455688477 -23.990585327148438 1 1 1 +v -18.710731506347656 12.634712219238281 -22.355607986450195 1 1 1 +v -16.962766647338867 21.690853118896484 -20.4646053314209 1 1 1 +v 0.5532503128051758 17.697351455688477 -23.990585327148438 1 1 1 +v -16.962766647338867 21.690853118896484 -20.4646053314209 1 1 1 +v -3.47137451171875 27.784055709838867 -22.0271053314209 1 1 1 +v -3.47137451171875 27.784055709838867 -22.0271053314209 1 1 1 +v -16.962766647338867 21.690853118896484 -20.4646053314209 1 1 1 +v -13.85345458984375 31.184247970581055 -16.449951171875 1 1 1 +v -3.47137451171875 27.784055709838867 -22.0271053314209 1 1 1 +v -13.85345458984375 31.184247970581055 -16.449951171875 1 1 1 +v -7.422924041748047 37.50237274169922 -17.331745147705078 1 1 1 +v 12.162232398986816 32.550628662109375 -21.80869483947754 1 1 1 +v -3.47137451171875 27.784055709838867 -22.0271053314209 1 1 1 +v -7.422924041748047 37.50237274169922 -17.331745147705078 1 1 1 +v 12.162232398986816 32.550628662109375 -21.80869483947754 1 1 1 +v -7.422924041748047 37.50237274169922 -17.331745147705078 1 1 1 +v 0.0286102294921875 41.531524658203125 -16.41400146484375 1 1 1 +v 20.42901611328125 21.42203712463379 21.506250381469727 1 1 1 +v 24.008560180664062 22.104433059692383 -0.38888269662857056 1 1 1 +v 12.492728233337402 32.62037658691406 -0.8444314002990723 1 1 1 +v 20.42901611328125 21.42203712463379 21.506250381469727 1 1 1 +v 12.492728233337402 32.62037658691406 -0.8444314002990723 1 1 1 +v 12.146782875061035 32.61277770996094 20.98918342590332 1 1 1 +v 24.008560180664062 22.104433059692383 -0.38888269662857056 1 1 1 +v 22.11053466796875 21.398813247680664 -23.82655906677246 1 1 1 +v 12.162232398986816 32.550628662109375 -21.80869483947754 1 1 1 +v 24.008560180664062 22.104433059692383 -0.38888269662857056 1 1 1 +v 12.162232398986816 32.550628662109375 -21.80869483947754 1 1 1 +v 12.492728233337402 32.62037658691406 -0.8444314002990723 1 1 1 +v 12.492728233337402 32.62037658691406 -0.8444314002990723 1 1 1 +v 12.162232398986816 32.550628662109375 -21.80869483947754 1 1 1 +v 0.0286102294921875 41.531524658203125 -16.41400146484375 1 1 1 +v 12.492728233337402 32.62037658691406 -0.8444314002990723 1 1 1 +v 0.0286102294921875 41.531524658203125 -16.41400146484375 1 1 1 +v 0.22161006927490234 42.54776382446289 -0.5730391144752502 1 1 1 +v 12.146782875061035 32.61277770996094 20.98918342590332 1 1 1 +v 12.492728233337402 32.62037658691406 -0.8444314002990723 1 1 1 +v 0.22161006927490234 42.54776382446289 -0.5730391144752502 1 1 1 +v 12.146782875061035 32.61277770996094 20.98918342590332 1 1 1 +v 0.22161006927490234 42.54776382446289 -0.5730391144752502 1 1 1 +v 0.3472328186035156 42.346988677978516 16.059913635253906 1 1 1 +vt 0.798905611038208 0.8846748471260071 +vt 0.7935385704040527 0.8622298836708069 +vt 0.8614128828048706 0.8630435466766357 +vt 0.798905611038208 0.8846748471260071 +vt 0.8614128828048706 0.8630435466766357 +vt 0.8613858222961426 0.8853878974914551 +vt 0.7935385704040527 0.8622298836708069 +vt 0.7934572696685791 0.8393980860710144 +vt 0.861678957939148 0.8394591808319092 +vt 0.7935385704040527 0.8622298836708069 +vt 0.861678957939148 0.8394591808319092 +vt 0.8614128828048706 0.8630435466766357 +vt 0.8614128828048706 0.8630435466766357 +vt 0.861678957939148 0.8394591808319092 +vt 0.9243384599685669 0.8400381207466125 +vt 0.8614128828048706 0.8630435466766357 +vt 0.9243384599685669 0.8400381207466125 +vt 0.9220530390739441 0.8631267547607422 +vt 0.8613858222961426 0.8853878974914551 +vt 0.8614128828048706 0.8630435466766357 +vt 0.9220530390739441 0.8631267547607422 +vt 0.8613858222961426 0.8853878974914551 +vt 0.9220530390739441 0.8631267547607422 +vt 0.9191895127296448 0.8847643733024597 +vt 0.003841985482722521 0.9961579442024231 +vt 0.008685518056154251 0.9752037525177002 +vt 0.06587769836187363 0.9673058390617371 +vt 0.003841985482722521 0.9961579442024231 +vt 0.06587769836187363 0.9673058390617371 +vt 0.06193755194544792 0.9956760406494141 +vt 0.008685518056154251 0.9752037525177002 +vt 0.01420876570045948 0.9528955817222595 +vt 0.06882666051387787 0.9381227493286133 +vt 0.008685518056154251 0.9752037525177002 +vt 0.06882666051387787 0.9381227493286133 +vt 0.06587769836187363 0.9673058390617371 +vt 0.06587769836187363 0.9673058390617371 +vt 0.06882666051387787 0.9381227493286133 +vt 0.12962321937084198 0.9267666339874268 +vt 0.06587769836187363 0.9673058390617371 +vt 0.12962321937084198 0.9267666339874268 +vt 0.12962321937084198 0.9603638648986816 +vt 0.06193755194544792 0.9956760406494141 +vt 0.06587769836187363 0.9673058390617371 +vt 0.12962321937084198 0.9603638648986816 +vt 0.06193755194544792 0.9956760406494141 +vt 0.12962321937084198 0.9603638648986816 +vt 0.12364975363016129 0.9946857690811157 +vt 0.559004008769989 0.9372794032096863 +vt 0.5399733185768127 0.9415040612220764 +vt 0.5436710715293884 0.8734409809112549 +vt 0.559004008769989 0.9372794032096863 +vt 0.5436710715293884 0.8734409809112549 +vt 0.5619469881057739 0.8754901885986328 +vt 0.5399733185768127 0.9415040612220764 +vt 0.5175911784172058 0.9405732750892639 +vt 0.5224881172180176 0.8743122220039368 +vt 0.5399733185768127 0.9415040612220764 +vt 0.5224881172180176 0.8743122220039368 +vt 0.5436710715293884 0.8734409809112549 +vt 0.5436710715293884 0.8734409809112549 +vt 0.5224881172180176 0.8743122220039368 +vt 0.5184112787246704 0.8121017217636108 +vt 0.5436710715293884 0.8734409809112549 +vt 0.5184112787246704 0.8121017217636108 +vt 0.5432066917419434 0.8093778491020203 +vt 0.5619469881057739 0.8754901885986328 +vt 0.5436710715293884 0.8734409809112549 +vt 0.5432066917419434 0.8093778491020203 +vt 0.5619469881057739 0.8754901885986328 +vt 0.5432066917419434 0.8093778491020203 +vt 0.5603617429733276 0.8164142966270447 +vt 0.33764275908470154 0.9348790049552917 +vt 0.30365124344825745 0.942414402961731 +vt 0.3093186318874359 0.8804537653923035 +vt 0.33764275908470154 0.9348790049552917 +vt 0.3093186318874359 0.8804537653923035 +vt 0.3378887474536896 0.8764901161193848 +vt 0.30365124344825745 0.942414402961731 +vt 0.2694956362247467 0.9400674104690552 +vt 0.28030648827552795 0.8838455677032471 +vt 0.30365124344825745 0.942414402961731 +vt 0.28030648827552795 0.8838455677032471 +vt 0.3093186318874359 0.8804537653923035 +vt 0.3093186318874359 0.8804537653923035 +vt 0.28030648827552795 0.8838455677032471 +vt 0.29231131076812744 0.8177387118339539 +vt 0.3093186318874359 0.8804537653923035 +vt 0.29231131076812744 0.8177387118339539 +vt 0.3151780068874359 0.8150942921638489 +vt 0.3378887474536896 0.8764901161193848 +vt 0.3093186318874359 0.8804537653923035 +vt 0.3151780068874359 0.8150942921638489 +vt 0.3378887474536896 0.8764901161193848 +vt 0.3151780068874359 0.8150942921638489 +vt 0.33787453174591064 0.8140461444854736 +vt 0.9243384599685669 0.8400381207466125 +vt 0.861678957939148 0.8394591808319092 +vt 0.8619852066040039 0.8110823631286621 +vt 0.9243384599685669 0.8400381207466125 +vt 0.8619852066040039 0.8110823631286621 +vt 0.9191564917564392 0.8138974905014038 +vt 0.861678957939148 0.8394591808319092 +vt 0.7934572696685791 0.8393980860710144 +vt 0.8036892414093018 0.8110170960426331 +vt 0.861678957939148 0.8394591808319092 +vt 0.8036892414093018 0.8110170960426331 +vt 0.8619852066040039 0.8110823631286621 +vt 0.8619852066040039 0.8110823631286621 +vt 0.8036892414093018 0.8110170960426331 +vt 0.8155189752578735 0.7831215858459473 +vt 0.8619852066040039 0.8110823631286621 +vt 0.8155189752578735 0.7831215858459473 +vt 0.8626238703727722 0.7832577228546143 +vt 0.9191564917564392 0.8138974905014038 +vt 0.8619852066040039 0.8110823631286621 +vt 0.8626238703727722 0.7832577228546143 +vt 0.9191564917564392 0.8138974905014038 +vt 0.8626238703727722 0.7832577228546143 +vt 0.9082185626029968 0.7855588793754578 +vt 0.9105263948440552 0.7475702166557312 +vt 0.9117996096611023 0.7637962698936462 +vt 0.8641217350959778 0.7627066969871521 +vt 0.9105263948440552 0.7475702166557312 +vt 0.8641217350959778 0.7627066969871521 +vt 0.8657678961753845 0.7442018389701843 +vt 0.9117996096611023 0.7637962698936462 +vt 0.9082185626029968 0.7855588793754578 +vt 0.8626238703727722 0.7832577228546143 +vt 0.9117996096611023 0.7637962698936462 +vt 0.8626238703727722 0.7832577228546143 +vt 0.8641217350959778 0.7627066969871521 +vt 0.8641217350959778 0.7627066969871521 +vt 0.8626238703727722 0.7832577228546143 +vt 0.8155189752578735 0.7831215858459473 +vt 0.8641217350959778 0.7627066969871521 +vt 0.8155189752578735 0.7831215858459473 +vt 0.8162076473236084 0.7624244689941406 +vt 0.8657678961753845 0.7442018389701843 +vt 0.8641217350959778 0.7627066969871521 +vt 0.8162076473236084 0.7624244689941406 +vt 0.8657678961753845 0.7442018389701843 +vt 0.8162076473236084 0.7624244689941406 +vt 0.8187801241874695 0.7442018389701843 +vt 0.29231131076812744 0.8177387118339539 +vt 0.28030648827552795 0.8838455677032471 +vt 0.25157809257507324 0.8725405335426331 +vt 0.29231131076812744 0.8177387118339539 +vt 0.25157809257507324 0.8725405335426331 +vt 0.2654893398284912 0.8287169933319092 +vt 0.28030648827552795 0.8838455677032471 +vt 0.2694956362247467 0.9400674104690552 +vt 0.23776744306087494 0.9166113138198853 +vt 0.28030648827552795 0.8838455677032471 +vt 0.23776744306087494 0.9166113138198853 +vt 0.25157809257507324 0.8725405335426331 +vt 0.25157809257507324 0.8725405335426331 +vt 0.23776744306087494 0.9166113138198853 +vt 0.20989131927490234 0.883242666721344 +vt 0.25157809257507324 0.8725405335426331 +vt 0.20989131927490234 0.883242666721344 +vt 0.22315941751003265 0.8610756993293762 +vt 0.2654893398284912 0.8287169933319092 +vt 0.25157809257507324 0.8725405335426331 +vt 0.22315941751003265 0.8610756993293762 +vt 0.2654893398284912 0.8287169933319092 +vt 0.22315941751003265 0.8610756993293762 +vt 0.2391199916601181 0.839714765548706 +vt 0.12962321937084198 0.9267666339874268 +vt 0.06882666051387787 0.9381227493286133 +vt 0.05680280178785324 0.9094063639640808 +vt 0.12962321937084198 0.9267666339874268 +vt 0.05680280178785324 0.9094063639640808 +vt 0.10081718862056732 0.8952670097351074 +vt 0.06882666051387787 0.9381227493286133 +vt 0.01420876570045948 0.9528955817222595 +vt 0.018542522564530373 0.9268742203712463 +vt 0.06882666051387787 0.9381227493286133 +vt 0.018542522564530373 0.9268742203712463 +vt 0.05680280178785324 0.9094063639640808 +vt 0.05680280178785324 0.9094063639640808 +vt 0.018542522564530373 0.9268742203712463 +vt 0.026310032233595848 0.8991629481315613 +vt 0.05680280178785324 0.9094063639640808 +vt 0.026310032233595848 0.8991629481315613 +vt 0.04447855055332184 0.8812142014503479 +vt 0.10081718862056732 0.8952670097351074 +vt 0.05680280178785324 0.9094063639640808 +vt 0.04447855055332184 0.8812142014503479 +vt 0.10081718862056732 0.8952670097351074 +vt 0.04447855055332184 0.8812142014503479 +vt 0.06525511294603348 0.8693552613258362 +vt 0.5184112787246704 0.8121017217636108 +vt 0.5224881172180176 0.8743122220039368 +vt 0.47829195857048035 0.8740934729576111 +vt 0.5184112787246704 0.8121017217636108 +vt 0.47829195857048035 0.8740934729576111 +vt 0.4796941876411438 0.8122531771659851 +vt 0.5224881172180176 0.8743122220039368 +vt 0.5175911784172058 0.9405732750892639 +vt 0.4757048189640045 0.9334274530410767 +vt 0.5224881172180176 0.8743122220039368 +vt 0.4757048189640045 0.9334274530410767 +vt 0.47829195857048035 0.8740934729576111 +vt 0.47829195857048035 0.8740934729576111 +vt 0.4757048189640045 0.9334274530410767 +vt 0.4337061643600464 0.9166962504386902 +vt 0.47829195857048035 0.8740934729576111 +vt 0.4337061643600464 0.9166962504386902 +vt 0.4337061643600464 0.8717978596687317 +vt 0.4796941876411438 0.8122531771659851 +vt 0.47829195857048035 0.8740934729576111 +vt 0.4337061643600464 0.8717978596687317 +vt 0.4796941876411438 0.8122531771659851 +vt 0.4337061643600464 0.8717978596687317 +vt 0.4359608292579651 0.8247285485267639 +vn -0.7658524512160326 -0.09311585147346466 0.6362385253745377 +vn -0.6960056284593561 -0.0192073337608014 0.7177793835731824 +vn -0.9882792960813065 0.13639172268933886 -0.06856625204043063 +vn -0.7658524512160326 -0.09311585147346466 0.6362385253745377 +vn -0.9882792960813065 0.13639172268933886 -0.06856625204043063 +vn -0.9936044277775063 0.09823478229962283 -0.05567915810677949 +vn -0.6960056284593561 -0.0192073337608014 0.7177793835731824 +vn -0.692892177480864 0.2335044537642879 0.6821847993455062 +vn -0.9690770227322479 0.2342792681825583 -0.07747869715119822 +vn -0.6960056284593561 -0.0192073337608014 0.7177793835731824 +vn -0.9690770227322479 0.2342792681825583 -0.07747869715119822 +vn -0.9882792960813065 0.13639172268933886 -0.06856625204043063 +vn -0.9882792960813065 0.13639172268933886 -0.06856625204043063 +vn -0.9690770227322479 0.2342792681825583 -0.07747869715119822 +vn -0.642982244231693 0.15608689182648408 -0.7498071190664456 +vn -0.9882792960813065 0.13639172268933886 -0.06856625204043063 +vn -0.642982244231693 0.15608689182648408 -0.7498071190664456 +vn -0.683877201053344 0.06026136995338454 -0.7271042161690341 +vn -0.9936044277775063 0.09823478229962283 -0.05567915810677949 +vn -0.9882792960813065 0.13639172268933886 -0.06856625204043063 +vn -0.683877201053344 0.06026136995338454 -0.7271042161690341 +vn -0.9936044277775063 0.09823478229962283 -0.05567915810677949 +vn -0.683877201053344 0.06026136995338454 -0.7271042161690341 +vn -0.7647800228916277 0.04492418735673611 -0.6427233728255246 +vn -0.7647800228916277 0.04492418735673611 -0.6427233728255246 +vn -0.683877201053344 0.06026136995338454 -0.7271042161690341 +vn -0.03997046448625307 -0.07198179419896308 -0.9966047276993278 +vn -0.7647800228916277 0.04492418735673611 -0.6427233728255246 +vn -0.03997046448625307 -0.07198179419896308 -0.9966047276993278 +vn -0.04449174744449951 -0.11033117321719993 -0.9928985429669293 +vn -0.683877201053344 0.06026136995338454 -0.7271042161690341 +vn -0.642982244231693 0.15608689182648408 -0.7498071190664456 +vn -0.06000629482956411 0.07591231495504497 -0.9953072716598597 +vn -0.683877201053344 0.06026136995338454 -0.7271042161690341 +vn -0.06000629482956411 0.07591231495504497 -0.9953072716598597 +vn -0.03997046448625307 -0.07198179419896308 -0.9966047276993278 +vn -0.03997046448625307 -0.07198179419896308 -0.9966047276993278 +vn -0.06000629482956411 0.07591231495504497 -0.9953072716598597 +vn 0.6848947465796044 0.2873341466318297 -0.6695956050386064 +vn -0.03997046448625307 -0.07198179419896308 -0.9966047276993278 +vn 0.6848947465796044 0.2873341466318297 -0.6695956050386064 +vn 0.6889308271838824 -0.12498175673661659 -0.7139705006782567 +vn -0.04449174744449951 -0.11033117321719993 -0.9928985429669293 +vn -0.03997046448625307 -0.07198179419896308 -0.9966047276993278 +vn 0.6889308271838824 -0.12498175673661659 -0.7139705006782567 +vn -0.04449174744449951 -0.11033117321719993 -0.9928985429669293 +vn 0.6889308271838824 -0.12498175673661659 -0.7139705006782567 +vn 0.6750775032660218 -0.2135959135395753 -0.7061495240409843 +vn 0.6750775032660218 -0.2135959135395753 -0.7061495240409843 +vn 0.6889308271838824 -0.12498175673661659 -0.7139705006782567 +vn 0.9928719399854794 -0.11584041315516197 0.0280412102005586 +vn 0.6750775032660218 -0.2135959135395753 -0.7061495240409843 +vn 0.9928719399854794 -0.11584041315516197 0.0280412102005586 +vn 0.9794475240871835 -0.2005157430712719 0.021817065340279825 +vn 0.6889308271838824 -0.12498175673661659 -0.7139705006782567 +vn 0.6848947465796044 0.2873341466318297 -0.6695956050386064 +vn 0.935117282275238 0.3536376869737989 0.022272286411464986 +vn 0.6889308271838824 -0.12498175673661659 -0.7139705006782567 +vn 0.935117282275238 0.3536376869737989 0.022272286411464986 +vn 0.9928719399854794 -0.11584041315516197 0.0280412102005586 +vn 0.9928719399854794 -0.11584041315516197 0.0280412102005586 +vn 0.935117282275238 0.3536376869737989 0.022272286411464986 +vn 0.6892475341759589 0.3110881084756211 0.6543409091577728 +vn 0.9928719399854794 -0.11584041315516197 0.0280412102005586 +vn 0.6892475341759589 0.3110881084756211 0.6543409091577728 +vn 0.6974296690735602 -0.1177265414858794 0.7069174761778901 +vn 0.9794475240871835 -0.2005157430712719 0.021817065340279825 +vn 0.9928719399854794 -0.11584041315516197 0.0280412102005586 +vn 0.6974296690735602 -0.1177265414858794 0.7069174761778901 +vn 0.9794475240871835 -0.2005157430712719 0.021817065340279825 +vn 0.6974296690735602 -0.1177265414858794 0.7069174761778901 +vn 0.673179723923595 -0.27288120103347857 0.687288083281442 +vn 0.673179723923595 -0.27288120103347857 0.687288083281442 +vn 0.6974296690735602 -0.1177265414858794 0.7069174761778901 +vn 0.03481894144832179 -0.10203793017301757 0.9941709622204951 +vn 0.673179723923595 -0.27288120103347857 0.687288083281442 +vn 0.03481894144832179 -0.10203793017301757 0.9941709622204951 +vn 0.03223567444743522 -0.20858278797701574 0.9774733151614188 +vn 0.6974296690735602 -0.1177265414858794 0.7069174761778901 +vn 0.6892475341759589 0.3110881084756211 0.6543409091577728 +vn 0.00453048294868246 0.14207755101982042 0.9898451617401897 +vn 0.6974296690735602 -0.1177265414858794 0.7069174761778901 +vn 0.00453048294868246 0.14207755101982042 0.9898451617401897 +vn 0.03481894144832179 -0.10203793017301757 0.9941709622204951 +vn 0.03481894144832179 -0.10203793017301757 0.9941709622204951 +vn 0.00453048294868246 0.14207755101982042 0.9898451617401897 +vn -0.692892177480864 0.2335044537642879 0.6821847993455062 +vn 0.03481894144832179 -0.10203793017301757 0.9941709622204951 +vn -0.692892177480864 0.2335044537642879 0.6821847993455062 +vn -0.6960056284593561 -0.0192073337608014 0.7177793835731824 +vn 0.03223567444743522 -0.20858278797701574 0.9774733151614188 +vn 0.03481894144832179 -0.10203793017301757 0.9941709622204951 +vn -0.6960056284593561 -0.0192073337608014 0.7177793835731824 +vn 0.03223567444743522 -0.20858278797701574 0.9774733151614188 +vn -0.6960056284593561 -0.0192073337608014 0.7177793835731824 +vn -0.7658524512160326 -0.09311585147346466 0.6362385253745377 +vn -0.642982244231693 0.15608689182648408 -0.7498071190664456 +vn -0.9690770227322479 0.2342792681825583 -0.07747869715119822 +vn -0.9356101157617274 0.34767136751758615 -0.06130523218110122 +vn -0.642982244231693 0.15608689182648408 -0.7498071190664456 +vn -0.9356101157617274 0.34767136751758615 -0.06130523218110122 +vn -0.6846666233354775 0.32547190297177336 -0.6521500251217722 +vn -0.9690770227322479 0.2342792681825583 -0.07747869715119822 +vn -0.692892177480864 0.2335044537642879 0.6821847993455062 +vn -0.665416780489932 0.45344406595040115 0.5929662615164388 +vn -0.9690770227322479 0.2342792681825583 -0.07747869715119822 +vn -0.665416780489932 0.45344406595040115 0.5929662615164388 +vn -0.9356101157617274 0.34767136751758615 -0.06130523218110122 +vn -0.9356101157617274 0.34767136751758615 -0.06130523218110122 +vn -0.665416780489932 0.45344406595040115 0.5929662615164388 +vn -0.6475796052717011 0.6070646000007461 0.4605575167794811 +vn -0.9356101157617274 0.34767136751758615 -0.06130523218110122 +vn -0.6475796052717011 0.6070646000007461 0.4605575167794811 +vn -0.792640893611793 0.6085381409529894 -0.03743988220838353 +vn -0.6846666233354775 0.32547190297177336 -0.6521500251217722 +vn -0.9356101157617274 0.34767136751758615 -0.06130523218110122 +vn -0.792640893611793 0.6085381409529894 -0.03743988220838353 +vn -0.6846666233354775 0.32547190297177336 -0.6521500251217722 +vn -0.792640893611793 0.6085381409529894 -0.03743988220838353 +vn -0.6978232905979236 0.5533658898126775 -0.4547843962702649 +vn 0.025496957528712894 0.8958672181455717 -0.443589712018768 +vn -0.45677883369588523 0.700727967860512 -0.5480268352421297 +vn -0.569571709848857 0.8217578785492288 -0.017379769334499195 +vn 0.025496957528712894 0.8958672181455717 -0.443589712018768 +vn -0.569571709848857 0.8217578785492288 -0.017379769334499195 +vn 0.06575791094630122 0.9977400822619501 -0.013806715608554225 +vn -0.45677883369588523 0.700727967860512 -0.5480268352421297 +vn -0.6978232905979236 0.5533658898126775 -0.4547843962702649 +vn -0.792640893611793 0.6085381409529894 -0.03743988220838353 +vn -0.45677883369588523 0.700727967860512 -0.5480268352421297 +vn -0.792640893611793 0.6085381409529894 -0.03743988220838353 +vn -0.569571709848857 0.8217578785492288 -0.017379769334499195 +vn -0.569571709848857 0.8217578785492288 -0.017379769334499195 +vn -0.792640893611793 0.6085381409529894 -0.03743988220838353 +vn -0.6475796052717011 0.6070646000007461 0.4605575167794811 +vn -0.569571709848857 0.8217578785492288 -0.017379769334499195 +vn -0.6475796052717011 0.6070646000007461 0.4605575167794811 +vn -0.4328885381523027 0.7061487444564377 0.5603226429825579 +vn 0.06575791094630122 0.9977400822619501 -0.013806715608554225 +vn -0.569571709848857 0.8217578785492288 -0.017379769334499195 +vn -0.4328885381523027 0.7061487444564377 0.5603226429825579 +vn 0.06575791094630122 0.9977400822619501 -0.013806715608554225 +vn -0.4328885381523027 0.7061487444564377 0.5603226429825579 +vn 0.027135236149421885 0.8870363209768896 0.46090155589550763 +vn -0.692892177480864 0.2335044537642879 0.6821847993455062 +vn 0.00453048294868246 0.14207755101982042 0.9898451617401897 +vn -0.10497748132216511 0.3152740083599685 0.9431765625098479 +vn -0.692892177480864 0.2335044537642879 0.6821847993455062 +vn -0.10497748132216511 0.3152740083599685 0.9431765625098479 +vn -0.665416780489932 0.45344406595040115 0.5929662615164388 +vn 0.00453048294868246 0.14207755101982042 0.9898451617401897 +vn 0.6892475341759589 0.3110881084756211 0.6543409091577728 +vn 0.4189406321917698 0.6233655194317278 0.6602303960606271 +vn 0.00453048294868246 0.14207755101982042 0.9898451617401897 +vn 0.4189406321917698 0.6233655194317278 0.6602303960606271 +vn -0.10497748132216511 0.3152740083599685 0.9431765625098479 +vn -0.10497748132216511 0.3152740083599685 0.9431765625098479 +vn 0.4189406321917698 0.6233655194317278 0.6602303960606271 +vn 0.027135236149421885 0.8870363209768896 0.46090155589550763 +vn -0.10497748132216511 0.3152740083599685 0.9431765625098479 +vn 0.027135236149421885 0.8870363209768896 0.46090155589550763 +vn -0.4328885381523027 0.7061487444564377 0.5603226429825579 +vn -0.665416780489932 0.45344406595040115 0.5929662615164388 +vn -0.10497748132216511 0.3152740083599685 0.9431765625098479 +vn -0.4328885381523027 0.7061487444564377 0.5603226429825579 +vn -0.665416780489932 0.45344406595040115 0.5929662615164388 +vn -0.4328885381523027 0.7061487444564377 0.5603226429825579 +vn -0.6475796052717011 0.6070646000007461 0.4605575167794811 +vn 0.6848947465796044 0.2873341466318297 -0.6695956050386064 +vn -0.06000629482956411 0.07591231495504497 -0.9953072716598597 +vn -0.16055593051477232 0.286806648996217 -0.9444383194619416 +vn 0.6848947465796044 0.2873341466318297 -0.6695956050386064 +vn -0.16055593051477232 0.286806648996217 -0.9444383194619416 +vn 0.3956119121280836 0.6405301209453955 -0.6581887108907586 +vn -0.06000629482956411 0.07591231495504497 -0.9953072716598597 +vn -0.642982244231693 0.15608689182648408 -0.7498071190664456 +vn -0.6846666233354775 0.32547190297177336 -0.6521500251217722 +vn -0.06000629482956411 0.07591231495504497 -0.9953072716598597 +vn -0.6846666233354775 0.32547190297177336 -0.6521500251217722 +vn -0.16055593051477232 0.286806648996217 -0.9444383194619416 +vn -0.16055593051477232 0.286806648996217 -0.9444383194619416 +vn -0.6846666233354775 0.32547190297177336 -0.6521500251217722 +vn -0.6978232905979236 0.5533658898126775 -0.4547843962702649 +vn -0.16055593051477232 0.286806648996217 -0.9444383194619416 +vn -0.6978232905979236 0.5533658898126775 -0.4547843962702649 +vn -0.45677883369588523 0.700727967860512 -0.5480268352421297 +vn 0.3956119121280836 0.6405301209453955 -0.6581887108907586 +vn -0.16055593051477232 0.286806648996217 -0.9444383194619416 +vn -0.45677883369588523 0.700727967860512 -0.5480268352421297 +vn 0.3956119121280836 0.6405301209453955 -0.6581887108907586 +vn -0.45677883369588523 0.700727967860512 -0.5480268352421297 +vn 0.025496957528712894 0.8958672181455717 -0.443589712018768 +vn 0.6892475341759589 0.3110881084756211 0.6543409091577728 +vn 0.935117282275238 0.3536376869737989 0.022272286411464986 +vn 0.6731883146249377 0.7394708835969569 0.0005525982007909237 +vn 0.6892475341759589 0.3110881084756211 0.6543409091577728 +vn 0.6731883146249377 0.7394708835969569 0.0005525982007909237 +vn 0.4189406321917698 0.6233655194317278 0.6602303960606271 +vn 0.935117282275238 0.3536376869737989 0.022272286411464986 +vn 0.6848947465796044 0.2873341466318297 -0.6695956050386064 +vn 0.3956119121280836 0.6405301209453955 -0.6581887108907586 +vn 0.935117282275238 0.3536376869737989 0.022272286411464986 +vn 0.3956119121280836 0.6405301209453955 -0.6581887108907586 +vn 0.6731883146249377 0.7394708835969569 0.0005525982007909237 +vn 0.6731883146249377 0.7394708835969569 0.0005525982007909237 +vn 0.3956119121280836 0.6405301209453955 -0.6581887108907586 +vn 0.025496957528712894 0.8958672181455717 -0.443589712018768 +vn 0.6731883146249377 0.7394708835969569 0.0005525982007909237 +vn 0.025496957528712894 0.8958672181455717 -0.443589712018768 +vn 0.06575791094630122 0.9977400822619501 -0.013806715608554225 +vn 0.4189406321917698 0.6233655194317278 0.6602303960606271 +vn 0.6731883146249377 0.7394708835969569 0.0005525982007909237 +vn 0.06575791094630122 0.9977400822619501 -0.013806715608554225 +vn 0.4189406321917698 0.6233655194317278 0.6602303960606271 +vn 0.06575791094630122 0.9977400822619501 -0.013806715608554225 +vn 0.027135236149421885 0.8870363209768896 0.46090155589550763 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 8/8/8 9/9/9 +f 10/10/10 11/11/11 12/12/12 +f 13/13/13 14/14/14 15/15/15 +f 16/16/16 17/17/17 18/18/18 +f 19/19/19 20/20/20 21/21/21 +f 22/22/22 23/23/23 24/24/24 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 29/29/29 30/30/30 +f 31/31/31 32/32/32 33/33/33 +f 34/34/34 35/35/35 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 40/40/40 41/41/41 42/42/42 +f 43/43/43 44/44/44 45/45/45 +f 46/46/46 47/47/47 48/48/48 +f 49/49/49 50/50/50 51/51/51 +f 52/52/52 53/53/53 54/54/54 +f 55/55/55 56/56/56 57/57/57 +f 58/58/58 59/59/59 60/60/60 +f 61/61/61 62/62/62 63/63/63 +f 64/64/64 65/65/65 66/66/66 +f 67/67/67 68/68/68 69/69/69 +f 70/70/70 71/71/71 72/72/72 +f 73/73/73 74/74/74 75/75/75 +f 76/76/76 77/77/77 78/78/78 +f 79/79/79 80/80/80 81/81/81 +f 82/82/82 83/83/83 84/84/84 +f 85/85/85 86/86/86 87/87/87 +f 88/88/88 89/89/89 90/90/90 +f 91/91/91 92/92/92 93/93/93 +f 94/94/94 95/95/95 96/96/96 +f 97/97/97 98/98/98 99/99/99 +f 100/100/100 101/101/101 102/102/102 +f 103/103/103 104/104/104 105/105/105 +f 106/106/106 107/107/107 108/108/108 +f 109/109/109 110/110/110 111/111/111 +f 112/112/112 113/113/113 114/114/114 +f 115/115/115 116/116/116 117/117/117 +f 118/118/118 119/119/119 120/120/120 +f 121/121/121 122/122/122 123/123/123 +f 124/124/124 125/125/125 126/126/126 +f 127/127/127 128/128/128 129/129/129 +f 130/130/130 131/131/131 132/132/132 +f 133/133/133 134/134/134 135/135/135 +f 136/136/136 137/137/137 138/138/138 +f 139/139/139 140/140/140 141/141/141 +f 142/142/142 143/143/143 144/144/144 +f 145/145/145 146/146/146 147/147/147 +f 148/148/148 149/149/149 150/150/150 +f 151/151/151 152/152/152 153/153/153 +f 154/154/154 155/155/155 156/156/156 +f 157/157/157 158/158/158 159/159/159 +f 160/160/160 161/161/161 162/162/162 +f 163/163/163 164/164/164 165/165/165 +f 166/166/166 167/167/167 168/168/168 +f 169/169/169 170/170/170 171/171/171 +f 172/172/172 173/173/173 174/174/174 +f 175/175/175 176/176/176 177/177/177 +f 178/178/178 179/179/179 180/180/180 +f 181/181/181 182/182/182 183/183/183 +f 184/184/184 185/185/185 186/186/186 +f 187/187/187 188/188/188 189/189/189 +f 190/190/190 191/191/191 192/192/192 +f 193/193/193 194/194/194 195/195/195 +f 196/196/196 197/197/197 198/198/198 +f 199/199/199 200/200/200 201/201/201 +f 202/202/202 203/203/203 204/204/204 +f 205/205/205 206/206/206 207/207/207 +f 208/208/208 209/209/209 210/210/210 +f 211/211/211 212/212/212 213/213/213 +f 214/214/214 215/215/215 216/216/216 diff --git a/apps/openmb/resources/models/rocks/SM_Rocks_03.obj b/apps/openmb/resources/models/rocks/SM_Rocks_03.obj new file mode 100644 index 0000000..0ccf8fb --- /dev/null +++ b/apps/openmb/resources/models/rocks/SM_Rocks_03.obj @@ -0,0 +1,1013 @@ +mtllib SM_Rocks_03.mtl +o SM_Rock_03 +usemtl SM_Rock_01 +v 24.102996826171875 2.109623432159424 -20.2135066986084 1 1 1 +v 25.17680549621582 20.669584274291992 -20.675390243530273 1 1 1 +v 27.105754852294922 21.046741485595703 0.8125303983688354 1 1 1 +v 24.102996826171875 2.109623432159424 -20.2135066986084 1 1 1 +v 27.105754852294922 21.046741485595703 0.8125303983688354 1 1 1 +v 27.063522338867188 2.102771282196045 0.8984864950180054 1 1 1 +v 25.17680549621582 20.669584274291992 -20.675390243530273 1 1 1 +v 25.3117618560791 45.796504974365234 -18.276704788208008 1 1 1 +v 26.901775360107422 46.14866256713867 1.0090612173080444 1 1 1 +v 25.17680549621582 20.669584274291992 -20.675390243530273 1 1 1 +v 26.901775360107422 46.14866256713867 1.0090612173080444 1 1 1 +v 27.105754852294922 21.046741485595703 0.8125303983688354 1 1 1 +v 27.105754852294922 21.046741485595703 0.8125303983688354 1 1 1 +v 26.901775360107422 46.14866256713867 1.0090612173080444 1 1 1 +v 21.960323333740234 44.71691131591797 17.9605712890625 1 1 1 +v 27.105754852294922 21.046741485595703 0.8125303983688354 1 1 1 +v 21.960323333740234 44.71691131591797 17.9605712890625 1 1 1 +v 22.81016731262207 20.644498825073242 21.59063720703125 1 1 1 +v 27.063522338867188 2.102771282196045 0.8984864950180054 1 1 1 +v 27.105754852294922 21.046741485595703 0.8125303983688354 1 1 1 +v 22.81016731262207 20.644498825073242 21.59063720703125 1 1 1 +v 27.063522338867188 2.102771282196045 0.8984864950180054 1 1 1 +v 22.81016731262207 20.644498825073242 21.59063720703125 1 1 1 +v 23.010488510131836 2.108046770095825 24.250598907470703 1 1 1 +v 23.010488510131836 2.108046770095825 24.250598907470703 1 1 1 +v 22.81016731262207 20.644498825073242 21.59063720703125 1 1 1 +v -0.5384087562561035 20.94900131225586 24.9691104888916 1 1 1 +v 23.010488510131836 2.108046770095825 24.250598907470703 1 1 1 +v -0.5384087562561035 20.94900131225586 24.9691104888916 1 1 1 +v -2.554523468017578 2.1057519912719727 25.57318878173828 1 1 1 +v 22.81016731262207 20.644498825073242 21.59063720703125 1 1 1 +v 21.960323333740234 44.71691131591797 17.9605712890625 1 1 1 +v 1.6479790210723877 46.197532653808594 22.29827880859375 1 1 1 +v 22.81016731262207 20.644498825073242 21.59063720703125 1 1 1 +v 1.6479790210723877 46.197532653808594 22.29827880859375 1 1 1 +v -0.5384087562561035 20.94900131225586 24.9691104888916 1 1 1 +v -26.291093826293945 20.63870620727539 19.6416072845459 1 1 1 +v -20.376386642456055 44.54086685180664 16.565536499023438 1 1 1 +v -21.786752700805664 45.70438766479492 0.9341658353805542 1 1 1 +v -26.291093826293945 20.63870620727539 19.6416072845459 1 1 1 +v -21.786752700805664 45.70438766479492 0.9341658353805542 1 1 1 +v -27.537437438964844 21.083316802978516 0.9495380520820618 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -30.438459396362305 2.104883909225464 0.9969171285629272 1 1 1 +v -28.676578521728516 -2.84039306640625 0.9735827445983887 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -28.676578521728516 -2.84039306640625 0.9735827445983887 1 1 1 +v -26.830217361450195 -2.833434820175171 16.838520050048828 1 1 1 +v -2.554523468017578 2.1057519912719727 25.57318878173828 1 1 1 +v -0.5384087562561035 20.94900131225586 24.9691104888916 1 1 1 +v -22.602901458740234 20.613067626953125 23.21518898010254 1 1 1 +v -2.554523468017578 2.1057519912719727 25.57318878173828 1 1 1 +v -22.602901458740234 20.613067626953125 23.21518898010254 1 1 1 +v -24.64027976989746 2.1127634048461914 21.9910945892334 1 1 1 +v -21.786752700805664 45.70438766479492 0.9341658353805542 1 1 1 +v -20.376386642456055 44.54086685180664 16.565536499023438 1 1 1 +v -14.949970245361328 56.596553802490234 14.897974014282227 1 1 1 +v -21.786752700805664 45.70438766479492 0.9341658353805542 1 1 1 +v -14.949970245361328 56.596553802490234 14.897974014282227 1 1 1 +v -16.1763916015625 57.27262496948242 0.9122868776321411 1 1 1 +v -27.537437438964844 21.083316802978516 0.9495380520820618 1 1 1 +v -21.786752700805664 45.70438766479492 0.9341658353805542 1 1 1 +v -21.627721786499023 45.612953186035156 -18.927734375 1 1 1 +v -27.537437438964844 21.083316802978516 0.9495380520820618 1 1 1 +v -21.627721786499023 45.612953186035156 -18.927734375 1 1 1 +v -26.759565353393555 20.709436416625977 -21.591917037963867 1 1 1 +v -30.438459396362305 2.104883909225464 0.9969171285629272 1 1 1 +v -27.537437438964844 21.083316802978516 0.9495380520820618 1 1 1 +v -26.759565353393555 20.709436416625977 -21.591917037963867 1 1 1 +v -30.438459396362305 2.104883909225464 0.9969171285629272 1 1 1 +v -26.759565353393555 20.709436416625977 -21.591917037963867 1 1 1 +v -28.77391815185547 2.108934164047241 -22.423187255859375 1 1 1 +v -28.77391815185547 2.108934164047241 -22.423187255859375 1 1 1 +v -26.759565353393555 20.709436416625977 -21.591917037963867 1 1 1 +v -0.6570637226104736 21.0732421875 -22.99456024169922 1 1 1 +v -28.77391815185547 2.108934164047241 -22.423187255859375 1 1 1 +v -0.6570637226104736 21.0732421875 -22.99456024169922 1 1 1 +v -2.6890134811401367 2.1030220985412598 -25.525798797607422 1 1 1 +v -26.759565353393555 20.709436416625977 -21.591917037963867 1 1 1 +v -21.627721786499023 45.612953186035156 -18.927734375 1 1 1 +v 1.7398536205291748 46.03704071044922 -20.196895599365234 1 1 1 +v -26.759565353393555 20.709436416625977 -21.591917037963867 1 1 1 +v 1.7398536205291748 46.03704071044922 -20.196895599365234 1 1 1 +v -0.6570637226104736 21.0732421875 -22.99456024169922 1 1 1 +v -0.6570637226104736 21.0732421875 -22.99456024169922 1 1 1 +v 1.7398536205291748 46.03704071044922 -20.196895599365234 1 1 1 +v 25.3117618560791 45.796504974365234 -18.276704788208008 1 1 1 +v -0.6570637226104736 21.0732421875 -22.99456024169922 1 1 1 +v 25.3117618560791 45.796504974365234 -18.276704788208008 1 1 1 +v 25.17680549621582 20.669584274291992 -20.675390243530273 1 1 1 +v -2.6890134811401367 2.1030220985412598 -25.525798797607422 1 1 1 +v -0.6570637226104736 21.0732421875 -22.99456024169922 1 1 1 +v 25.17680549621582 20.669584274291992 -20.675390243530273 1 1 1 +v -2.6890134811401367 2.1030220985412598 -25.525798797607422 1 1 1 +v 25.17680549621582 20.669584274291992 -20.675390243530273 1 1 1 +v 24.102996826171875 2.109623432159424 -20.2135066986084 1 1 1 +v -21.627721786499023 45.612953186035156 -18.927734375 1 1 1 +v -21.786752700805664 45.70438766479492 0.9341658353805542 1 1 1 +v -16.1763916015625 57.27262496948242 0.9122868776321411 1 1 1 +v -21.627721786499023 45.612953186035156 -18.927734375 1 1 1 +v -16.1763916015625 57.27262496948242 0.9122868776321411 1 1 1 +v -16.09264373779297 56.52162551879883 -16.337142944335938 1 1 1 +v -11.084192276000977 56.81629180908203 18.64681625366211 1 1 1 +v 3.086501359939575 58.3183479309082 20.437314987182617 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v -11.084192276000977 56.81629180908203 18.64681625366211 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v -4.9680585861206055 67.9369125366211 17.239137649536133 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v -9.047629356384277 66.65656280517578 14.070704460144043 1 1 1 +v -4.9680585861206055 67.9369125366211 17.239137649536133 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v -4.9680585861206055 67.9369125366211 17.239137649536133 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v 4.825991630554199 69.64688873291016 0.9021260738372803 1 1 1 +v -16.09264373779297 56.52162551879883 -16.337142944335938 1 1 1 +v -16.1763916015625 57.27262496948242 0.9122868776321411 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v -16.09264373779297 56.52162551879883 -16.337142944335938 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v -9.032130241394043 64.44466400146484 -15.526206970214844 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v 14.833868026733398 63.24214172363281 11.738170623779297 1 1 1 +v 11.598214149475098 71.0783920288086 9.441937446594238 1 1 1 +v 4.825991630554199 69.64688873291016 0.9021260738372803 1 1 1 +v 21.03374671936035 69.18138885498047 1.0395972728729248 1 1 1 +v 20.918495178222656 68.42858123779297 -15.427020072937012 1 1 1 +v 4.825991630554199 69.64688873291016 0.9021260738372803 1 1 1 +v 20.918495178222656 68.42858123779297 -15.427020072937012 1 1 1 +v 5.033344268798828 68.26182556152344 -15.076560020446777 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v 4.825991630554199 69.64688873291016 0.9021260738372803 1 1 1 +v 5.033344268798828 68.26182556152344 -15.076560020446777 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v 5.033344268798828 68.26182556152344 -15.076560020446777 1 1 1 +v -9.032130241394043 64.44466400146484 -15.526206970214844 1 1 1 +v 21.960323333740234 44.71691131591797 17.9605712890625 1 1 1 +v 26.901775360107422 46.14866256713867 1.0090612173080444 1 1 1 +v 24.363643646240234 57.438236236572266 0.3839377164840698 1 1 1 +v 21.960323333740234 44.71691131591797 17.9605712890625 1 1 1 +v 24.363643646240234 57.438236236572266 0.3839377164840698 1 1 1 +v 17.606029510498047 54.68180847167969 13.835805892944336 1 1 1 +v 26.901775360107422 46.14866256713867 1.0090612173080444 1 1 1 +v 25.3117618560791 45.796504974365234 -18.276704788208008 1 1 1 +v 22.87507438659668 57.75265121459961 -17.21247673034668 1 1 1 +v 26.901775360107422 46.14866256713867 1.0090612173080444 1 1 1 +v 22.87507438659668 57.75265121459961 -17.21247673034668 1 1 1 +v 24.363643646240234 57.438236236572266 0.3839377164840698 1 1 1 +v 24.363643646240234 57.438236236572266 0.3839377164840698 1 1 1 +v 22.87507438659668 57.75265121459961 -17.21247673034668 1 1 1 +v 20.918495178222656 68.42858123779297 -15.427020072937012 1 1 1 +v 24.363643646240234 57.438236236572266 0.3839377164840698 1 1 1 +v 20.918495178222656 68.42858123779297 -15.427020072937012 1 1 1 +v 21.03374671936035 69.18138885498047 1.0395972728729248 1 1 1 +v 17.606029510498047 54.68180847167969 13.835805892944336 1 1 1 +v 24.363643646240234 57.438236236572266 0.3839377164840698 1 1 1 +v 21.03374671936035 69.18138885498047 1.0395972728729248 1 1 1 +v 17.606029510498047 54.68180847167969 13.835805892944336 1 1 1 +v 21.03374671936035 69.18138885498047 1.0395972728729248 1 1 1 +v 14.833868026733398 63.24214172363281 11.738170623779297 1 1 1 +v 25.3117618560791 45.796504974365234 -18.276704788208008 1 1 1 +v 1.7398536205291748 46.03704071044922 -20.196895599365234 1 1 1 +v 3.3124923706054688 58.01219177246094 -18.6970157623291 1 1 1 +v 25.3117618560791 45.796504974365234 -18.276704788208008 1 1 1 +v 3.3124923706054688 58.01219177246094 -18.6970157623291 1 1 1 +v 22.87507438659668 57.75265121459961 -17.21247673034668 1 1 1 +v 1.7398536205291748 46.03704071044922 -20.196895599365234 1 1 1 +v -21.627721786499023 45.612953186035156 -18.927734375 1 1 1 +v -16.09264373779297 56.52162551879883 -16.337142944335938 1 1 1 +v 1.7398536205291748 46.03704071044922 -20.196895599365234 1 1 1 +v -16.09264373779297 56.52162551879883 -16.337142944335938 1 1 1 +v 3.3124923706054688 58.01219177246094 -18.6970157623291 1 1 1 +v 3.3124923706054688 58.01219177246094 -18.6970157623291 1 1 1 +v -16.09264373779297 56.52162551879883 -16.337142944335938 1 1 1 +v -9.032130241394043 64.44466400146484 -15.526206970214844 1 1 1 +v 3.3124923706054688 58.01219177246094 -18.6970157623291 1 1 1 +v -9.032130241394043 64.44466400146484 -15.526206970214844 1 1 1 +v 5.033344268798828 68.26182556152344 -15.076560020446777 1 1 1 +v 22.87507438659668 57.75265121459961 -17.21247673034668 1 1 1 +v 3.3124923706054688 58.01219177246094 -18.6970157623291 1 1 1 +v 5.033344268798828 68.26182556152344 -15.076560020446777 1 1 1 +v 22.87507438659668 57.75265121459961 -17.21247673034668 1 1 1 +v 5.033344268798828 68.26182556152344 -15.076560020446777 1 1 1 +v 20.918495178222656 68.42858123779297 -15.427020072937012 1 1 1 +v -0.5384087562561035 20.94900131225586 24.9691104888916 1 1 1 +v 1.6479790210723877 46.197532653808594 22.29827880859375 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v -0.5384087562561035 20.94900131225586 24.9691104888916 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v -22.602901458740234 20.613067626953125 23.21518898010254 1 1 1 +v 1.6479790210723877 46.197532653808594 22.29827880859375 1 1 1 +v 21.960323333740234 44.71691131591797 17.9605712890625 1 1 1 +v 17.606029510498047 54.68180847167969 13.835805892944336 1 1 1 +v 1.6479790210723877 46.197532653808594 22.29827880859375 1 1 1 +v 17.606029510498047 54.68180847167969 13.835805892944336 1 1 1 +v 3.086501359939575 58.3183479309082 20.437314987182617 1 1 1 +v 3.086501359939575 58.3183479309082 20.437314987182617 1 1 1 +v 17.606029510498047 54.68180847167969 13.835805892944336 1 1 1 +v 14.833868026733398 63.24214172363281 11.738170623779297 1 1 1 +v 3.086501359939575 58.3183479309082 20.437314987182617 1 1 1 +v 14.833868026733398 63.24214172363281 11.738170623779297 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v -16.1763916015625 57.27262496948242 0.9122868776321411 1 1 1 +v -14.949970245361328 56.596553802490234 14.897974014282227 1 1 1 +v -9.047629356384277 66.65656280517578 14.070704460144043 1 1 1 +v -16.1763916015625 57.27262496948242 0.9122868776321411 1 1 1 +v -9.047629356384277 66.65656280517578 14.070704460144043 1 1 1 +v -9.33358097076416 65.68399047851562 1.5693678855895996 1 1 1 +v 4.825991630554199 69.64688873291016 0.9021260738372803 1 1 1 +v 11.598214149475098 71.0783920288086 9.441937446594238 1 1 1 +v 21.03374671936035 69.18138885498047 1.0395972728729248 1 1 1 +v 21.03374671936035 69.18138885498047 1.0395972728729248 1 1 1 +v 11.598214149475098 71.0783920288086 9.441937446594238 1 1 1 +v 14.833868026733398 63.24214172363281 11.738170623779297 1 1 1 +v 11.598214149475098 71.0783920288086 9.441937446594238 1 1 1 +v 4.825991630554199 69.64688873291016 0.9021260738372803 1 1 1 +v 3.7630434036254883 70.16995239257812 16.965778350830078 1 1 1 +v -28.77391815185547 2.108934164047241 -22.423187255859375 1 1 1 +v -2.6890134811401367 2.1030220985412598 -25.525798797607422 1 1 1 +v -2.664181709289551 -2.8421382904052734 -23.88887596130371 1 1 1 +v -28.77391815185547 2.108934164047241 -22.423187255859375 1 1 1 +v -2.664181709289551 -2.8421382904052734 -23.88887596130371 1 1 1 +v -27.116233825683594 -2.8365964889526367 -20.980478286743164 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v 1.6479790210723877 46.197532653808594 22.29827880859375 1 1 1 +v 3.086501359939575 58.3183479309082 20.437314987182617 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v 3.086501359939575 58.3183479309082 20.437314987182617 1 1 1 +v -11.084192276000977 56.81629180908203 18.64681625366211 1 1 1 +v -2.6890134811401367 2.1030220985412598 -25.525798797607422 1 1 1 +v 24.102996826171875 2.109623432159424 -20.2135066986084 1 1 1 +v 22.450716018676758 -2.8359503746032715 -18.909120559692383 1 1 1 +v -2.6890134811401367 2.1030220985412598 -25.525798797607422 1 1 1 +v 22.450716018676758 -2.8359503746032715 -18.909120559692383 1 1 1 +v -2.664181709289551 -2.8421382904052734 -23.88887596130371 1 1 1 +v -2.554523468017578 2.1057519912719727 25.57318878173828 1 1 1 +v -24.64027976989746 2.1127634048461914 21.9910945892334 1 1 1 +v -23.029817581176758 -2.833073854446411 20.687883377075195 1 1 1 +v -2.554523468017578 2.1057519912719727 25.57318878173828 1 1 1 +v -23.029817581176758 -2.833073854446411 20.687883377075195 1 1 1 +v -2.5381104946136475 -2.8395793437957764 24.011438369750977 1 1 1 +v 27.063522338867188 2.102771282196045 0.8984864950180054 1 1 1 +v 23.010488510131836 2.108046770095825 24.250598907470703 1 1 1 +v 21.426591873168945 -2.837428331375122 22.77164077758789 1 1 1 +v 27.063522338867188 2.102771282196045 0.8984864950180054 1 1 1 +v 21.426591873168945 -2.837428331375122 22.77164077758789 1 1 1 +v 25.225915908813477 -2.8423733711242676 0.8813136219978333 1 1 1 +v -30.438459396362305 2.104883909225464 0.9969171285629272 1 1 1 +v -28.77391815185547 2.108934164047241 -22.423187255859375 1 1 1 +v -27.116233825683594 -2.8365964889526367 -20.980478286743164 1 1 1 +v -30.438459396362305 2.104883909225464 0.9969171285629272 1 1 1 +v -27.116233825683594 -2.8365964889526367 -20.980478286743164 1 1 1 +v -28.676578521728516 -2.84039306640625 0.9735827445983887 1 1 1 +v 24.102996826171875 2.109623432159424 -20.2135066986084 1 1 1 +v 27.063522338867188 2.102771282196045 0.8984864950180054 1 1 1 +v 25.225915908813477 -2.8423733711242676 0.8813136219978333 1 1 1 +v 24.102996826171875 2.109623432159424 -20.2135066986084 1 1 1 +v 25.225915908813477 -2.8423733711242676 0.8813136219978333 1 1 1 +v 22.450716018676758 -2.8359503746032715 -18.909120559692383 1 1 1 +v 23.010488510131836 2.108046770095825 24.250598907470703 1 1 1 +v -2.554523468017578 2.1057519912719727 25.57318878173828 1 1 1 +v -2.5381104946136475 -2.8395793437957764 24.011438369750977 1 1 1 +v 23.010488510131836 2.108046770095825 24.250598907470703 1 1 1 +v -2.5381104946136475 -2.8395793437957764 24.011438369750977 1 1 1 +v 21.426591873168945 -2.837428331375122 22.77164077758789 1 1 1 +v -20.376386642456055 44.54086685180664 16.565536499023438 1 1 1 +v -26.291093826293945 20.63870620727539 19.6416072845459 1 1 1 +v -22.602901458740234 20.613067626953125 23.21518898010254 1 1 1 +v -20.376386642456055 44.54086685180664 16.565536499023438 1 1 1 +v -22.602901458740234 20.613067626953125 23.21518898010254 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v -26.291093826293945 20.63870620727539 19.6416072845459 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -24.64027976989746 2.1127634048461914 21.9910945892334 1 1 1 +v -26.291093826293945 20.63870620727539 19.6416072845459 1 1 1 +v -24.64027976989746 2.1127634048461914 21.9910945892334 1 1 1 +v -22.602901458740234 20.613067626953125 23.21518898010254 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v -11.084192276000977 56.81629180908203 18.64681625366211 1 1 1 +v -14.949970245361328 56.596553802490234 14.897974014282227 1 1 1 +v -16.54390525817871 44.60447311401367 20.264305114746094 1 1 1 +v -14.949970245361328 56.596553802490234 14.897974014282227 1 1 1 +v -20.376386642456055 44.54086685180664 16.565536499023438 1 1 1 +v -11.084192276000977 56.81629180908203 18.64681625366211 1 1 1 +v -4.9680585861206055 67.9369125366211 17.239137649536133 1 1 1 +v -9.047629356384277 66.65656280517578 14.070704460144043 1 1 1 +v -11.084192276000977 56.81629180908203 18.64681625366211 1 1 1 +v -9.047629356384277 66.65656280517578 14.070704460144043 1 1 1 +v -14.949970245361328 56.596553802490234 14.897974014282227 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -26.830217361450195 -2.833434820175171 16.838520050048828 1 1 1 +v -23.029817581176758 -2.833073854446411 20.687883377075195 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -23.029817581176758 -2.833073854446411 20.687883377075195 1 1 1 +v -24.64027976989746 2.1127634048461914 21.9910945892334 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -26.291093826293945 20.63870620727539 19.6416072845459 1 1 1 +v -27.537437438964844 21.083316802978516 0.9495380520820618 1 1 1 +v -28.443017959594727 2.1124043464660645 18.142826080322266 1 1 1 +v -27.537437438964844 21.083316802978516 0.9495380520820618 1 1 1 +v -30.438459396362305 2.104883909225464 0.9969171285629272 1 1 1 +vt 0.643281102180481 0.4869915246963501 +vt 0.6489467024803162 0.43546026945114136 +vt 0.7086883187294006 0.4439382553100586 +vt 0.643281102180481 0.4869915246963501 +vt 0.7086883187294006 0.4439382553100586 +vt 0.7015703320503235 0.49670857191085815 +vt 0.6489467024803162 0.43546026945114136 +vt 0.6653923988342285 0.36653459072113037 +vt 0.7190513610839844 0.37406110763549805 +vt 0.6489467024803162 0.43546026945114136 +vt 0.7190513610839844 0.37406110763549805 +vt 0.7086883187294006 0.4439382553100586 +vt 0.7086883187294006 0.4439382553100586 +vt 0.7190513610839844 0.37406110763549805 +vt 0.7670877575874329 0.38352280855178833 +vt 0.7086883187294006 0.4439382553100586 +vt 0.7670877575874329 0.38352280855178833 +vt 0.7676640152931213 0.452325701713562 +vt 0.7015703320503235 0.49670857191085815 +vt 0.7086883187294006 0.4439382553100586 +vt 0.7676640152931213 0.452325701713562 +vt 0.7015703320503235 0.49670857191085815 +vt 0.7676640152931213 0.452325701713562 +vt 0.7678405046463013 0.5051062703132629 +vt 0.6432810425758362 0.7227435111999512 +vt 0.6436856985092163 0.6699236631393433 +vt 0.7098723649978638 0.6693590879440308 +vt 0.6432810425758362 0.7227435111999512 +vt 0.7098723649978638 0.6693590879440308 +vt 0.7157201766967773 0.7227434515953064 +vt 0.6436856985092163 0.6699236631393433 +vt 0.6458792686462402 0.601300060749054 +vt 0.7034701108932495 0.5975643992424011 +vt 0.6436856985092163 0.6699236631393433 +vt 0.7034701108932495 0.5975643992424011 +vt 0.7098723649978638 0.6693590879440308 +vt 0.690540075302124 0.1479201316833496 +vt 0.700365424156189 0.07832419872283936 +vt 0.7447772026062012 0.0767446756362915 +vt 0.690540075302124 0.1479201316833496 +vt 0.7447772026062012 0.0767446756362915 +vt 0.7435660362243652 0.1483595371246338 +vt 0.6937839984893799 0.20047730207443237 +vt 0.7424463033676147 0.20257443189620972 +vt 0.7421149611473083 0.21508288383483887 +vt 0.6937839984893799 0.20047730207443237 +vt 0.7421149611473083 0.21508288383483887 +vt 0.6970882415771484 0.21314239501953125 +vt 0.7157201766967773 0.7227434515953064 +vt 0.7098723649978638 0.6693590879440308 +vt 0.7723549604415894 0.6698998212814331 +vt 0.7157201766967773 0.7227434515953064 +vt 0.7723549604415894 0.6698998212814331 +vt 0.7782354354858398 0.7220585346221924 +vt 0.7447772026062012 0.0767446756362915 +vt 0.700365424156189 0.07832419872283936 +vt 0.7055132985115051 0.04165482521057129 +vt 0.7447772026062012 0.0767446756362915 +vt 0.7055132985115051 0.04165482521057129 +vt 0.7452253103256226 0.04122549295425415 +vt 0.7435660362243652 0.1483595371246338 +vt 0.7447772026062012 0.0767446756362915 +vt 0.8010048866271973 0.07781237363815308 +vt 0.7435660362243652 0.1483595371246338 +vt 0.8010048866271973 0.07781237363815308 +vt 0.8073296546936035 0.14993196725845337 +vt 0.7424463033676147 0.20257443189620972 +vt 0.7435660362243652 0.1483595371246338 +vt 0.8073296546936035 0.14993196725845337 +vt 0.7424463033676147 0.20257443189620972 +vt 0.8073296546936035 0.14993196725845337 +vt 0.8086712956428528 0.20257443189620972 +vt 0.20989134907722473 0.7926543354988098 +vt 0.21520638465881348 0.7398747801780701 +vt 0.28910690546035767 0.7385429739952087 +vt 0.20989134907722473 0.7926543354988098 +vt 0.28910690546035767 0.7385429739952087 +vt 0.2837119996547699 0.792654275894165 +vt 0.21520638465881348 0.7398747801780701 +vt 0.2292546033859253 0.6688989996910095 +vt 0.29540959000587463 0.6674306988716125 +vt 0.21520638465881348 0.7398747801780701 +vt 0.29540959000587463 0.6674306988716125 +vt 0.28910690546035767 0.7385429739952087 +vt 0.28910690546035767 0.7385429739952087 +vt 0.29540959000587463 0.6674306988716125 +vt 0.3622296154499054 0.6673010587692261 +vt 0.28910690546035767 0.7385429739952087 +vt 0.3622296154499054 0.6673010587692261 +vt 0.3623468279838562 0.7387607097625732 +vt 0.2837119996547699 0.792654275894165 +vt 0.28910690546035767 0.7385429739952087 +vt 0.3623468279838562 0.7387607097625732 +vt 0.2837119996547699 0.792654275894165 +vt 0.3623468279838562 0.7387607097625732 +vt 0.3597241938114166 0.791188657283783 +vt 0.8010048866271973 0.07781237363815308 +vt 0.7447772026062012 0.0767446756362915 +vt 0.7452253103256226 0.04122549295425415 +vt 0.8010048866271973 0.07781237363815308 +vt 0.7452253103256226 0.04122549295425415 +vt 0.7940196990966797 0.0440402626991272 +vt 0.7394152283668518 0.5669148564338684 +vt 0.6992868781089783 0.5630207657814026 +vt 0.6972417831420898 0.5290083289146423 +vt 0.7394152283668518 0.5669148564338684 +vt 0.6972417831420898 0.5290083289146423 +vt 0.7219942808151245 0.5352993607521057 +vt 0.7934572696685791 0.9376599788665771 +vt 0.7947403192520142 0.902155876159668 +vt 0.8067024350166321 0.8930720090866089 +vt 0.832048237323761 0.8936619162559509 +vt 0.7934572696685791 0.9376599788665771 +vt 0.8067024350166321 0.8930720090866089 +vt 0.7934572696685791 0.9376599788665771 +vt 0.832048237323761 0.8936619162559509 +vt 0.8346858620643616 0.9391646981239319 +vt 0.7940196990966797 0.0440402626991272 +vt 0.7452253103256226 0.04122549295425415 +vt 0.7434911131858826 0.013589799404144287 +vt 0.7940196990966797 0.0440402626991272 +vt 0.7434911131858826 0.013589799404144287 +vt 0.7918081283569336 0.017604410648345947 +vt 0.6972417831420898 0.5290083289146423 +vt 0.6658551692962646 0.5479629039764404 +vt 0.6749361157417297 0.525446355342865 +vt 0.8346858620643616 0.9391646981239319 +vt 0.8800348043441772 0.939571738243103 +vt 0.8792744874954224 0.9862185716629028 +vt 0.8346858620643616 0.9391646981239319 +vt 0.8792744874954224 0.9862185716629028 +vt 0.8346021771430969 0.9846034049987793 +vt 0.7934572696685791 0.9376599788665771 +vt 0.8346858620643616 0.9391646981239319 +vt 0.8346021771430969 0.9846034049987793 +vt 0.7934572696685791 0.9376599788665771 +vt 0.8346021771430969 0.9846034049987793 +vt 0.7936810851097107 0.9862185716629028 +vt 0.7670877575874329 0.38352280855178833 +vt 0.7190513610839844 0.37406110763549805 +vt 0.7223155498504639 0.34156501293182373 +vt 0.7670877575874329 0.38352280855178833 +vt 0.7223155498504639 0.34156501293182373 +vt 0.7604978680610657 0.35268890857696533 +vt 0.7190513610839844 0.37406110763549805 +vt 0.6653923988342285 0.36653459072113037 +vt 0.673613429069519 0.33291566371917725 +vt 0.7190513610839844 0.37406110763549805 +vt 0.673613429069519 0.33291566371917725 +vt 0.7223155498504639 0.34156501293182373 +vt 0.7223155498504639 0.34156501293182373 +vt 0.673613429069519 0.33291566371917725 +vt 0.683235228061676 0.30331242084503174 +vt 0.7223155498504639 0.34156501293182373 +vt 0.683235228061676 0.30331242084503174 +vt 0.7295299172401428 0.30808746814727783 +vt 0.7604978680610657 0.35268890857696533 +vt 0.7223155498504639 0.34156501293182373 +vt 0.7295299172401428 0.30808746814727783 +vt 0.7604978680610657 0.35268890857696533 +vt 0.7295299172401428 0.30808746814727783 +vt 0.7586414813995361 0.3271070122718811 +vt 0.3622296154499054 0.6673010587692261 +vt 0.29540959000587463 0.6674306988716125 +vt 0.29963430762290955 0.6332828402519226 +vt 0.3622296154499054 0.6673010587692261 +vt 0.29963430762290955 0.6332828402519226 +vt 0.35508784651756287 0.6333630681037903 +vt 0.29540959000587463 0.6674306988716125 +vt 0.2292546033859253 0.6688989996910095 +vt 0.24475157260894775 0.63750159740448 +vt 0.29540959000587463 0.6674306988716125 +vt 0.24475157260894775 0.63750159740448 +vt 0.29963430762290955 0.6332828402519226 +vt 0.29963430762290955 0.6332828402519226 +vt 0.24475157260894775 0.63750159740448 +vt 0.2645954489707947 0.6148147583007812 +vt 0.29963430762290955 0.6332828402519226 +vt 0.2645954489707947 0.6148147583007812 +vt 0.3043644428253174 0.6036545634269714 +vt 0.35508784651756287 0.6333630681037903 +vt 0.29963430762290955 0.6332828402519226 +vt 0.3043644428253174 0.6036545634269714 +vt 0.35508784651756287 0.6333630681037903 +vt 0.3043644428253174 0.6036545634269714 +vt 0.3493504226207733 0.6029139161109924 +vt 0.7098723649978638 0.6693590879440308 +vt 0.7034701108932495 0.5975643992424011 +vt 0.7549870014190674 0.6016519069671631 +vt 0.7098723649978638 0.6693590879440308 +vt 0.7549870014190674 0.6016519069671631 +vt 0.7723549604415894 0.6698998212814331 +vt 0.7034701108932495 0.5975643992424011 +vt 0.6458792686462402 0.601300060749054 +vt 0.6580893397331238 0.5724970698356628 +vt 0.7034701108932495 0.5975643992424011 +vt 0.6580893397331238 0.5724970698356628 +vt 0.6992868781089783 0.5630207657814026 +vt 0.6992868781089783 0.5630207657814026 +vt 0.6580893397331238 0.5724970698356628 +vt 0.6658551692962646 0.5479629039764404 +vt 0.6992868781089783 0.5630207657814026 +vt 0.6658551692962646 0.5479629039764404 +vt 0.6972417831420898 0.5290083289146423 +vt 0.7452253103256226 0.04122549295425415 +vt 0.7055132985115051 0.04165482521057129 +vt 0.7081344723701477 0.010145306587219238 +vt 0.7452253103256226 0.04122549295425415 +vt 0.7081344723701477 0.010145306587219238 +vt 0.7434911131858826 0.013589799404144287 +vt 0.8346858620643616 0.9391646981239319 +vt 0.8543177843093872 0.9149993658065796 +vt 0.8800348043441772 0.939571738243103 +vt 0.7295299172401428 0.30808746814727783 +vt 0.7560615539550781 0.30331242084503174 +vt 0.7586414813995361 0.3271070122718811 +vt 0.8543177843093872 0.9149993658065796 +vt 0.8346858620643616 0.9391646981239319 +vt 0.832048237323761 0.8936619162559509 +vt 0.20989134907722473 0.7926543354988098 +vt 0.2837119996547699 0.792654275894165 +vt 0.2839279770851135 0.8063622117042542 +vt 0.20989134907722473 0.7926543354988098 +vt 0.2839279770851135 0.8063622117042542 +vt 0.21472831070423126 0.8063622117042542 +vt 0.7549870014190674 0.6016519069671631 +vt 0.7034701108932495 0.5975643992424011 +vt 0.6992868781089783 0.5630207657814026 +vt 0.7549870014190674 0.6016519069671631 +vt 0.6992868781089783 0.5630207657814026 +vt 0.7394152283668518 0.5669148564338684 +vt 0.2837119996547699 0.792654275894165 +vt 0.3597241938114166 0.791188657283783 +vt 0.3551819622516632 0.8049882650375366 +vt 0.2837119996547699 0.792654275894165 +vt 0.3551819622516632 0.8049882650375366 +vt 0.2839279770851135 0.8063622117042542 +vt 0.7157201766967773 0.7227434515953064 +vt 0.7782354354858398 0.7220585346221924 +vt 0.7736889719963074 0.7358824014663696 +vt 0.7157201766967773 0.7227434515953064 +vt 0.7736889719963074 0.7358824014663696 +vt 0.7156857848167419 0.7365179061889648 +vt 0.7015703320503235 0.49670857191085815 +vt 0.7678405046463013 0.5051062703132629 +vt 0.7621698379516602 0.5177623629570007 +vt 0.7015703320503235 0.49670857191085815 +vt 0.7621698379516602 0.5177623629570007 +vt 0.7000479698181152 0.5098903775215149 +vt 0.7424463033676147 0.20257443189620972 +vt 0.8086712956428528 0.20257443189620972 +vt 0.8041943907737732 0.21508288383483887 +vt 0.7424463033676147 0.20257443189620972 +vt 0.8041943907737732 0.21508288383483887 +vt 0.7421149611473083 0.21508288383483887 +vt 0.643281102180481 0.4869915246963501 +vt 0.7015703320503235 0.49670857191085815 +vt 0.7000479698181152 0.5098903775215149 +vt 0.643281102180481 0.4869915246963501 +vt 0.7000479698181152 0.5098903775215149 +vt 0.645407497882843 0.5007815361022949 +vt 0.6432810425758362 0.7227435111999512 +vt 0.7157201766967773 0.7227434515953064 +vt 0.7156857848167419 0.7365179061889648 +vt 0.6432810425758362 0.7227435111999512 +vt 0.7156857848167419 0.7365179061889648 +vt 0.6477811932563782 0.7365179657936096 +vt 0.700365424156189 0.07832419872283936 +vt 0.690540075302124 0.1479201316833496 +vt 0.6802133321762085 0.1454523801803589 +vt 0.700365424156189 0.07832419872283936 +vt 0.6802133321762085 0.1454523801803589 +vt 0.6896815896034241 0.075511634349823 +vt 0.690540075302124 0.1479201316833496 +vt 0.6937839984893799 0.20047730207443237 +vt 0.6826746463775635 0.19785141944885254 +vt 0.690540075302124 0.1479201316833496 +vt 0.6826746463775635 0.19785141944885254 +vt 0.6802133321762085 0.1454523801803589 +vt 0.6896815896034241 0.075511634349823 +vt 0.694695234298706 0.03838789463043213 +vt 0.7055132985115051 0.04165482521057129 +vt 0.6896815896034241 0.075511634349823 +vt 0.7055132985115051 0.04165482521057129 +vt 0.700365424156189 0.07832419872283936 +vt 0.694695234298706 0.03838789463043213 +vt 0.6990121603012085 0.003841996192932129 +vt 0.7081344723701477 0.010145306587219238 +vt 0.694695234298706 0.03838789463043213 +vt 0.7081344723701477 0.010145306587219238 +vt 0.7055132985115051 0.04165482521057129 +vt 0.7889547348022461 0.7214939594268799 +vt 0.7844015955924988 0.7353177070617676 +vt 0.7736889719963074 0.7358824014663696 +vt 0.7889547348022461 0.7214939594268799 +vt 0.7736889719963074 0.7358824014663696 +vt 0.7782354354858398 0.7220585346221924 +vt 0.6937839984893799 0.20047730207443237 +vt 0.690540075302124 0.1479201316833496 +vt 0.7435660362243652 0.1483595371246338 +vt 0.6937839984893799 0.20047730207443237 +vt 0.7435660362243652 0.1483595371246338 +vt 0.7424463033676147 0.20257443189620972 +vn 0.7097417492795982 -0.1829898151808711 -0.6802803663708125 +vn 0.7058310449119094 0.03760175747706376 -0.7073815405233574 +vn 0.9983612816873655 0.0076505280432351665 0.056711732897354136 +vn 0.7097417492795982 -0.1829898151808711 -0.6802803663708125 +vn 0.9983612816873655 0.0076505280432351665 0.056711732897354136 +vn 0.9837901350634028 -0.17733885327973467 0.02660641406428711 +vn 0.7058310449119094 0.03760175747706376 -0.7073815405233574 +vn 0.7208662084698857 0.13378547227812645 -0.6800392318782572 +vn 0.9792895558713576 0.16276540263773298 0.1204134106545272 +vn 0.7058310449119094 0.03760175747706376 -0.7073815405233574 +vn 0.9792895558713576 0.16276540263773298 0.1204134106545272 +vn 0.9983612816873655 0.0076505280432351665 0.056711732897354136 +vn 0.9983612816873655 0.0076505280432351665 0.056711732897354136 +vn 0.9792895558713576 0.16276540263773298 0.1204134106545272 +vn 0.6810698852418977 0.2080724013091918 0.7020325400079507 +vn 0.9983612816873655 0.0076505280432351665 0.056711732897354136 +vn 0.6810698852418977 0.2080724013091918 0.7020325400079507 +vn 0.6814371370208067 0.07766392852997338 0.727744283724838 +vn 0.9837901350634028 -0.17733885327973467 0.02660641406428711 +vn 0.9983612816873655 0.0076505280432351665 0.056711732897354136 +vn 0.6814371370208067 0.07766392852997338 0.727744283724838 +vn 0.9837901350634028 -0.17733885327973467 0.02660641406428711 +vn 0.6814371370208067 0.07766392852997338 0.727744283724838 +vn 0.6517133562709272 -0.15851294629372636 0.741716487018703 +vn 0.6517133562709272 -0.15851294629372636 0.741716487018703 +vn 0.6814371370208067 0.07766392852997338 0.727744283724838 +vn 0.01358643573754679 0.08449273145537824 0.9963314644711161 +vn 0.6517133562709272 -0.15851294629372636 0.741716487018703 +vn 0.01358643573754679 0.08449273145537824 0.9963314644711161 +vn -0.03567480384470595 -0.13271598951652872 0.9905118749905476 +vn 0.6814371370208067 0.07766392852997338 0.727744283724838 +vn 0.6810698852418977 0.2080724013091918 0.7020325400079507 +vn 0.06512300008157354 0.1817122960150499 0.9811929659028922 +vn 0.6814371370208067 0.07766392852997338 0.727744283724838 +vn 0.06512300008157354 0.1817122960150499 0.9811929659028922 +vn 0.01358643573754679 0.08449273145537824 0.9963314644711161 +vn -0.8841383452573867 0.16795282414964627 0.4359945358667791 +vn -0.8511331717889251 0.3364868776101403 0.4029254336433759 +vn -0.941227499687925 0.3355829134006586 0.03840445370973725 +vn -0.8841383452573867 0.16795282414964627 0.4359945358667791 +vn -0.941227499687925 0.3355829134006586 0.03840445370973725 +vn -0.9834605097559777 0.17940530615475422 0.024882963529921857 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.9943567713149957 -0.10411073596521707 0.020385435899152794 +vn -0.9417535786574657 -0.33562446938233104 0.021363816084343658 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.9417535786574657 -0.33562446938233104 0.021363816084343658 +vn -0.8435083940194295 -0.3760793114928615 0.3834813433347417 +vn -0.03567480384470595 -0.13271598951652872 0.9905118749905476 +vn 0.01358643573754679 0.08449273145537824 0.9963314644711161 +vn -0.42850222208687605 0.10894018151150854 0.8969492084387215 +vn -0.03567480384470595 -0.13271598951652872 0.9905118749905476 +vn -0.42850222208687605 0.10894018151150854 0.8969492084387215 +vn -0.4633038123683755 -0.17104412199178726 0.8695363625386737 +vn -0.941227499687925 0.3355829134006586 0.03840445370973725 +vn -0.8511331717889251 0.3364868776101403 0.4029254336433759 +vn -0.7980895498222257 0.4722984052156664 0.3741487496909424 +vn -0.941227499687925 0.3355829134006586 0.03840445370973725 +vn -0.7980895498222257 0.4722984052156664 0.3741487496909424 +vn -0.8486909055579567 0.5285002455522558 0.020278986030386838 +vn -0.9834605097559777 0.17940530615475422 0.024882963529921857 +vn -0.941227499687925 0.3355829134006586 0.03840445370973725 +vn -0.6872191260632746 0.3152074438531002 -0.6545029718132863 +vn -0.9834605097559777 0.17940530615475422 0.024882963529921857 +vn -0.6872191260632746 0.3152074438531002 -0.6545029718132863 +vn -0.7065522299265036 0.18490274838189358 -0.6830775358820604 +vn -0.9943567713149957 -0.10411073596521707 0.020385435899152794 +vn -0.9834605097559777 0.17940530615475422 0.024882963529921857 +vn -0.7065522299265036 0.18490274838189358 -0.6830775358820604 +vn -0.9943567713149957 -0.10411073596521707 0.020385435899152794 +vn -0.7065522299265036 0.18490274838189358 -0.6830775358820604 +vn -0.7239451931682047 -0.1200571718668144 -0.6793302825371418 +vn -0.7239451931682047 -0.1200571718668144 -0.6793302825371418 +vn -0.7065522299265036 0.18490274838189358 -0.6830775358820604 +vn 0.023936930166870388 0.08888390334636201 -0.9957543246705489 +vn -0.7239451931682047 -0.1200571718668144 -0.6793302825371418 +vn 0.023936930166870388 0.08888390334636201 -0.9957543246705489 +vn 0.02842898504555128 -0.12066283133185045 -0.9922863870598353 +vn -0.7065522299265036 0.18490274838189358 -0.6830775358820604 +vn -0.6872191260632746 0.3152074438531002 -0.6545029718132863 +vn 0.0032124219887417317 0.13418687279576144 -0.9909508380915071 +vn -0.7065522299265036 0.18490274838189358 -0.6830775358820604 +vn 0.0032124219887417317 0.13418687279576144 -0.9909508380915071 +vn 0.023936930166870388 0.08888390334636201 -0.9957543246705489 +vn 0.023936930166870388 0.08888390334636201 -0.9957543246705489 +vn 0.0032124219887417317 0.13418687279576144 -0.9909508380915071 +vn 0.7208662084698857 0.13378547227812645 -0.6800392318782572 +vn 0.023936930166870388 0.08888390334636201 -0.9957543246705489 +vn 0.7208662084698857 0.13378547227812645 -0.6800392318782572 +vn 0.7058310449119094 0.03760175747706376 -0.7073815405233574 +vn 0.02842898504555128 -0.12066283133185045 -0.9922863870598353 +vn 0.023936930166870388 0.08888390334636201 -0.9957543246705489 +vn 0.7058310449119094 0.03760175747706376 -0.7073815405233574 +vn 0.02842898504555128 -0.12066283133185045 -0.9922863870598353 +vn 0.7058310449119094 0.03760175747706376 -0.7073815405233574 +vn 0.7097417492795982 -0.1829898151808711 -0.6802803663708125 +vn -0.6872191260632746 0.3152074438531002 -0.6545029718132863 +vn -0.941227499687925 0.3355829134006586 0.03840445370973725 +vn -0.8486909055579567 0.5285002455522558 0.020278986030386838 +vn -0.6872191260632746 0.3152074438531002 -0.6545029718132863 +vn -0.8486909055579567 0.5285002455522558 0.020278986030386838 +vn -0.6260926457987154 0.5006357815164799 -0.5978058323085746 +vn -0.41113035063210696 0.32260129775719243 0.8525844459491952 +vn 0.15822398156616502 0.25602244512131117 0.9536339335675167 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn -0.41113035063210696 0.32260129775719243 0.8525844459491952 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn -0.33381177749086666 0.7293253273127284 0.5972053785328543 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.6124933152538132 0.7508812289933203 0.24704112757772534 +vn -0.33381177749086666 0.7293253273127284 0.5972053785328543 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.33381177749086666 0.7293253273127284 0.5972053785328543 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn -0.14215544931887256 0.9863233867876754 -0.08341465641384077 +vn -0.6260926457987154 0.5006357815164799 -0.5978058323085746 +vn -0.8486909055579567 0.5285002455522558 0.020278986030386838 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.6260926457987154 0.5006357815164799 -0.5978058323085746 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.4177276093459393 0.7081685491662232 -0.5692108136375598 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn 0.6469167811389347 0.3375269637269374 0.6837939945905598 +vn 0.322318590237706 0.8933716366834041 0.3130460751339866 +vn -0.14215544931887256 0.9863233867876754 -0.08341465641384077 +vn 0.6570188351403856 0.7325003685503467 0.1782398954902558 +vn 0.5071302661966973 0.679713190889666 -0.5299140224959663 +vn -0.14215544931887256 0.9863233867876754 -0.08341465641384077 +vn 0.5071302661966973 0.679713190889666 -0.5299140224959663 +vn -0.09548820079878363 0.7884330972221066 -0.6076637678132272 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.14215544931887256 0.9863233867876754 -0.08341465641384077 +vn -0.09548820079878363 0.7884330972221066 -0.6076637678132272 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.09548820079878363 0.7884330972221066 -0.6076637678132272 +vn -0.4177276093459393 0.7081685491662232 -0.5692108136375598 +vn 0.6810698852418977 0.2080724013091918 0.7020325400079507 +vn 0.9792895558713576 0.16276540263773298 0.1204134106545272 +vn 0.9402272936450381 0.2795676006462085 0.194459746358595 +vn 0.6810698852418977 0.2080724013091918 0.7020325400079507 +vn 0.9402272936450381 0.2795676006462085 0.194459746358595 +vn 0.6470120134562971 0.32214550099601613 0.6910844598392111 +vn 0.9792895558713576 0.16276540263773298 0.1204134106545272 +vn 0.7208662084698857 0.13378547227812645 -0.6800392318782572 +vn 0.6678655760015628 0.25752237502456715 -0.6983106749533525 +vn 0.9792895558713576 0.16276540263773298 0.1204134106545272 +vn 0.6678655760015628 0.25752237502456715 -0.6983106749533525 +vn 0.9402272936450381 0.2795676006462085 0.194459746358595 +vn 0.9402272936450381 0.2795676006462085 0.194459746358595 +vn 0.6678655760015628 0.25752237502456715 -0.6983106749533525 +vn 0.5071302661966973 0.679713190889666 -0.5299140224959663 +vn 0.9402272936450381 0.2795676006462085 0.194459746358595 +vn 0.5071302661966973 0.679713190889666 -0.5299140224959663 +vn 0.6570188351403856 0.7325003685503467 0.1782398954902558 +vn 0.6470120134562971 0.32214550099601613 0.6910844598392111 +vn 0.9402272936450381 0.2795676006462085 0.194459746358595 +vn 0.6570188351403856 0.7325003685503467 0.1782398954902558 +vn 0.6470120134562971 0.32214550099601613 0.6910844598392111 +vn 0.6570188351403856 0.7325003685503467 0.1782398954902558 +vn 0.6469167811389347 0.3375269637269374 0.6837939945905598 +vn 0.7208662084698857 0.13378547227812645 -0.6800392318782572 +vn 0.0032124219887417317 0.13418687279576144 -0.9909508380915071 +vn -0.01962378074917468 0.2110693118951234 -0.9772740929776189 +vn 0.7208662084698857 0.13378547227812645 -0.6800392318782572 +vn -0.01962378074917468 0.2110693118951234 -0.9772740929776189 +vn 0.6678655760015628 0.25752237502456715 -0.6983106749533525 +vn 0.0032124219887417317 0.13418687279576144 -0.9909508380915071 +vn -0.6872191260632746 0.3152074438531002 -0.6545029718132863 +vn -0.6260926457987154 0.5006357815164799 -0.5978058323085746 +vn 0.0032124219887417317 0.13418687279576144 -0.9909508380915071 +vn -0.6260926457987154 0.5006357815164799 -0.5978058323085746 +vn -0.01962378074917468 0.2110693118951234 -0.9772740929776189 +vn -0.01962378074917468 0.2110693118951234 -0.9772740929776189 +vn -0.6260926457987154 0.5006357815164799 -0.5978058323085746 +vn -0.4177276093459393 0.7081685491662232 -0.5692108136375598 +vn -0.01962378074917468 0.2110693118951234 -0.9772740929776189 +vn -0.4177276093459393 0.7081685491662232 -0.5692108136375598 +vn -0.09548820079878363 0.7884330972221066 -0.6076637678132272 +vn 0.6678655760015628 0.25752237502456715 -0.6983106749533525 +vn -0.01962378074917468 0.2110693118951234 -0.9772740929776189 +vn -0.09548820079878363 0.7884330972221066 -0.6076637678132272 +vn 0.6678655760015628 0.25752237502456715 -0.6983106749533525 +vn -0.09548820079878363 0.7884330972221066 -0.6076637678132272 +vn 0.5071302661966973 0.679713190889666 -0.5299140224959663 +vn 0.01358643573754679 0.08449273145537824 0.9963314644711161 +vn 0.06512300008157354 0.1817122960150499 0.9811929659028922 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn 0.01358643573754679 0.08449273145537824 0.9963314644711161 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn -0.42850222208687605 0.10894018151150854 0.8969492084387215 +vn 0.06512300008157354 0.1817122960150499 0.9811929659028922 +vn 0.6810698852418977 0.2080724013091918 0.7020325400079507 +vn 0.6470120134562971 0.32214550099601613 0.6910844598392111 +vn 0.06512300008157354 0.1817122960150499 0.9811929659028922 +vn 0.6470120134562971 0.32214550099601613 0.6910844598392111 +vn 0.15822398156616502 0.25602244512131117 0.9536339335675167 +vn 0.15822398156616502 0.25602244512131117 0.9536339335675167 +vn 0.6470120134562971 0.32214550099601613 0.6910844598392111 +vn 0.6469167811389347 0.3375269637269374 0.6837939945905598 +vn 0.15822398156616502 0.25602244512131117 0.9536339335675167 +vn 0.6469167811389347 0.3375269637269374 0.6837939945905598 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn -0.8486909055579567 0.5285002455522558 0.020278986030386838 +vn -0.7980895498222257 0.4722984052156664 0.3741487496909424 +vn -0.6124933152538132 0.7508812289933203 0.24704112757772534 +vn -0.8486909055579567 0.5285002455522558 0.020278986030386838 +vn -0.6124933152538132 0.7508812289933203 0.24704112757772534 +vn -0.5614847532242626 0.8267078105428459 -0.035903591521501535 +vn -0.14215544931887256 0.9863233867876754 -0.08341465641384077 +vn 0.322318590237706 0.8933716366834041 0.3130460751339866 +vn 0.6570188351403856 0.7325003685503467 0.1782398954902558 +vn 0.6570188351403856 0.7325003685503467 0.1782398954902558 +vn 0.322318590237706 0.8933716366834041 0.3130460751339866 +vn 0.6469167811389347 0.3375269637269374 0.6837939945905598 +vn 0.322318590237706 0.8933716366834041 0.3130460751339866 +vn -0.14215544931887256 0.9863233867876754 -0.08341465641384077 +vn 0.08027150295075214 0.7838061734035136 0.6157957196575569 +vn -0.7239451931682047 -0.1200571718668144 -0.6793302825371418 +vn 0.02842898504555128 -0.12066283133185045 -0.9922863870598353 +vn 0.038390780432269365 -0.31384103429059534 -0.9486990846275812 +vn -0.7239451931682047 -0.1200571718668144 -0.6793302825371418 +vn 0.038390780432269365 -0.31384103429059534 -0.9486990846275812 +vn -0.6552077295232146 -0.4055494221640525 -0.6373637088471835 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn 0.06512300008157354 0.1817122960150499 0.9811929659028922 +vn 0.15822398156616502 0.25602244512131117 0.9536339335675167 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn 0.15822398156616502 0.25602244512131117 0.9536339335675167 +vn -0.41113035063210696 0.32260129775719243 0.8525844459491952 +vn 0.02842898504555128 -0.12066283133185045 -0.9922863870598353 +vn 0.7097417492795982 -0.1829898151808711 -0.6802803663708125 +vn 0.6588789857307925 -0.38981446840557793 -0.6433686053764504 +vn 0.02842898504555128 -0.12066283133185045 -0.9922863870598353 +vn 0.6588789857307925 -0.38981446840557793 -0.6433686053764504 +vn 0.038390780432269365 -0.31384103429059534 -0.9486990846275812 +vn -0.03567480384470595 -0.13271598951652872 0.9905118749905476 +vn -0.4633038123683755 -0.17104412199178726 0.8695363625386737 +vn -0.40002549681229516 -0.35320575265136483 0.8457099373863709 +vn -0.03567480384470595 -0.13271598951652872 0.9905118749905476 +vn -0.40002549681229516 -0.35320575265136483 0.8457099373863709 +vn -0.05290294202028155 -0.30088077630193094 0.9521932772171553 +vn 0.9837901350634028 -0.17733885327973467 0.02660641406428711 +vn 0.6517133562709272 -0.15851294629372636 0.741716487018703 +vn 0.5946519669805319 -0.39915860658432406 0.6978978757353007 +vn 0.9837901350634028 -0.17733885327973467 0.02660641406428711 +vn 0.5946519669805319 -0.39915860658432406 0.6978978757353007 +vn 0.9372438037171197 -0.34833148310033496 0.0154670706659773 +vn -0.9943567713149957 -0.10411073596521707 0.020385435899152794 +vn -0.7239451931682047 -0.1200571718668144 -0.6793302825371418 +vn -0.6552077295232146 -0.4055494221640525 -0.6373637088471835 +vn -0.9943567713149957 -0.10411073596521707 0.020385435899152794 +vn -0.6552077295232146 -0.4055494221640525 -0.6373637088471835 +vn -0.9417535786574657 -0.33562446938233104 0.021363816084343658 +vn 0.7097417492795982 -0.1829898151808711 -0.6802803663708125 +vn 0.9837901350634028 -0.17733885327973467 0.02660641406428711 +vn 0.9372438037171197 -0.34833148310033496 0.0154670706659773 +vn 0.7097417492795982 -0.1829898151808711 -0.6802803663708125 +vn 0.9372438037171197 -0.34833148310033496 0.0154670706659773 +vn 0.6588789857307925 -0.38981446840557793 -0.6433686053764504 +vn 0.6517133562709272 -0.15851294629372636 0.741716487018703 +vn -0.03567480384470595 -0.13271598951652872 0.9905118749905476 +vn -0.05290294202028155 -0.30088077630193094 0.9521932772171553 +vn 0.6517133562709272 -0.15851294629372636 0.741716487018703 +vn -0.05290294202028155 -0.30088077630193094 0.9521932772171553 +vn 0.5946519669805319 -0.39915860658432406 0.6978978757353007 +vn -0.8511331717889251 0.3364868776101403 0.4029254336433759 +vn -0.8841383452573867 0.16795282414964627 0.4359945358667791 +vn -0.42850222208687605 0.10894018151150854 0.8969492084387215 +vn -0.8511331717889251 0.3364868776101403 0.4029254336433759 +vn -0.42850222208687605 0.10894018151150854 0.8969492084387215 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn -0.8841383452573867 0.16795282414964627 0.4359945358667791 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.4633038123683755 -0.17104412199178726 0.8695363625386737 +vn -0.8841383452573867 0.16795282414964627 0.4359945358667791 +vn -0.4633038123683755 -0.17104412199178726 0.8695363625386737 +vn -0.42850222208687605 0.10894018151150854 0.8969492084387215 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn -0.41113035063210696 0.32260129775719243 0.8525844459491952 +vn -0.7980895498222257 0.4722984052156664 0.3741487496909424 +vn -0.422079644008911 0.2538695700822324 0.8702867432631464 +vn -0.7980895498222257 0.4722984052156664 0.3741487496909424 +vn -0.8511331717889251 0.3364868776101403 0.4029254336433759 +vn -0.41113035063210696 0.32260129775719243 0.8525844459491952 +vn -0.33381177749086666 0.7293253273127284 0.5972053785328543 +vn -0.6124933152538132 0.7508812289933203 0.24704112757772534 +vn -0.41113035063210696 0.32260129775719243 0.8525844459491952 +vn -0.6124933152538132 0.7508812289933203 0.24704112757772534 +vn -0.7980895498222257 0.4722984052156664 0.3741487496909424 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.8435083940194295 -0.3760793114928615 0.3834813433347417 +vn -0.40002549681229516 -0.35320575265136483 0.8457099373863709 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.40002549681229516 -0.35320575265136483 0.8457099373863709 +vn -0.4633038123683755 -0.17104412199178726 0.8695363625386737 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.8841383452573867 0.16795282414964627 0.4359945358667791 +vn -0.9834605097559777 0.17940530615475422 0.024882963529921857 +vn -0.8961485599960235 -0.14356160124866077 0.41989025359488164 +vn -0.9834605097559777 0.17940530615475422 0.024882963529921857 +vn -0.9943567713149957 -0.10411073596521707 0.020385435899152794 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 8/8/8 9/9/9 +f 10/10/10 11/11/11 12/12/12 +f 13/13/13 14/14/14 15/15/15 +f 16/16/16 17/17/17 18/18/18 +f 19/19/19 20/20/20 21/21/21 +f 22/22/22 23/23/23 24/24/24 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 29/29/29 30/30/30 +f 31/31/31 32/32/32 33/33/33 +f 34/34/34 35/35/35 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 40/40/40 41/41/41 42/42/42 +f 43/43/43 44/44/44 45/45/45 +f 46/46/46 47/47/47 48/48/48 +f 49/49/49 50/50/50 51/51/51 +f 52/52/52 53/53/53 54/54/54 +f 55/55/55 56/56/56 57/57/57 +f 58/58/58 59/59/59 60/60/60 +f 61/61/61 62/62/62 63/63/63 +f 64/64/64 65/65/65 66/66/66 +f 67/67/67 68/68/68 69/69/69 +f 70/70/70 71/71/71 72/72/72 +f 73/73/73 74/74/74 75/75/75 +f 76/76/76 77/77/77 78/78/78 +f 79/79/79 80/80/80 81/81/81 +f 82/82/82 83/83/83 84/84/84 +f 85/85/85 86/86/86 87/87/87 +f 88/88/88 89/89/89 90/90/90 +f 91/91/91 92/92/92 93/93/93 +f 94/94/94 95/95/95 96/96/96 +f 97/97/97 98/98/98 99/99/99 +f 100/100/100 101/101/101 102/102/102 +f 103/103/103 104/104/104 105/105/105 +f 106/106/106 107/107/107 108/108/108 +f 109/109/109 110/110/110 111/111/111 +f 112/112/112 113/113/113 114/114/114 +f 115/115/115 116/116/116 117/117/117 +f 118/118/118 119/119/119 120/120/120 +f 121/121/121 122/122/122 123/123/123 +f 124/124/124 125/125/125 126/126/126 +f 127/127/127 128/128/128 129/129/129 +f 130/130/130 131/131/131 132/132/132 +f 133/133/133 134/134/134 135/135/135 +f 136/136/136 137/137/137 138/138/138 +f 139/139/139 140/140/140 141/141/141 +f 142/142/142 143/143/143 144/144/144 +f 145/145/145 146/146/146 147/147/147 +f 148/148/148 149/149/149 150/150/150 +f 151/151/151 152/152/152 153/153/153 +f 154/154/154 155/155/155 156/156/156 +f 157/157/157 158/158/158 159/159/159 +f 160/160/160 161/161/161 162/162/162 +f 163/163/163 164/164/164 165/165/165 +f 166/166/166 167/167/167 168/168/168 +f 169/169/169 170/170/170 171/171/171 +f 172/172/172 173/173/173 174/174/174 +f 175/175/175 176/176/176 177/177/177 +f 178/178/178 179/179/179 180/180/180 +f 181/181/181 182/182/182 183/183/183 +f 184/184/184 185/185/185 186/186/186 +f 187/187/187 188/188/188 189/189/189 +f 190/190/190 191/191/191 192/192/192 +f 193/193/193 194/194/194 195/195/195 +f 196/196/196 197/197/197 198/198/198 +f 199/199/199 200/200/200 201/201/201 +f 202/202/202 203/203/203 204/204/204 +f 205/205/205 206/206/206 207/207/207 +f 208/208/208 209/209/209 210/210/210 +f 211/211/211 212/212/212 213/213/213 +f 214/214/214 215/215/215 216/216/216 +f 217/217/217 218/218/218 219/219/219 +f 220/220/220 221/221/221 222/222/222 +f 223/223/223 224/224/224 225/225/225 +f 226/226/226 227/227/227 228/228/228 +f 229/229/229 230/230/230 231/231/231 +f 232/232/232 233/233/233 234/234/234 +f 235/235/235 236/236/236 237/237/237 +f 238/238/238 239/239/239 240/240/240 +f 241/241/241 242/242/242 243/243/243 +f 244/244/244 245/245/245 246/246/246 +f 247/247/247 248/248/248 249/249/249 +f 250/250/250 251/251/251 252/252/252 +f 253/253/253 254/254/254 255/255/255 +f 256/256/256 257/257/257 258/258/258 +f 259/259/259 260/260/260 261/261/261 +f 262/262/262 263/263/263 264/264/264 +f 265/265/265 266/266/266 267/267/267 +f 268/268/268 269/269/269 270/270/270 +f 271/271/271 272/272/272 273/273/273 +f 274/274/274 275/275/275 276/276/276 +f 277/277/277 278/278/278 279/279/279 +f 280/280/280 281/281/281 282/282/282 +f 283/283/283 284/284/284 285/285/285 +f 286/286/286 287/287/287 288/288/288 +f 289/289/289 290/290/290 291/291/291 +f 292/292/292 293/293/293 294/294/294 +f 295/295/295 296/296/296 297/297/297 +f 298/298/298 299/299/299 300/300/300 +f 301/301/301 302/302/302 303/303/303 diff --git a/apps/openmb/resources/models/rocks/SM_Rocks_04.obj b/apps/openmb/resources/models/rocks/SM_Rocks_04.obj new file mode 100644 index 0000000..7236bbd --- /dev/null +++ b/apps/openmb/resources/models/rocks/SM_Rocks_04.obj @@ -0,0 +1,373 @@ +mtllib SM_Rocks_04.mtl +o SM_Rock_04 +usemtl SM_Rock_01 +v -43.19601058959961 30.734363555908203 28.441789627075195 1 1 1 +v -29.872751235961914 64.30950164794922 16.75210952758789 1 1 1 +v -17.701387405395508 64.43751525878906 -23.968463897705078 1 1 1 +v -43.19601058959961 30.734363555908203 28.441789627075195 1 1 1 +v -17.701387405395508 64.43751525878906 -23.968463897705078 1 1 1 +v -29.772281646728516 31.171714782714844 -34.29191589355469 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 9.810304641723633 29.882055282592773 -35.11172103881836 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 42.13508224487305 36.413055419921875 -26.57986831665039 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v -29.872751235961914 64.30950164794922 16.75210952758789 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v -29.872751235961914 64.30950164794922 16.75210952758789 1 1 1 +v -43.19601058959961 30.734363555908203 28.441789627075195 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v -17.701387405395508 64.43751525878906 -23.968463897705078 1 1 1 +v -29.872751235961914 64.30950164794922 16.75210952758789 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v -29.872751235961914 64.30950164794922 16.75210952758789 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v 7.273340225219727 -2.6153628826141357 35.4881706237793 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v -43.19601058959961 30.734363555908203 28.441789627075195 1 1 1 +v 7.273340225219727 -2.6153628826141357 35.4881706237793 1 1 1 +v -43.19601058959961 30.734363555908203 28.441789627075195 1 1 1 +v -55.033447265625 -3.083256721496582 26.640764236450195 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 45.1383171081543 26.66870880126953 -17.448444366455078 1 1 1 +v 42.13508224487305 36.413055419921875 -26.57986831665039 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 42.13508224487305 36.413055419921875 -26.57986831665039 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 31.017959594726562 52.629913330078125 26.992488861083984 1 1 1 +v 38.726280212402344 -0.8372985124588013 -18.067529678344727 1 1 1 +v 45.1383171081543 26.66870880126953 -17.448444366455078 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 38.726280212402344 -0.8372985124588013 -18.067529678344727 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 33.438865661621094 -2.486894130706787 32.72226333618164 1 1 1 +v -55.033447265625 -3.083256721496582 26.640764236450195 1 1 1 +v -43.19601058959961 30.734363555908203 28.441789627075195 1 1 1 +v -29.772281646728516 31.171714782714844 -34.29191589355469 1 1 1 +v -55.033447265625 -3.083256721496582 26.640764236450195 1 1 1 +v -29.772281646728516 31.171714782714844 -34.29191589355469 1 1 1 +v -41.63890075683594 -2.820389747619629 -31.34072494506836 1 1 1 +v -41.63890075683594 -2.820389747619629 -31.34072494506836 1 1 1 +v -29.772281646728516 31.171714782714844 -34.29191589355469 1 1 1 +v 9.810304641723633 29.882055282592773 -35.11172103881836 1 1 1 +v -41.63890075683594 -2.820389747619629 -31.34072494506836 1 1 1 +v 9.810304641723633 29.882055282592773 -35.11172103881836 1 1 1 +v 9.735822677612305 -2.8241753578186035 -40.674346923828125 1 1 1 +v 33.438865661621094 -2.486894130706787 32.72226333618164 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v 33.438865661621094 -2.486894130706787 32.72226333618164 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v 7.273340225219727 -2.6153628826141357 35.4881706237793 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v 24.20393943786621 72.47430419921875 14.655621528625488 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 22.798749923706055 53.188026428222656 28.880756378173828 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v -29.772281646728516 31.171714782714844 -34.29191589355469 1 1 1 +v -17.701387405395508 64.43751525878906 -23.968463897705078 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v -29.772281646728516 31.171714782714844 -34.29191589355469 1 1 1 +v 9.623098373413086 70.37802124023438 -26.080387115478516 1 1 1 +v 9.810304641723633 29.882055282592773 -35.11172103881836 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v 22.798749923706055 53.188026428222656 28.880756378173828 1 1 1 +v 31.017959594726562 52.629913330078125 26.992488861083984 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v 31.017959594726562 52.629913330078125 26.992488861083984 1 1 1 +v 24.20393943786621 72.47430419921875 14.655621528625488 1 1 1 +v 31.017959594726562 52.629913330078125 26.992488861083984 1 1 1 +v 22.798749923706055 53.188026428222656 28.880756378173828 1 1 1 +v 41.65410232543945 20.471298217773438 34.866695404052734 1 1 1 +v 7.537317276000977 30.22222137451172 31.765287399291992 1 1 1 +v 22.798749923706055 53.188026428222656 28.880756378173828 1 1 1 +v 7.250070571899414 71.78343200683594 21.94721031188965 1 1 1 +v 31.017959594726562 52.629913330078125 26.992488861083984 1 1 1 +v 28.456357955932617 71.23019409179688 -20.94366455078125 1 1 1 +v 24.20393943786621 72.47430419921875 14.655621528625488 1 1 1 +v 45.1383171081543 26.66870880126953 -17.448444366455078 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 42.13508224487305 36.413055419921875 -26.57986831665039 1 1 1 +v 30.425613403320312 -1.2934051752090454 -31.27834129333496 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 45.1383171081543 26.66870880126953 -17.448444366455078 1 1 1 +v 30.425613403320312 -1.2934051752090454 -31.27834129333496 1 1 1 +v 45.1383171081543 26.66870880126953 -17.448444366455078 1 1 1 +v 38.726280212402344 -0.8372985124588013 -18.067529678344727 1 1 1 +v 9.735822677612305 -2.8241753578186035 -40.674346923828125 1 1 1 +v 9.810304641723633 29.882055282592773 -35.11172103881836 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 9.735822677612305 -2.8241753578186035 -40.674346923828125 1 1 1 +v 36.006526947021484 28.326520919799805 -28.65474510192871 1 1 1 +v 30.425613403320312 -1.2934051752090454 -31.27834129333496 1 1 1 +vt 0.4367067813873291 0.7001103758811951 +vt 0.4778760075569153 0.6008245348930359 +vt 0.5980533957481384 0.598456859588623 +vt 0.4367067813873291 0.7001103758811951 +vt 0.5980533957481384 0.598456859588623 +vt 0.6184154748916626 0.700675368309021 +vt 0.18712486326694489 0.5098891854286194 +vt 0.11431802064180374 0.5305035710334778 +vt 0.08036277443170547 0.41818636655807495 +vt 0.13108490407466888 0.3978651165962219 +vt 0.18712486326694489 0.5098891854286194 +vt 0.08036277443170547 0.41818636655807495 +vt 0.18712486326694489 0.5098891854286194 +vt 0.13108490407466888 0.3978651165962219 +vt 0.1970166563987732 0.4822726845741272 +vt 0.5791115760803223 0.18038535118103027 +vt 0.45834165811538696 0.17720985412597656 +vt 0.4784361720085144 0.07184475660324097 +vt 0.5791115760803223 0.18038535118103027 +vt 0.4784361720085144 0.07184475660324097 +vt 0.578572154045105 0.03641456365585327 +vt 0.9111959338188171 0.36068034172058105 +vt 0.8945875763893127 0.4380154609680176 +vt 0.7755244374275208 0.45587849617004395 +vt 0.9111959338188171 0.36068034172058105 +vt 0.7755244374275208 0.45587849617004395 +vt 0.7755244374275208 0.3478517532348633 +vt 0.672529399394989 0.1810988187789917 +vt 0.5791115760803223 0.18038535118103027 +vt 0.578572154045105 0.03641456365585327 +vt 0.672529399394989 0.1810988187789917 +vt 0.578572154045105 0.03641456365585327 +vt 0.672529399394989 0.003841996192932129 +vt 0.18977078795433044 0.7926868200302124 +vt 0.04147539287805557 0.7737540602684021 +vt 0.01649971306324005 0.7497761845588684 +vt 0.03594992309808731 0.6659449934959412 +vt 0.18977078795433044 0.7926868200302124 +vt 0.01649971306324005 0.7497761845588684 +vt 0.18977078795433044 0.7926868200302124 +vt 0.03594992309808731 0.6659449934959412 +vt 0.1704154908657074 0.7138378024101257 +vt 0.0398271270096302 0.8536456227302551 +vt 0.04147539287805557 0.7737540602684021 +vt 0.18977078795433044 0.7926868200302124 +vt 0.0398271270096302 0.8536456227302551 +vt 0.18977078795433044 0.7926868200302124 +vt 0.18427087366580963 0.8616713285446167 +vt 0.4337061941623688 0.8016939163208008 +vt 0.4367067813873291 0.7001103758811951 +vt 0.6184154748916626 0.700675368309021 +vt 0.4337061941623688 0.8016939163208008 +vt 0.6184154748916626 0.700675368309021 +vt 0.6022860407829285 0.801693856716156 +vt 0.0038419701159000397 0.6577960848808289 +vt 0.006501962896436453 0.5590629577636719 +vt 0.11431802064180374 0.5305035710334778 +vt 0.0038419701159000397 0.6577960848808289 +vt 0.11431802064180374 0.5305035710334778 +vt 0.14134392142295837 0.6205140948295593 +vt 0.6694618463516235 0.2548877000808716 +vt 0.6061301231384277 0.27760010957717896 +vt 0.5791115760803223 0.18038535118103027 +vt 0.6694618463516235 0.2548877000808716 +vt 0.5791115760803223 0.18038535118103027 +vt 0.672529399394989 0.1810988187789917 +vt 0.9043798446655273 0.3059588670730591 +vt 0.9111959338188171 0.36068034172058105 +vt 0.7755244374275208 0.3478517532348633 +vt 0.9043798446655273 0.3059588670730591 +vt 0.7755244374275208 0.3478517532348633 +vt 0.8027920722961426 0.30331242084503174 +vt 0.6061301231384277 0.27760010957717896 +vt 0.512876033782959 0.22253865003585815 +vt 0.5791115760803223 0.18038535118103027 +vt 0.006501962896436453 0.5590629577636719 +vt 0.011952386237680912 0.4553014039993286 +vt 0.08036277443170547 0.41818636655807495 +vt 0.006501962896436453 0.5590629577636719 +vt 0.08036277443170547 0.41818636655807495 +vt 0.11431802064180374 0.5305035710334778 +vt 0.45834165811538696 0.17720985412597656 +vt 0.512876033782959 0.22253865003585815 +vt 0.5130683183670044 0.2456347942352295 +vt 0.45834165811538696 0.17720985412597656 +vt 0.5130683183670044 0.2456347942352295 +vt 0.4518965482711792 0.2244480848312378 +vt 0.5130683183670044 0.2456347942352295 +vt 0.512876033782959 0.22253865003585815 +vt 0.6061301231384277 0.27760010957717896 +vt 0.5791115760803223 0.18038535118103027 +vt 0.512876033782959 0.22253865003585815 +vt 0.45834165811538696 0.17720985412597656 +vt 0.1704154908657074 0.7138378024101257 +vt 0.03594992309808731 0.6659449934959412 +vt 0.13736848533153534 0.6654801368713379 +vt 0.04147539287805557 0.7737540602684021 +vt 0.0113717932254076 0.7766685485839844 +vt 0.01649971306324005 0.7497761845588684 +vt 0.0038419971242547035 0.8616713285446167 +vt 0.0113717932254076 0.7766685485839844 +vt 0.04147539287805557 0.7737540602684021 +vt 0.0038419971242547035 0.8616713285446167 +vt 0.04147539287805557 0.7737540602684021 +vt 0.0398271270096302 0.8536456227302551 +vt 0.14134392142295837 0.6205140948295593 +vt 0.11431802064180374 0.5305035710334778 +vt 0.18712486326694489 0.5098891854286194 +vt 0.14134392142295837 0.6205140948295593 +vt 0.18712486326694489 0.5098891854286194 +vt 0.1970166563987732 0.5946849584579468 +vn -0.7157215323560417 0.337741695599858 0.611288176865259 +vn -0.6088136470227327 0.6974004547927667 0.3781250439388028 +vn -0.47315092157166316 0.6811844888289839 -0.5586733371073671 +vn -0.7157215323560417 0.337741695599858 0.611288176865259 +vn -0.47315092157166316 0.6811844888289839 -0.5586733371073671 +vn -0.5863432100539792 0.28169181158222495 -0.7595073161669474 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn 0.09447895418186718 0.1586745798979265 -0.9828001347735545 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn 0.7866441323316651 0.17337355881502692 -0.5925644422102747 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn -0.6088136470227327 0.6974004547927667 0.3781250439388028 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn -0.6088136470227327 0.6974004547927667 0.3781250439388028 +vn -0.7157215323560417 0.337741695599858 0.611288176865259 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn -0.47315092157166316 0.6811844888289839 -0.5586733371073671 +vn -0.6088136470227327 0.6974004547927667 0.3781250439388028 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn -0.6088136470227327 0.6974004547927667 0.3781250439388028 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn -0.05445489001765192 0.03837041728114668 0.9977787209751651 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn -0.7157215323560417 0.337741695599858 0.611288176865259 +vn -0.05445489001765192 0.03837041728114668 0.9977787209751651 +vn -0.7157215323560417 0.337741695599858 0.611288176865259 +vn -0.8274922513719093 0.2933713844384553 0.47873772016847915 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn 0.981756335737993 -0.011495907863576193 -0.18979552508081196 +vn 0.7866441323316651 0.17337355881502692 -0.5925644422102747 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn 0.7866441323316651 0.17337355881502692 -0.5925644422102747 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn 0.668746728282906 0.45002077271961904 0.5918269320770608 +vn 0.9318677121397121 -0.21812245191220234 -0.289905438105786 +vn 0.981756335737993 -0.011495907863576193 -0.18979552508081196 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn 0.9318677121397121 -0.21812245191220234 -0.289905438105786 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn 0.5985417453835973 -0.15448180019410104 0.7860554385295906 +vn -0.8274922513719093 0.2933713844384553 0.47873772016847915 +vn -0.7157215323560417 0.337741695599858 0.611288176865259 +vn -0.5863432100539792 0.28169181158222495 -0.7595073161669474 +vn -0.8274922513719093 0.2933713844384553 0.47873772016847915 +vn -0.5863432100539792 0.28169181158222495 -0.7595073161669474 +vn -0.7165060974330482 0.25818081749418853 -0.6480445029620233 +vn -0.7165060974330482 0.25818081749418853 -0.6480445029620233 +vn -0.5863432100539792 0.28169181158222495 -0.7595073161669474 +vn 0.09447895418186718 0.1586745798979265 -0.9828001347735545 +vn -0.7165060974330482 0.25818081749418853 -0.6480445029620233 +vn 0.09447895418186718 0.1586745798979265 -0.9828001347735545 +vn 0.09890089624040926 0.0778997888974533 -0.99204346457833 +vn 0.5985417453835973 -0.15448180019410104 0.7860554385295906 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn 0.5985417453835973 -0.15448180019410104 0.7860554385295906 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn -0.05445489001765192 0.03837041728114668 0.9977787209751651 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn 0.4873899318332148 0.8198584670639274 0.30047154329686754 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn 0.08624149391751162 0.3561094508373157 0.9304560514883125 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn -0.5863432100539792 0.28169181158222495 -0.7595073161669474 +vn -0.47315092157166316 0.6811844888289839 -0.5586733371073671 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn -0.5863432100539792 0.28169181158222495 -0.7595073161669474 +vn -0.014116165970960468 0.7541001338369113 -0.6566077383076083 +vn 0.09447895418186718 0.1586745798979265 -0.9828001347735545 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn 0.08624149391751162 0.3561094508373157 0.9304560514883125 +vn 0.668746728282906 0.45002077271961904 0.5918269320770608 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn 0.668746728282906 0.45002077271961904 0.5918269320770608 +vn 0.4873899318332148 0.8198584670639274 0.30047154329686754 +vn 0.668746728282906 0.45002077271961904 0.5918269320770608 +vn 0.08624149391751162 0.3561094508373157 0.9304560514883125 +vn 0.7148287441594655 0.05391033475903227 0.6972184322933312 +vn -0.08018530835205877 0.143189250172142 0.9864416632318533 +vn 0.08624149391751162 0.3561094508373157 0.9304560514883125 +vn -0.06411527903658107 0.8038538771331262 0.5913612899168341 +vn 0.668746728282906 0.45002077271961904 0.5918269320770608 +vn 0.5312390249885971 0.7260330809441002 -0.4366475279948141 +vn 0.4873899318332148 0.8198584670639274 0.30047154329686754 +vn 0.981756335737993 -0.011495907863576193 -0.18979552508081196 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn 0.7866441323316651 0.17337355881502692 -0.5925644422102747 +vn 0.5545206928214875 -0.0035577463172636495 -0.8321623301219055 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn 0.981756335737993 -0.011495907863576193 -0.18979552508081196 +vn 0.5545206928214875 -0.0035577463172636495 -0.8321623301219055 +vn 0.981756335737993 -0.011495907863576193 -0.18979552508081196 +vn 0.9318677121397121 -0.21812245191220234 -0.289905438105786 +vn 0.09890089624040926 0.0778997888974533 -0.99204346457833 +vn 0.09447895418186718 0.1586745798979265 -0.9828001347735545 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn 0.09890089624040926 0.0778997888974533 -0.99204346457833 +vn 0.5138889051374591 -0.006636006881918351 -0.8578310769547154 +vn 0.5545206928214875 -0.0035577463172636495 -0.8321623301219055 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 8/8/8 9/9/9 +f 10/10/10 11/11/11 12/12/12 +f 13/13/13 14/14/14 15/15/15 +f 16/16/16 17/17/17 18/18/18 +f 19/19/19 20/20/20 21/21/21 +f 22/22/22 23/23/23 24/24/24 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 29/29/29 30/30/30 +f 31/31/31 32/32/32 33/33/33 +f 34/34/34 35/35/35 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 40/40/40 41/41/41 42/42/42 +f 43/43/43 44/44/44 45/45/45 +f 46/46/46 47/47/47 48/48/48 +f 49/49/49 50/50/50 51/51/51 +f 52/52/52 53/53/53 54/54/54 +f 55/55/55 56/56/56 57/57/57 +f 58/58/58 59/59/59 60/60/60 +f 61/61/61 62/62/62 63/63/63 +f 64/64/64 65/65/65 66/66/66 +f 67/67/67 68/68/68 69/69/69 +f 70/70/70 71/71/71 72/72/72 +f 73/73/73 74/74/74 75/75/75 +f 76/76/76 77/77/77 78/78/78 +f 79/79/79 80/80/80 81/81/81 +f 82/82/82 83/83/83 84/84/84 +f 85/85/85 86/86/86 87/87/87 +f 88/88/88 89/89/89 90/90/90 +f 91/91/91 92/92/92 93/93/93 +f 94/94/94 95/95/95 96/96/96 +f 97/97/97 98/98/98 99/99/99 +f 100/100/100 101/101/101 102/102/102 +f 103/103/103 104/104/104 105/105/105 +f 106/106/106 107/107/107 108/108/108 +f 109/109/109 110/110/110 111/111/111 diff --git a/apps/openmb/resources/models/rocks/SM_Rocks_05.obj b/apps/openmb/resources/models/rocks/SM_Rocks_05.obj new file mode 100644 index 0000000..8542373 --- /dev/null +++ b/apps/openmb/resources/models/rocks/SM_Rocks_05.obj @@ -0,0 +1,283 @@ +mtllib SM_Rocks_05.mtl +o SM_Rock_05 +usemtl SM_Rock_01 +v -40.50653076171875 46.60209274291992 27.66851234436035 1 1 1 +v -38.85527801513672 96.24703979492188 12.692525863647461 1 1 1 +v -37.72928237915039 98.91350555419922 -17.942962646484375 1 1 1 +v -40.50653076171875 46.60209274291992 27.66851234436035 1 1 1 +v -37.72928237915039 98.91350555419922 -17.942962646484375 1 1 1 +v -40.456756591796875 46.42837905883789 -33.537349700927734 1 1 1 +v -6.37501335144043 46.57329177856445 -43.0497932434082 1 1 1 +v -19.741682052612305 94.74181365966797 -28.24983024597168 1 1 1 +v 0.13704803586006165 89.18071746826172 -13.498573303222656 1 1 1 +v -6.37501335144043 46.57329177856445 -43.0497932434082 1 1 1 +v 0.13704803586006165 89.18071746826172 -13.498573303222656 1 1 1 +v 27.812252044677734 46.73490905761719 -12.94567584991455 1 1 1 +v 27.812252044677734 46.73490905761719 -12.94567584991455 1 1 1 +v 0.13704803586006165 89.18071746826172 -13.498573303222656 1 1 1 +v -1.4110591411590576 87.11785888671875 18.313655853271484 1 1 1 +v 27.812252044677734 46.73490905761719 -12.94567584991455 1 1 1 +v -1.4110591411590576 87.11785888671875 18.313655853271484 1 1 1 +v 24.609643936157227 46.474308013916016 33.71485900878906 1 1 1 +v -7.459566116333008 46.733516693115234 32.7945556640625 1 1 1 +v -20.50605583190918 93.2823715209961 18.686105728149414 1 1 1 +v -38.85527801513672 96.24703979492188 12.692525863647461 1 1 1 +v -7.459566116333008 46.733516693115234 32.7945556640625 1 1 1 +v -38.85527801513672 96.24703979492188 12.692525863647461 1 1 1 +v -40.50653076171875 46.60209274291992 27.66851234436035 1 1 1 +v -19.741682052612305 94.74181365966797 -28.24983024597168 1 1 1 +v -37.72928237915039 98.91350555419922 -17.942962646484375 1 1 1 +v -38.85527801513672 96.24703979492188 12.692525863647461 1 1 1 +v -19.741682052612305 94.74181365966797 -28.24983024597168 1 1 1 +v -38.85527801513672 96.24703979492188 12.692525863647461 1 1 1 +v -20.50605583190918 93.2823715209961 18.686105728149414 1 1 1 +v 0.8742848634719849 -2.4600632190704346 43.09696960449219 1 1 1 +v -7.459566116333008 46.733516693115234 32.7945556640625 1 1 1 +v -40.50653076171875 46.60209274291992 27.66851234436035 1 1 1 +v 0.8742848634719849 -2.4600632190704346 43.09696960449219 1 1 1 +v -40.50653076171875 46.60209274291992 27.66851234436035 1 1 1 +v -40.38329315185547 -2.5335843563079834 36.885772705078125 1 1 1 +v 45.409767150878906 -2.484806776046753 -13.021038055419922 1 1 1 +v 27.812252044677734 46.73490905761719 -12.94567584991455 1 1 1 +v 24.609643936157227 46.474308013916016 33.71485900878906 1 1 1 +v 45.409767150878906 -2.484806776046753 -13.021038055419922 1 1 1 +v 24.609643936157227 46.474308013916016 33.71485900878906 1 1 1 +v 42.05434036254883 -2.6127004623413086 43.10321044921875 1 1 1 +v 2.3169233798980713 -2.429234027862549 -43.255126953125 1 1 1 +v -6.37501335144043 46.57329177856445 -43.0497932434082 1 1 1 +v 27.812252044677734 46.73490905761719 -12.94567584991455 1 1 1 +v 2.3169233798980713 -2.429234027862549 -43.255126953125 1 1 1 +v 27.812252044677734 46.73490905761719 -12.94567584991455 1 1 1 +v 45.409767150878906 -2.484806776046753 -13.021038055419922 1 1 1 +v -40.38329315185547 -2.5335843563079834 36.885772705078125 1 1 1 +v -40.50653076171875 46.60209274291992 27.66851234436035 1 1 1 +v -40.456756591796875 46.42837905883789 -33.537349700927734 1 1 1 +v -40.38329315185547 -2.5335843563079834 36.885772705078125 1 1 1 +v -40.456756591796875 46.42837905883789 -33.537349700927734 1 1 1 +v -40.46354675292969 -2.4489197731018066 -34.38356399536133 1 1 1 +v -40.46354675292969 -2.4489197731018066 -34.38356399536133 1 1 1 +v -40.456756591796875 46.42837905883789 -33.537349700927734 1 1 1 +v -6.37501335144043 46.57329177856445 -43.0497932434082 1 1 1 +v -40.46354675292969 -2.4489197731018066 -34.38356399536133 1 1 1 +v -6.37501335144043 46.57329177856445 -43.0497932434082 1 1 1 +v 2.3169233798980713 -2.429234027862549 -43.255126953125 1 1 1 +v 42.05434036254883 -2.6127004623413086 43.10321044921875 1 1 1 +v 24.609643936157227 46.474308013916016 33.71485900878906 1 1 1 +v -7.459566116333008 46.733516693115234 32.7945556640625 1 1 1 +v 42.05434036254883 -2.6127004623413086 43.10321044921875 1 1 1 +v -7.459566116333008 46.733516693115234 32.7945556640625 1 1 1 +v 0.8742848634719849 -2.4600632190704346 43.09696960449219 1 1 1 +v 0.13704803586006165 89.18071746826172 -13.498573303222656 1 1 1 +v -19.741682052612305 94.74181365966797 -28.24983024597168 1 1 1 +v -20.50605583190918 93.2823715209961 18.686105728149414 1 1 1 +v 0.13704803586006165 89.18071746826172 -13.498573303222656 1 1 1 +v -20.50605583190918 93.2823715209961 18.686105728149414 1 1 1 +v -1.4110591411590576 87.11785888671875 18.313655853271484 1 1 1 +v 24.609643936157227 46.474308013916016 33.71485900878906 1 1 1 +v -1.4110591411590576 87.11785888671875 18.313655853271484 1 1 1 +v -20.50605583190918 93.2823715209961 18.686105728149414 1 1 1 +v 24.609643936157227 46.474308013916016 33.71485900878906 1 1 1 +v -20.50605583190918 93.2823715209961 18.686105728149414 1 1 1 +v -7.459566116333008 46.733516693115234 32.7945556640625 1 1 1 +v -40.456756591796875 46.42837905883789 -33.537349700927734 1 1 1 +v -37.72928237915039 98.91350555419922 -17.942962646484375 1 1 1 +v -19.741682052612305 94.74181365966797 -28.24983024597168 1 1 1 +v -40.456756591796875 46.42837905883789 -33.537349700927734 1 1 1 +v -19.741682052612305 94.74181365966797 -28.24983024597168 1 1 1 +v -6.37501335144043 46.57329177856445 -43.0497932434082 1 1 1 +vt 0.4598149061203003 0.4516195058822632 +vt 0.5022656321525574 0.310920774936676 +vt 0.5890682339668274 0.30331242084503174 +vt 0.4598149061203003 0.4516195058822632 +vt 0.5890682339668274 0.30331242084503174 +vt 0.6332000494003296 0.45212918519973755 +vt 0.003841998288407922 0.1566031575202942 +vt 0.07301238924264908 0.02964681386947632 +vt 0.10249044746160507 0.07651758193969727 +vt 0.003841998288407922 0.1566031575202942 +vt 0.10249044746160507 0.07651758193969727 +vt 0.07215281575918198 0.21590596437454224 +vt 0.07215281575918198 0.21590596437454224 +vt 0.10249044746160507 0.07651758193969727 +vt 0.19000186026096344 0.0992354154586792 +vt 0.07215281575918198 0.21590596437454224 +vt 0.19000186026096344 0.0992354154586792 +vt 0.20220735669136047 0.24122107028961182 +vt 0.34975001215934753 0.1534515619277954 +vt 0.38760825991630554 0.015950024127960205 +vt 0.4406205117702484 0.003841996192932129 +vt 0.34975001215934753 0.1534515619277954 +vt 0.4406205117702484 0.003841996192932129 +vt 0.4442126750946045 0.1506001353263855 +vt 0.07301238924264908 0.02964681386947632 +vt 0.11122466623783112 0.0038419365882873535 +vt 0.19502270221710205 0.02785205841064453 +vt 0.07301238924264908 0.02964681386947632 +vt 0.19502270221710205 0.02785205841064453 +vt 0.20220735669136047 0.061058640480041504 +vt 0.32616686820983887 0.2956284284591675 +vt 0.34975001215934753 0.1534515619277954 +vt 0.4442126750946045 0.1506001353263855 +vt 0.32616686820983887 0.2956284284591675 +vt 0.4442126750946045 0.1506001353263855 +vt 0.44405293464660645 0.29195040464401245 +vt 0.04129339009523392 0.3595932722091675 +vt 0.07215281575918198 0.21590596437454224 +vt 0.20220735669136047 0.24122107028961182 +vt 0.04129339009523392 0.3595932722091675 +vt 0.20220735669136047 0.24122107028961182 +vt 0.19759654998779297 0.3901810646057129 +vt 0.3332149088382721 0.5952299237251282 +vt 0.3122228682041168 0.45766007900238037 +vt 0.3809558153152466 0.4458489418029785 +vt 0.3332149088382721 0.5952299237251282 +vt 0.3809558153152466 0.4458489418029785 +vt 0.4260222017765045 0.5836359262466431 +vt 0.4337061643600464 0.5907729268074036 +vt 0.4598149061203003 0.4516195058822632 +vt 0.6332000494003296 0.45212918519973755 +vt 0.4337061643600464 0.5907729268074036 +vt 0.6332000494003296 0.45212918519973755 +vt 0.6355971097946167 0.5905618667602539 +vt 0.20989133417606354 0.5940188765525818 +vt 0.2120072841644287 0.4562457799911499 +vt 0.3122228682041168 0.45766007900238037 +vt 0.20989133417606354 0.5940188765525818 +vt 0.3122228682041168 0.45766007900238037 +vt 0.3332149088382721 0.5952299237251282 +vt 0.20989134907722473 0.2956284284591675 +vt 0.2590023875236511 0.15447145700454712 +vt 0.34975001215934753 0.1534515619277954 +vt 0.20989134907722473 0.2956284284591675 +vt 0.34975001215934753 0.1534515619277954 +vt 0.32616686820983887 0.2956284284591675 +vt 0.10249044746160507 0.07651758193969727 +vt 0.07301238924264908 0.02964681386947632 +vt 0.20220735669136047 0.061058640480041504 +vt 0.10249044746160507 0.07651758193969727 +vt 0.20220735669136047 0.061058640480041504 +vt 0.19000186026096344 0.0992354154586792 +vt 0.2590023875236511 0.15447145700454712 +vt 0.33405324816703796 0.032427966594696045 +vt 0.38760825991630554 0.015950024127960205 +vt 0.2590023875236511 0.15447145700454712 +vt 0.38760825991630554 0.015950024127960205 +vt 0.34975001215934753 0.1534515619277954 +vt 0.2120072841644287 0.4562457799911499 +vt 0.20989136397838593 0.30331242084503174 +vt 0.2667810618877411 0.3177669048309326 +vt 0.2120072841644287 0.4562457799911499 +vt 0.2667810618877411 0.3177669048309326 +vt 0.3122228682041168 0.45766007900238037 +vn -0.7572498372999124 0.158828053377099 0.6335190078992877 +vn -0.5706052151986355 0.7018495758604838 0.42639988420797886 +vn -0.5550298286839305 0.7612513941802773 -0.3353180641266899 +vn -0.7572498372999124 0.158828053377099 0.6335190078992877 +vn -0.5550298286839305 0.7612513941802773 -0.3353180641266899 +vn -0.7787844744038005 0.08731374374782407 -0.6211851999044533 +vn 0.19484776919781263 0.21413928997127954 -0.9571722474712857 +vn 0.14086980450775322 0.7258771910322607 -0.6732443848388655 +vn 0.626905745312635 0.7348083821518948 -0.25893209150919166 +vn 0.19484776919781263 0.21413928997127954 -0.9571722474712857 +vn 0.626905745312635 0.7348083821518948 -0.25893209150919166 +vn 0.8427307453405789 0.3923032212867617 -0.36865034033043104 +vn 0.8427307453405789 0.3923032212867617 -0.36865034033043104 +vn 0.626905745312635 0.7348083821518948 -0.25893209150919166 +vn 0.44751232912724975 0.7244215133345491 0.5243531122222753 +vn 0.8427307453405789 0.3923032212867617 -0.36865034033043104 +vn 0.44751232912724975 0.7244215133345491 0.5243531122222753 +vn 0.5977325011734748 0.44326458629530474 0.6680062601333573 +vn -0.07392964468225123 0.24670541140024185 0.9662664475303866 +vn 0.06570325963075113 0.7614497473416393 0.6448855432921782 +vn -0.5706052151986355 0.7018495758604838 0.42639988420797886 +vn -0.07392964468225123 0.24670541140024185 0.9662664475303866 +vn -0.5706052151986355 0.7018495758604838 0.42639988420797886 +vn -0.7572498372999124 0.158828053377099 0.6335190078992877 +vn 0.14086980450775322 0.7258771910322607 -0.6732443848388655 +vn -0.5550298286839305 0.7612513941802773 -0.3353180641266899 +vn -0.5706052151986355 0.7018495758604838 0.42639988420797886 +vn 0.14086980450775322 0.7258771910322607 -0.6732443848388655 +vn -0.5706052151986355 0.7018495758604838 0.42639988420797886 +vn 0.06570325963075113 0.7614497473416393 0.6448855432921782 +vn -0.07233257618517844 0.18811179767193992 0.9794804490131728 +vn -0.07392964468225123 0.24670541140024185 0.9662664475303866 +vn -0.7572498372999124 0.158828053377099 0.6335190078992877 +vn -0.07233257618517844 0.18811179767193992 0.9794804490131728 +vn -0.7572498372999124 0.158828053377099 0.6335190078992877 +vn -0.7161014037497411 0.12648911698999613 0.6864395696860297 +vn 0.8858925722248271 0.2929421968602402 -0.3596932300941676 +vn 0.8427307453405789 0.3923032212867617 -0.36865034033043104 +vn 0.5977325011734748 0.44326458629530474 0.6680062601333573 +vn 0.8858925722248271 0.2929421968602402 -0.3596932300941676 +vn 0.5977325011734748 0.44326458629530474 0.6680062601333573 +vn 0.6626612593852685 0.36345809971210374 0.6548116256325907 +vn 0.25526761305033085 0.09570637081503638 -0.9621219965851532 +vn 0.19484776919781263 0.21413928997127954 -0.9571722474712857 +vn 0.8427307453405789 0.3923032212867617 -0.36865034033043104 +vn 0.25526761305033085 0.09570637081503638 -0.9621219965851532 +vn 0.8427307453405789 0.3923032212867617 -0.36865034033043104 +vn 0.8858925722248271 0.2929421968602402 -0.3596932300941676 +vn -0.7161014037497411 0.12648911698999613 0.6864395696860297 +vn -0.7572498372999124 0.158828053377099 0.6335190078992877 +vn -0.7787844744038005 0.08731374374782407 -0.6211851999044533 +vn -0.7161014037497411 0.12648911698999613 0.6864395696860297 +vn -0.7787844744038005 0.08731374374782407 -0.6211851999044533 +vn -0.7821251490730478 -0.0072697604411478935 -0.6230789691287862 +vn -0.7821251490730478 -0.0072697604411478935 -0.6230789691287862 +vn -0.7787844744038005 0.08731374374782407 -0.6211851999044533 +vn 0.19484776919781263 0.21413928997127954 -0.9571722474712857 +vn -0.7821251490730478 -0.0072697604411478935 -0.6230789691287862 +vn 0.19484776919781263 0.21413928997127954 -0.9571722474712857 +vn 0.25526761305033085 0.09570637081503638 -0.9621219965851532 +vn 0.6626612593852685 0.36345809971210374 0.6548116256325907 +vn 0.5977325011734748 0.44326458629530474 0.6680062601333573 +vn -0.07392964468225123 0.24670541140024185 0.9662664475303866 +vn 0.6626612593852685 0.36345809971210374 0.6548116256325907 +vn -0.07392964468225123 0.24670541140024185 0.9662664475303866 +vn -0.07233257618517844 0.18811179767193992 0.9794804490131728 +vn 0.626905745312635 0.7348083821518948 -0.25893209150919166 +vn 0.14086980450775322 0.7258771910322607 -0.6732443848388655 +vn 0.06570325963075113 0.7614497473416393 0.6448855432921782 +vn 0.626905745312635 0.7348083821518948 -0.25893209150919166 +vn 0.06570325963075113 0.7614497473416393 0.6448855432921782 +vn 0.44751232912724975 0.7244215133345491 0.5243531122222753 +vn 0.5977325011734748 0.44326458629530474 0.6680062601333573 +vn 0.44751232912724975 0.7244215133345491 0.5243531122222753 +vn 0.06570325963075113 0.7614497473416393 0.6448855432921782 +vn 0.5977325011734748 0.44326458629530474 0.6680062601333573 +vn 0.06570325963075113 0.7614497473416393 0.6448855432921782 +vn -0.07392964468225123 0.24670541140024185 0.9662664475303866 +vn -0.7787844744038005 0.08731374374782407 -0.6211851999044533 +vn -0.5550298286839305 0.7612513941802773 -0.3353180641266899 +vn 0.14086980450775322 0.7258771910322607 -0.6732443848388655 +vn -0.7787844744038005 0.08731374374782407 -0.6211851999044533 +vn 0.14086980450775322 0.7258771910322607 -0.6732443848388655 +vn 0.19484776919781263 0.21413928997127954 -0.9571722474712857 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 8/8/8 9/9/9 +f 10/10/10 11/11/11 12/12/12 +f 13/13/13 14/14/14 15/15/15 +f 16/16/16 17/17/17 18/18/18 +f 19/19/19 20/20/20 21/21/21 +f 22/22/22 23/23/23 24/24/24 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 29/29/29 30/30/30 +f 31/31/31 32/32/32 33/33/33 +f 34/34/34 35/35/35 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 40/40/40 41/41/41 42/42/42 +f 43/43/43 44/44/44 45/45/45 +f 46/46/46 47/47/47 48/48/48 +f 49/49/49 50/50/50 51/51/51 +f 52/52/52 53/53/53 54/54/54 +f 55/55/55 56/56/56 57/57/57 +f 58/58/58 59/59/59 60/60/60 +f 61/61/61 62/62/62 63/63/63 +f 64/64/64 65/65/65 66/66/66 +f 67/67/67 68/68/68 69/69/69 +f 70/70/70 71/71/71 72/72/72 +f 73/73/73 74/74/74 75/75/75 +f 76/76/76 77/77/77 78/78/78 +f 79/79/79 80/80/80 81/81/81 +f 82/82/82 83/83/83 84/84/84 diff --git a/apps/openmb/resources/shaders/.gitkeep b/apps/openmb/resources/shaders/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/apps/openmb/resources/shaders/.gitkeep diff --git a/apps/openmb/resources/shaders/cube.frag b/apps/openmb/resources/shaders/cube.frag new file mode 100644 index 0000000..cb15430 --- /dev/null +++ b/apps/openmb/resources/shaders/cube.frag @@ -0,0 +1,21 @@ +#version 330 core +out vec4 FragColor; +uniform vec3 color; +in vec3 vFragPos; +uniform vec3 cameraPos; +uniform vec3 fogColor; +uniform float fogDensity; +uniform float fogAmount; + +void main() +{ + // Basic color with fog applied + vec3 base = color; + + // vFragPos provided by vertex shader + float dist = length(vFragPos - cameraPos); + float fogFactor = 1.0 - exp(-fogDensity * dist); + fogFactor = clamp(fogFactor * fogAmount, 0.0, 1.0); + vec3 finalColor = mix(base, fogColor, fogFactor); + FragColor = vec4(finalColor, 1.0); +} diff --git a/apps/openmb/resources/shaders/cube.vert b/apps/openmb/resources/shaders/cube.vert new file mode 100644 index 0000000..805c883 --- /dev/null +++ b/apps/openmb/resources/shaders/cube.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; +out vec3 vFragPos; +void main() +{ + vFragPos = vec3(model * vec4(aPos, 1.0)); + gl_Position = proj * view * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/depth.frag b/apps/openmb/resources/shaders/depth.frag new file mode 100644 index 0000000..f6ba8e2 --- /dev/null +++ b/apps/openmb/resources/shaders/depth.frag @@ -0,0 +1,5 @@ +#version 330 core +void main() +{ + +} diff --git a/apps/openmb/resources/shaders/depth.vert b/apps/openmb/resources/shaders/depth.vert new file mode 100644 index 0000000..e80ee01 --- /dev/null +++ b/apps/openmb/resources/shaders/depth.vert @@ -0,0 +1,10 @@ +#version 330 core +layout(location = 0) in vec3 aPos; + +uniform mat4 model; +uniform mat4 lightSpace; + +void main() +{ + gl_Position = lightSpace * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/gbuffer.frag b/apps/openmb/resources/shaders/gbuffer.frag new file mode 100644 index 0000000..f6ddb45 --- /dev/null +++ b/apps/openmb/resources/shaders/gbuffer.frag @@ -0,0 +1,10 @@ +#version 330 core +in vec2 vUV; +in vec3 vNormalView; +layout(location = 0) out vec3 gNormal; + +void main() +{ + vec3 n = normalize(vNormalView); + gNormal = n * 0.5 + 0.5; +} diff --git a/apps/openmb/resources/shaders/gbuffer.vert b/apps/openmb/resources/shaders/gbuffer.vert new file mode 100644 index 0000000..c9e677c --- /dev/null +++ b/apps/openmb/resources/shaders/gbuffer.vert @@ -0,0 +1,19 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; + +out vec2 vUV; +out vec3 vNormalView; + +void main() +{ + vUV = aUV; + vec4 viewPos = view * model * vec4(aPos, 1.0); + vNormalView = mat3(transpose(inverse(view * model))) * aNormal; + gl_Position = proj * viewPos; +} diff --git a/apps/openmb/resources/shaders/godrays_quad.vert b/apps/openmb/resources/shaders/godrays_quad.vert new file mode 100644 index 0000000..6a33825 --- /dev/null +++ b/apps/openmb/resources/shaders/godrays_quad.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTex; + +out vec2 vTex; + +void main() +{ + vTex = aTex; + gl_Position = vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/godrays_radial.frag b/apps/openmb/resources/shaders/godrays_radial.frag new file mode 100644 index 0000000..3dfac87 --- /dev/null +++ b/apps/openmb/resources/shaders/godrays_radial.frag @@ -0,0 +1,44 @@ +#version 330 core +in vec2 vTex; +out vec4 FragColor; + +uniform sampler2D occlusionTex; +uniform vec2 lightScreenPos; // in [0,1] +uniform vec3 sunColor; +uniform float sunIntensity; +uniform float globalIntensity; +uniform int samples; +uniform float density; +uniform float weight; +uniform float decay; + +void main() +{ + vec2 texCoord = vTex; + // vector from current pixel to light + vec2 delta = lightScreenPos - texCoord; + float dist = length(delta); + vec2 stepv = delta * (1.0 / float(samples)) * density; + + vec3 illumination = vec3(0.0); + float illumDecay = 1.0; + + vec2 coord = texCoord; + for (int i = 0; i < samples; ++i) + { + coord += stepv; + vec3 sample = texture(occlusionTex, coord).rgb; + // occlusion tex stores white where geometry present + float occ = sample.r; + illumination += occ * illumDecay * weight; + illumDecay *= decay; + } + + vec3 result = illumination * sunColor * sunIntensity * globalIntensity; + // tone-map / clamp to avoid extreme brightness + result = clamp(result, vec3(0.0), vec3(1.0)); + // use luminance as alpha so we can composite less aggressively + float lum = dot(result, vec3(0.299, 0.587, 0.114)); + float alpha = clamp(lum, 0.0, 1.0); + FragColor = vec4(result, alpha); +} diff --git a/apps/openmb/resources/shaders/occlusion.frag b/apps/openmb/resources/shaders/occlusion.frag new file mode 100644 index 0000000..02a0732 --- /dev/null +++ b/apps/openmb/resources/shaders/occlusion.frag @@ -0,0 +1,8 @@ +#version 330 core +out vec4 FragColor; + +void main() +{ + // Solid white occluder + FragColor = vec4(1.0); +} diff --git a/apps/openmb/resources/shaders/occlusion.vert b/apps/openmb/resources/shaders/occlusion.vert new file mode 100644 index 0000000..9d95f3a --- /dev/null +++ b/apps/openmb/resources/shaders/occlusion.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; + +void main() +{ + gl_Position = proj * view * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/skybox.frag b/apps/openmb/resources/shaders/skybox.frag new file mode 100644 index 0000000..f9e41eb --- /dev/null +++ b/apps/openmb/resources/shaders/skybox.frag @@ -0,0 +1,8 @@ +#version 330 core +in vec3 TexCoords; +out vec4 FragColor; +uniform samplerCube skybox; +void main() +{ + FragColor = texture(skybox, TexCoords); +} diff --git a/apps/openmb/resources/shaders/skybox.vert b/apps/openmb/resources/shaders/skybox.vert new file mode 100644 index 0000000..8e66a99 --- /dev/null +++ b/apps/openmb/resources/shaders/skybox.vert @@ -0,0 +1,10 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +out vec3 TexCoords; +uniform mat4 view; +uniform mat4 proj; +void main() +{ + TexCoords = aPos; + gl_Position = proj * view * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/ssao.frag b/apps/openmb/resources/shaders/ssao.frag new file mode 100644 index 0000000..60479f2 --- /dev/null +++ b/apps/openmb/resources/shaders/ssao.frag @@ -0,0 +1,76 @@ +#version 330 core +in vec2 vUV; +out float FragColor; + +uniform sampler2D gDepth; +uniform sampler2D gNormal; +uniform sampler2D texNoise; + +uniform vec3 samples[64]; +uniform mat4 proj; +uniform mat4 invProj; +uniform float radius; +uniform float bias; +uniform float noiseScale; + +uniform int kernelSize; +uniform float power; + +vec3 getViewPos(vec2 uv) +{ + float depth = texture(gDepth, uv).r; + if (depth == 1.0) return vec3(0.0); + float z = depth * 2.0 - 1.0; + vec4 clip = vec4(uv * 2.0 - 1.0, z, 1.0); + vec4 viewPos = invProj * clip; + viewPos /= viewPos.w; + return viewPos.xyz; +} + +void main() +{ + vec3 fragPos = getViewPos(vUV); + if (fragPos == vec3(0.0)) + { + FragColor = 1.0; + return; + } + + vec3 normal = texture(gNormal, vUV).rgb; + normal = normalize(normal * 2.0 - 1.0); + + vec3 randomVec = normalize(texture(texNoise, vUV * noiseScale).xyz * 2.0 - 1.0); + + + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 TBN = mat3(tangent, bitangent, normal); + + float occlusion = 0.0; + for (int i = 0; i < kernelSize; ++i) + { + vec3 sample = TBN * samples[i]; + sample = fragPos + sample * radius; + + + vec4 offset = proj * vec4(sample, 1.0); + offset.xyz /= offset.w; + vec2 sampleUV = offset.xy * 0.5 + 0.5; + + if (sampleUV.x < 0.0 || sampleUV.x > 1.0 || sampleUV.y < 0.0 || sampleUV.y > 1.0) + continue; + + vec3 samplePos = getViewPos(sampleUV); + if (samplePos == vec3(0.0)) + continue; + + float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - samplePos.z)); + float diff = samplePos.z - sample.z; + if (diff > bias) + occlusion += rangeCheck; + } + + occlusion = 1.0 - (occlusion / float(kernelSize)); + occlusion = pow(occlusion, power); + FragColor = occlusion; +} diff --git a/apps/openmb/resources/shaders/ssao.vert b/apps/openmb/resources/shaders/ssao.vert new file mode 100644 index 0000000..5afd1d3 --- /dev/null +++ b/apps/openmb/resources/shaders/ssao.vert @@ -0,0 +1,9 @@ +#version 330 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +out vec2 vUV; +void main() +{ + vUV = aUV; + gl_Position = vec4(aPos, 0.0, 1.0); +} diff --git a/apps/openmb/resources/shaders/ssao_blur.frag b/apps/openmb/resources/shaders/ssao_blur.frag new file mode 100644 index 0000000..e093eff --- /dev/null +++ b/apps/openmb/resources/shaders/ssao_blur.frag @@ -0,0 +1,45 @@ +#version 330 core +in vec2 vUV; +out float FragColor; + +uniform sampler2D ssaoInput; +uniform vec2 texelSize; +uniform int horizontal; + + +const float w0 = 0.2270270270; +const float w1 = 0.1945945946; +const float w2 = 0.1216216216; +const float w3 = 0.0540540541; +const float w4 = 0.0162162162; + +void main() +{ + float result = 0.0; + if (horizontal == 1) + { + result += texture(ssaoInput, vUV).r * w0; + result += texture(ssaoInput, vUV + vec2(texelSize.x, 0.0)).r * w1; + result += texture(ssaoInput, vUV - vec2(texelSize.x, 0.0)).r * w1; + result += texture(ssaoInput, vUV + vec2(2.0 * texelSize.x, 0.0)).r * w2; + result += texture(ssaoInput, vUV - vec2(2.0 * texelSize.x, 0.0)).r * w2; + result += texture(ssaoInput, vUV + vec2(3.0 * texelSize.x, 0.0)).r * w3; + result += texture(ssaoInput, vUV - vec2(3.0 * texelSize.x, 0.0)).r * w3; + result += texture(ssaoInput, vUV + vec2(4.0 * texelSize.x, 0.0)).r * w4; + result += texture(ssaoInput, vUV - vec2(4.0 * texelSize.x, 0.0)).r * w4; + } + else + { + result += texture(ssaoInput, vUV).r * w0; + result += texture(ssaoInput, vUV + vec2(0.0, texelSize.y)).r * w1; + result += texture(ssaoInput, vUV - vec2(0.0, texelSize.y)).r * w1; + result += texture(ssaoInput, vUV + vec2(0.0, 2.0 * texelSize.y)).r * w2; + result += texture(ssaoInput, vUV - vec2(0.0, 2.0 * texelSize.y)).r * w2; + result += texture(ssaoInput, vUV + vec2(0.0, 3.0 * texelSize.y)).r * w3; + result += texture(ssaoInput, vUV - vec2(0.0, 3.0 * texelSize.y)).r * w3; + result += texture(ssaoInput, vUV + vec2(0.0, 4.0 * texelSize.y)).r * w4; + result += texture(ssaoInput, vUV - vec2(0.0, 4.0 * texelSize.y)).r * w4; + } + + FragColor = result; +} diff --git a/apps/openmb/resources/shaders/textured.frag b/apps/openmb/resources/shaders/textured.frag new file mode 100644 index 0000000..ea5e207 --- /dev/null +++ b/apps/openmb/resources/shaders/textured.frag @@ -0,0 +1,45 @@ +#version 330 core + +in vec2 vUV; +out vec4 FragColor; + +uniform sampler2D albedo; +uniform sampler2D normalMap; +uniform int normalEnabled; +uniform float normalStrength; +uniform vec3 tint; +uniform int radialEnabled; +uniform float radialInner; +uniform float radialOuter; + +void main() +{ + vec4 tex = texture(albedo, vUV); + vec3 color = tex.rgb * tint; + float alpha = tex.a; + vec3 finalNormal = vec3(0.0, 0.0, 1.0); + if (normalEnabled == 1) + { + vec3 n = texture(normalMap, vUV).rgb; + n = n * 2.0 - 1.0; + finalNormal = normalize(vec3(n.x * normalStrength, n.y * normalStrength, 1.0)); + } + if (radialEnabled == 1) + { + + float dist = distance(vUV, vec2(0.5, 0.5)); + + float mask = 1.0 - smoothstep(radialInner, radialOuter, dist); + alpha *= mask; + } + + if (normalEnabled == 1) + { + vec3 lightDir = normalize(vec3(0.3, 1.0, 0.5)); + float l = max(dot(normalize(finalNormal), lightDir), 0.0); + + color *= (0.4 + 0.6 * l); + } + + FragColor = vec4(color, alpha); +} diff --git a/apps/openmb/resources/shaders/textured.vert b/apps/openmb/resources/shaders/textured.vert new file mode 100644 index 0000000..f71f407 --- /dev/null +++ b/apps/openmb/resources/shaders/textured.vert @@ -0,0 +1,23 @@ +#version 330 core +layout(location = 0) in vec3 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; +uniform mat4 lightSpace; + +out vec2 vUV; +out vec3 vNormal; +out vec3 vFragPos; +out vec4 vFragPosLightSpace; + +void main() +{ + vUV = aUV; + vFragPos = vec3(model * vec4(aPos, 1.0)); + vNormal = mat3(transpose(inverse(model))) * aNormal; + vFragPosLightSpace = lightSpace * vec4(vFragPos, 1.0); + gl_Position = proj * view * model * vec4(aPos, 1.0); +} diff --git a/apps/openmb/resources/shaders/textured_lit.frag b/apps/openmb/resources/shaders/textured_lit.frag new file mode 100644 index 0000000..58c71f7 --- /dev/null +++ b/apps/openmb/resources/shaders/textured_lit.frag @@ -0,0 +1,121 @@ +#version 330 core + +in vec2 vUV; +in vec3 vNormal; +in vec3 vFragPos; +in vec4 vFragPosLightSpace; +out vec4 FragColor; + +uniform sampler2D albedo; +uniform sampler2D normalMap; +uniform int normalEnabled; +uniform float normalStrength; +uniform vec3 tint; +uniform int radialEnabled; +uniform float radialInner; +uniform float radialOuter; + +struct DirectionalLight +{ + vec3 direction; + vec3 color; + float intensity; +}; + +uniform DirectionalLight dirLight; +uniform vec3 ambientColor = vec3(0.15, 0.15, 0.15); +uniform sampler2D shadowMap; +uniform float shadowBiasMin; +uniform float shadowBiasScale; +uniform int pcfRadius; +uniform sampler2D ssao; +uniform float aoStrength; +uniform float screenWidth; +uniform float screenHeight; + +// Fog +uniform vec3 cameraPos; +uniform vec3 fogColor; +uniform float fogDensity; // e.g. 0.02 +uniform float fogAmount; // 0..1 blend factor +float ShadowCalculation(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) +{ + + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + + projCoords = projCoords * 0.5 + 0.5; + + if (projCoords.z > 1.0) + return 0.0; + + + float currentDepth = projCoords.z; + + float bias = max(shadowBiasScale * (1.0 - max(dot(normal, lightDir), 0.0)), shadowBiasMin); + + + ivec2 texSize = textureSize(shadowMap, 0); + vec2 texelSize = 1.0 / vec2(texSize); + float vis = 0.0; + int samples = 0; + for (int x = -pcfRadius; x <= pcfRadius; ++x) + { + for (int y = -pcfRadius; y <= pcfRadius; ++y) + { + vec2 offset = vec2(x, y) * texelSize; + float depthSample = texture(shadowMap, projCoords.xy + offset).r; + // texture returns stored light-space depth. If our fragment's depth (minus bias) + // is less than or equal to the sampled depth, it's visible to the light. + vis += (currentDepth - bias <= depthSample) ? 1.0 : 0.0; + samples++; + } + } + float visibility = vis / float(samples); + float shadow = 1.0 - visibility; + return shadow; +} + +void main() +{ + vec4 tex = texture(albedo, vUV); + vec3 color = tex.rgb * tint; + float alpha = tex.a; + vec3 finalNormal = vec3(0.0, 0.0, 1.0); + if (normalEnabled == 1) + { + vec3 n = texture(normalMap, vUV).rgb; + n = n * 2.0 - 1.0; + finalNormal = normalize(vec3(n.x * normalStrength, n.y * normalStrength, 1.0)); + } + if (radialEnabled == 1) + { + float dist = distance(vUV, vec2(0.5, 0.5)); + float mask = 1.0 - smoothstep(radialInner, radialOuter, dist); + alpha *= mask; + } + + + vec3 N = normalize(finalNormal); + vec3 L = normalize(dirLight.direction); + float diff = max(dot(N, L), 0.0); + vec3 diffuse = dirLight.color * dirLight.intensity * diff; + + float shadow = ShadowCalculation(vFragPosLightSpace, N, L); + float shadowFactor = 1.0 - shadow * 0.9; + float ao = 1.0; + if (aoStrength > 0.0) + { + vec2 ssaoUV = gl_FragCoord.xy / vec2(screenWidth, screenHeight); + ao = texture(ssao, ssaoUV).r; + } + float aoFactor = mix(1.0, ao, aoStrength); + vec3 result = color * (ambientColor * aoFactor + diffuse * shadowFactor); + + // Compute fog based on distance from camera + float dist = length(vFragPos - cameraPos); + float fogFactor = 1.0 - exp(-fogDensity * dist); + fogFactor = clamp(fogFactor * fogAmount, 0.0, 1.0); + vec3 finalColor = mix(result, fogColor, fogFactor); + + FragColor = vec4(finalColor, alpha); +} diff --git a/apps/openmb/resources/skybox/Daylight-Back.bmp b/apps/openmb/resources/skybox/Daylight-Back.bmp Binary files differnew file mode 100644 index 0000000..1b6c44e --- /dev/null +++ b/apps/openmb/resources/skybox/Daylight-Back.bmp diff --git a/apps/openmb/resources/skybox/Daylight-Bottom.bmp b/apps/openmb/resources/skybox/Daylight-Bottom.bmp Binary files differnew file mode 100644 index 0000000..4e36683 --- /dev/null +++ b/apps/openmb/resources/skybox/Daylight-Bottom.bmp diff --git a/apps/openmb/resources/skybox/Daylight-Front.bmp b/apps/openmb/resources/skybox/Daylight-Front.bmp Binary files differnew file mode 100644 index 0000000..571df47 --- /dev/null +++ b/apps/openmb/resources/skybox/Daylight-Front.bmp diff --git a/apps/openmb/resources/skybox/Daylight-Left.bmp b/apps/openmb/resources/skybox/Daylight-Left.bmp Binary files differnew file mode 100644 index 0000000..b3954a3 --- /dev/null +++ b/apps/openmb/resources/skybox/Daylight-Left.bmp diff --git a/apps/openmb/resources/skybox/Daylight-Right.bmp b/apps/openmb/resources/skybox/Daylight-Right.bmp Binary files differnew file mode 100644 index 0000000..48c6433 --- /dev/null +++ b/apps/openmb/resources/skybox/Daylight-Right.bmp diff --git a/apps/openmb/resources/skybox/Daylight-Top.bmp b/apps/openmb/resources/skybox/Daylight-Top.bmp Binary files differnew file mode 100644 index 0000000..f949f7f --- /dev/null +++ b/apps/openmb/resources/skybox/Daylight-Top.bmp diff --git a/apps/openmb/resources/textures/brush/basic/blue.tga b/apps/openmb/resources/textures/brush/basic/blue.tga Binary files differnew file mode 100644 index 0000000..a731a65 --- /dev/null +++ b/apps/openmb/resources/textures/brush/basic/blue.tga diff --git a/apps/openmb/resources/textures/testing/dark/texture_01.png b/apps/openmb/resources/textures/testing/dark/texture_01.png Binary files differnew file mode 100644 index 0000000..69be211 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_01.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_02.png b/apps/openmb/resources/textures/testing/dark/texture_02.png Binary files differnew file mode 100644 index 0000000..6fb471b --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_02.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_03.png b/apps/openmb/resources/textures/testing/dark/texture_03.png Binary files differnew file mode 100644 index 0000000..3f8b186 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_03.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_04.png b/apps/openmb/resources/textures/testing/dark/texture_04.png Binary files differnew file mode 100644 index 0000000..e2bc22b --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_04.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_05.png b/apps/openmb/resources/textures/testing/dark/texture_05.png Binary files differnew file mode 100644 index 0000000..3fd2e56 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_05.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_06.png b/apps/openmb/resources/textures/testing/dark/texture_06.png Binary files differnew file mode 100644 index 0000000..45d4a34 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_06.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_07.png b/apps/openmb/resources/textures/testing/dark/texture_07.png Binary files differnew file mode 100644 index 0000000..adf5e6f --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_07.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_08.png b/apps/openmb/resources/textures/testing/dark/texture_08.png Binary files differnew file mode 100644 index 0000000..a5a9f24 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_08.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_09.png b/apps/openmb/resources/textures/testing/dark/texture_09.png Binary files differnew file mode 100644 index 0000000..57cc607 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_09.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_10.png b/apps/openmb/resources/textures/testing/dark/texture_10.png Binary files differnew file mode 100644 index 0000000..4c737d0 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_10.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_11.png b/apps/openmb/resources/textures/testing/dark/texture_11.png Binary files differnew file mode 100644 index 0000000..424ba71 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_11.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_12.png b/apps/openmb/resources/textures/testing/dark/texture_12.png Binary files differnew file mode 100644 index 0000000..32169db --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_12.png diff --git a/apps/openmb/resources/textures/testing/dark/texture_13.png b/apps/openmb/resources/textures/testing/dark/texture_13.png Binary files differnew file mode 100644 index 0000000..13c4388 --- /dev/null +++ b/apps/openmb/resources/textures/testing/dark/texture_13.png diff --git a/apps/openmb/resources/textures/testing/light/texture_01.png b/apps/openmb/resources/textures/testing/light/texture_01.png Binary files differnew file mode 100644 index 0000000..60b632b --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_01.png diff --git a/apps/openmb/resources/textures/testing/light/texture_02.png b/apps/openmb/resources/textures/testing/light/texture_02.png Binary files differnew file mode 100644 index 0000000..19aad62 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_02.png diff --git a/apps/openmb/resources/textures/testing/light/texture_03.png b/apps/openmb/resources/textures/testing/light/texture_03.png Binary files differnew file mode 100644 index 0000000..a8a6c06 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_03.png diff --git a/apps/openmb/resources/textures/testing/light/texture_04.png b/apps/openmb/resources/textures/testing/light/texture_04.png Binary files differnew file mode 100644 index 0000000..b8270e1 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_04.png diff --git a/apps/openmb/resources/textures/testing/light/texture_05.png b/apps/openmb/resources/textures/testing/light/texture_05.png Binary files differnew file mode 100644 index 0000000..5b985bf --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_05.png diff --git a/apps/openmb/resources/textures/testing/light/texture_06.png b/apps/openmb/resources/textures/testing/light/texture_06.png Binary files differnew file mode 100644 index 0000000..195ad77 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_06.png diff --git a/apps/openmb/resources/textures/testing/light/texture_07.png b/apps/openmb/resources/textures/testing/light/texture_07.png Binary files differnew file mode 100644 index 0000000..fbf92e0 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_07.png diff --git a/apps/openmb/resources/textures/testing/light/texture_08.png b/apps/openmb/resources/textures/testing/light/texture_08.png Binary files differnew file mode 100644 index 0000000..72e1a07 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_08.png diff --git a/apps/openmb/resources/textures/testing/light/texture_09.png b/apps/openmb/resources/textures/testing/light/texture_09.png Binary files differnew file mode 100644 index 0000000..9ada5dd --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_09.png diff --git a/apps/openmb/resources/textures/testing/light/texture_10.png b/apps/openmb/resources/textures/testing/light/texture_10.png Binary files differnew file mode 100644 index 0000000..4fbcc80 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_10.png diff --git a/apps/openmb/resources/textures/testing/light/texture_11.png b/apps/openmb/resources/textures/testing/light/texture_11.png Binary files differnew file mode 100644 index 0000000..840ecec --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_11.png diff --git a/apps/openmb/resources/textures/testing/light/texture_12.png b/apps/openmb/resources/textures/testing/light/texture_12.png Binary files differnew file mode 100644 index 0000000..25c2e78 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_12.png diff --git a/apps/openmb/resources/textures/testing/light/texture_13.png b/apps/openmb/resources/textures/testing/light/texture_13.png Binary files differnew file mode 100644 index 0000000..a235965 --- /dev/null +++ b/apps/openmb/resources/textures/testing/light/texture_13.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_01.png b/apps/openmb/resources/textures/testing/orange/texture_01.png Binary files differnew file mode 100644 index 0000000..4f5bf92 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_01.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_02.png b/apps/openmb/resources/textures/testing/orange/texture_02.png Binary files differnew file mode 100644 index 0000000..dec5b59 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_02.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_03.png b/apps/openmb/resources/textures/testing/orange/texture_03.png Binary files differnew file mode 100644 index 0000000..666197f --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_03.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_04.png b/apps/openmb/resources/textures/testing/orange/texture_04.png Binary files differnew file mode 100644 index 0000000..23d6fc4 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_04.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_05.png b/apps/openmb/resources/textures/testing/orange/texture_05.png Binary files differnew file mode 100644 index 0000000..1e0448a --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_05.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_06.png b/apps/openmb/resources/textures/testing/orange/texture_06.png Binary files differnew file mode 100644 index 0000000..5486825 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_06.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_07.png b/apps/openmb/resources/textures/testing/orange/texture_07.png Binary files differnew file mode 100644 index 0000000..95f2790 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_07.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_08.png b/apps/openmb/resources/textures/testing/orange/texture_08.png Binary files differnew file mode 100644 index 0000000..5a500d9 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_08.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_09.png b/apps/openmb/resources/textures/testing/orange/texture_09.png Binary files differnew file mode 100644 index 0000000..adcfa33 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_09.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_10.png b/apps/openmb/resources/textures/testing/orange/texture_10.png Binary files differnew file mode 100644 index 0000000..aa227e5 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_10.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_11.png b/apps/openmb/resources/textures/testing/orange/texture_11.png Binary files differnew file mode 100644 index 0000000..dc94567 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_11.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_12.png b/apps/openmb/resources/textures/testing/orange/texture_12.png Binary files differnew file mode 100644 index 0000000..b730544 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_12.png diff --git a/apps/openmb/resources/textures/testing/orange/texture_13.png b/apps/openmb/resources/textures/testing/orange/texture_13.png Binary files differnew file mode 100644 index 0000000..01f4aa8 --- /dev/null +++ b/apps/openmb/resources/textures/testing/orange/texture_13.png diff --git a/apps/openmb/scene/Camera.cpp b/apps/openmb/scene/Camera.cpp new file mode 100644 index 0000000..d3a3e7d --- /dev/null +++ b/apps/openmb/scene/Camera.cpp @@ -0,0 +1,203 @@ +#include "Camera.hpp" + +#include <algorithm> +#include <glm/gtc/matrix_transform.hpp> +#include <vector> + +namespace scene { +Camera::Camera () + : mPosition( 0.0f, 0.0f, 3.0f ), mFront( 0.0f, 0.0f, -1.0f ), mWorldUp( 0.0f, 1.0f, 0.0f ), mYaw( -90.0f ), + mPitch( 0.0f ), mMovementSpeed( 3.0f ), mMouseSensitivity( 0.1f ), mFov( 60.0f ), + mVelocity( 0.0f, 0.0f, 0.0f ), mFlying( true ), mGrounded( false ), mSpeedMultiplier( 1.0f ) { + updateCameraVectors(); +} + +Camera::Camera ( const glm::vec3& position, const glm::vec3& up, float yaw, float pitch ) + : mPosition( position ), mWorldUp( up ), mYaw( yaw ), mPitch( pitch ), mMovementSpeed( 3.0f ), + mMouseSensitivity( 0.1f ), mFov( 60.0f ), mVelocity( 0.0f, 0.0f, 0.0f ), mFlying( true ), mGrounded( false ), + mSpeedMultiplier( 1.0f ) { + mFront = glm::vec3( 0.0f, 0.0f, -1.0f ); + updateCameraVectors(); +} + +glm::mat4 Camera::getViewMatrix () const { + return glm::lookAt( mPosition, mPosition + mFront, mUp ); +} + +glm::mat4 Camera::getProjectionMatrix ( float aspect ) const { + return glm::perspective( glm::radians( mFov ), aspect, 0.1f, 100.0f ); +} + +void Camera::processKeyboard ( Movement dir, float deltaTime ) { + float velocity = mMovementSpeed * mSpeedMultiplier * deltaTime; + + glm::vec3 moveForward = mFront; + glm::vec3 moveRight = mRight; + if( !mFlying ) { + moveForward.y = 0.0f; + if( glm::length( moveForward ) < 1e-6f ) + moveForward = glm::vec3( 0.0f, 0.0f, -1.0f ); + moveForward = glm::normalize( moveForward ); + moveRight = glm::normalize( glm::cross( moveForward, mWorldUp ) ); + } + + if( dir == Movement::Forward ) + mPosition += moveForward * velocity; + if( dir == Movement::Backward ) + mPosition -= moveForward * velocity; + if( dir == Movement::Left ) + mPosition -= moveRight * velocity; + if( dir == Movement::Right ) + mPosition += moveRight * velocity; + if( dir == Movement::Up && mFlying ) + mPosition += mWorldUp * velocity; + if( dir == Movement::Down && mFlying ) + mPosition -= mWorldUp * velocity; +} + +void Camera::toggleFly () { + mFlying = !mFlying; + if( mFlying ) { + + mVelocity.y = 0.0f; + } +} + +void Camera::setSpeedMultiplier ( float m ) { + mSpeedMultiplier = m; +} + +static bool aabbOverlap ( const glm::vec3& amin, const glm::vec3& amax, const glm::vec3& bmin, + const glm::vec3& bmax ) { + return ( amin.x <= bmax.x && amax.x >= bmin.x ) && ( amin.y <= bmax.y && amax.y >= bmin.y ) && + ( amin.z <= bmax.z && amax.z >= bmin.z ); +} + +void Camera::updatePhysics ( float deltaTime, const std::vector<std::pair<glm::vec3, glm::vec3>>& worldAABBs, + float floorY ) { + const glm::vec3 halfExtents( 0.3f, 0.9f, 0.3f ); + + if( mFlying ) { + mGrounded = false; + return; + } + + if( !mFlying ) { + const float gravity = -9.8f; + mVelocity.y += gravity * deltaTime; + if( mVelocity.y < -50.0f ) + mVelocity.y = -50.0f; + } + + glm::vec3 newPos = mPosition + mVelocity * deltaTime; + + float camBottom = newPos.y - halfExtents.y; + if( camBottom < floorY ) { + newPos.y = floorY + halfExtents.y; + mVelocity.y = 0.0f; + mGrounded = true; + } else { + mGrounded = false; + } + + for( const auto& box : worldAABBs ) { + glm::vec3 bmin = box.first; + glm::vec3 bmax = box.second; + + glm::vec3 camMin = newPos - halfExtents; + glm::vec3 camMax = newPos + halfExtents; + + if( !aabbOverlap( camMin, camMax, bmin, bmax ) ) + continue; + + float ox = std::min( camMax.x, bmax.x ) - std::max( camMin.x, bmin.x ); + float oy = std::min( camMax.y, bmax.y ) - std::max( camMin.y, bmin.y ); + float oz = std::min( camMax.z, bmax.z ) - std::max( camMin.z, bmin.z ); + + if( ox <= oy && ox <= oz ) { + + float boxCenterX = ( bmin.x + bmax.x ) * 0.5f; + if( newPos.x < boxCenterX ) + newPos.x -= ox; + else + newPos.x += ox; + } else if( oy <= ox && oy <= oz ) { + float boxCenterY = ( bmin.y + bmax.y ) * 0.5f; + if( newPos.y < boxCenterY ) { + newPos.y -= oy; + mVelocity.y = 0.0f; + } else { + newPos.y += oy; + mVelocity.y = 0.0f; + mGrounded = true; + } + } else { + float boxCenterZ = ( bmin.z + bmax.z ) * 0.5f; + if( newPos.z < boxCenterZ ) + newPos.z -= oz; + else + newPos.z += oz; + } + } + + mPosition = newPos; +} + +void Camera::jump () { + if( mFlying ) + return; + if( mGrounded ) { + const float jumpImpulse = 5.0f; + mVelocity.y = jumpImpulse; + mGrounded = false; + } +} + +bool Camera::isFlying () const { + return mFlying; +} + +bool Camera::isGrounded () const { + return mGrounded; +} + +float Camera::getSpeedMultiplier () const { + return mSpeedMultiplier; +} + +void Camera::processMouseMovement ( float xoffset, float yoffset, bool constrainPitch ) { + xoffset *= mMouseSensitivity; + yoffset *= mMouseSensitivity; + + mYaw += xoffset; + mPitch += yoffset; + + if( constrainPitch ) { + if( mPitch > 89.0f ) + mPitch = 89.0f; + if( mPitch < -89.0f ) + mPitch = -89.0f; + } + + updateCameraVectors(); +} + +void Camera::processMouseScroll ( float yoffset ) { + mFov -= yoffset; + if( mFov < 1.0f ) + mFov = 1.0f; + if( mFov > 90.0f ) + mFov = 90.0f; +} + +void Camera::updateCameraVectors () { + glm::vec3 front; + front.x = cos( glm::radians( mYaw ) ) * cos( glm::radians( mPitch ) ); + front.y = sin( glm::radians( mPitch ) ); + front.z = sin( glm::radians( mYaw ) ) * cos( glm::radians( mPitch ) ); + mFront = glm::normalize( front ); + mRight = glm::normalize( glm::cross( mFront, mWorldUp ) ); + mUp = glm::normalize( glm::cross( mRight, mFront ) ); +} + +} // namespace scene diff --git a/apps/openmb/scene/Camera.hpp b/apps/openmb/scene/Camera.hpp new file mode 100644 index 0000000..7c5edc7 --- /dev/null +++ b/apps/openmb/scene/Camera.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include <glm/glm.hpp> +#include <utility> +#include <vector> + +namespace scene { +enum class Movement { + Forward, + Backward, + Left, + Right, + Up, + Down +}; + +class Camera { + public: + Camera(); + Camera( const glm::vec3& position, const glm::vec3& up, float yaw, float pitch ); + + glm::mat4 getViewMatrix() const; + glm::mat4 getProjectionMatrix( float aspect ) const; + + void processKeyboard( Movement dir, float deltaTime ); + void processMouseMovement( float xoffset, float yoffset, bool constrainPitch = true ); + void processMouseScroll( float yoffset ); + + void toggleFly(); + void setSpeedMultiplier( float m ); + void jump(); + + bool isFlying() const; + bool isGrounded() const; + float getSpeedMultiplier() const; + + void updatePhysics( float deltaTime, const std::vector<std::pair<glm::vec3, glm::vec3>>& worldAABBs, + float floorY = 0.0f ); + + glm::vec3 position () const { return mPosition; } + + float getPitch () const { return mPitch; } + + float getYaw () const { return mYaw; } + + private: + void updateCameraVectors(); + + private: + glm::vec3 mPosition; + glm::vec3 mFront; + glm::vec3 mUp; + glm::vec3 mRight; + glm::vec3 mWorldUp; + + float mYaw; + float mPitch; + + float mMovementSpeed; + float mMouseSensitivity; + float mFov; + + glm::vec3 mVelocity; + bool mFlying; + bool mGrounded; + float mSpeedMultiplier; +}; + +} // namespace scene diff --git a/apps/openmb/scene/GridSystem.cpp b/apps/openmb/scene/GridSystem.cpp new file mode 100644 index 0000000..273cb02 --- /dev/null +++ b/apps/openmb/scene/GridSystem.cpp @@ -0,0 +1,121 @@ +#include "GridSystem.hpp" + +#include <cmath> + +namespace scene { +GridSystem::GridSystem () + : mCellSize( 1.0f ), mFloorY( 0.0f ), mGridWidth( 1000 ), mGridDepth( 1000 ), mWallHeight( 4 ) { +} + +float GridSystem::getCellSize () const { + return mCellSize; +} + +float GridSystem::getFloorY () const { + return mFloorY; +} + +int GridSystem::getGridWidth () const { + return mGridWidth; +} + +int GridSystem::getGridDepth () const { + return mGridDepth; +} + +int GridSystem::getWallHeight () const { + return mWallHeight; +} + +glm::vec3 GridSystem::gridToWorld ( int gridX, int gridZ, float y ) const { + float halfW = mGridWidth * 0.5f; + float halfD = mGridDepth * 0.5f; + + float worldX = ( gridX - halfW ) * mCellSize + mCellSize * 0.5f; + float worldZ = ( gridZ - halfD ) * mCellSize + mCellSize * 0.5f; + + return glm::vec3( worldX, y, worldZ ); +} + +glm::vec3 GridSystem::gridToWorldFloor ( int gridX, int gridZ ) const { + return gridToWorld( gridX, gridZ, mFloorY ); +} + +bool GridSystem::worldToGrid ( const glm::vec3& worldPos, int& outGridX, int& outGridZ ) const { + float halfW = mGridWidth * 0.5f; + float halfD = mGridDepth * 0.5f; + + float localX = worldPos.x / mCellSize + halfW - 0.5f; + float localZ = worldPos.z / mCellSize + halfD - 0.5f; + + outGridX = static_cast<int>( std::floor( localX ) ); + outGridZ = static_cast<int>( std::floor( localZ ) ); + + return ( outGridX >= 0 && outGridX < mGridWidth && outGridZ >= 0 && outGridZ < mGridDepth ); +} + +glm::vec3 GridSystem::getCellCenter ( int gridX, int gridZ, int cellY ) const { + float y = mFloorY + cellY * mCellSize + mCellSize * 0.5f; + return gridToWorld( gridX, gridZ, y ); +} + +float GridSystem::getMinWorldX () const { + float halfW = mGridWidth * 0.5f; + return ( 0 - halfW ) * mCellSize; +} + +float GridSystem::getMaxWorldX () const { + float halfW = mGridWidth * 0.5f; + return ( mGridWidth - 1 - halfW ) * mCellSize + mCellSize; +} + +float GridSystem::getMinWorldZ () const { + float halfD = mGridDepth * 0.5f; + return ( 0 - halfD ) * mCellSize; +} + +float GridSystem::getMaxWorldZ () const { + float halfD = mGridDepth * 0.5f; + return ( mGridDepth - 1 - halfD ) * mCellSize + mCellSize; +} + +float GridSystem::getHalfWidth () const { + return mGridWidth * 0.5f; +} + +float GridSystem::getHalfDepth () const { + return mGridDepth * 0.5f; +} + +float GridSystem::getFrontWallZ () const { + float halfD = mGridDepth * 0.5f; + return ( 0 - halfD ) * mCellSize + mCellSize * 0.5f; +} + +float GridSystem::getBackWallZ () const { + float halfD = mGridDepth * 0.5f; + return ( mGridDepth - 1 - halfD ) * mCellSize + mCellSize * 0.5f; +} + +float GridSystem::getLeftWallX () const { + float halfW = mGridWidth * 0.5f; + return ( 0 - halfW ) * mCellSize + mCellSize * 0.5f; +} + +float GridSystem::getRightWallX () const { + float halfW = mGridWidth * 0.5f; + return ( mGridWidth - 1 - halfW ) * mCellSize + mCellSize * 0.5f; +} + +float GridSystem::getWallMinY () const { + return mFloorY; +} + +float GridSystem::getWallMaxY () const { + return mFloorY + mWallHeight * mCellSize; +} + +float GridSystem::getWallBaseY () const { + return mFloorY + mCellSize; +} +} // namespace scene diff --git a/apps/openmb/scene/GridSystem.hpp b/apps/openmb/scene/GridSystem.hpp new file mode 100644 index 0000000..7fff5d2 --- /dev/null +++ b/apps/openmb/scene/GridSystem.hpp @@ -0,0 +1,66 @@ +#ifndef OPENMB_APPS_OPENMB_SCENE_GRIDSYSTEM_H +#define OPENMB_APPS_OPENMB_SCENE_GRIDSYSTEM_H + +#include <glm/glm.hpp> + +namespace scene { + +class GridSystem { + public: + GridSystem(); + ~GridSystem() = default; + + float getCellSize() const; + + float getFloorY() const; + + int getGridWidth() const; + + int getGridDepth() const; + + int getWallHeight() const; + + glm::vec3 gridToWorld( int gridX, int gridZ, float y ) const; + + glm::vec3 gridToWorldFloor( int gridX, int gridZ ) const; + + bool worldToGrid( const glm::vec3& worldPos, int& outGridX, int& outGridZ ) const; + + glm::vec3 getCellCenter( int gridX, int gridZ, int cellY ) const; + + float getMinWorldX() const; + + float getMaxWorldX() const; + + float getMinWorldZ() const; + + float getMaxWorldZ() const; + + float getHalfWidth() const; + + float getHalfDepth() const; + + float getFrontWallZ() const; + + float getBackWallZ() const; + + float getLeftWallX() const; + + float getRightWallX() const; + + float getWallMinY() const; + + float getWallMaxY() const; + + float getWallBaseY() const; + + private: + float mCellSize; + float mFloorY; + int mGridWidth; + int mGridDepth; + int mWallHeight; +}; +} // namespace scene + +#endif diff --git a/apps/openmb/scene/VoxelEditor.cpp b/apps/openmb/scene/VoxelEditor.cpp new file mode 100644 index 0000000..b113580 --- /dev/null +++ b/apps/openmb/scene/VoxelEditor.cpp @@ -0,0 +1,602 @@ +#include "VoxelEditor.hpp" + +#include "GridSystem.hpp" + +#include <algorithm> +#include <cmath> +#include <fstream> + +#include <nlohmann/json.hpp> + +namespace scene { +VoxelEditor::VoxelEditor ( const GridSystem& gridSystem ) + : mGridSystem( gridSystem ), mPlacedSet(), mPlacedList(), mCellTextureIds(), mCellCollidable(), mUndoStack(), + mRedoStack(), mPlacedModels(), mDragging( false ), mDragButton( -1 ), mDragStartCell( 0 ), mPreviewCells(), + mPrevLeftDown( false ), mPrevRightDown( false ) { +} + +void VoxelEditor::addModelInstance ( const ModelInstance& mi ) { + + Action action; + Action::ModelInstance ami; + ami.modelIndex = mi.modelIndex; + ami.pos = mi.pos; + ami.yaw = mi.yaw; + ami.scale = mi.scale; + ami.mCollidable = mi.mCollidable; + action.mAddedModels.push_back( ami ); + mPlacedModels.push_back( mi ); + + mUndoStack.push_back( action ); + if( mUndoStack.size() > mMaxUndoSteps ) + mUndoStack.erase( mUndoStack.begin() ); + mRedoStack.clear(); +} + +const std::vector<VoxelEditor::ModelInstance>& VoxelEditor::getPlacedModels () const { + return mPlacedModels; +} + +void VoxelEditor::processInput ( const glm::vec3& rayOrigin, const glm::vec3& rayDir, bool leftMouseDown, + bool rightMouseDown, bool shiftPressed, + const std::vector<std::pair<glm::vec3, glm::vec3>>& baseWorldBoxes, + int currentTextureId, bool placeCollidable ) { + bool hitExisting = false; + float bestT = FLT_MAX; + glm::ivec3 hitCell( 0 ); + glm::vec3 hitNormal( 0.0f ); + + for( const auto& c : mPlacedList ) { + auto aabb = cellToAABB( c ); + float t = 0.0f; + if( rayAABBIntersect( rayOrigin, rayDir, aabb.first, aabb.second, t ) ) { + if( t >= 0.0f && t < bestT ) { + bestT = t; + hitExisting = true; + hitCell = c; + glm::vec3 hitPoint = rayOrigin + rayDir * t; + glm::vec3 center = ( aabb.first + aabb.second ) * 0.5f; + glm::vec3 diff = hitPoint - center; + glm::vec3 ad = glm::abs( diff ); + if( ad.x > ad.y && ad.x > ad.z ) + hitNormal = glm::vec3( diff.x > 0.0f ? 1.0f : -1.0f, 0.0f, 0.0f ); + else if( ad.y > ad.x && ad.y > ad.z ) + hitNormal = glm::vec3( 0.0f, diff.y > 0.0f ? 1.0f : -1.0f, 0.0f ); + else + hitNormal = glm::vec3( 0.0f, 0.0f, diff.z > 0.0f ? 1.0f : -1.0f ); + } + } + } + + glm::ivec3 placeCell( 0 ); + bool validHit = false; + + if( !hitExisting ) { + float wallT = FLT_MAX; + glm::vec3 wallHitPoint( 0.0f ); + glm::vec3 wallHitNormal( 0.0f ); + bool hitWall = false; + + for( const auto& box : baseWorldBoxes ) { + float t = 0.0f; + if( rayAABBIntersect( rayOrigin, rayDir, box.first, box.second, t ) ) { + if( t > 0.0f && t < wallT ) { + wallT = t; + wallHitPoint = rayOrigin + rayDir * t; + glm::vec3 center = ( box.first + box.second ) * 0.5f; + glm::vec3 diff = wallHitPoint - center; + glm::vec3 ad = glm::abs( diff ); + if( ad.x > ad.y && ad.x > ad.z ) + wallHitNormal = glm::vec3( diff.x > 0.0f ? 1.0f : -1.0f, 0.0f, 0.0f ); + else if( ad.y > ad.x && ad.y > ad.z ) + wallHitNormal = glm::vec3( 0.0f, diff.y > 0.0f ? 1.0f : -1.0f, 0.0f ); + else + wallHitNormal = glm::vec3( 0.0f, 0.0f, diff.z > 0.0f ? 1.0f : -1.0f ); + hitWall = true; + } + } + } + + if( hitWall ) { + + glm::vec3 offsetPoint = wallHitPoint + wallHitNormal * 0.01f; + + int xi = 0, zi = 0; + mGridSystem.worldToGrid( offsetPoint, xi, zi ); + int yi = static_cast<int>( std::floor( offsetPoint.y / mGridSystem.getCellSize() ) ); + + hitCell = glm::ivec3( xi, yi, zi ); + hitNormal = wallHitNormal; + placeCell = hitCell; + validHit = true; + } else if( std::abs( rayDir.y ) > 1e-6f ) { + float t = ( 0.0f - rayOrigin.y ) / rayDir.y; + if( t > 0.0f ) { + glm::vec3 hitPoint = rayOrigin + rayDir * t; + hitCell = worldPosToCell( hitPoint ); + hitNormal = glm::vec3( 0.0f, 1.0f, 0.0f ); + placeCell = hitCell; + validHit = true; + } + } + } + + if( hitExisting ) { + validHit = true; + placeCell = hitCell + glm::ivec3( static_cast<int>( std::round( hitNormal.x ) ), + static_cast<int>( std::round( hitNormal.y ) ), + static_cast<int>( std::round( hitNormal.z ) ) ); + placeCell.x = std::clamp( placeCell.x, 0, mGridSystem.getGridWidth() - 1 ); + placeCell.z = std::clamp( placeCell.z, 0, mGridSystem.getGridDepth() - 1 ); + } else if( validHit ) { + placeCell.x = std::clamp( placeCell.x, 0, mGridSystem.getGridWidth() - 1 ); + placeCell.z = std::clamp( placeCell.z, 0, mGridSystem.getGridDepth() - 1 ); + } + + if( leftMouseDown && !mPrevLeftDown ) { + mDragging = true; + mDragButton = 0; + mDragStartCell = placeCell; + } + if( rightMouseDown && !mPrevRightDown ) { + mDragging = true; + mDragButton = 1; + mDragStartCell = placeCell; + } + + if( mDragging ) { + glm::ivec3 endCell = placeCell; + if( shiftPressed ) { + endCell.y = mDragStartCell.y; + } + mPreviewCells = rasterizeGridBox( mDragStartCell, endCell ); + } + + if( !leftMouseDown && mPrevLeftDown && mDragButton == 0 ) { + Action action; + for( const auto& cell : mPreviewCells ) { + if( mPlacedSet.insert( cell ).second ) { + mPlacedList.push_back( cell ); + mCellTextureIds[cell] = currentTextureId; + mCellCollidable[cell] = placeCollidable; + VoxelData voxelData; + voxelData.mCell = cell; + voxelData.mTextureId = currentTextureId; + voxelData.mCollidable = placeCollidable; + action.mAddedCells.push_back( voxelData ); + } + } + if( !action.mAddedCells.empty() ) { + mUndoStack.push_back( action ); + if( mUndoStack.size() > mMaxUndoSteps ) + mUndoStack.erase( mUndoStack.begin() ); + mRedoStack.clear(); + } + mDragging = false; + } + + if( !rightMouseDown && mPrevRightDown && mDragButton == 1 ) { + Action action; + for( const auto& cell : mPreviewCells ) { + if( mPlacedSet.erase( cell ) > 0 ) { + mPlacedList.erase( std::remove( mPlacedList.begin(), mPlacedList.end(), cell ), mPlacedList.end() ); + auto texIt = mCellTextureIds.find( cell ); + VoxelData voxelData; + voxelData.mCell = cell; + voxelData.mTextureId = ( texIt != mCellTextureIds.end() ) ? texIt->second : 0; + auto collIt = mCellCollidable.find( cell ); + voxelData.mCollidable = ( collIt != mCellCollidable.end() ) ? collIt->second : true; + action.mRemovedCells.push_back( voxelData ); + mCellTextureIds.erase( cell ); + mCellCollidable.erase( cell ); + } + } + if( !action.mRemovedCells.empty() ) { + mUndoStack.push_back( action ); + if( mUndoStack.size() > mMaxUndoSteps ) + mUndoStack.erase( mUndoStack.begin() ); + mRedoStack.clear(); + } + mDragging = false; + } + + if( !mDragging ) { + if( validHit ) { + mPreviewCells.clear(); + mPreviewCells.push_back( placeCell ); + } else { + mPreviewCells.clear(); + } + } + + mPrevLeftDown = leftMouseDown; + mPrevRightDown = rightMouseDown; +} + +void VoxelEditor::undo () { + if( mUndoStack.empty() ) + return; + + Action action = mUndoStack.back(); + mUndoStack.pop_back(); + + for( const auto& voxelData : action.mAddedCells ) { + mPlacedSet.erase( voxelData.mCell ); + mPlacedList.erase( std::remove( mPlacedList.begin(), mPlacedList.end(), voxelData.mCell ), + mPlacedList.end() ); + mCellTextureIds.erase( voxelData.mCell ); + mCellCollidable.erase( voxelData.mCell ); + } + for( const auto& voxelData : action.mRemovedCells ) { + if( mPlacedSet.insert( voxelData.mCell ).second ) { + mPlacedList.push_back( voxelData.mCell ); + mCellTextureIds[voxelData.mCell] = voxelData.mTextureId; + mCellCollidable[voxelData.mCell] = voxelData.mCollidable; + } + } + + for( const auto& mi : action.mAddedModels ) { + + auto it = std::find_if( mPlacedModels.begin(), mPlacedModels.end(), + [&] ( const ModelInstance& m ) { + return m.modelIndex == mi.modelIndex && m.pos == mi.pos && m.yaw == mi.yaw && + m.scale == mi.scale; + } ); + if( it != mPlacedModels.end() ) + mPlacedModels.erase( it ); + } + for( const auto& mi : action.mRemovedModels ) { + ModelInstance m; + m.modelIndex = mi.modelIndex; + m.pos = mi.pos; + m.yaw = mi.yaw; + m.scale = mi.scale; + m.mCollidable = mi.mCollidable; + mPlacedModels.push_back( m ); + } + + mRedoStack.push_back( action ); +} + +void VoxelEditor::redo () { + if( mRedoStack.empty() ) + return; + + Action action = mRedoStack.back(); + mRedoStack.pop_back(); + + for( const auto& voxelData : action.mAddedCells ) { + if( mPlacedSet.insert( voxelData.mCell ).second ) { + mPlacedList.push_back( voxelData.mCell ); + mCellTextureIds[voxelData.mCell] = voxelData.mTextureId; + mCellCollidable[voxelData.mCell] = voxelData.mCollidable; + } + } + for( const auto& voxelData : action.mRemovedCells ) { + mPlacedSet.erase( voxelData.mCell ); + mPlacedList.erase( std::remove( mPlacedList.begin(), mPlacedList.end(), voxelData.mCell ), + mPlacedList.end() ); + mCellTextureIds.erase( voxelData.mCell ); + mCellCollidable.erase( voxelData.mCell ); + } + + for( const auto& mi : action.mAddedModels ) { + ModelInstance m; + m.modelIndex = mi.modelIndex; + m.pos = mi.pos; + m.yaw = mi.yaw; + m.scale = mi.scale; + m.mCollidable = mi.mCollidable; + mPlacedModels.push_back( m ); + } + for( const auto& mi : action.mRemovedModels ) { + auto it = std::find_if( mPlacedModels.begin(), mPlacedModels.end(), + [&] ( const ModelInstance& m ) { + return m.modelIndex == mi.modelIndex && m.pos == mi.pos && m.yaw == mi.yaw && + m.scale == mi.scale; + } ); + if( it != mPlacedModels.end() ) + mPlacedModels.erase( it ); + } + + mUndoStack.push_back( action ); +} + +const std::vector<glm::ivec3>& VoxelEditor::getPlacedCells () const { + return mPlacedList; +} + +const std::vector<glm::ivec3>& VoxelEditor::getPreviewCells () const { + return mPreviewCells; +} + +size_t VoxelEditor::getUndoStackSize () const { + return mUndoStack.size(); +} + +size_t VoxelEditor::getRedoStackSize () const { + return mRedoStack.size(); +} + +glm::ivec3 VoxelEditor::worldPosToCell ( const glm::vec3& pos ) const { + int xi = 0, zi = 0; + mGridSystem.worldToGrid( pos, xi, zi ); + int yi = static_cast<int>( std::floor( ( pos.y - mGridSystem.getFloorY() ) / mGridSystem.getCellSize() ) ); + return glm::ivec3( xi, yi, zi ); +} + +glm::vec3 VoxelEditor::cellToWorldCenter ( const glm::ivec3& cell ) const { + return mGridSystem.getCellCenter( cell.x, cell.z, cell.y ); +} + +std::pair<glm::vec3, glm::vec3> VoxelEditor::cellToAABB ( const glm::ivec3& cell ) const { + glm::vec3 center = cellToWorldCenter( cell ); + float halfSize = mGridSystem.getCellSize() * 0.5f; + glm::vec3 he( halfSize, halfSize, halfSize ); + return { center - he, center + he }; +} + +std::vector<std::pair<glm::vec3, glm::vec3>> +VoxelEditor::getAllCollisionBoxes ( const std::vector<std::pair<glm::vec3, glm::vec3>>& baseWorldBoxes ) const { + std::vector<std::pair<glm::vec3, glm::vec3>> boxes = baseWorldBoxes; + for( const auto& c : mPlacedList ) { + auto it = mCellCollidable.find( c ); + bool coll = true; + if( it != mCellCollidable.end() ) + coll = it->second; + if( coll ) + boxes.push_back( cellToAABB( c ) ); + } + + return boxes; +} + +bool VoxelEditor::rayAABBIntersect ( const glm::vec3& ro, const glm::vec3& rd, const glm::vec3& bmin, + const glm::vec3& bmax, float& outT ) const { + float tmin = -FLT_MAX; + float tmax = FLT_MAX; + for( int i = 0; i < 3; ++i ) { + float origin = ro[i]; + float dir = rd[i]; + float minB = bmin[i]; + float maxB = bmax[i]; + if( std::abs( dir ) < 1e-6f ) { + if( origin < minB || origin > maxB ) + return false; + } else { + float t1 = ( minB - origin ) / dir; + float t2 = ( maxB - origin ) / dir; + if( t1 > t2 ) + std::swap( t1, t2 ); + tmin = std::max( tmin, t1 ); + tmax = std::min( tmax, t2 ); + if( tmin > tmax ) + return false; + } + } + if( tmax < 0.0f ) + return false; + outT = tmin >= 0.0f ? tmin : tmax; + return true; +} + +std::vector<glm::ivec3> VoxelEditor::rasterizeGridBox ( const glm::ivec3& a, const glm::ivec3& b ) const { + std::vector<glm::ivec3> out; + glm::ivec3 minC( std::min( a.x, b.x ), std::min( a.y, b.y ), std::min( a.z, b.z ) ); + glm::ivec3 maxC( std::max( a.x, b.x ), std::max( a.y, b.y ), std::max( a.z, b.z ) ); + + minC.x = std::clamp( minC.x, 0, mGridSystem.getGridWidth() - 1 ); + maxC.x = std::clamp( maxC.x, 0, mGridSystem.getGridWidth() - 1 ); + minC.z = std::clamp( minC.z, 0, mGridSystem.getGridDepth() - 1 ); + maxC.z = std::clamp( maxC.z, 0, mGridSystem.getGridDepth() - 1 ); + + for( int x = minC.x; x <= maxC.x; ++x ) { + for( int y = minC.y; y <= maxC.y; ++y ) { + for( int z = minC.z; z <= maxC.z; ++z ) { + out.emplace_back( x, y, z ); + } + } + } + + return out; +} + +std::vector<glm::ivec3> VoxelEditor::rasterizeCircle ( const glm::ivec3& centerCell, int radiusCells, + int heightLayers ) const { + std::vector<glm::ivec3> out; + + if( radiusCells < 1 ) + radiusCells = 1; + if( heightLayers < 1 ) + heightLayers = 1; + + int minX = std::max( 0, centerCell.x - radiusCells ); + int maxX = std::min( mGridSystem.getGridWidth() - 1, centerCell.x + radiusCells ); + int minZ = std::max( 0, centerCell.z - radiusCells ); + int maxZ = std::min( mGridSystem.getGridDepth() - 1, centerCell.z + radiusCells ); + + int maxY = mGridSystem.getWallHeight() - 1; + + int r2 = radiusCells * radiusCells; + + for( int x = minX; x <= maxX; ++x ) { + for( int z = minZ; z <= maxZ; ++z ) { + int dx = x - centerCell.x; + int dz = z - centerCell.z; + if( dx * dx + dz * dz <= r2 ) { + for( int h = 0; h < heightLayers; ++h ) { + int y = centerCell.y + h; + y = std::clamp( y, 0, maxY ); + out.emplace_back( x, y, z ); + } + } + } + } + + return out; +} + +void VoxelEditor::applyCircularBrush ( const glm::vec3& centerWorld, float radiusWorld, float /*heightWorld*/, + int textureId, bool placeCollidable ) { + float cellSize = mGridSystem.getCellSize(); + + int radiusCells = std::max( 1, static_cast<int>( std::ceil( radiusWorld / cellSize ) ) ); + + glm::ivec3 centerCell = worldPosToCell( centerWorld ); + + int minX = std::max( 0, centerCell.x - radiusCells ); + int maxX = std::min( mGridSystem.getGridWidth() - 1, centerCell.x + radiusCells ); + int minZ = std::max( 0, centerCell.z - radiusCells ); + int maxZ = std::min( mGridSystem.getGridDepth() - 1, centerCell.z + radiusCells ); + + int targetY = centerCell.y; + int maxY = mGridSystem.getWallHeight() - 1; + targetY = std::clamp( targetY, 0, maxY ); + + float r2 = radiusWorld * radiusWorld; + + Action action; + + for( int x = minX; x <= maxX; ++x ) { + for( int z = minZ; z <= maxZ; ++z ) { + + glm::vec3 cellCenter = mGridSystem.getCellCenter( x, z, targetY ); + float dx = cellCenter.x - centerWorld.x; + float dz = cellCenter.z - centerWorld.z; + if( dx * dx + dz * dz <= r2 ) { + glm::ivec3 cell( x, targetY, z ); + if( mPlacedSet.insert( cell ).second ) { + mPlacedList.push_back( cell ); + mCellTextureIds[cell] = textureId; + mCellCollidable[cell] = placeCollidable; + VoxelData vd; + vd.mCell = cell; + vd.mTextureId = textureId; + vd.mCollidable = placeCollidable; + action.mAddedCells.push_back( vd ); + } + } + } + } + + if( !action.mAddedCells.empty() ) { + mUndoStack.push_back( action ); + if( mUndoStack.size() > mMaxUndoSteps ) + mUndoStack.erase( mUndoStack.begin() ); + mRedoStack.clear(); + } +} + +int VoxelEditor::getTextureIdForCell ( const glm::ivec3& cell ) const { + auto it = mCellTextureIds.find( cell ); + if( it != mCellTextureIds.end() ) + return it->second; + return -1; +} + +bool VoxelEditor::saveToFile ( const std::string& filepath ) const { + try { + nlohmann::json j; + j["version"] = 1; + + nlohmann::json voxelsArray = nlohmann::json::array(); + for( const auto& cell : mPlacedList ) { + auto it = mCellTextureIds.find( cell ); + int textureId = ( it != mCellTextureIds.end() ) ? it->second : 0; + + nlohmann::json voxel; + voxel["x"] = cell.x; + voxel["y"] = cell.y; + voxel["z"] = cell.z; + voxel["textureId"] = textureId; + auto cit = mCellCollidable.find( cell ); + voxel["collidable"] = ( cit != mCellCollidable.end() ) ? cit->second : true; + voxelsArray.push_back( voxel ); + } + + j["voxels"] = voxelsArray; + + nlohmann::json modelsArray = nlohmann::json::array(); + for( const auto& m : mPlacedModels ) { + nlohmann::json mj; + mj["modelIndex"] = m.modelIndex; + mj["x"] = m.pos.x; + mj["y"] = m.pos.y; + mj["z"] = m.pos.z; + mj["yaw"] = m.yaw; + mj["scale"] = m.scale; + mj["collidable"] = m.mCollidable; + modelsArray.push_back( mj ); + } + j["models"] = modelsArray; + + std::ofstream file( filepath ); + if( !file.is_open() ) + return false; + + file << j.dump( 2 ); + file.close(); + return true; + } catch( ... ) { + return false; + } +} + +bool VoxelEditor::loadFromFile ( const std::string& filepath ) { + try { + std::ifstream file( filepath ); + if( !file.is_open() ) + return false; + + nlohmann::json j; + file >> j; + file.close(); + + if( !j.contains( "version" ) || !j.contains( "voxels" ) ) + return false; + + clear(); + + for( const auto& voxelJson : j["voxels"] ) { + glm::ivec3 cell( voxelJson["x"].get<int>(), voxelJson["y"].get<int>(), + voxelJson["z"].get<int>() ); + + int textureId = voxelJson.value( "textureId", 0 ); + bool collidable = voxelJson.value( "collidable", true ); + + if( mPlacedSet.insert( cell ).second ) { + mPlacedList.push_back( cell ); + mCellTextureIds[cell] = textureId; + mCellCollidable[cell] = collidable; + } + } + + if( j.contains( "models" ) && j["models"].is_array() ) { + for( const auto& mj : j["models"] ) { + ModelInstance mi; + mi.modelIndex = mj.value( "modelIndex", 0 ); + mi.pos.x = mj.value( "x", 0.0f ); + mi.pos.y = mj.value( "y", 0.0f ); + mi.pos.z = mj.value( "z", 0.0f ); + mi.yaw = mj.value( "yaw", 0.0f ); + mi.scale = mj.value( "scale", 1.0f ); + mi.mCollidable = mj.value( "collidable", true ); + mPlacedModels.push_back( mi ); + } + } + + return true; + } catch( ... ) { + return false; + } +} + +void VoxelEditor::clear () { + mPlacedSet.clear(); + mPlacedList.clear(); + mCellTextureIds.clear(); + mUndoStack.clear(); + mRedoStack.clear(); + mPlacedModels.clear(); +} +} // namespace scene diff --git a/apps/openmb/scene/VoxelEditor.hpp b/apps/openmb/scene/VoxelEditor.hpp new file mode 100644 index 0000000..a77f547 --- /dev/null +++ b/apps/openmb/scene/VoxelEditor.hpp @@ -0,0 +1,132 @@ +#ifndef OPENMB_APPS_OPENMB_SCENE_VOXELEDITOR_H +#define OPENMB_APPS_OPENMB_SCENE_VOXELEDITOR_H + +#include <glm/glm.hpp> +#include <string> +#include <unordered_map> +#include <unordered_set> +#include <vector> + +namespace scene { +class GridSystem; + +struct IVec3Hash { + size_t operator()( const glm::ivec3& v ) const noexcept { + uint32_t x = static_cast<uint32_t>( v.x ); + uint32_t y = static_cast<uint32_t>( v.y ); + uint32_t z = static_cast<uint32_t>( v.z ); + return (size_t)( ( x * 73856093u ) ^ ( y * 19349663u ) ^ ( z * 83492791u ) ); + } +}; + +struct IVec3Eq { + bool operator()( const glm::ivec3& a, const glm::ivec3& b ) const noexcept { + return a.x == b.x && a.y == b.y && a.z == b.z; + } +}; + +class VoxelEditor { + public: + VoxelEditor( const GridSystem& gridSystem ); + ~VoxelEditor() = default; + + void processInput( const glm::vec3& rayOrigin, const glm::vec3& rayDir, bool leftMouseDown, bool rightMouseDown, + bool shiftPressed, const std::vector<std::pair<glm::vec3, glm::vec3>>& baseWorldBoxes, + int currentTextureId, bool placeCollidable ); + + void applyCircularBrush( const glm::vec3& centerWorld, float radiusWorld, float heightWorld, int textureId, + bool placeCollidable ); + + void undo(); + + void redo(); + + const std::vector<glm::ivec3>& getPlacedCells() const; + + const std::vector<glm::ivec3>& getPreviewCells() const; + + size_t getUndoStackSize() const; + + size_t getRedoStackSize() const; + + glm::ivec3 worldPosToCell( const glm::vec3& pos ) const; + + glm::vec3 cellToWorldCenter( const glm::ivec3& cell ) const; + + std::pair<glm::vec3, glm::vec3> cellToAABB( const glm::ivec3& cell ) const; + + std::vector<std::pair<glm::vec3, glm::vec3>> + getAllCollisionBoxes( const std::vector<std::pair<glm::vec3, glm::vec3>>& baseWorldBoxes ) const; + + int getTextureIdForCell( const glm::ivec3& cell ) const; + + bool saveToFile( const std::string& filepath ) const; + + bool loadFromFile( const std::string& filepath ); + + void clear(); + + struct ModelInstance { + int modelIndex; + glm::vec3 pos; + float yaw; + float scale; + bool mCollidable; + }; + + void addModelInstance( const ModelInstance& mi ); + const std::vector<ModelInstance>& getPlacedModels() const; + + private: + struct VoxelData { + glm::ivec3 mCell; + int mTextureId; + bool mCollidable; + }; + + struct Action { + std::vector<VoxelData> mAddedCells; + std::vector<VoxelData> mRemovedCells; + struct ModelInstance { + int modelIndex; + glm::vec3 pos; + float yaw; + float scale; + bool mCollidable; + }; + std::vector<ModelInstance> mAddedModels; + std::vector<ModelInstance> mRemovedModels; + }; + + bool rayAABBIntersect( const glm::vec3& ro, const glm::vec3& rd, const glm::vec3& bmin, const glm::vec3& bmax, + float& outT ) const; + + std::vector<glm::ivec3> rasterizeGridBox( const glm::ivec3& a, const glm::ivec3& b ) const; + + std::vector<glm::ivec3> rasterizeCircle( const glm::ivec3& centerCell, int radiusCells, + int heightLayers ) const; + + const GridSystem& mGridSystem; + + std::unordered_set<glm::ivec3, IVec3Hash, IVec3Eq> mPlacedSet; + std::vector<glm::ivec3> mPlacedList; + std::unordered_map<glm::ivec3, int, IVec3Hash, IVec3Eq> mCellTextureIds; + std::unordered_map<glm::ivec3, bool, IVec3Hash, IVec3Eq> mCellCollidable; + + std::vector<Action> mUndoStack; + std::vector<Action> mRedoStack; + static constexpr int mMaxUndoSteps = 100; + + std::vector<ModelInstance> mPlacedModels; + + bool mDragging; + int mDragButton; + glm::ivec3 mDragStartCell; + std::vector<glm::ivec3> mPreviewCells; + + bool mPrevLeftDown; + bool mPrevRightDown; +}; +} // namespace scene + +#endif |