From 3f3d2e6b5782da00c529afef4e6ff1906d759a3b Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Tue, 14 Jan 2025 18:18:56 -0600 Subject: [PATCH] remove Quadtree and IntList --- meson.build | 2 +- source/IntList.c | 118 ------------ source/IntList.h | 90 --------- source/Quadtree.c | 457 ---------------------------------------------- source/Quadtree.h | 83 --------- source/jsffi.c | 64 ------- 6 files changed, 1 insertion(+), 813 deletions(-) delete mode 100644 source/IntList.c delete mode 100644 source/IntList.h delete mode 100644 source/Quadtree.c delete mode 100644 source/Quadtree.h diff --git a/meson.build b/meson.build index 1cf242c0..be15f90c 100644 --- a/meson.build +++ b/meson.build @@ -89,7 +89,7 @@ if get_option('enet') endif sources = [] -src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','warp.c','yugine.c', 'wildmatch.c', 'sprite.c', 'quadtree.c', 'aabb.c', 'Quadtree.c', 'IntList.c', 'rtree.c'] +src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','warp.c','yugine.c', 'wildmatch.c', 'sprite.c', 'quadtree.c', 'aabb.c', 'rtree.c'] imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp', 'imgui_impl_sdlrenderer3.cpp', 'imgui_impl_sdl3.cpp', 'imgui_impl_sdlgpu3.cpp'] diff --git a/source/IntList.c b/source/IntList.c deleted file mode 100644 index daef4b33..00000000 --- a/source/IntList.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This code was initially authored by the Stackoverflow user dragon-energy and posted under following page: - * https://stackoverflow.com/questions/41946007/efficient-and-well-explained-implementation-of-a-quadtree-for-2d-collision-det - * - * As for the license, the author has kindly noted: - * - * "Oh and feel free to use this code I post however you want, even for commercial projects. - * I would really love it if people let me know if they find it useful, but do as you wish." - * - * And generally all Stackoverflow-posted code is by default licensed with CC BY-SA 4.0: - * https://creativecommons.org/licenses/by-sa/4.0/ - */ - -#include "IntList.h" -#include -#include -#include - -void il_create(IntList* il, int num_fields) -{ - il->data = il->fixed; - il->num = 0; - il->cap = il_fixed_cap; - il->num_fields = num_fields; - il->free_element = -1; -} - -void il_destroy(IntList* il) -{ - // Free the buffer only if it was heap allocated. - if (il->data != il->fixed) - free(il->data); -} - -void il_clear(IntList* il) -{ - il->num = 0; - il->free_element = -1; -} - -int il_size(const IntList* il) -{ - return il->num; -} - -int il_get(const IntList* il, int n, int field) -{ - assert(n >= 0 && n < il->num); - return il->data[n*il->num_fields + field]; -} - -void il_set(IntList* il, int n, int field, int val) -{ - assert(n >= 0 && n < il->num); - il->data[n*il->num_fields + field] = val; -} - -int il_push_back(IntList* il) -{ - const int new_pos = (il->num+1) * il->num_fields; - - // If the list is full, we need to reallocate the buffer to make room - // for the new element. - if (new_pos > il->cap) - { - // Use double the size for the new capacity. - const int new_cap = new_pos * 2; - - // If we're pointing to the fixed buffer, allocate a new array on the - // heap and copy the fixed buffer contents to it. - if (il->cap == il_fixed_cap) - { - il->data = malloc(new_cap * sizeof(*il->data)); - memcpy(il->data, il->fixed, sizeof(il->fixed)); - } - else - { - // Otherwise reallocate the heap buffer to the new size. - il->data = realloc(il->data, new_cap * sizeof(*il->data)); - } - // Set the old capacity to the new capacity. - il->cap = new_cap; - } - return il->num++; -} - -void il_pop_back(IntList* il) -{ - // Just decrement the list size. - assert(il->num > 0); - --il->num; -} - -int il_insert(IntList* il) -{ - // If there's a free index in the free list, pop that and use it. - if (il->free_element != -1) - { - const int index = il->free_element; - const int pos = index * il->num_fields; - - // Set the free index to the next free index. - il->free_element = il->data[pos]; - - // Return the free index. - return index; - } - // Otherwise insert to the back of the array. - return il_push_back(il); -} - -void il_erase(IntList* il, int n) -{ - // Push the element to the free list. - const int pos = n * il->num_fields; - il->data[pos] = il->free_element; - il->free_element = n; -} \ No newline at end of file diff --git a/source/IntList.h b/source/IntList.h deleted file mode 100644 index ee685ad8..00000000 --- a/source/IntList.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This code was initially authored by the Stackoverflow user dragon-energy and posted under following page: - * https://stackoverflow.com/questions/41946007/efficient-and-well-explained-implementation-of-a-quadtree-for-2d-collision-det - * - * As for the license, the author has kindly noted: - * - * "Oh and feel free to use this code I post however you want, even for commercial projects. - * I would really love it if people let me know if they find it useful, but do as you wish." - * - * And generally all Stackoverflow-posted code is by default licensed with CC BY-SA 4.0: - * https://creativecommons.org/licenses/by-sa/4.0/ - */ - -#ifndef INT_LIST_H -#define INT_LIST_H - -#ifdef __cplusplus -#define IL_FUNC extern "C" -#else -#define IL_FUNC -#endif - -typedef struct IntList IntList; -enum {il_fixed_cap = 128}; - -struct IntList -{ - // Stores a fixed-size buffer in advance to avoid requiring - // a heap allocation until we run out of space. - int fixed[il_fixed_cap]; - - // Points to the buffer used by the list. Initially this will - // point to 'fixed'. - int* data; - - // Stores how many integer fields each element has. - int num_fields; - - // Stores the number of elements in the list. - int num; - - // Stores the capacity of the array. - int cap; - - // Stores an index to the free element or -1 if the free list - // is empty. - int free_element; -}; - -// --------------------------------------------------------------------------------- -// List Interface -// --------------------------------------------------------------------------------- -// Creates a new list of elements which each consist of integer fields. -// 'num_fields' specifies the number of integer fields each element has. -IL_FUNC void il_create(IntList* il, int num_fields); - -// Destroys the specified list. -IL_FUNC void il_destroy(IntList* il); - -// Returns the number of elements in the list. -IL_FUNC int il_size(const IntList* il); - -// Returns the value of the specified field for the nth element. -IL_FUNC int il_get(const IntList* il, int n, int field); - -// Sets the value of the specified field for the nth element. -IL_FUNC void il_set(IntList* il, int n, int field, int val); - -// Clears the specified list, making it empty. -IL_FUNC void il_clear(IntList* il); - -// --------------------------------------------------------------------------------- -// Stack Interface (do not mix with free list usage; use one or the other) -// --------------------------------------------------------------------------------- -// Inserts an element to the back of the list and returns an index to it. -IL_FUNC int il_push_back(IntList* il); - -// Removes the element at the back of the list. -IL_FUNC void il_pop_back(IntList* il); - -// --------------------------------------------------------------------------------- -// Free List Interface (do not mix with stack usage; use one or the other) -// --------------------------------------------------------------------------------- -// Inserts an element to a vacant position in the list and returns an index to it. -IL_FUNC int il_insert(IntList* il); - -// Removes the nth element in the list. -IL_FUNC void il_erase(IntList* il, int n); - -#endif \ No newline at end of file diff --git a/source/Quadtree.c b/source/Quadtree.c deleted file mode 100644 index 15407ea0..00000000 --- a/source/Quadtree.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * This code was initially authored by the Stackoverflow user dragon-energy and posted under following page: - * https://stackoverflow.com/questions/41946007/efficient-and-well-explained-implementation-of-a-quadtree-for-2d-collision-det - * - * As for the license, the author has kindly noted: - * - * "Oh and feel free to use this code I post however you want, even for commercial projects. - * I would really love it if people let me know if they find it useful, but do as you wish." - * - * And generally all Stackoverflow-posted code is by default licensed with CC BY-SA 4.0: - * https://creativecommons.org/licenses/by-sa/4.0/ - */ - -#include "Quadtree.h" -#include -#include "string.h" - -enum -{ - // ---------------------------------------------------------------------------------------- - // Element node fields: - // ---------------------------------------------------------------------------------------- - enode_num = 2, - - // Points to the next element in the leaf node. A value of -1 - // indicates the end of the list. - enode_idx_next = 0, - - // Stores the element index. - enode_idx_elt = 1, - - // ---------------------------------------------------------------------------------------- - // Element fields: - // ---------------------------------------------------------------------------------------- - elt_num = 5, - - // Stores the rectangle encompassing the element. - elt_idx_lft = 0, elt_idx_top = 1, elt_idx_rgt = 2, elt_idx_btm = 3, - - // Stores the ID of the element. - elt_idx_id = 4, - - // ---------------------------------------------------------------------------------------- - // Node fields: - // ---------------------------------------------------------------------------------------- - node_num = 2, - - // Points to the first child if this node is a branch or the first element - // if this node is a leaf. - node_idx_fc = 0, - - // Stores the number of elements in the node or -1 if it is not a leaf. - node_idx_num = 1, - - // ---------------------------------------------------------------------------------------- - // Node data fields: - // ---------------------------------------------------------------------------------------- - nd_num = 6, - - // Stores the extents of the node using a centered rectangle and half-size. - nd_idx_mx = 0, nd_idx_my = 1, nd_idx_sx = 2, nd_idx_sy = 3, - - // Stores the index of the node. - nd_idx_index = 4, - - // Stores the depth of the node. - nd_idx_depth = 5, -}; - -static void node_insert(Quadtree* qt, int index, int depth, int mx, int my, int sx, int sy, int element); - -static int intersect(int l1, int t1, int r1, int b1, - int l2, int t2, int r2, int b2) -{ - return l2 <= r1 && r2 >= l1 && t2 <= b1 && b2 >= t1; -} - -void leaf_insert(Quadtree* qt, int node, int depth, int mx, int my, int sx, int sy, int element) -{ - // Insert the element node to the leaf. - const int nd_fc = il_get(&qt->nodes, node, node_idx_fc); - il_set(&qt->nodes, node, node_idx_fc, il_insert(&qt->enodes)); - il_set(&qt->enodes, il_get(&qt->nodes, node, node_idx_fc), enode_idx_next, nd_fc); - il_set(&qt->enodes, il_get(&qt->nodes, node, node_idx_fc), enode_idx_elt, element); - - // If the leaf is full, split it. - if (il_get(&qt->nodes, node, node_idx_num) == qt->max_elements && depth < qt->max_depth) - { - int fc = 0, j = 0; - IntList elts = {0}; - il_create(&elts, 1); - - // Transfer elements from the leaf node to a list of elements. - while (il_get(&qt->nodes, node, node_idx_fc) != -1) - { - const int index = il_get(&qt->nodes, node, node_idx_fc); - const int next_index = il_get(&qt->enodes, index, enode_idx_next); - const int elt = il_get(&qt->enodes, index, enode_idx_elt); - - // Pop off the element node from the leaf and remove it from the qt. - il_set(&qt->nodes, node, node_idx_fc, next_index); - il_erase(&qt->enodes, index); - - // Insert element to the list. - il_set(&elts, il_push_back(&elts), 0, elt); - } - - // Start by allocating 4 child nodes. - fc = il_insert(&qt->nodes); - il_insert(&qt->nodes); - il_insert(&qt->nodes); - il_insert(&qt->nodes); - il_set(&qt->nodes, node, node_idx_fc, fc); - - // Initialize the new child nodes. - for (j=0; j < 4; ++j) - { - il_set(&qt->nodes, fc+j, node_idx_fc, -1); - il_set(&qt->nodes, fc+j, node_idx_num, 0); - } - - // Transfer the elements in the former leaf node to its new children. - il_set(&qt->nodes, node, node_idx_num, -1); - for (j=0; j < il_size(&elts); ++j) - node_insert(qt, node, depth, mx, my, sx, sy, il_get(&elts, j, 0)); - il_destroy(&elts); - } - else - { - // Increment the leaf element count. - il_set(&qt->nodes, node, node_idx_num, il_get(&qt->nodes, node, node_idx_num) + 1); - } -} - -static void push_node(IntList* nodes, int nd_index, int nd_depth, int nd_mx, int nd_my, int nd_sx, int nd_sy) -{ - const int back_idx = il_push_back(nodes); - il_set(nodes, back_idx, nd_idx_mx, nd_mx); - il_set(nodes, back_idx, nd_idx_my, nd_my); - il_set(nodes, back_idx, nd_idx_sx, nd_sx); - il_set(nodes, back_idx, nd_idx_sy, nd_sy); - il_set(nodes, back_idx, nd_idx_index, nd_index); - il_set(nodes, back_idx, nd_idx_depth, nd_depth); -} - -static void find_leaves(IntList* out, const Quadtree* qt, int node, int depth, - int mx, int my, int sx, int sy, - int lft, int top, int rgt, int btm) -{ - IntList to_process = {0}; - il_create(&to_process, nd_num); - push_node(&to_process, node, depth, mx, my, sx, sy); - - while (il_size(&to_process) > 0) - { - const int back_idx = il_size(&to_process) - 1; - const int nd_mx = il_get(&to_process, back_idx, nd_idx_mx); - const int nd_my = il_get(&to_process, back_idx, nd_idx_my); - const int nd_sx = il_get(&to_process, back_idx, nd_idx_sx); - const int nd_sy = il_get(&to_process, back_idx, nd_idx_sy); - const int nd_index = il_get(&to_process, back_idx, nd_idx_index); - const int nd_depth = il_get(&to_process, back_idx, nd_idx_depth); - il_pop_back(&to_process); - - // If this node is a leaf, insert it to the list. - if (il_get(&qt->nodes, nd_index, node_idx_num) != -1) - push_node(out, nd_index, nd_depth, nd_mx, nd_my, nd_sx, nd_sy); - else - { - // Otherwise push the children that intersect the rectangle. - const int fc = il_get(&qt->nodes, nd_index, node_idx_fc); - const int hx = nd_sx >> 1, hy = nd_sy >> 1; - const int l = nd_mx-hx, t = nd_my-hy, r = nd_mx+hx, b = nd_my+hy; - - if (top <= nd_my) - { - if (lft <= nd_mx) - push_node(&to_process, fc+0, nd_depth+1, l,t,hx,hy); - if (rgt > nd_mx) - push_node(&to_process, fc+1, nd_depth+1, r,t,hx,hy); - } - if (btm > nd_my) - { - if (lft <= nd_mx) - push_node(&to_process, fc+2, nd_depth+1, l,b,hx,hy); - if (rgt > nd_mx) - push_node(&to_process, fc+3, nd_depth+1, r,b,hx,hy); - } - } - } - il_destroy(&to_process); -} - -static void node_insert(Quadtree* qt, int index, int depth, int mx, int my, int sx, int sy, int element) -{ - // Find the leaves and insert the element to all the leaves found. - int j = 0; - IntList leaves = {0}; - - const int lft = il_get(&qt->elts, element, elt_idx_lft); - const int top = il_get(&qt->elts, element, elt_idx_top); - const int rgt = il_get(&qt->elts, element, elt_idx_rgt); - const int btm = il_get(&qt->elts, element, elt_idx_btm); - - il_create(&leaves, nd_num); - find_leaves(&leaves, qt, index, depth, mx, my, sx, sy, lft, top, rgt, btm); - for (j=0; j < il_size(&leaves); ++j) - { - const int nd_mx = il_get(&leaves, j, nd_idx_mx); - const int nd_my = il_get(&leaves, j, nd_idx_my); - const int nd_sx = il_get(&leaves, j, nd_idx_sx); - const int nd_sy = il_get(&leaves, j, nd_idx_sy); - const int nd_index = il_get(&leaves, j, nd_idx_index); - const int nd_depth = il_get(&leaves, j, nd_idx_depth); - leaf_insert(qt, nd_index, nd_depth, nd_mx, nd_my, nd_sx, nd_sy, element); - } - il_destroy(&leaves); -} - -void qt_create(Quadtree* qt, int x1, int y1, int x2, int y2, int max_elements, int max_depth) -{ - qt->max_elements = max_elements; - qt->max_depth = max_depth; - qt->temp = 0; - qt->temp_size = 0; - il_create(&qt->nodes, node_num); - il_create(&qt->elts, elt_num); - il_create(&qt->enodes, enode_num); - - // Insert the root node to the qt. - il_insert(&qt->nodes); - il_set(&qt->nodes, 0, node_idx_fc, -1); - il_set(&qt->nodes, 0, node_idx_num, 0); - - int half_width = (x2-x1) >> 1; - int half_height = (y2-y1) >> 1; - qt->root_sx = half_width; - qt->root_sy = half_height; - - // Center - qt->root_mx = x1 + half_width; - qt->root_my = y1 + half_height; -} - -void qt_destroy(Quadtree* qt) -{ - il_destroy(&qt->nodes); - il_destroy(&qt->elts); - il_destroy(&qt->enodes); - free(qt->temp); -} - -int qt_insert(Quadtree* qt, int id, int x1, int y1, int x2, int y2) -{ - // Insert a new element. - const int new_element = il_insert(&qt->elts); - - // Set the fields of the new element. - il_set(&qt->elts, new_element, elt_idx_lft, x1); - il_set(&qt->elts, new_element, elt_idx_top, y1); - il_set(&qt->elts, new_element, elt_idx_rgt, x2); - il_set(&qt->elts, new_element, elt_idx_btm, y2); - il_set(&qt->elts, new_element, elt_idx_id, id); - - // Insert the element to the appropriate leaf node(s). - node_insert(qt, 0, 0, qt->root_mx, qt->root_my, qt->root_sx, qt->root_sy, new_element); - return new_element; -} - -void qt_remove(Quadtree* qt, int element) -{ - // Find the leaves. - int j = 0; - IntList leaves = {0}; - - const int lft = il_get(&qt->elts, element, elt_idx_lft); - const int top = il_get(&qt->elts, element, elt_idx_top); - const int rgt = il_get(&qt->elts, element, elt_idx_rgt); - const int btm = il_get(&qt->elts, element, elt_idx_btm); - - il_create(&leaves, nd_num); - find_leaves(&leaves, qt, 0, 0, qt->root_mx, qt->root_my, qt->root_sx, qt->root_sy, lft, top, rgt, btm); - - // For each leaf node, remove the element node. - for (j=0; j < il_size(&leaves); ++j) - { - const int nd_index = il_get(&leaves, j, nd_idx_index); - - // Walk the list until we find the element node. - int node_index = il_get(&qt->nodes, nd_index, node_idx_fc); - int prev_index = -1; - while (node_index != -1 && il_get(&qt->enodes, node_index, enode_idx_elt) != element) - { - prev_index = node_index; - node_index = il_get(&qt->enodes, node_index, enode_idx_next); - } - - if (node_index != -1) - { - // Remove the element node. - const int next_index = il_get(&qt->enodes, node_index, enode_idx_next); - if (prev_index == -1) - il_set(&qt->nodes, nd_index, node_idx_fc, next_index); - else - il_set(&qt->enodes, prev_index, enode_idx_next, next_index); - il_erase(&qt->enodes, node_index); - - // Decrement the leaf element count. - il_set(&qt->nodes, nd_index, node_idx_num, il_get(&qt->nodes, nd_index, node_idx_num)-1); - } - } - il_destroy(&leaves); - - // Remove the element. - il_erase(&qt->elts, element); -} - -void qt_query(Quadtree* qt, IntList* out, int qlft, int qtop, int qrgt, int qbtm, int omit_element) -{ - // Find the leaves that intersect the specified query rectangle. - int j = 0; - IntList leaves = {0}; - const int elt_cap = il_size(&qt->elts); - - if (qt->temp_size < elt_cap) - { - qt->temp_size = elt_cap; - qt->temp = realloc(qt->temp, qt->temp_size * sizeof(*qt->temp)); - memset(qt->temp, 0, qt->temp_size * sizeof(*qt->temp)); - } - - // For each leaf node, look for elements that intersect. - il_create(&leaves, nd_num); - find_leaves(&leaves, qt, 0, 0, qt->root_mx, qt->root_my, qt->root_sx, qt->root_sy, qlft, qtop, qrgt, qbtm); - - il_clear(out); - for (j=0; j < il_size(&leaves); ++j) - { - const int nd_index = il_get(&leaves, j, nd_idx_index); - - // Walk the list and add elements that intersect. - int elt_node_index = il_get(&qt->nodes, nd_index, node_idx_fc); - while (elt_node_index != -1) - { - const int element = il_get(&qt->enodes, elt_node_index, enode_idx_elt); - const int lft = il_get(&qt->elts, element, elt_idx_lft); - const int top = il_get(&qt->elts, element, elt_idx_top); - const int rgt = il_get(&qt->elts, element, elt_idx_rgt); - const int btm = il_get(&qt->elts, element, elt_idx_btm); - if (!qt->temp[element] && element != omit_element && intersect(qlft,qtop,qrgt,qbtm, lft,top,rgt,btm)) - { - il_set(out, il_push_back(out), 0, element); - qt->temp[element] = 1; - } - elt_node_index = il_get(&qt->enodes, elt_node_index, enode_idx_next); - } - } - il_destroy(&leaves); - - // Unmark the elements that were inserted. - for (j=0; j < il_size(out); ++j) - qt->temp[il_get(out, j, 0)] = 0; -} - -void qt_cleanup(Quadtree* qt) -{ - IntList to_process = {0}; - il_create(&to_process, 1); - - // Only process the root if it's not a leaf. - if (il_get(&qt->nodes, 0, node_idx_num) == -1) - { - // Push the root index to the stack. - il_set(&to_process, il_push_back(&to_process), 0, 0); - } - - while (il_size(&to_process) > 0) - { - // Pop a node from the stack. - const int node = il_get(&to_process, il_size(&to_process)-1, 0); - const int fc = il_get(&qt->nodes, node, node_idx_fc); - int num_empty_leaves = 0; - int j = 0; - il_pop_back(&to_process); - - // Loop through the children. - for (j=0; j < 4; ++j) - { - const int child = fc + j; - - // Increment empty leaf count if the child is an empty - // leaf. Otherwise if the child is a branch, add it to - // the stack to be processed in the next iteration. - if (il_get(&qt->nodes, child, node_idx_num) == 0) - ++num_empty_leaves; - else if (il_get(&qt->nodes, child, node_idx_num) == -1) - { - // Push the child index to the stack. - il_set(&to_process, il_push_back(&to_process), 0, child); - } - } - - // If all the children were empty leaves, remove them and - // make this node the new empty leaf. - if (num_empty_leaves == 4) - { - // Remove all 4 children in reverse order so that they - // can be reclaimed on subsequent insertions in proper - // order. - il_erase(&qt->nodes, fc + 3); - il_erase(&qt->nodes, fc + 2); - il_erase(&qt->nodes, fc + 1); - il_erase(&qt->nodes, fc + 0); - - // Make this node the new empty leaf. - il_set(&qt->nodes, node, node_idx_fc, -1); - il_set(&qt->nodes, node, node_idx_num, 0); - } - } - il_destroy(&to_process); -} - -void qt_traverse(Quadtree* qt, void* user_data, QtNodeFunc* branch, QtNodeFunc* leaf) -{ - IntList to_process = {0}; - il_create(&to_process, nd_num); - push_node(&to_process, 0, 0, qt->root_mx, qt->root_my, qt->root_sx, qt->root_sy); - - while (il_size(&to_process) > 0) - { - const int back_idx = il_size(&to_process) - 1; - const int nd_mx = il_get(&to_process, back_idx, nd_idx_mx); - const int nd_my = il_get(&to_process, back_idx, nd_idx_my); - const int nd_sx = il_get(&to_process, back_idx, nd_idx_sx); - const int nd_sy = il_get(&to_process, back_idx, nd_idx_sy); - const int nd_index = il_get(&to_process, back_idx, nd_idx_index); - const int nd_depth = il_get(&to_process, back_idx, nd_idx_depth); - const int fc = il_get(&qt->nodes, nd_index, node_idx_fc); - il_pop_back(&to_process); - - if (il_get(&qt->nodes, nd_index, node_idx_num) == -1) - { - // Push the children of the branch to the stack. - const int hx = nd_sx >> 1, hy = nd_sy >> 1; - const int l = nd_mx-hx, t = nd_my-hy, r = nd_mx+hx, b = nd_my+hy; - push_node(&to_process, fc+0, nd_depth+1, l,t, hx,hy); - push_node(&to_process, fc+1, nd_depth+1, r,t, hx,hy); - push_node(&to_process, fc+2, nd_depth+1, l,b, hx,hy); - push_node(&to_process, fc+3, nd_depth+1, r,b, hx,hy); - if (branch) - branch(qt, user_data, nd_index, nd_depth, nd_mx, nd_my, nd_sx, nd_sy); - } - else if (leaf) - leaf(qt, user_data, nd_index, nd_depth, nd_mx, nd_my, nd_sx, nd_sy); - } - il_destroy(&to_process); -} \ No newline at end of file diff --git a/source/Quadtree.h b/source/Quadtree.h deleted file mode 100644 index caf31ba0..00000000 --- a/source/Quadtree.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This code was initially authored by the Stackoverflow user dragon-energy and posted under following page: - * https://stackoverflow.com/questions/41946007/efficient-and-well-explained-implementation-of-a-quadtree-for-2d-collision-det - * - * As for the license, the author has kindly noted: - * - * "Oh and feel free to use this code I post however you want, even for commercial projects. - * I would really love it if people let me know if they find it useful, but do as you wish." - * - * And generally all Stackoverflow-posted code is by default licensed with CC BY-SA 4.0: - * https://creativecommons.org/licenses/by-sa/4.0/ - */ - -#ifndef QUADTREE_H -#define QUADTREE_H - -#include "IntList.h" - -#ifdef __cplusplus -#define QTREE_FUNC extern "C" -#else -#define QTREE_FUNC -#endif - -typedef struct Quadtree Quadtree; - -struct Quadtree -{ - // Stores all the nodes in the quadtree. The first node in this - // sequence is always the root. - IntList nodes; - - // Stores all the elements in the quadtree. - IntList elts; - - // Stores all the element nodes in the quadtree. - IntList enodes; - - // Stores the quadtree extents. - int root_mx, root_my, root_sx, root_sy; - - // Maximum allowed elements in a leaf before the leaf is subdivided/split unless - // the leaf is at the maximum allowed tree depth. - int max_elements; - - // Stores the maximum depth allowed for the quadtree. - int max_depth; - - // Temporary buffer used for queries. - - char* temp; - - // Stores the size of the temporary buffer. - int temp_size; -}; - -// Function signature used for traversing a tree node. -typedef void QtNodeFunc(Quadtree* qt, void* user_data, int node, int depth, int mx, int my, int sx, int sy); - -// Creates a quadtree with the requested extents, maximum elements per leaf, and maximum tree depth. -QTREE_FUNC void qt_create(Quadtree* qt, int x1, int y1, int x2, int y2, int max_elements, int max_depth); - -// Destroys the quadtree. -QTREE_FUNC void qt_destroy(Quadtree* qt); - -// Inserts a new element to the tree. -// Returns an index to the new element. -QTREE_FUNC int qt_insert(Quadtree* qt, int id, int x1, int y1, int x2, int y2); - -// Removes the specified element from the tree. -QTREE_FUNC void qt_remove(Quadtree* qt, int element); - -// Cleans up the tree, removing empty leaves. -QTREE_FUNC void qt_cleanup(Quadtree* qt); - -// Outputs a list of elements found in the specified rectangle. -QTREE_FUNC void qt_query(Quadtree* qt, IntList* out, int x1, int y1, int x2, int y2, int omit_element); - -// Traverses all the nodes in the tree, calling 'branch' for branch nodes and 'leaf' -// for leaf nodes. -QTREE_FUNC void qt_traverse(Quadtree* qt, void* user_data, QtNodeFunc* branch, QtNodeFunc* leaf); - -#endif \ No newline at end of file diff --git a/source/jsffi.c b/source/jsffi.c index abda9b37..c08acbb8 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -34,7 +34,6 @@ #include "sprite.h" #include "quadtree.h" -#include "Quadtree.h" #include "rtree.h" typedef struct rtree rtree; @@ -1165,13 +1164,6 @@ void qtree_free(JSRuntime *rt, qtree *tree) QJSCLASS(qtree) -void Quadtree_free(JSRuntime *rt, Quadtree *tree) -{ - qt_destroy(tree); -} - -QJSCLASS(Quadtree) - void rtree_free(JSRuntime *rt, rtree *tree) { rtree_destroy(tree); @@ -7158,16 +7150,6 @@ JSC_CCALL(os_make_quadtree, return qtree2js(js,tree); ) -struct { int key; JSValue value; } *qthash = NULL; - -JSC_CCALL(os_make_qtree, - hmdefault(qthash, JS_UNDEFINED); - rect area = js2rect(js,argv[0]); - Quadtree *tree = malloc(sizeof(*tree)); - qt_create(tree, area.x, area.y, area.x+area.w, area.y+area.h, 4, 8); - return Quadtree2js(js,tree); -) - JSC_CCALL(os_make_rtree, struct rtree *tree = rtree_new(); return rtree2js(js,tree); @@ -7190,7 +7172,6 @@ static const JSCFunctionListEntry js_os_funcs[] = { MIST_FUNC_DEF(os, gc, 0), MIST_FUNC_DEF(os, eval, 2), MIST_FUNC_DEF(os, make_quadtree, 1), - MIST_FUNC_DEF(os, make_qtree, 1), MIST_FUNC_DEF(os, make_rtree, 0), MIST_FUNC_DEF(os, make_texture, 1), MIST_FUNC_DEF(os, make_gif, 1), @@ -7275,50 +7256,6 @@ static const JSCFunctionListEntry js_qtree_funcs[] = { MIST_FUNC_DEF(qtree, query, 2), }; - - -JSC_CCALL(Quadtree_insert, - Quadtree *tree = js2Quadtree(js,self); - JSValue v = argv[0]; - rect r; - JS_GETATOM(js,r,v,rect_atom,rect) - int id = (int)JS_VALUE_GET_PTR(v); - int e = qt_insert(tree, id, r.x,r.y,r.x+r.w,r.y+r.h); - hmput(qthash, e, JS_DupValue(js,v)); -) - -JSC_CCALL(Quadtree_remove, - return JS_UNDEFINED; - Quadtree *tree = js2Quadtree(js,self); - int e = js2number(js,argv[0]); - qt_remove(tree, e); - // free jsvalue -) - -JSC_CCALL(Quadtree_query, - Quadtree *tree = js2Quadtree(js,self); - rect area = js2rect(js,argv[0]); - IntList out; - il_create(&out,1); - qt_query(tree,&out,area.x,area.y,area.x+area.w,area.y+area.h,-1); - - ret = JS_NewArray(js); - - int n = 0; - for (int i = 0; i < il_size(&out); i++) { - int id = il_get(&out, i, 0); - JSValue v = hmget(qthash, id); - if (!JS_IsUndefined(v)) - JS_SetPropertyUint32(js,ret,n++,JS_DupValue(js,v)); - } -) - -static const JSCFunctionListEntry js_Quadtree_funcs[] = { - MIST_FUNC_DEF(Quadtree, insert, 1), - MIST_FUNC_DEF(Quadtree, remove, 1), - MIST_FUNC_DEF(Quadtree, query, 1), -}; - JSC_CCALL(rtree_insert, rtree *tree = js2rtree(js,self); JSValue v = argv[0]; @@ -7461,7 +7398,6 @@ void ffi_load(JSContext *js) { JSValue globalThis = JS_GetGlobalObject(js); QJSCLASSPREP_FUNCS(qtree) - QJSCLASSPREP_FUNCS(Quadtree) QJSCLASSPREP_FUNCS(rtree) QJSCLASSPREP_FUNCS(SDL_Window) QJSCLASSPREP_FUNCS(SDL_Surface)