void PeriodicExploration::periodic_inflate(bool use_reflective_inflator) {
    ParameterCommon::Variables vars;
    MatrixFr offset = m_parameters->evaluate_offset(vars);
    MatrixFr ori_vertices = m_wire_network->get_vertices();
    m_wire_network->set_vertices(ori_vertices+ offset);

    InflatorEngine::Ptr inflator;
    if (use_reflective_inflator) {
        inflator = InflatorEngine::create_isotropic_parametric(
                m_wire_network, m_parameters);
    } else {
        inflator = InflatorEngine::create_parametric(m_wire_network, m_parameters);
    }
    inflator->set_profile(m_profile);
    inflator->with_shape_velocities();
    if (m_refine_order > 0)
        inflator->with_refinement(m_refine_algorithm, m_refine_order);

    try {
        inflator->inflate();
    } catch (...) {
        m_wire_network->set_vertices(ori_vertices);
        throw;
    }

    m_wire_network->set_vertices(ori_vertices);

    m_vertices = inflator->get_vertices();
    m_faces = inflator->get_faces();
    m_voxels = MatrixIr::Zero(0, 4);
    m_face_sources = inflator->get_face_sources();
    m_shape_velocities = inflator->get_shape_velocities();
    update_mesh();
}
Beispiel #2
0
void Spine::draw_mesh()
{
    update_mesh();
    flat_program->load();

    int N = n * p * q;
    int M = m;
    while ((N + 1) * (M + 1) >= 65536)
        N--;

    glEnableVertexAttribArray(flat_program->vertexPositionAttribute);
    glEnableVertexAttribArray(flat_program->paramAttribute);
    if (mesh_rings)
    {
        // rings around the spine
        // there are N(+1) of these, and each has M(+1) points
        // and they are adjacent
        // with M=5, N=3
        // 11111X
        //       22222X
        //             33333X
        //                   YYYYYX
        glBindBuffer(GL_ARRAY_BUFFER, mesh_points);
        glVertexAttribPointer(flat_program->vertexPositionAttribute, 3, GL_FLOAT, GL_FALSE,
                0, (GLvoid*) 0);
        glBindBuffer(GL_ARRAY_BUFFER, mesh_params);
        glVertexAttribPointer(flat_program->paramAttribute, 4, GL_FLOAT, GL_FALSE,
                0, (GLvoid*) 0);
        for (int i = 0; i < N; ++i)
        {
            glDrawArrays(GL_LINE_STRIP, i * (M + 1), M + 1);
        }
    }
    if (mesh_longs)
    {
        // the long bits "parallel" to the spine
        // there are M(+1) of these, and each has N(+1) points
        // but they are interleaved
        // with M=5, N=3
        // 1     1     1     Y
        //  2     2     2     Y
        //   3     3     3     Y
        //    4     4     4     Y
        //     5     5     5     Y
        //      X     X     X     X
        for (int j = 0; j < M; ++j)
        {
            glBindBuffer(GL_ARRAY_BUFFER, mesh_points);
            glVertexAttribPointer(flat_program->vertexPositionAttribute, 3, GL_FLOAT, GL_FALSE,
                    (M + 1) * sizeof(vec3), (GLvoid*) (j * sizeof(vec3)));
            glBindBuffer(GL_ARRAY_BUFFER, mesh_params);
            glVertexAttribPointer(flat_program->paramAttribute, 4, GL_FLOAT, GL_FALSE,
                    (M + 1) * sizeof(vec4), (GLvoid*) (j * sizeof(vec4)));
            glDrawArrays(GL_LINE_STRIP, 0, N + 1);
        }
    }
    glDisableVertexAttribArray(flat_program->vertexPositionAttribute);
    glDisableVertexAttribArray(flat_program->paramAttribute);
}
Beispiel #3
0
    void box::set_position(float x, float y, float z)
    {
        position.set_x(x);
        position.set_y(y);
        position.set_z(z);

        update_mesh();
    }
Beispiel #4
0
    void box::set_size(float length, float height, float depth)
    {
        size.set_x(length);
        size.set_y(height);
        size.set_z(depth);

        update_mesh();
    }
Beispiel #5
0
    box::box(float x, float y, float z, float length, float height, float depth, std::shared_ptr<graphics::material> material) : box()
    {
        position.set_x(x);
        position.set_y(y);
        position.set_z(z);
        size.set_x(length);
        size.set_y(height);
        size.set_z(depth);
        update_mesh();

        if (material)
        {
            set_material(material);
        }
    }
Beispiel #6
0
	int superMi::tuetee_mapping(Solid* mesh, double deltaE, double deltaT)
	{
		double oldEnergy = 0;
		double newEnergy = 0;
		int error = 0;
		bool flag = false;

		error = energy(mesh, &oldEnergy, TUETEE);
		std::cout << "Initial Tuette energy: " << oldEnergy << std::endl;
		for (int i = 0; (i < 100000) && !flag; i++){
			error = gradient(mesh, TUETEE);
			error = absolute_derivative(mesh);
			error = update_mesh(mesh, deltaT);
			error = energy(mesh, &newEnergy, TUETEE);
			if (i % 1000 == 0) std::cout << i + 1 << ": " << newEnergy << std::endl;
			error = check_energy_change(&oldEnergy, &newEnergy, deltaE, &flag);
		}

		return 0;
	}
bool PeriodicExploration::run_tetgen(Float max_tet_vol) {
    const size_t dim = m_vertices.cols();
    const size_t num_vertices = m_vertices.rows();
    TetgenWrapper tetgen(m_vertices, m_faces);
    std::stringstream flags;
    if (max_tet_vol == 0.0) {
        max_tet_vol =
            pow(m_default_thickness * pow(0.5, m_refine_order), dim);
    }
    flags << "pqYQa" << max_tet_vol;
    try {
        tetgen.run(flags.str());
    } catch (TetgenException& e) {
        save_mesh("tetgen_debug.msh");
        std::cerr << "Tetgen failed!  Flags: " << flags.str() << std::endl;
        std::cerr << e.what() << std::endl;
        std::cerr << "Data saved in tetgen_debug.msh" << std::endl;
        return false;
    }

    // Important note:
    //
    // The following code is based on rather shaky the observation that tetgen
    // will only append to the existing list of vertices.  Therefore, the face
    // arrays are still valid given the "Y" flag is used.
    MatrixFr vertices = tetgen.get_vertices();
    assert(vertices.rows() > 0);
    assert((vertices.block(0, 0, num_vertices, dim).array()==m_vertices.array()).all());
    m_vertices = vertices;
    m_voxels = tetgen.get_voxels();

    const size_t num_vol_vertices = m_vertices.rows();
    for (auto& velocity : m_shape_velocities) {
        velocity.conservativeResize(num_vol_vertices, dim);
        velocity.block(num_vertices, 0,
                num_vol_vertices-num_vertices, dim).setZero();
    }
    update_mesh();

    return true;
}
Beispiel #8
0
	int superMi::harmonic_mapping(Solid* mesh, double deltaE, double deltaT)
	{
		double oldEnergy = 0;
		double newEnergy = 0;
		int error = 0;
		bool flag = false;

		error = energy(mesh, &oldEnergy, HARMONIC);
		std::cout << "Initial Harmonic energy: " << oldEnergy << std::endl;
		for (int i = 0; (i < 13) && !flag; i++){
			error = gradient(mesh, HARMONIC);
			error = absolute_derivative(mesh);
			error = update_mesh(mesh, deltaT);
			error = mass_center(mesh);
			error = energy(mesh, &newEnergy, HARMONIC);
			if (i % 1 == 0) std::cout << i + 1 << ": " << newEnergy << std::endl;
			error = check_energy_change(&oldEnergy, &newEnergy, deltaE, &flag);
		}

		return 0;
	}
Beispiel #9
0
void Spine::draw_shade()
{
    update_mesh();
    shade_program->load();

    int N = n * p * q;
    int M = m;
    while ((N + 1) * (M + 1) >= 65536)
        N--;

    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1.0f, 1.0f);
    glEnableVertexAttribArray(shade_program->vertexPositionAttribute);
    glEnableVertexAttribArray(shade_program->vertexNormalAttribute);
    glEnableVertexAttribArray(shade_program->paramAttribute);
    {
        glBindBuffer(GL_ARRAY_BUFFER, mesh_points);
        glVertexAttribPointer(shade_program->vertexPositionAttribute, 3, GL_FLOAT, GL_FALSE,
                0, (GLvoid*) 0);
        glBindBuffer(GL_ARRAY_BUFFER, mesh_norms);
        glVertexAttribPointer(shade_program->vertexNormalAttribute, 3, GL_FLOAT, GL_FALSE,
                0, (GLvoid*) 0);
        glBindBuffer(GL_ARRAY_BUFFER, mesh_params);
        glVertexAttribPointer(shade_program->paramAttribute, 4, GL_FLOAT, GL_FALSE,
                0, (GLvoid*) 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_indices);
        //for (int i = 0; i < N; ++i)
        {
            glDrawElements(GL_TRIANGLE_STRIP, 2 * (M + 1) * N, GL_UNSIGNED_SHORT,
                    (GLvoid *) 0);
        }
    }
    glDisableVertexAttribArray(shade_program->vertexPositionAttribute);
    glDisableVertexAttribArray(shade_program->vertexNormalAttribute);
    glDisableVertexAttribArray(shade_program->paramAttribute);
    glDisable(GL_POLYGON_OFFSET_FILL);
}
Beispiel #10
0
    void box::set_position(const math::vector<float, 3>& position)
    {
        this->position = position;

        update_mesh();
    }
Beispiel #11
0
    void box::set_x(float x)
    {
        position.set_x(x);

        update_mesh();
    }
Beispiel #12
0
void Skeleton::update(unsigned long dt)
{
    const float delta = dt / 1000.0f;
    spSkeleton_update(skeleton_, delta);
    spAnimationState_update(state_, delta * time_scale_);
    spAnimationState_apply(state_, skeleton_);
    spSkeleton_updateWorldTransform(skeleton_);

    // This solution is not ideal. We iterate over the bones twice: First to
    // determine number of vertices, second to update the vertex buffer.
    num_vertices_ = get_vertex_count(skeleton_, &texture_);
    if (num_vertices_ > max_vertices_)
    {
        max_vertices_ = num_vertices_;
        vertices_ = std::make_unique<SpriteVertex[]>(max_vertices_);
    }

    size_t i = 0;
    for_each(skeleton_, [this, &i](spSlot* slot) {
        if (!slot->attachment)
            return;

        switch (slot->attachment->type)
        {
            case SP_ATTACHMENT_REGION: {
                float vertices[8];
                spRegionAttachment* region =
                    reinterpret_cast<spRegionAttachment*>(slot->attachment);
                R_ASSERT(texture_ == get_texture(region),
                         kErrorMultipleTexturesUnsupported);
                spRegionAttachment_computeWorldVertices(
                    region, slot->bone, vertices);

                const char r = skeleton_->r * slot->r * 0xff;
                const char g = skeleton_->g * slot->g * 0xff;
                const char b = skeleton_->b * slot->b * 0xff;
                const char a = skeleton_->a * slot->a * 0xff;

                vertices_[i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X1];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y1];
                vertices_[i].position.x = vertices[SP_VERTEX_X1];
                vertices_[i].position.y = vertices[SP_VERTEX_Y1];

                vertices_[++i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X2];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y2];
                vertices_[i].position.x = vertices[SP_VERTEX_X2];
                vertices_[i].position.y = vertices[SP_VERTEX_Y2];

                vertices_[++i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X3];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y3];
                vertices_[i].position.x = vertices[SP_VERTEX_X3];
                vertices_[i].position.y = vertices[SP_VERTEX_Y3];

                ++i;
                vertices_[i] = vertices_[i - 1];

                vertices_[++i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X4];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y4];
                vertices_[i].position.x = vertices[SP_VERTEX_X4];
                vertices_[i].position.y = vertices[SP_VERTEX_Y4];

                ++i;
                vertices_[i] = vertices_[i - 5];

                ++i;
                break;
            }
            case SP_ATTACHMENT_BOUNDING_BOX:
                break;
            case SP_ATTACHMENT_MESH: {
                spMeshAttachment* mesh =
                    reinterpret_cast<spMeshAttachment*>(slot->attachment);
                R_ASSERT(texture_ == get_texture(mesh),
                         kErrorMultipleTexturesUnsupported);
                i += update_mesh(&vertices_[i], skeleton_, mesh, slot);
                break;
            }
            case SP_ATTACHMENT_SKINNED_MESH: {
                spSkinnedMeshAttachment* mesh =
                    reinterpret_cast<spSkinnedMeshAttachment*>(
                        slot->attachment);
                R_ASSERT(texture_ == get_texture(mesh),
                         kErrorMultipleTexturesUnsupported);
                i += update_mesh(&vertices_[i], skeleton_, mesh, slot);
                break;
            }
        }
        if (slot->data->blendMode != SP_BLEND_MODE_NORMAL)  // TODO: Implement.
            LOGE("Non-normal blend mode not yet implemented");
    });

    vertex_buffer_.upload(vertices_.get(), i * sizeof(SpriteVertex));
}
Beispiel #13
0
    void box::set_depth(float depth)
    {
        size.set_z(depth);

        update_mesh();
    }
Beispiel #14
0
    void box::set_height(float height)
    {
        size.set_y(height);

        update_mesh();
    }
Beispiel #15
0
    void box::set_y(float y)
    {
        position.set_y(y);

        update_mesh();
    }
Beispiel #16
0
int main(int argc, char** argv)
{
    GLFWwindow* window;
    int iter;
    double dt;
    double last_update_time;
    int frame;
    float f;
    GLint uloc_modelview;
    GLint uloc_project;

    GLuint shader_program;

    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
        exit(EXIT_FAILURE);

    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    window = glfwCreateWindow(800, 600, "GLFW OpenGL3 Heightmap demo", NULL, NULL);
    if (! window )
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    /* Register events callback */
    glfwSetKeyCallback(window, key_callback);

    glfwMakeContextCurrent(window);
    gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);

    /* Prepare opengl resources for rendering */
    shader_program = make_shader_program(vertex_shader_text, fragment_shader_text);

    if (shader_program == 0u)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glUseProgram(shader_program);
    uloc_project   = glGetUniformLocation(shader_program, "project");
    uloc_modelview = glGetUniformLocation(shader_program, "modelview");

    /* Compute the projection matrix */
    f = 1.0f / tanf(view_angle / 2.0f);
    projection_matrix[0]  = f / aspect_ratio;
    projection_matrix[5]  = f;
    projection_matrix[10] = (z_far + z_near)/ (z_near - z_far);
    projection_matrix[11] = -1.0f;
    projection_matrix[14] = 2.0f * (z_far * z_near) / (z_near - z_far);
    glUniformMatrix4fv(uloc_project, 1, GL_FALSE, projection_matrix);

    /* Set the camera position */
    modelview_matrix[12]  = -5.0f;
    modelview_matrix[13]  = -5.0f;
    modelview_matrix[14]  = -20.0f;
    glUniformMatrix4fv(uloc_modelview, 1, GL_FALSE, modelview_matrix);

    /* Create mesh data */
    init_map();
    make_mesh(shader_program);

    /* Create vao + vbo to store the mesh */
    /* Create the vbo to store all the information for the grid and the height */

    /* setup the scene ready for rendering */
    glViewport(0, 0, 800, 600);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    /* main loop */
    frame = 0;
    iter = 0;
    last_update_time = glfwGetTime();

    while (!glfwWindowShouldClose(window))
    {
        ++frame;
        /* render the next frame */
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawElements(GL_LINES, 2* MAP_NUM_LINES , GL_UNSIGNED_INT, 0);

        /* display and process events through callbacks */
        glfwSwapBuffers(window);
        glfwPollEvents();
        /* Check the frame rate and update the heightmap if needed */
        dt = glfwGetTime();
        if ((dt - last_update_time) > 0.2)
        {
            /* generate the next iteration of the heightmap */
            if (iter < MAX_ITER)
            {
                update_map(NUM_ITER_AT_A_TIME);
                update_mesh();
                iter += NUM_ITER_AT_A_TIME;
            }
            last_update_time = dt;
            frame = 0;
        }
    }

    glfwTerminate();
    exit(EXIT_SUCCESS);
}
Beispiel #17
0
    void box::set_z(float z)
    {
        position.set_z(z);

        update_mesh();
    }
Beispiel #18
0
    void box::set_size(const math::vector<float, 3>& size)
    {
        this->size = size;

        update_mesh();
    }
Beispiel #19
0
    void box::set_length(float length)
    {
        size.set_x(length);

        update_mesh();
    }
Beispiel #20
0
int main(int argc, char** argv)
{
    GLFWwindow window;
    int ch, iter;
    double dt;
    double last_update_time;
    int frame;
    float f;
    GLint uloc_modelview;
    GLint uloc_project;

    char* vertex_shader_path = NULL;
    char* fragment_shader_path = NULL;
    char* vertex_shader_src = NULL;
    char* fragment_shader_src = NULL;
    GLuint shader_program;

    while ((ch = getopt(argc, argv, "f:v:h")) != -1)
    {
        switch (ch)
        {
            case 'f':
                fragment_shader_path = optarg;
                break;
            case 'v':
                vertex_shader_path = optarg;
                break;
            case 'h':
                usage();
                exit(EXIT_SUCCESS);
            default:
                usage();
                exit(EXIT_FAILURE);
        }
    }

    if (fragment_shader_path)
    {
        vertex_shader_src = read_file_content(fragment_shader_path);
        if (!fragment_shader_src)
        {
            fprintf(stderr,
                    "ERROR: unable to load fragment shader from '%s'\n",
                    fragment_shader_path);
            exit(EXIT_FAILURE);
        }
    }

    if (vertex_shader_path)
    {
        vertex_shader_src = read_file_content(vertex_shader_path);
        if (!vertex_shader_src)
        {
            fprintf(stderr,
                    "ERROR: unable to load vertex shader from '%s'\n",
                    fragment_shader_path);
            exit(EXIT_FAILURE);
        }
    }

    if (!glfwInit())
    {
        fprintf(stderr, "ERROR: Unable to initialize GLFW\n");
        usage();

        free(vertex_shader_src);
        free(fragment_shader_src);
        exit(EXIT_FAILURE);
    }

    glfwOpenWindowHint(GLFW_WINDOW_RESIZABLE, GL_FALSE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2);
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);

    window = glfwOpenWindow(800, 600, GLFW_WINDOWED, "GLFW OpenGL3 Heightmap demo", NULL);
    if (! window )
    {
        fprintf(stderr, "ERROR: Unable to create the OpenGL context and associated window\n");
        usage();

        free(vertex_shader_src);
        free(fragment_shader_src);
        exit(EXIT_FAILURE);
    }
    glfwSetWindowCloseCallback(window_close_callback);
    glfwSetKeyCallback(key_callback);
    /* Register events callback */

    if (GL_TRUE != init_opengl())
    {
        fprintf(stderr, "ERROR: unable to resolve OpenGL function pointers\n");
        free(vertex_shader_src);
        free(fragment_shader_src);
        exit(EXIT_FAILURE);
    }
    /* Prepare opengl resources for rendering */
    shader_program = make_shader_program(vertex_shader_src , fragment_shader_src);
    free(vertex_shader_src);
    free(fragment_shader_src);

    if (shader_program == 0u)
    {
        fprintf(stderr, "ERROR: during creation of the shader program\n");
        usage();
        exit(EXIT_FAILURE);
    }

    pglUseProgram(shader_program);
    uloc_project   = pglGetUniformLocation(shader_program, "project");
    uloc_modelview = pglGetUniformLocation(shader_program, "modelview");

    /* Compute the projection matrix */
    f = 1.0f / tanf(view_angle / 2.0f);
    projection_matrix[0]  = f / aspect_ratio;
    projection_matrix[5]  = f;
    projection_matrix[10] = (z_far + z_near)/ (z_near - z_far);
    projection_matrix[11] = -1.0f;
    projection_matrix[14] = 2.0f * (z_far * z_near) / (z_near - z_far);
    pglUniformMatrix4fv(uloc_project, 1, GL_FALSE, projection_matrix);

    /* Set the camera position */
    modelview_matrix[12]  = -5.0f;
    modelview_matrix[13]  = -5.0f;
    modelview_matrix[14]  = -20.0f;
    pglUniformMatrix4fv(uloc_modelview, 1, GL_FALSE, modelview_matrix);

    /* Create mesh data */
    init_map();
    make_mesh(shader_program);

    /* Create vao + vbo to store the mesh */
    /* Create the vbo to store all the information for the grid and the height */

    /* setup the scene ready for rendering */
    glViewport(0, 0, 800, 600);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    /* main loop */
    frame = 0;
    iter = 0;
    dt = last_update_time = glfwGetTime();

    while (running)
    {
        ++frame;
        /* render the next frame */
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawElements(GL_LINES, 2* MAP_NUM_LINES , GL_UNSIGNED_INT, 0);

        /* display and process events through callbacks */
        glfwSwapBuffers();
        glfwPollEvents();
        /* Check the frame rate and update the heightmap if needed */
        dt = glfwGetTime();
        if ((dt - last_update_time) > 0.2)
        {
            /* generate the next iteration of the heightmap */
            if (iter < MAX_ITER)
            {
                update_map(NUM_ITER_AT_A_TIME);
                update_mesh();
                iter += NUM_ITER_AT_A_TIME;
            }
            last_update_time = dt;
            frame = 0;
        }
    }

    exit(EXIT_SUCCESS);
}
Beispiel #21
0
void World::process_completed_chunk_update(decltype(ChunkUpdateArray::value_type::first)& chunk_update)
{
	auto chunk = get_chunk(chunk_update->get_x(), chunk_update->get_y(), chunk_update->get_z());

	if (!chunk)
	{
		// Chunk has been unloaded while we were updating it's data
		return;
	}

	chunk->update_mesh(chunk_update->get_vertices().data(), chunk_update->get_indices().data(), chunk_update->get_num_vertices(), chunk_update->get_num_indices());

	// If this chunk has just been filled, we need to update any adjacent chunks that are now
	// completely surrounded. This is to achieve full obstruction culling for those chunks.

	auto update_chunk_if_surrounded = [this](int chunk_x, int chunk_y, int chunk_z)
	{
		Chunk* chunk = get_chunk(chunk_x, chunk_y, chunk_z);

		if (!chunk)
		{
			return;
		}

		Chunk* adjacent = get_chunk(chunk_x - 1, chunk_y, chunk_z);
		if (adjacent && !adjacent->filled())
		{
			return;
		}

		adjacent = get_chunk(chunk_x + 1, chunk_y, chunk_z);
		if (adjacent && !adjacent->filled())
		{
			return;
		}

		adjacent = get_chunk(chunk_x, chunk_y - 1, chunk_z);
		if (adjacent && !adjacent->filled())
		{
			return;
		}

		adjacent = get_chunk(chunk_x, chunk_y + 1, chunk_z);
		if (adjacent && !adjacent->filled())
		{
			return;
		}

		adjacent = get_chunk(chunk_x, chunk_y, chunk_z - 1);
		if (adjacent && !adjacent->filled())
		{
			return;
		}

		adjacent = get_chunk(chunk_x, chunk_y, chunk_z + 1);
		if (adjacent && !adjacent->filled())
		{
			return;
		}

		chunk->set_up_to_date(false);
	};

	if (!chunk->filled())
	{
		chunk->set_filled(true);

		update_chunk_if_surrounded(chunk->get_x() - 1, chunk->get_y(), chunk->get_z());
		update_chunk_if_surrounded(chunk->get_x() + 1, chunk->get_y(), chunk->get_z());
		update_chunk_if_surrounded(chunk->get_x(), chunk->get_y() - 1, chunk->get_z());
		update_chunk_if_surrounded(chunk->get_x(), chunk->get_y() + 1, chunk->get_z());
		update_chunk_if_surrounded(chunk->get_x(), chunk->get_y(), chunk->get_z() - 1);
		update_chunk_if_surrounded(chunk->get_x(), chunk->get_y(), chunk->get_z() + 1);
	}

	if (!chunk->reupdate())
	{
		chunk->set_up_to_date(true);
	}
	
	chunk->set_update_queued(false);
	chunk->set_low_priority_update(false);
}