| @@ -1,8 +1,8 @@ | |||||
| // | // | ||||
| // Lol Engine — Simplex Noise tutorial | // Lol Engine — Simplex Noise tutorial | ||||
| // | // | ||||
| // Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // | // | ||||
| // Lol Engine is free software. It comes without any warranty, to | // Lol Engine is free software. It comes without any warranty, to | ||||
| // the extent permitted by applicable law. You can redistribute it | // the extent permitted by applicable law. You can redistribute it | ||||
| @@ -16,6 +16,7 @@ | |||||
| #endif | #endif | ||||
| #include <lol/engine.h> | #include <lol/engine.h> | ||||
| #include <../legacy/lol/math/noise/simplex.h> | |||||
| using namespace lol; | using namespace lol; | ||||
| @@ -16,6 +16,7 @@ | |||||
| #include <lol/engine.h> | #include <lol/engine.h> | ||||
| #include <lol/image/movie.h> | #include <lol/image/movie.h> | ||||
| #include <../legacy/lol/math/noise/perlin.h> | |||||
| #include "loldebug.h" | #include "loldebug.h" | ||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||
| @@ -1 +1 @@ | |||||
| Subproject commit f65ab0fa1e93fe8268a9511095d8a4ea71ae777c | |||||
| Subproject commit 2235ce1635fa404fc8e7f700258de7c0a903136a | |||||
| @@ -31,18 +31,11 @@ liblol_core_headers = \ | |||||
| lol/lua.h \ | lol/lua.h \ | ||||
| \ | \ | ||||
| lol/base/all.h \ | lol/base/all.h \ | ||||
| lol/base/avl_tree.h lol/base/tuple.h lol/base/types.h \ | |||||
| lol/base/array.h lol/base/assert.h lol/base/map.h lol/base/enum.h \ | |||||
| lol/base/tuple.h lol/base/array.h lol/base/map.h lol/base/enum.h \ | |||||
| lol/base/log.h \ | lol/base/log.h \ | ||||
| \ | \ | ||||
| lol/math/all.h \ | |||||
| lol/math/functions.h \ | |||||
| lol/math/geometry.h lol/math/interp.h lol/math/arraynd.h \ | |||||
| lol/math/noise/gradient.h lol/math/noise/perlin.h \ | |||||
| lol/math/noise/simplex.h \ | |||||
| \ | |||||
| lol/algorithm/all.h \ | lol/algorithm/all.h \ | ||||
| lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \ | |||||
| lol/algorithm/sort.h lol/algorithm/portal.h \ | |||||
| \ | \ | ||||
| lol/audio/all.h \ | lol/audio/all.h \ | ||||
| lol/audio/audio.h lol/audio/sample.h \ | lol/audio/audio.h lol/audio/sample.h \ | ||||
| @@ -54,7 +47,7 @@ liblol_core_headers = \ | |||||
| lol/sys/init.h lol/sys/file.h \ | lol/sys/init.h lol/sys/file.h \ | ||||
| \ | \ | ||||
| lol/image/all.h \ | lol/image/all.h \ | ||||
| lol/image/pixel.h lol/image/color.h lol/image/image.h \ | |||||
| lol/image/image.h \ | |||||
| lol/image/resource.h lol/image/movie.h \ | lol/image/resource.h lol/image/movie.h \ | ||||
| \ | \ | ||||
| lol/net/all.h \ | lol/net/all.h \ | ||||
| @@ -235,7 +235,6 @@ | |||||
| <ClInclude Include="loldebug.h" /> | <ClInclude Include="loldebug.h" /> | ||||
| <ClInclude Include="lolgl.h" /> | <ClInclude Include="lolgl.h" /> | ||||
| <ClInclude Include="lolua\baselua.h" /> | <ClInclude Include="lolua\baselua.h" /> | ||||
| <ClInclude Include="lol\algorithm\aabb_tree.h" /> | |||||
| <ClInclude Include="lol\algorithm\all.h" /> | <ClInclude Include="lol\algorithm\all.h" /> | ||||
| <ClInclude Include="lol\algorithm\portal.h" /> | <ClInclude Include="lol\algorithm\portal.h" /> | ||||
| <ClInclude Include="lol\algorithm\sort.h" /> | <ClInclude Include="lol\algorithm\sort.h" /> | ||||
| @@ -244,11 +243,8 @@ | |||||
| <ClInclude Include="lol\audio\sample.h" /> | <ClInclude Include="lol\audio\sample.h" /> | ||||
| <ClInclude Include="lol\base\all.h" /> | <ClInclude Include="lol\base\all.h" /> | ||||
| <ClInclude Include="lol\base\array.h" /> | <ClInclude Include="lol\base\array.h" /> | ||||
| <ClInclude Include="lol\base\assert.h" /> | |||||
| <ClInclude Include="lol\base\enum.h" /> | <ClInclude Include="lol\base\enum.h" /> | ||||
| <ClInclude Include="lol\base\log.h" /> | <ClInclude Include="lol\base\log.h" /> | ||||
| <ClInclude Include="lol\base\map.h" /> | |||||
| <ClInclude Include="lol\base\types.h" /> | |||||
| <ClInclude Include="lol\base\tuple.h" /> | <ClInclude Include="lol\base\tuple.h" /> | ||||
| <ClInclude Include="lol\debug\all.h" /> | <ClInclude Include="lol\debug\all.h" /> | ||||
| <ClInclude Include="lol\debug\lines.h" /> | <ClInclude Include="lol\debug\lines.h" /> | ||||
| @@ -268,20 +264,10 @@ | |||||
| <ClInclude Include="lol\gpu\texture.h" /> | <ClInclude Include="lol\gpu\texture.h" /> | ||||
| <ClInclude Include="lol\gpu\vertexbuffer.h" /> | <ClInclude Include="lol\gpu\vertexbuffer.h" /> | ||||
| <ClInclude Include="lol\image\all.h" /> | <ClInclude Include="lol\image\all.h" /> | ||||
| <ClInclude Include="lol\image\color.h" /> | |||||
| <ClInclude Include="lol\image\image.h" /> | <ClInclude Include="lol\image\image.h" /> | ||||
| <ClInclude Include="lol\image\movie.h" /> | <ClInclude Include="lol\image\movie.h" /> | ||||
| <ClInclude Include="lol\image\pixel.h" /> | |||||
| <ClInclude Include="lol\image\resource.h" /> | <ClInclude Include="lol\image\resource.h" /> | ||||
| <ClInclude Include="lol\lua.h" /> | <ClInclude Include="lol\lua.h" /> | ||||
| <ClInclude Include="lol\math\all.h" /> | |||||
| <ClInclude Include="lol\math\arraynd.h" /> | |||||
| <ClInclude Include="lol\math\functions.h" /> | |||||
| <ClInclude Include="lol\math\geometry.h" /> | |||||
| <ClInclude Include="lol\math\interp.h" /> | |||||
| <ClInclude Include="lol\math\noise\gradient.h" /> | |||||
| <ClInclude Include="lol\math\noise\perlin.h" /> | |||||
| <ClInclude Include="lol\math\noise\simplex.h" /> | |||||
| <ClInclude Include="lol\net\all.h" /> | <ClInclude Include="lol\net\all.h" /> | ||||
| <ClInclude Include="lol\net\http.h" /> | <ClInclude Include="lol\net\http.h" /> | ||||
| <ClInclude Include="lol\public.h" /> | <ClInclude Include="lol\public.h" /> | ||||
| @@ -305,9 +305,6 @@ | |||||
| <ClInclude Include="lolua\baselua.h"> | <ClInclude Include="lolua\baselua.h"> | ||||
| <Filter>lolua</Filter> | <Filter>lolua</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\algorithm\aabb_tree.h"> | |||||
| <Filter>lol\algorithm</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\algorithm\all.h"> | <ClInclude Include="lol\algorithm\all.h"> | ||||
| <Filter>lol\algorithm</Filter> | <Filter>lol\algorithm</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| @@ -320,21 +317,12 @@ | |||||
| <ClInclude Include="lol\base\array.h"> | <ClInclude Include="lol\base\array.h"> | ||||
| <Filter>lol\base</Filter> | <Filter>lol\base</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\base\assert.h"> | |||||
| <Filter>lol\base</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\base\enum.h"> | <ClInclude Include="lol\base\enum.h"> | ||||
| <Filter>lol\base</Filter> | <Filter>lol\base</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\base\log.h"> | <ClInclude Include="lol\base\log.h"> | ||||
| <Filter>lol\base</Filter> | <Filter>lol\base</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\base\map.h"> | |||||
| <Filter>lol\base</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\base\types.h"> | |||||
| <Filter>lol\base</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\base\tuple.h"> | <ClInclude Include="lol\base\tuple.h"> | ||||
| <Filter>lol\base</Filter> | <Filter>lol\base</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| @@ -392,45 +380,18 @@ | |||||
| <ClInclude Include="lol\image\all.h"> | <ClInclude Include="lol\image\all.h"> | ||||
| <Filter>lol\image</Filter> | <Filter>lol\image</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\image\color.h"> | |||||
| <Filter>lol\image</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\image\image.h"> | <ClInclude Include="lol\image\image.h"> | ||||
| <Filter>lol\image</Filter> | <Filter>lol\image</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\image\movie.h"> | <ClInclude Include="lol\image\movie.h"> | ||||
| <Filter>lol\image</Filter> | <Filter>lol\image</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\image\pixel.h"> | |||||
| <Filter>lol\image</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\image\resource.h"> | <ClInclude Include="lol\image\resource.h"> | ||||
| <Filter>lol\image</Filter> | <Filter>lol\image</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\lua.h"> | <ClInclude Include="lol\lua.h"> | ||||
| <Filter>lol</Filter> | <Filter>lol</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="lol\math\arraynd.h"> | |||||
| <Filter>lol\math</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\math\functions.h"> | |||||
| <Filter>lol\math</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\math\geometry.h"> | |||||
| <Filter>lol\math</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\math\interp.h"> | |||||
| <Filter>lol\math</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\math\noise\gradient.h"> | |||||
| <Filter>lol\math\noise</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\math\noise\perlin.h"> | |||||
| <Filter>lol\math\noise</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\math\noise\simplex.h"> | |||||
| <Filter>lol\math\noise</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\net\all.h"> | <ClInclude Include="lol\net\all.h"> | ||||
| <Filter>lol\net</Filter> | <Filter>lol\net</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| @@ -485,9 +446,6 @@ | |||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="utils.h" /> | <ClInclude Include="utils.h" /> | ||||
| <ClInclude Include="video.h" /> | <ClInclude Include="video.h" /> | ||||
| <ClInclude Include="lol\math\all.h"> | |||||
| <Filter>lol\math</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="lol\base\all.h"> | <ClInclude Include="lol\base\all.h"> | ||||
| <Filter>lol\base</Filter> | <Filter>lol\base</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| @@ -1,402 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <lol/base/array.h> | |||||
| #include <lol/debug/lines.h> | |||||
| #include <lol/image/color.h> | |||||
| namespace lol | |||||
| { | |||||
| //------ AABB TREE SYSTEM ----- | |||||
| template <typename TE, typename TV, typename TB, size_t child_nb> class AABBTree; | |||||
| template <typename TE> class Quadtree; | |||||
| template <typename TE> class Octree; | |||||
| //-- | |||||
| namespace Debug { | |||||
| //-- | |||||
| template<typename TREE, typename TE, typename TBB> | |||||
| void DrawInner(TREE *tree, array<TBB, vec4> &boxes, | |||||
| array<TE *, int, vec4> &elements, | |||||
| array<int, TBB> &leaves, int children, vec4 color) | |||||
| { | |||||
| boxes.push(tree->GetAABB(), color::white); | |||||
| leaves.push(0, boxes.last().m1); | |||||
| while (leaves.count() > 0) | |||||
| { | |||||
| for (int j = 0; j < tree->GetTree()[leaves[0].m1].m_elements.count(); j++) | |||||
| { | |||||
| bool done = false; | |||||
| for (int k = 0; k < elements.count(); k++) | |||||
| { | |||||
| if (elements[k].m1 == tree->GetElements()[tree->GetTree()[leaves[0].m1].m_elements[j]].m_element) | |||||
| { | |||||
| elements[k].m2++; | |||||
| done = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (!done) | |||||
| elements.push(tree->GetElements()[tree->GetTree()[leaves[0].m1].m_elements[j]].m_element, 1, color::red); | |||||
| } | |||||
| for (int i = 0; i < children; i++) | |||||
| { | |||||
| if (tree->GetTree()[leaves[0].m1].m_children[i] != 0) | |||||
| { | |||||
| TBB bbox = tree->GetSubAABB(leaves[0].m2, i); | |||||
| leaves.push(tree->GetTree()[leaves[0].m1].m_children[i], bbox); | |||||
| boxes.push(bbox, color); | |||||
| } | |||||
| } | |||||
| leaves.remove(0); | |||||
| } | |||||
| } | |||||
| //-- | |||||
| template <typename TE, typename TV = void> | |||||
| void Draw(Quadtree<TE>* tree, vec4 color) | |||||
| { | |||||
| array<box2, vec4> boxes; | |||||
| array<TE*, int, vec4> elements; | |||||
| array<int, box2> leaves; | |||||
| DrawInner<Quadtree<TE>, TE, box2>(tree, boxes, elements, leaves, 4, color); | |||||
| vec3 off = vec3(0.0f, 0.1f, 0.0f); | |||||
| //vec3 add = vec3(0.0f, 0.1f, 0.0f); | |||||
| while (boxes.count() > 0) | |||||
| { | |||||
| Debug::DrawBox(vec3(boxes[0].m1.aa.x, tree->m_debug_y_offset, boxes[0].m1.aa.y), | |||||
| vec3(boxes[0].m1.bb.x, tree->m_debug_y_offset, boxes[0].m1.bb.y), | |||||
| boxes[0].m2); | |||||
| boxes.remove(0); | |||||
| } | |||||
| while (elements.count() > 0) | |||||
| { | |||||
| while (elements[0].m2 > 0) | |||||
| { | |||||
| Debug::DrawBox(vec3(elements[0].m1->GetAABB().aa.x, tree->m_debug_y_offset, elements[0].m1->GetAABB().aa.y) + off * (float)elements[0].m2, | |||||
| vec3(elements[0].m1->GetAABB().bb.x, tree->m_debug_y_offset, elements[0].m1->GetAABB().bb.y) + off * (float)elements[0].m2, | |||||
| elements[0].m3); | |||||
| elements[0].m2--; | |||||
| } | |||||
| elements.remove(0); | |||||
| } | |||||
| } | |||||
| //-- | |||||
| template <typename TE, typename TV = void> | |||||
| void Draw(Octree<TE>* tree, vec4 color) | |||||
| { | |||||
| array<box3, vec4> boxes; | |||||
| array<TE*, int, vec4> elements; | |||||
| array<int, box3> leaves; | |||||
| DrawInner<Octree<TE>, TE, box3>(tree, boxes, elements, leaves, 8, color); | |||||
| vec3 off = vec3(0.0f, 0.1f, 0.0f); | |||||
| //vec3 add = vec3(0.0f, 0.1f, 0.0f); | |||||
| while (boxes.count() > 0) | |||||
| { | |||||
| //float size = boxes[0].m1.bb.x - boxes[0].m1.aa.x; | |||||
| Debug::DrawBox(vec3(boxes[0].m1.aa.x, boxes[0].m1.aa.y, boxes[0].m1.aa.z) /* + off * (m_size.x / size) */, | |||||
| vec3(boxes[0].m1.bb.x, boxes[0].m1.bb.y, boxes[0].m1.bb.z) /* + off * (m_size.x / size) */, | |||||
| boxes[0].m2); | |||||
| //off += add; | |||||
| boxes.remove(0); | |||||
| } | |||||
| while (elements.count() > 0) | |||||
| { | |||||
| while (elements[0].m2 > 0) | |||||
| { | |||||
| Debug::DrawBox(vec3(elements[0].m1->GetAABB().aa.x, elements[0].m1->GetAABB().aa.y, elements[0].m1->GetAABB().aa.z) + off * (float)elements[0].m2, | |||||
| vec3(elements[0].m1->GetAABB().bb.x, elements[0].m1->GetAABB().bb.y, elements[0].m1->GetAABB().bb.z) + off * (float)elements[0].m2, | |||||
| elements[0].m3); | |||||
| elements[0].m2--; | |||||
| } | |||||
| elements.remove(0); | |||||
| } | |||||
| } | |||||
| //-- | |||||
| } | |||||
| //-- | |||||
| template <typename TE, typename TV, typename TB, size_t child_nb> | |||||
| class AABBTree | |||||
| { | |||||
| struct NodeLeaf | |||||
| { | |||||
| int m_parent; | |||||
| //Children pos in the list | |||||
| int m_children[child_nb]; | |||||
| //Element list | |||||
| array<int> m_elements; | |||||
| NodeLeaf(int parent) | |||||
| { | |||||
| m_parent = parent; | |||||
| for (size_t i = 0; i < child_nb; ++i) | |||||
| m_children[i] = 0; | |||||
| } | |||||
| }; | |||||
| struct TreeElement | |||||
| { | |||||
| TE* m_element; | |||||
| array<int> m_leaves; | |||||
| inline bool operator==(const TE*& element) { return m_element == element; } | |||||
| }; | |||||
| public: | |||||
| AABBTree() | |||||
| { | |||||
| m_max_depth = 1; | |||||
| m_max_element = 1; | |||||
| AddLeaf(0); | |||||
| } | |||||
| ~AABBTree() | |||||
| { | |||||
| Clear(); | |||||
| } | |||||
| void CopySetup(const AABBTree<TE, TV, TB, child_nb>* src) | |||||
| { | |||||
| CopySetup(*src); | |||||
| } | |||||
| void CopySetup(const AABBTree<TE, TV, TB, child_nb>& src) | |||||
| { | |||||
| m_size = src.m_size; | |||||
| m_max_depth = src.m_max_depth; | |||||
| m_max_element = src.m_max_element; | |||||
| } | |||||
| private: | |||||
| //-- | |||||
| bool CleanupEmptyLeaves(int leaf=0) | |||||
| { | |||||
| int empty_children = 0; | |||||
| for (size_t i = 0; i < child_nb; ++i) | |||||
| { | |||||
| bool child_empty = false; | |||||
| if (m_tree[leaf].m_children[i] != 0) | |||||
| child_empty = CleanupEmptyLeaves(m_tree[leaf].m_children[i]); | |||||
| empty_children += (int)(m_tree[leaf].m_children[i] == 0 || child_empty); | |||||
| } | |||||
| if (empty_children == 4 && leaf != 0) | |||||
| { | |||||
| for (size_t i = 0; i < child_nb; ++i) | |||||
| { | |||||
| int old_leaf = m_tree[leaf].m_children[i]; | |||||
| if (old_leaf != 0) | |||||
| m_free_leaves << old_leaf; | |||||
| m_tree[leaf].m_children[i] = 0; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //-- | |||||
| void RemoveElement(TE* element) | |||||
| { | |||||
| int idx = INDEX_NONE; | |||||
| for (int i = 0; i < m_elements.count(); ++i) | |||||
| if (m_elements[i].m_element == element) | |||||
| idx = i; | |||||
| if (idx == INDEX_NONE) | |||||
| return; | |||||
| //Remove item from tree leaves | |||||
| for (int i = 0; i < m_elements[idx].m_leaves.count(); i++) | |||||
| m_tree[m_elements[idx].m_leaves[i]].m_elements.removeItem(idx); | |||||
| //Try leaves cleanup | |||||
| CleanupEmptyLeaves(); | |||||
| } | |||||
| //-- | |||||
| int AddElement(TE* element) | |||||
| { | |||||
| for (int i = 0; i < m_elements.count(); ++i) | |||||
| if (m_elements[i].m_element == element) | |||||
| return i; | |||||
| TreeElement new_element; | |||||
| new_element.m_element = element; | |||||
| new_element.m_leaves = array<int>(); | |||||
| m_elements << new_element; | |||||
| return m_elements.count() - 1; | |||||
| } | |||||
| //-- | |||||
| int AddLeaf(int parent) | |||||
| { | |||||
| int idx = m_tree.count(); | |||||
| if (m_free_leaves.count()) | |||||
| { | |||||
| idx = m_free_leaves.pop(); | |||||
| m_tree[idx] = NodeLeaf(parent); | |||||
| } | |||||
| else | |||||
| m_tree << NodeLeaf(parent); | |||||
| return idx; | |||||
| } | |||||
| //-- | |||||
| bool TestLeaf(int leaf, const TB& leaf_bb, const TB& test_bb, array<TE*>& elements) | |||||
| { | |||||
| bool result = false; | |||||
| if (TestAABBVsAABB(leaf_bb, test_bb)) | |||||
| { | |||||
| NodeLeaf& node = m_tree[leaf]; | |||||
| for (size_t i = 0; i < child_nb; ++i) | |||||
| { | |||||
| if (node.m_children[i] != 0) | |||||
| { | |||||
| TB sub_aabb = GetSubAABB(leaf_bb, (int)i); | |||||
| result = result | TestLeaf(node.m_children[i], sub_aabb, test_bb, elements); | |||||
| } | |||||
| else | |||||
| { | |||||
| for (int j = 0; j < node.m_elements.count(); j++) | |||||
| elements.push_unique(m_elements[node.m_elements[j]].m_element); | |||||
| result = true; | |||||
| } | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| //-- | |||||
| bool RegisterElement(TE* element, int leaf, TB leaf_bb, int depth) | |||||
| { | |||||
| if (TestAABBVsAABB(leaf_bb, element->GetAABB())) | |||||
| { | |||||
| bool found_child = false; | |||||
| for (size_t i = 0; i < child_nb; ++i) | |||||
| { | |||||
| TB child_bb = GetSubAABB(leaf_bb, (int)i); | |||||
| int child_leaf = m_tree[leaf].m_children[i]; | |||||
| //there is a child, go further down | |||||
| if (child_leaf != 0) | |||||
| found_child = found_child | RegisterElement(element, child_leaf, child_bb, depth + 1); | |||||
| } | |||||
| if (found_child) | |||||
| return true; | |||||
| //Too much elements, we need to re-dispatch the elements | |||||
| if (m_tree[leaf].m_elements.count() + 1 > m_max_element && | |||||
| depth < m_max_depth) | |||||
| { | |||||
| //Extract elements | |||||
| array<int> elements = m_tree[leaf].m_elements; | |||||
| elements.push_unique(AddElement(element)); | |||||
| m_tree[leaf].m_elements.clear(); | |||||
| //Add children | |||||
| for (size_t j = 0; j < child_nb; ++j) | |||||
| m_tree[leaf].m_children[j] = AddLeaf(leaf); | |||||
| //Re-run extracted elements | |||||
| while (elements.count()) | |||||
| { | |||||
| RegisterElement(m_elements[elements[0]].m_element, leaf, leaf_bb, depth); | |||||
| elements.remove(0); | |||||
| } | |||||
| } | |||||
| //else add to list. | |||||
| else | |||||
| { | |||||
| int idx = AddElement(element); | |||||
| m_elements[idx].m_leaves.push_unique(leaf); | |||||
| m_tree[leaf].m_elements.push_unique(idx); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public: | |||||
| void RegisterElement(TE* element) { RegisterElement(element, 0, GetAABB(), 0); } | |||||
| void UnregisterElement(TE* element) { RemoveElement(element); } | |||||
| bool FindElements(const TB& bbox, array<TE*>& elements) { return TestLeaf(0, GetAABB(), bbox, elements); } | |||||
| void Clear() | |||||
| { | |||||
| m_tree.clear(); | |||||
| m_elements.clear(); | |||||
| } | |||||
| //-- | |||||
| virtual TV GetSubOffset(int sub) = 0; | |||||
| virtual TB GetAABB() { return TB(-m_size * .5f, m_size * .5f); } | |||||
| virtual TB GetSubAABB(const TB& bbox, int sub) | |||||
| { | |||||
| TV v(GetSubOffset(sub)); | |||||
| TV half_vec = bbox.extent() * .5f; | |||||
| return TB(bbox.aa + half_vec * v, | |||||
| bbox.aa + half_vec * (v + TV(1.f))); | |||||
| } | |||||
| //-- | |||||
| TV GetSize() { return m_size; } | |||||
| int GetMaxDepth() { return m_max_depth; } | |||||
| int GetMaxElement() { return m_max_element; } | |||||
| void SetSize(TV size) { m_size = size; } | |||||
| void SetMaxDepth(int max_depth) { m_max_depth = max_depth; } | |||||
| void SetMaxElement(int max_element) { m_max_element = max_element; } | |||||
| array<NodeLeaf> const & GetTree() const | |||||
| { | |||||
| return m_tree; | |||||
| } | |||||
| array<TreeElement> const & GetElements() const | |||||
| { | |||||
| return m_elements; | |||||
| } | |||||
| protected: | |||||
| array<NodeLeaf> m_tree; //actual tree | |||||
| array<TreeElement> m_elements; //elements to leaves | |||||
| array<int> m_free_leaves; //leaves removed from tree | |||||
| TV m_size; //Main tree size | |||||
| int m_max_depth; //Maximum depth possible | |||||
| int m_max_element; //Maximum element per leaf | |||||
| }; | |||||
| //-- | |||||
| template <typename TE> | |||||
| class Quadtree : public AABBTree<TE, vec2, box2, 4> | |||||
| { | |||||
| friend void Debug::Draw<TE,void>(Octree<TE>* tree, vec4 color); | |||||
| public: | |||||
| Quadtree() { m_debug_y_offset = 0.f; } | |||||
| virtual ~Quadtree() { } | |||||
| float m_debug_y_offset; | |||||
| protected: | |||||
| virtual vec2 GetSubOffset(int sub) { return vec2(ivec2(sub % 2, sub / 2)); } | |||||
| }; | |||||
| //-- | |||||
| template <typename TE> | |||||
| class Octree : public AABBTree<TE, vec3, box3, 8> | |||||
| { | |||||
| friend void Debug::Draw<TE,void>(Octree<TE>* tree, vec4 color); | |||||
| public: | |||||
| Octree() { } | |||||
| virtual ~Octree() { } | |||||
| protected: | |||||
| virtual vec3 GetSubOffset(int sub) { return vec3(ivec3(sub % 2, sub / 4, (sub % 4) / 2)); } | |||||
| }; | |||||
| } /* namespace lol */ | |||||
| @@ -1,16 +1,18 @@ | |||||
| // | // | ||||
| // Lol Engine | |||||
| // Lol Engine | |||||
| // | // | ||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | // | ||||
| #pragma once | #pragma once | ||||
| #include <lol/algorithm/sort.h> | #include <lol/algorithm/sort.h> | ||||
| #include <lol/algorithm/aabb_tree.h> | |||||
| #include <../legacy/lol/algorithm/aabb_tree.h> | |||||
| #include <lol/algorithm/portal.h> | #include <lol/algorithm/portal.h> | ||||
| @@ -14,6 +14,8 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <lol/base/array.h> | #include <lol/base/array.h> | ||||
| #include <lol/math/vector.h> // vec_t | |||||
| #include <lol/math/transform.h> // mat_t | |||||
| #include <lol/debug/lines.h> | #include <lol/debug/lines.h> | ||||
| #include <lol/image/color.h> | #include <lol/image/color.h> | ||||
| @@ -14,6 +14,8 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <lol/base/array.h> | #include <lol/base/array.h> | ||||
| #include <lol/math/rand.h> | |||||
| #include <../legacy/lol/math/functions.h> // lol::max | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -12,12 +12,12 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <lol/base/types.h> | |||||
| #include <../legacy/lol/base/types.h> | |||||
| #include <lol/base/log.h> | #include <lol/base/log.h> | ||||
| #include <lol/base/assert.h> | |||||
| #include <../legacy/lol/base/assert.h> | |||||
| #include <lol/base/tuple.h> | #include <lol/base/tuple.h> | ||||
| #include <lol/base/array.h> | #include <lol/base/array.h> | ||||
| #include <lol/base/avl_tree.h> | |||||
| #include <../legacy/lol/base/avl_tree.h> | |||||
| #include <lol/base/utils.h> | #include <lol/base/utils.h> | ||||
| #include <lol/base/enum.h> | #include <lol/base/enum.h> | ||||
| @@ -20,7 +20,7 @@ | |||||
| // additional features, eg. array<int,float> for automatic arrays of tuples. | // additional features, eg. array<int,float> for automatic arrays of tuples. | ||||
| // | // | ||||
| #include <lol/base/assert.h> | |||||
| #include <../legacy/lol/base/assert.h> | |||||
| #include <lol/base/tuple.h> | #include <lol/base/tuple.h> | ||||
| #include <new> /* for placement new */ | #include <new> /* for placement new */ | ||||
| @@ -1,156 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <lol/base/log.h> | |||||
| #include <cstdlib> | |||||
| #if defined _WIN32 | |||||
| # ifdef WIN32_LEAN_AND_MEAN | |||||
| # include <windows.h> | |||||
| # else | |||||
| # define WIN32_LEAN_AND_MEAN 1 | |||||
| # include <windows.h> | |||||
| # undef WIN32_LEAN_AND_MEAN | |||||
| # endif | |||||
| #endif | |||||
| namespace lol | |||||
| { | |||||
| static inline void abort() | |||||
| { | |||||
| //*(uint32_t *)nullptr = 0xdead; | |||||
| std::abort(); | |||||
| } | |||||
| /* FIXME: see http://stackoverflow.com/q/3596781/111461 for discussions | |||||
| * on implementing __debugbreak() on POSIX systems. */ | |||||
| namespace debug | |||||
| { | |||||
| extern void dump_stack(); | |||||
| static inline void abort() | |||||
| { | |||||
| dump_stack(); | |||||
| #if defined _WIN32 | |||||
| __debugbreak(); | |||||
| #endif | |||||
| lol::abort(); | |||||
| } | |||||
| } | |||||
| #define LOL_CALL(macro, args) macro args | |||||
| #define LOL_EVAL(a) a | |||||
| #define LOL_1ST(a, ...) a | |||||
| #define LOL_GET_63RD(a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, \ | |||||
| a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, \ | |||||
| a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, \ | |||||
| a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, \ | |||||
| a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, \ | |||||
| a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, \ | |||||
| a61, a62, a63, ...) a63 | |||||
| #define LOL_COUNT_TO_3(...) \ | |||||
| LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \ | |||||
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \ | |||||
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \ | |||||
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \ | |||||
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \ | |||||
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \ | |||||
| 2, 1, TOO_FEW_ARGUMENTS)) | |||||
| #define LOL_COUNT_TO_8(...) \ | |||||
| LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, \ | |||||
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, \ | |||||
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, \ | |||||
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, \ | |||||
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, \ | |||||
| 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, \ | |||||
| 2, 1, TOO_FEW_ARGUMENTS)) | |||||
| #define LOL_COUNT_TO_12(...) \ | |||||
| LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,11,10,9, 8, 7, 6, 5, 4, 3, \ | |||||
| 2, 1, TOO_FEW_ARGUMENTS)) | |||||
| /* Three levels of dispatch are needed because of Visual Studio's bizarre | |||||
| * handling of __VA_ARGS__ inside macro calls */ | |||||
| #define LOL_CAT3(a, b) a##b | |||||
| #define LOL_CAT2(a, b) LOL_CAT3(a,b) | |||||
| #define LOL_CAT(a, b) LOL_CAT2(a,b) | |||||
| /* | |||||
| * UNUSED(): declare one or several variables as unused | |||||
| */ | |||||
| #define LOL_UNUSED_1(a01) \ | |||||
| sizeof(a01) | |||||
| #define LOL_UNUSED_2(a01, a02) \ | |||||
| sizeof(a01) + LOL_UNUSED_1(a02) | |||||
| #define LOL_UNUSED_3(a01, a02, a03) \ | |||||
| sizeof(a01) + LOL_UNUSED_2(a02, a03) | |||||
| #define LOL_UNUSED_4(a01, a02, a03, a04) \ | |||||
| sizeof(a01) + LOL_UNUSED_3(a02, a03, a04) | |||||
| #define LOL_UNUSED_5(a01, a02, a03, a04, a05) \ | |||||
| sizeof(a01) + LOL_UNUSED_4(a02, a03, a04, a05) | |||||
| #define LOL_UNUSED_6(a01, a02, a03, a04, a05, a06) \ | |||||
| sizeof(a01) + LOL_UNUSED_5(a02, a03, a04, a05, a06) | |||||
| #define LOL_UNUSED_7(a01, a02, a03, a04, a05, a06, a07) \ | |||||
| sizeof(a01) + LOL_UNUSED_6(a02, a03, a04, a05, a06, a07) | |||||
| #define LOL_UNUSED_8(a01, a02, a03, a04, a05, a06, a07, a08) \ | |||||
| sizeof(a01) + LOL_UNUSED_7(a02, a03, a04, a05, a06, a07, a08) | |||||
| #define UNUSED(...) (void)sizeof((void)( \ | |||||
| LOL_CALL(LOL_CAT(LOL_UNUSED_, LOL_CALL(LOL_COUNT_TO_8, (__VA_ARGS__))), \ | |||||
| (__VA_ARGS__))), 0) \ | |||||
| /* | |||||
| * ASSERT(): test and enforce conditions at runtime | |||||
| */ | |||||
| #define LOL_ERROR_1(t) \ | |||||
| lol::msg::error("assertion at %s:%d: %s\n", __FILE__, __LINE__, #t) | |||||
| #define LOL_ERROR_2(t, s) \ | |||||
| lol::msg::error("assertion at %s:%d: %s\n", __FILE__, __LINE__, s) | |||||
| #define LOL_ERROR_3(t, s, ...) \ | |||||
| lol::msg::error("assertion at %s:%d: " s "\n", __FILE__, __LINE__, __VA_ARGS__) | |||||
| #if LOL_BUILD_RELEASE | |||||
| # define ASSERT(...) UNUSED(LOL_CALL(LOL_1ST, (__VA_ARGS__))) | |||||
| #else | |||||
| # define ASSERT(...) \ | |||||
| if (LOL_CALL(LOL_1ST, (__VA_ARGS__))) \ | |||||
| { \ | |||||
| /* Don't use "!" so that ASSERT(x = 1) instead of ASSERT(x == 1) | |||||
| * triggers a compilation warning. */ \ | |||||
| } \ | |||||
| else \ | |||||
| { \ | |||||
| LOL_CALL(LOL_CAT(LOL_ERROR_, LOL_CALL(LOL_COUNT_TO_3, \ | |||||
| (__VA_ARGS__))), \ | |||||
| (__VA_ARGS__)); \ | |||||
| lol::debug::abort(); \ | |||||
| } | |||||
| #endif | |||||
| } /* namespace lol */ | |||||
| @@ -1,646 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010-2015 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013-2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // © 2013-2015 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| namespace lol | |||||
| { | |||||
| #include <lol/base/all.h> | |||||
| template<typename K, typename V> | |||||
| class avl_tree | |||||
| { | |||||
| public: | |||||
| avl_tree() : | |||||
| m_root(nullptr), | |||||
| m_count(0) | |||||
| { | |||||
| } | |||||
| avl_tree(avl_tree const & other) : | |||||
| m_root(nullptr), | |||||
| m_count(0) | |||||
| { | |||||
| for (auto it : other) | |||||
| insert(it.key, it.value); | |||||
| } | |||||
| avl_tree & operator=(avl_tree const & other) | |||||
| { | |||||
| if (&other != this) | |||||
| { | |||||
| clear(); | |||||
| for (auto it : other) | |||||
| insert(it.key, it.value); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| ~avl_tree() | |||||
| { | |||||
| clear(); | |||||
| } | |||||
| bool insert(K const & key, V const & value) | |||||
| { | |||||
| if (!m_root) | |||||
| { | |||||
| m_root = new tree_node(key, value, &m_root); | |||||
| ++m_count; | |||||
| return true; | |||||
| } | |||||
| if (m_root->insert(key, value)) | |||||
| { | |||||
| ++m_count; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool erase(K const & key) | |||||
| { | |||||
| if (!m_root) | |||||
| return false; | |||||
| if (m_root->erase(key)) | |||||
| { | |||||
| --m_count; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool exists(K const & key) | |||||
| { | |||||
| if (!m_root) | |||||
| return false; | |||||
| return m_root->exists(key); | |||||
| } | |||||
| void clear() | |||||
| { | |||||
| if (m_root) | |||||
| { | |||||
| tree_node * node = nullptr; | |||||
| m_root->get_min(node); | |||||
| while (node) | |||||
| { | |||||
| tree_node * next = node->get_next(); | |||||
| delete node; | |||||
| node = next; | |||||
| } | |||||
| } | |||||
| m_root = nullptr; | |||||
| m_count = 0; | |||||
| } | |||||
| bool try_get(K const & key, V * & value_ptr) const | |||||
| { | |||||
| if (m_root) | |||||
| return m_root->try_get(key, value_ptr); | |||||
| return false; | |||||
| } | |||||
| bool try_get_min(K const * & key_ptr, V * & value_ptr) const | |||||
| { | |||||
| tree_node * min_node = nullptr; | |||||
| if (m_root) | |||||
| { | |||||
| m_root->get_min(min_node); | |||||
| key_ptr = &min_node->get_key(); | |||||
| value_ptr = &min_node->get_value(); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool try_get_max(K const * & key_ptr, V * & value_ptr) const | |||||
| { | |||||
| tree_node * max_node = nullptr; | |||||
| if (m_root) | |||||
| { | |||||
| m_root->get_max(max_node); | |||||
| key_ptr = &max_node->get_key(); | |||||
| value_ptr = &max_node->get_value(); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| class iterator; | |||||
| class const_iterator; | |||||
| iterator begin() | |||||
| { | |||||
| tree_node * node = nullptr; | |||||
| if (m_root) | |||||
| m_root->get_min(node); | |||||
| return iterator(node); | |||||
| } | |||||
| const_iterator begin() const | |||||
| { | |||||
| tree_node * node = nullptr; | |||||
| if (m_root) | |||||
| m_root->get_min(node); | |||||
| return const_iterator(node); | |||||
| } | |||||
| int count() const | |||||
| { | |||||
| return m_count; | |||||
| } | |||||
| iterator end() | |||||
| { | |||||
| return iterator(nullptr); | |||||
| } | |||||
| const_iterator end() const | |||||
| { | |||||
| return const_iterator(nullptr); | |||||
| } | |||||
| protected: | |||||
| class tree_node | |||||
| { | |||||
| public: | |||||
| tree_node(K key, V value, tree_node ** parent_slot) : | |||||
| m_key(key), | |||||
| m_value(value), | |||||
| m_parent_slot(parent_slot) | |||||
| { | |||||
| m_child[0] = m_child[1] = nullptr; | |||||
| m_stairs[0] = m_stairs[1] = 0; | |||||
| m_chain[0] = m_chain[1] = nullptr; | |||||
| } | |||||
| K const & get_key() | |||||
| { | |||||
| return m_key; | |||||
| } | |||||
| V & get_value() | |||||
| { | |||||
| return m_value; | |||||
| } | |||||
| /* Insert a value in tree and return true or update an existing value for | |||||
| * the existing key and return false */ | |||||
| bool insert(K const & key, V const & value) | |||||
| { | |||||
| int i = -1 + (key < m_key) + 2 * (m_key < key); | |||||
| bool created = false; | |||||
| if (i < 0) | |||||
| m_value = value; | |||||
| else if (m_child[i]) | |||||
| created = m_child[i]->insert(key, value); | |||||
| else | |||||
| { | |||||
| created = true; | |||||
| m_child[i] = new tree_node(key, value, &m_child[i]); | |||||
| m_child[i]->m_chain[i] = m_chain[i]; | |||||
| m_child[i]->m_chain[i ? 0 : 1] = this; | |||||
| if (m_chain[i]) | |||||
| m_chain[i]->m_chain[i ? 0 : 1] = m_child[i]; | |||||
| m_chain[i] = m_child[i]; | |||||
| } | |||||
| if (created) | |||||
| { | |||||
| rebalance_if_needed(); | |||||
| } | |||||
| return created; | |||||
| } | |||||
| /* Erase a value in tree and return true or return false */ | |||||
| bool erase(K const & key) | |||||
| { | |||||
| int i = -1 + (key < m_key) + 2 * (m_key < key); | |||||
| bool erased = false; | |||||
| bool suicide = false; | |||||
| if (i < 0) | |||||
| { | |||||
| erase_self(); | |||||
| erased = true; | |||||
| suicide = true; | |||||
| } | |||||
| else if (m_child[i] && m_child[i]->erase(key)) | |||||
| { | |||||
| rebalance_if_needed(); | |||||
| erased = true; | |||||
| } | |||||
| if (suicide) | |||||
| delete this; | |||||
| return erased; | |||||
| } | |||||
| bool try_get(K const & key, V * & value_ptr) | |||||
| { | |||||
| int i = -1 + (key < m_key) + 2 * (m_key < key); | |||||
| if (i < 0) | |||||
| { | |||||
| value_ptr = &m_value; | |||||
| return true; | |||||
| } | |||||
| if (m_child[i]) | |||||
| return m_child[i]->try_get(key, value_ptr); | |||||
| return false; | |||||
| } | |||||
| bool exists(K const & key) | |||||
| { | |||||
| int i = -1 + (key < m_key) + 2 * (m_key < key); | |||||
| if (i < 0) | |||||
| return true; | |||||
| if (m_child[i]) | |||||
| return m_child[i]->exists(key); | |||||
| return false; | |||||
| } | |||||
| void get_min(tree_node * & min_node) | |||||
| { | |||||
| min_node = this; | |||||
| while (min_node->m_child[0]) | |||||
| min_node = min_node->m_child[0]; | |||||
| } | |||||
| void get_max(tree_node * & max_node) const | |||||
| { | |||||
| max_node = this; | |||||
| while (max_node->m_child[1]) | |||||
| max_node = max_node->m_child[1]; | |||||
| } | |||||
| int get_balance() const | |||||
| { | |||||
| return m_stairs[1] - m_stairs[0]; | |||||
| } | |||||
| tree_node * get_previous() const | |||||
| { | |||||
| return m_chain[0]; | |||||
| } | |||||
| tree_node * get_next() const | |||||
| { | |||||
| return m_chain[1]; | |||||
| } | |||||
| protected: | |||||
| void update_balance() | |||||
| { | |||||
| for (int i = 0; i <= 1; ++i) | |||||
| m_stairs[i] = m_child[i] ? std::max(m_child[i]->m_stairs[0], m_child[i]->m_stairs[1]) + 1 : 0; | |||||
| } | |||||
| void rebalance_if_needed() | |||||
| { | |||||
| update_balance(); | |||||
| int i = -1 + (get_balance() == -2) + 2 * (get_balance() == 2); | |||||
| if (i != -1) | |||||
| { | |||||
| tree_node * replacement = nullptr; | |||||
| if (get_balance() / 2 + m_child[i]->get_balance() == 0) | |||||
| { | |||||
| replacement = m_child[i]->m_child[1 - i]; | |||||
| tree_node * save0 = replacement->m_child[i]; | |||||
| tree_node * save1 = replacement->m_child[1 - i]; | |||||
| replacement->m_parent_slot = this->m_parent_slot; | |||||
| *replacement->m_parent_slot = replacement; | |||||
| replacement->m_child[i] = m_child[i]; | |||||
| m_child[i]->m_parent_slot = &replacement->m_child[i]; | |||||
| replacement->m_child[1 - i] = this; | |||||
| this->m_parent_slot = &replacement->m_child[1 - i]; | |||||
| replacement->m_child[i]->m_child[1 - i] = save0; | |||||
| if (save0) | |||||
| save0->m_parent_slot = &replacement->m_child[i]->m_child[1 - i]; | |||||
| replacement->m_child[1 - i]->m_child[i] = save1; | |||||
| if (save1) | |||||
| save1->m_parent_slot = &replacement->m_child[1 - i]->m_child[i]; | |||||
| } | |||||
| else | |||||
| { | |||||
| replacement = m_child[i]; | |||||
| tree_node * save = replacement->m_child[1 - i]; | |||||
| replacement->m_parent_slot = this->m_parent_slot; | |||||
| *replacement->m_parent_slot = replacement; | |||||
| replacement->m_child[1 - i] = this; | |||||
| this->m_parent_slot = &replacement->m_child[1 - i]; | |||||
| this->m_child[i] = save; | |||||
| if (save) | |||||
| save->m_parent_slot = &this->m_child[i]; | |||||
| } | |||||
| if (replacement->m_child[0]) | |||||
| replacement->m_child[0]->update_balance(); | |||||
| if (replacement->m_child[1]) | |||||
| replacement->m_child[1]->update_balance(); | |||||
| replacement->update_balance(); | |||||
| } | |||||
| } | |||||
| void erase_self() | |||||
| { | |||||
| int i = (get_balance() == -1); | |||||
| tree_node * replacement = m_child[1 - i]; | |||||
| if (replacement) | |||||
| { | |||||
| while (replacement->m_child[i]) | |||||
| replacement = replacement->m_child[i]; | |||||
| } | |||||
| if (replacement) | |||||
| { | |||||
| *replacement->m_parent_slot = replacement->m_child[1 - i]; | |||||
| if (replacement->m_child[1 - i]) | |||||
| replacement->m_child[1 - i]->m_parent_slot = replacement->m_parent_slot; | |||||
| replacement->m_parent_slot = m_parent_slot; | |||||
| *replacement->m_parent_slot = replacement; | |||||
| replacement->m_child[0] = m_child[0]; | |||||
| if (replacement->m_child[0]) | |||||
| replacement->m_child[0]->m_parent_slot = &replacement->m_child[0]; | |||||
| replacement->m_child[1] = m_child[1]; | |||||
| if (replacement->m_child[1]) | |||||
| replacement->m_child[1]->m_parent_slot = &replacement->m_child[1]; | |||||
| if (replacement->m_child[1-i]) | |||||
| replacement->m_child[1-i]->deep_balance(replacement->m_key); | |||||
| replacement->update_balance(); | |||||
| } | |||||
| else | |||||
| { | |||||
| *m_parent_slot = m_child[i]; | |||||
| if (m_child[i]) | |||||
| m_child[i]->m_parent_slot = m_parent_slot; | |||||
| replacement = m_child[i]; | |||||
| } | |||||
| replace_chain(replacement); | |||||
| } | |||||
| void deep_balance(K const & key) | |||||
| { | |||||
| int i = -1 + (key < m_key) + 2 * (m_key < key); | |||||
| if (i != -1 && m_child[i]) | |||||
| m_child[i]->deep_balance(key); | |||||
| update_balance(); | |||||
| } | |||||
| void replace_chain(tree_node * replacement) | |||||
| { | |||||
| if (replacement) | |||||
| { | |||||
| if (replacement->m_chain[0]) | |||||
| replacement->m_chain[0]->m_chain[1] = replacement->m_chain[1]; | |||||
| if (replacement->m_chain[1]) | |||||
| replacement->m_chain[1]->m_chain[0] = replacement->m_chain[0]; | |||||
| replacement->m_chain[0] = m_chain[0]; | |||||
| replacement->m_chain[1] = m_chain[1]; | |||||
| if (replacement->m_chain[0]) | |||||
| replacement->m_chain[0]->m_chain[1] = replacement; | |||||
| if (replacement->m_chain[1]) | |||||
| replacement->m_chain[1]->m_chain[0] = replacement; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (m_chain[0]) | |||||
| m_chain[0]->m_chain[1] = m_chain[1]; | |||||
| if (m_chain[1]) | |||||
| m_chain[1]->m_chain[0] = m_chain[0]; | |||||
| } | |||||
| } | |||||
| K m_key; | |||||
| V m_value; | |||||
| tree_node *m_child[2]; | |||||
| int m_stairs[2]; | |||||
| tree_node ** m_parent_slot; | |||||
| tree_node * m_chain[2]; // Linked list used to keep order between nodes | |||||
| }; | |||||
| public: | |||||
| /* Iterators related */ | |||||
| struct output_value | |||||
| { | |||||
| output_value(K const & key_, V & value_) : | |||||
| key(key_), | |||||
| value(value_) | |||||
| { | |||||
| } | |||||
| K const & key; | |||||
| V & value; | |||||
| }; | |||||
| class iterator | |||||
| { | |||||
| public: | |||||
| iterator(tree_node * node) : | |||||
| m_node(node) | |||||
| { | |||||
| } | |||||
| iterator & operator++(int) | |||||
| { | |||||
| m_node = m_node->get_next(); | |||||
| return *this; | |||||
| } | |||||
| iterator & operator--(int) | |||||
| { | |||||
| m_node = m_node->get_previous(); | |||||
| return *this; | |||||
| } | |||||
| iterator operator++() | |||||
| { | |||||
| tree_node * ret = m_node; | |||||
| m_node = m_node->get_next(); | |||||
| return iterator(ret); | |||||
| } | |||||
| iterator operator--() | |||||
| { | |||||
| tree_node * ret = m_node; | |||||
| m_node = m_node->get_previous(); | |||||
| return iterator(ret); | |||||
| } | |||||
| output_value operator*() | |||||
| { | |||||
| return output_value(m_node->get_key(), m_node->get_value()); | |||||
| } | |||||
| bool operator!=(iterator const & that) const | |||||
| { | |||||
| return m_node != that.m_node; | |||||
| } | |||||
| protected: | |||||
| tree_node * m_node; | |||||
| }; | |||||
| struct const_output_value | |||||
| { | |||||
| const_output_value(K const & key_, V const & value_) : | |||||
| key(key_), | |||||
| value(value_) | |||||
| { | |||||
| } | |||||
| K const & key; | |||||
| V const & value; | |||||
| }; | |||||
| class const_iterator | |||||
| { | |||||
| public: | |||||
| const_iterator(tree_node * node) : | |||||
| m_node(node) | |||||
| { | |||||
| } | |||||
| const_iterator & operator++(int) | |||||
| { | |||||
| m_node = m_node->get_next(); | |||||
| return *this; | |||||
| } | |||||
| const_iterator & operator--(int) | |||||
| { | |||||
| m_node = m_node->get_previous(); | |||||
| return *this; | |||||
| } | |||||
| const_iterator operator++() | |||||
| { | |||||
| tree_node * ret = m_node; | |||||
| m_node = m_node->get_next(); | |||||
| return const_iterator(ret); | |||||
| } | |||||
| const_iterator operator--() | |||||
| { | |||||
| tree_node * ret = m_node; | |||||
| m_node = m_node->get_previous(); | |||||
| return const_iterator(ret); | |||||
| } | |||||
| const_output_value operator*() | |||||
| { | |||||
| return const_output_value(m_node->get_key(), m_node->get_value()); | |||||
| } | |||||
| bool operator!=(const_iterator const & that) const | |||||
| { | |||||
| return m_node != that.m_node; | |||||
| } | |||||
| protected: | |||||
| tree_node * m_node; | |||||
| }; | |||||
| protected: | |||||
| tree_node * m_root; | |||||
| int m_count; | |||||
| }; | |||||
| } | |||||
| @@ -13,6 +13,8 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <lol/base/utils.h> // has_key() | |||||
| #include <string> | #include <string> | ||||
| #include <map> | #include <map> | ||||
| @@ -1,55 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2018 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2015 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| // | |||||
| // Simple map utilities | |||||
| // -------------------- | |||||
| // | |||||
| #include <lol/base/array.h> | |||||
| #include <map> | |||||
| namespace lol | |||||
| { | |||||
| template <typename T> | |||||
| static inline bool has_key(T const &m, typename T::key_type const &key) | |||||
| { | |||||
| return m.count(key) > 0; | |||||
| } | |||||
| template <typename T> | |||||
| static inline bool try_get(T const &m, typename T::key_type const &key, | |||||
| typename T::mapped_type &val) | |||||
| { | |||||
| auto const &kv = m.find(key); | |||||
| if (kv == m.end()) | |||||
| return false; | |||||
| val = kv->second; | |||||
| return true; | |||||
| } | |||||
| template <typename T> | |||||
| static inline array<typename T::key_type> keys(T const &m) | |||||
| { | |||||
| array<typename T::key_type> ret; | |||||
| for (auto const &it : m) | |||||
| ret << it.first; | |||||
| return ret; | |||||
| } | |||||
| } /* namespace lol */ | |||||
| @@ -1,12 +1,14 @@ | |||||
| // | // | ||||
| // Lol Engine | |||||
| // Lol Engine | |||||
| // | // | ||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | // | ||||
| #pragma once | #pragma once | ||||
| @@ -17,7 +19,7 @@ | |||||
| // A very simple tuple class. | // A very simple tuple class. | ||||
| // | // | ||||
| #include <lol/base/assert.h> | |||||
| #include <../legacy/lol/base/assert.h> | |||||
| #include <tuple> | #include <tuple> | ||||
| @@ -1,160 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <stdint.h> | |||||
| namespace lol | |||||
| { | |||||
| /* It’s nice to have single-word type names, so define this. */ | |||||
| typedef long double ldouble; | |||||
| /* The “real” type used for real numbers. It’s a specialisation of the | |||||
| * “real_t” template class. */ | |||||
| template<typename T> class real_t; | |||||
| typedef real_t<uint32_t> real; | |||||
| /* The “half” type used for 16-bit floating point numbers. */ | |||||
| class half; | |||||
| /* | |||||
| * Forward declaration of vec_t, mat_t, cmplx_t, quat_t, etc. | |||||
| */ | |||||
| /* HACK: if this is declared int const, Visual Studio becomes unable | |||||
| * to perform template argument deduction. */ | |||||
| #define FULL_SWIZZLE (0) | |||||
| template<typename T, int N, int SWIZZLE = FULL_SWIZZLE> struct vec_t; | |||||
| template<typename T, int N> struct box_t; | |||||
| template<typename T, int COLS, int ROWS> struct mat_t; | |||||
| template<typename T> struct cmplx_t; | |||||
| template<typename T> struct quat_t; | |||||
| template<typename T> struct dualquat_t; | |||||
| template<typename T> struct sqt_t; | |||||
| /* | |||||
| * Generic GLSL-like type names | |||||
| */ | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft half tright f16##suffix; \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft ldouble tright f128##suffix; \ | |||||
| typedef tleft int8_t tright i8##suffix; \ | |||||
| typedef tleft uint8_t tright u8##suffix; \ | |||||
| typedef tleft int16_t tright i16##suffix; \ | |||||
| typedef tleft uint16_t tright u16##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; \ | |||||
| typedef tleft int64_t tright i64##suffix; \ | |||||
| typedef tleft uint64_t tright u64##suffix; \ | |||||
| typedef tleft real tright r##suffix; | |||||
| /* Idiotic hack to put "," inside a macro argument */ | |||||
| #define C_ , | |||||
| T_(vec_t<, C_ 2>, vec2) | |||||
| T_(vec_t<, C_ 3>, vec3) | |||||
| T_(vec_t<, C_ 4>, vec4) | |||||
| T_(vec_t<, C_ 5>, vec5) | |||||
| T_(vec_t<, C_ 6>, vec6) | |||||
| T_(vec_t<, C_ 7>, vec7) | |||||
| T_(vec_t<, C_ 8>, vec8) | |||||
| T_(vec_t<, C_ 9>, vec9) | |||||
| T_(vec_t<, C_ 10>, vec10) | |||||
| T_(vec_t<, C_ 11>, vec11) | |||||
| T_(vec_t<, C_ 12>, vec12) | |||||
| T_(mat_t<, C_ 2 C_ 2>, mat2) | |||||
| T_(mat_t<, C_ 3 C_ 3>, mat3) | |||||
| T_(mat_t<, C_ 4 C_ 4>, mat4) | |||||
| T_(mat_t<, C_ 2 C_ 3>, mat2x3) | |||||
| T_(mat_t<, C_ 2 C_ 4>, mat2x4) | |||||
| T_(mat_t<, C_ 3 C_ 2>, mat3x2) | |||||
| T_(mat_t<, C_ 3 C_ 4>, mat3x4) | |||||
| T_(mat_t<, C_ 4 C_ 2>, mat4x2) | |||||
| T_(mat_t<, C_ 4 C_ 3>, mat4x3) | |||||
| T_(cmplx_t<, >, cmplx) | |||||
| T_(quat_t<, >, quat) | |||||
| T_(dualquat_t<, >, dualquat) | |||||
| T_(sqt_t<, >, sqt) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| /* | |||||
| * HLSL/Cg-compliant type names | |||||
| */ | |||||
| typedef vec2 float2; | |||||
| typedef vec3 float3; | |||||
| typedef vec4 float4; | |||||
| typedef vec5 float5; | |||||
| typedef vec6 float6; | |||||
| typedef vec7 float7; | |||||
| typedef vec8 float8; | |||||
| typedef vec9 float9; | |||||
| typedef vec10 float10; | |||||
| typedef vec11 float11; | |||||
| typedef vec12 float12; | |||||
| typedef mat2 float2x2; | |||||
| typedef mat3 float3x3; | |||||
| typedef mat4 float4x4; | |||||
| typedef mat2x3 float2x3; | |||||
| typedef mat2x4 float2x4; | |||||
| typedef mat3x2 float3x2; | |||||
| typedef mat3x4 float3x4; | |||||
| typedef mat4x2 float4x2; | |||||
| typedef mat4x3 float4x3; | |||||
| typedef f16vec2 half2; | |||||
| typedef f16vec3 half3; | |||||
| typedef f16vec4 half4; | |||||
| typedef f16mat2 half2x2; | |||||
| typedef f16mat3 half3x3; | |||||
| typedef f16mat4 half4x4; | |||||
| typedef f16mat2x3 half2x3; | |||||
| typedef f16mat2x4 half2x4; | |||||
| typedef f16mat3x2 half3x2; | |||||
| typedef f16mat3x4 half3x4; | |||||
| typedef f16mat4x2 half4x2; | |||||
| typedef f16mat4x3 half4x3; | |||||
| typedef ivec2 int2; | |||||
| typedef ivec3 int3; | |||||
| typedef ivec4 int4; | |||||
| typedef ivec5 int5; | |||||
| typedef ivec6 int6; | |||||
| typedef ivec7 int7; | |||||
| typedef ivec8 int8; | |||||
| typedef ivec9 int9; | |||||
| typedef ivec10 int10; | |||||
| typedef ivec11 int11; | |||||
| typedef ivec12 int12; | |||||
| typedef imat2 int2x2; | |||||
| typedef imat3 int3x3; | |||||
| typedef imat4 int4x4; | |||||
| typedef imat2x3 int2x3; | |||||
| typedef imat2x4 int2x4; | |||||
| typedef imat3x2 int3x2; | |||||
| typedef imat3x4 int3x4; | |||||
| typedef imat4x2 int4x2; | |||||
| typedef imat4x3 int4x3; | |||||
| } /* namespace lol */ | |||||
| @@ -15,6 +15,9 @@ | |||||
| // --------------------- | // --------------------- | ||||
| // | // | ||||
| #include <../legacy/lol/math/geometry.h> // box3 | |||||
| #include <lol/math/vector.h> // vec3, vec4 etc. | |||||
| #include <stdint.h> | #include <stdint.h> | ||||
| namespace lol | namespace lol | ||||
| @@ -12,6 +12,6 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <lol/image/pixel.h> | |||||
| #include <../legacy/lol/image/pixel.h> | |||||
| #include <lol/image/resource.h> | #include <lol/image/resource.h> | ||||
| @@ -17,10 +17,9 @@ | |||||
| // --------------- | // --------------- | ||||
| // | // | ||||
| #include <lol/math/arraynd.h> | |||||
| #include <../legacy/lol/math/arraynd.h> | |||||
| #include <lol/math/vector.h> | #include <lol/math/vector.h> | ||||
| #include <lol/math/geometry.h> | |||||
| #include <lol/image/pixel.h> | |||||
| #include <../legacy/lol/image/pixel.h> | |||||
| #include <string> | #include <string> | ||||
| @@ -17,7 +17,7 @@ | |||||
| // --------------- | // --------------- | ||||
| // | // | ||||
| #include <lol/image/pixel.h> | |||||
| #include <../legacy/lol/image/pixel.h> | |||||
| #include <lol/image/image.h> | #include <lol/image/image.h> | ||||
| extern "C" struct AVFormatContext; | extern "C" struct AVFormatContext; | ||||
| @@ -1,79 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2004—2015 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| // | |||||
| // The Pixel-related classes | |||||
| // ------------------------- | |||||
| // | |||||
| #include <lol/base/types.h> | |||||
| #include <lol/math/vector.h> | |||||
| namespace lol | |||||
| { | |||||
| /* The pixel formats we know about */ | |||||
| enum class PixelFormat | |||||
| { | |||||
| /* XXX: make sure to update image.cpp and texture.cpp when this changes */ | |||||
| Unknown, | |||||
| Y_8, | |||||
| RGB_8, | |||||
| RGBA_8, | |||||
| Y_F32, | |||||
| RGB_F32, | |||||
| RGBA_F32, | |||||
| }; | |||||
| /* Associated storage types for each pixel format */ | |||||
| template <PixelFormat T> struct PixelType { typedef void type; }; | |||||
| template<> struct PixelType<PixelFormat::Y_8> { typedef uint8_t type; }; | |||||
| template<> struct PixelType<PixelFormat::RGB_8> { typedef u8vec3 type; }; | |||||
| template<> struct PixelType<PixelFormat::RGBA_8> { typedef u8vec4 type; }; | |||||
| template<> struct PixelType<PixelFormat::Y_F32> { typedef float type; }; | |||||
| template<> struct PixelType<PixelFormat::RGB_F32> { typedef vec3 type; }; | |||||
| template<> struct PixelType<PixelFormat::RGBA_F32> { typedef vec4 type; }; | |||||
| /* Number of bytes used by each pixel format */ | |||||
| static inline uint8_t BytesPerPixel(PixelFormat format) | |||||
| { | |||||
| #if __GNUC__ | |||||
| #pragma GCC diagnostic push | |||||
| #pragma GCC diagnostic error "-Wswitch" | |||||
| #endif | |||||
| switch (format) | |||||
| { | |||||
| case PixelFormat::Unknown: | |||||
| break; | |||||
| case PixelFormat::Y_8: | |||||
| return sizeof(PixelType<PixelFormat::Y_8>::type); | |||||
| case PixelFormat::RGB_8: | |||||
| return sizeof(PixelType<PixelFormat::RGB_8>::type); | |||||
| case PixelFormat::RGBA_8: | |||||
| return sizeof(PixelType<PixelFormat::RGBA_8>::type); | |||||
| case PixelFormat::Y_F32: | |||||
| return sizeof(PixelType<PixelFormat::Y_F32>::type); | |||||
| case PixelFormat::RGB_F32: | |||||
| return sizeof(PixelType<PixelFormat::RGB_F32>::type); | |||||
| case PixelFormat::RGBA_F32: | |||||
| return sizeof(PixelType<PixelFormat::RGBA_F32>::type); | |||||
| } | |||||
| return 0; | |||||
| #if __GNUC__ | |||||
| #pragma GCC diagnostic pop | |||||
| #endif | |||||
| }; | |||||
| } /* namespace lol */ | |||||
| @@ -18,11 +18,11 @@ | |||||
| // —————————————————— | // —————————————————— | ||||
| // | // | ||||
| #include <lol/math/arraynd.h> | |||||
| #include <../legacy/lol/math/arraynd.h> | |||||
| #include <lol/math/vector.h> | #include <lol/math/vector.h> | ||||
| #include <lol/math/geometry.h> | |||||
| #include <../legacy/lol/math/geometry.h> | |||||
| #include <lol/image/image.h> | #include <lol/image/image.h> | ||||
| #include <lol/image/pixel.h> | |||||
| #include <../legacy/lol/image/pixel.h> | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -1,27 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <lol/math/constants.h> | |||||
| #include <lol/math/functions.h> | |||||
| #include <lol/math/vector.h> | |||||
| #include <lol/math/transform.h> | |||||
| #include <lol/math/arraynd.h> | |||||
| #include <lol/math/geometry.h> | |||||
| #include <lol/math/interp.h> | |||||
| #include <lol/math/rand.h> | |||||
| #include <lol/math/noise/gradient.h> | |||||
| #include <lol/math/noise/perlin.h> | |||||
| #include <lol/math/noise/simplex.h> | |||||
| @@ -1,282 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2014 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // © 2013—2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| // | |||||
| // The arraynd class | |||||
| // ----------------- | |||||
| // A N-Dimensional array class allowing var[i][j][k]... indexing, | |||||
| // | |||||
| // | |||||
| // XXX: This file is in lol/math/ instead of lol/base/ because it uses vec_t. | |||||
| // | |||||
| #include <lol/base/array.h> | |||||
| #include <lol/base/assert.h> | |||||
| #include <cstddef> | |||||
| #include <climits> | |||||
| #include <type_traits> | |||||
| namespace lol | |||||
| { | |||||
| template<typename T, int L> | |||||
| class arraynd_initializer | |||||
| { | |||||
| public: | |||||
| arraynd_initializer(std::initializer_list<arraynd_initializer<T, L - 1> > const & initializers) : | |||||
| m_initializers(initializers) | |||||
| { | |||||
| } | |||||
| void fill_sizes(ptrdiff_t * sizes) | |||||
| { | |||||
| *sizes = max(*sizes, (ptrdiff_t)m_initializers.size()); | |||||
| for (auto subinitializer : m_initializers) | |||||
| subinitializer.fill_sizes(sizes - 1); | |||||
| } | |||||
| void fill_values(T * origin, ptrdiff_t prev, ptrdiff_t * sizes) | |||||
| { | |||||
| int pos = 0; | |||||
| for (auto subinitializer : m_initializers) | |||||
| subinitializer.fill_values(origin, pos++ + prev * *sizes, sizes - 1); | |||||
| } | |||||
| private: | |||||
| std::initializer_list<arraynd_initializer<T, L - 1> > const & m_initializers; | |||||
| }; | |||||
| template<typename T> | |||||
| class arraynd_initializer<T, 1> | |||||
| { | |||||
| public: | |||||
| arraynd_initializer(std::initializer_list<T> const & initializers) : | |||||
| m_initializers(initializers) | |||||
| { | |||||
| } | |||||
| void fill_sizes(ptrdiff_t * sizes) | |||||
| { | |||||
| *sizes = max(*sizes, (ptrdiff_t)m_initializers.size()); | |||||
| } | |||||
| void fill_values(T * origin, ptrdiff_t prev, ptrdiff_t * sizes) | |||||
| { | |||||
| int pos = 0; | |||||
| for (auto value : m_initializers) | |||||
| *(origin + prev * *sizes + pos++) = value; | |||||
| } | |||||
| private: | |||||
| std::initializer_list<T> const & m_initializers; | |||||
| }; | |||||
| template<int N, typename... T> | |||||
| class [[nodiscard]] arraynd : protected array<T...> | |||||
| { | |||||
| public: | |||||
| typedef array<T...> super; | |||||
| typedef typename super::element_t element_t; | |||||
| inline arraynd() = default; | |||||
| inline arraynd(vec_t<ptrdiff_t, N> sizes, element_t e = element_t()) | |||||
| : m_sizes(sizes) | |||||
| { | |||||
| resize_data(e); | |||||
| } | |||||
| /* Additional constructor if ptrdiff_t != int */ | |||||
| template<typename T2 = int, typename T3 = typename std::enable_if<!std::is_same<ptrdiff_t, T2>::value, int>::type> | |||||
| inline arraynd(vec_t<T2, N> sizes, element_t e = element_t()) | |||||
| : m_sizes(vec_t<ptrdiff_t, N>(sizes)) | |||||
| { | |||||
| resize_data(e); | |||||
| } | |||||
| inline arraynd(std::initializer_list<arraynd_initializer<element_t, N - 1> > initializer) | |||||
| { | |||||
| m_sizes[N - 1] = initializer.size(); | |||||
| for (auto inner_initializer : initializer) | |||||
| inner_initializer.fill_sizes(&m_sizes[N - 2]); | |||||
| resize_data(); | |||||
| int pos = 0; | |||||
| for (auto inner_initializer : initializer) | |||||
| inner_initializer.fill_values(&super::operator[](0), pos++, &m_sizes[N - 2]); | |||||
| } | |||||
| /* Access elements directly using an vec_t<ptrdiff_t, N> index */ | |||||
| inline element_t const & operator[](vec_t<ptrdiff_t, N> const &pos) const | |||||
| { | |||||
| ptrdiff_t n = pos[N - 1]; | |||||
| for (ptrdiff_t i = N - 2; i >= 0; --i) | |||||
| n = pos[i] + m_sizes[i + 1] * n; | |||||
| return super::operator[](n); | |||||
| } | |||||
| inline element_t & operator[](vec_t<ptrdiff_t, N> const &pos) | |||||
| { | |||||
| return const_cast<element_t &>( | |||||
| const_cast<arraynd<N, T...> const&>(*this)[pos]); | |||||
| } | |||||
| /* If int != ptrdiff_t, access elements directly using an ivec2, | |||||
| * ivec3 etc. */ | |||||
| template<typename T2 = int, typename T3 = typename std::enable_if<!std::is_same<ptrdiff_t, T2>::value, int>::type> | |||||
| inline element_t const & operator[](vec_t<T2, N> const &pos) const | |||||
| { | |||||
| ptrdiff_t n = pos[N - 1]; | |||||
| for (ptrdiff_t i = N - 2; i >= 0; --i) | |||||
| n = pos[i] + m_sizes[i + 1] * n; | |||||
| return super::operator[](n); | |||||
| } | |||||
| template<typename T2 = int, typename T3 = typename std::enable_if<!std::is_same<ptrdiff_t, T2>::value, int>::type> | |||||
| inline element_t & operator[](vec_t<T2, N> const &pos) | |||||
| { | |||||
| return const_cast<element_t &>( | |||||
| const_cast<arraynd<N, T...> const&>(*this)[pos]); | |||||
| } | |||||
| /* Proxy to access slices */ | |||||
| template<typename ARRAY_TYPE, int L = N - 1> | |||||
| class slice | |||||
| { | |||||
| public: | |||||
| typedef slice<ARRAY_TYPE, L - 1> subslice; | |||||
| inline slice(ARRAY_TYPE &array, ptrdiff_t index, ptrdiff_t accumulator) | |||||
| : m_array(array), | |||||
| m_index(index), | |||||
| m_accumulator(accumulator) | |||||
| { | |||||
| } | |||||
| /* Accessors for the const version of the proxy */ | |||||
| template<bool V = L != 1 && std::is_const<ARRAY_TYPE>::value> | |||||
| inline typename std::enable_if<V, subslice>::type | |||||
| operator[](ptrdiff_t pos) const | |||||
| { | |||||
| return subslice(m_array, m_index + pos * m_accumulator, | |||||
| m_accumulator * m_array.m_sizes[N - L]); | |||||
| } | |||||
| template<bool V = L == 1 && std::is_const<ARRAY_TYPE>::value> | |||||
| inline typename std::enable_if<V, typename ARRAY_TYPE::element_t>::type | |||||
| const & operator[](ptrdiff_t pos) const | |||||
| { | |||||
| return m_array.super::operator[](m_index + pos * m_accumulator); | |||||
| } | |||||
| /* Accessors for the non-const version of the proxy */ | |||||
| template<bool V = L != 1 && !std::is_const<ARRAY_TYPE>::value> | |||||
| inline typename std::enable_if<V, subslice>::type | |||||
| operator[](ptrdiff_t pos) | |||||
| { | |||||
| return subslice(m_array, m_index + pos * m_accumulator, | |||||
| m_accumulator * m_array.m_sizes[N - L]); | |||||
| } | |||||
| template<bool V = L == 1 && !std::is_const<ARRAY_TYPE>::value> | |||||
| inline typename std::enable_if<V, typename ARRAY_TYPE::element_t>::type | |||||
| & operator[](ptrdiff_t pos) | |||||
| { | |||||
| return m_array.super::operator[](m_index + pos * m_accumulator); | |||||
| } | |||||
| private: | |||||
| ARRAY_TYPE &m_array; | |||||
| ptrdiff_t m_index, m_accumulator; | |||||
| }; | |||||
| /* Access addressable slices, allowing for array[i][j][...] syntax. */ | |||||
| inline slice<arraynd<N, T...> const> operator[](ptrdiff_t pos) const | |||||
| { | |||||
| return slice<arraynd<N, T...> const>(*this, pos, m_sizes[0]); | |||||
| } | |||||
| inline slice<arraynd<N, T...>> operator[](ptrdiff_t pos) | |||||
| { | |||||
| return slice<arraynd<N, T...>>(*this, pos, m_sizes[0]); | |||||
| } | |||||
| /* Resize the array. | |||||
| * FIXME: data gets scrambled; should we care? */ | |||||
| inline void resize(vec_t<int, N> sizes, element_t e = element_t()) | |||||
| { | |||||
| resize_s(vec_t<ptrdiff_t, N>(sizes), e); | |||||
| } | |||||
| inline void resize_s(vec_t<ptrdiff_t, N> sizes, element_t e = element_t()) | |||||
| { | |||||
| m_sizes = sizes; | |||||
| resize_data(e); | |||||
| } | |||||
| inline vec_t<int, N> size() const | |||||
| { | |||||
| return vec_t<int, N>(this->m_sizes); | |||||
| } | |||||
| inline vec_t<ptrdiff_t, N> size_s() const | |||||
| { | |||||
| return this->m_sizes; | |||||
| } | |||||
| public: | |||||
| inline element_t *data() { return super::data(); } | |||||
| inline element_t const *data() const { return super::data(); } | |||||
| inline int count() const { return super::count(); } | |||||
| inline int bytes() const { return super::bytes(); } | |||||
| inline ptrdiff_t count_s() const { return super::count_s(); } | |||||
| inline ptrdiff_t bytes_s() const { return super::bytes_s(); } | |||||
| private: | |||||
| inline void resize_data(element_t e = element_t()) | |||||
| { | |||||
| ptrdiff_t total_size = 1; | |||||
| /* HACK: we can't use for (auto s : m_sizes) because of an ICE in | |||||
| * the Visual Studio compiler. */ | |||||
| for (int i = 0; i < N; ++i) | |||||
| total_size *= m_sizes[i]; | |||||
| this->array<T...>::resize(total_size, e); | |||||
| } | |||||
| vec_t<ptrdiff_t, N> m_sizes { 0 }; | |||||
| }; | |||||
| template<typename... T> using array2d = arraynd<2, T...>; | |||||
| template<typename... T> using array3d = arraynd<3, T...>; | |||||
| } /* namespace lol */ | |||||
| @@ -1,185 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| // | |||||
| // Various maths functions | |||||
| // ----------------------- | |||||
| // | |||||
| #include <lol/math/constants.h> | |||||
| #include <cmath> | |||||
| #include <cstdio> | |||||
| #include <algorithm> | |||||
| #include <type_traits> | |||||
| #include <stdint.h> | |||||
| namespace lol | |||||
| { | |||||
| // This is OUR namespace. Don't let Windows headers mess with it. | |||||
| #undef min | |||||
| #undef max | |||||
| // Macros for type traits | |||||
| #define LOL_T_ARITHMETIC typename std::enable_if<std::is_arithmetic<T>::value, T>::type | |||||
| #define LOL_T_SIGNED typename std::enable_if<std::is_signed<T>::value, T>::type | |||||
| #define LOL_T_UNSIGNED typename std::enable_if<std::is_arithmetic<T>::value && \ | |||||
| !std::is_signed<T>::value, T>::type | |||||
| #define LOL_T_INTEGRAL typename std::enable_if<std::is_integral<T>::value, T>::type | |||||
| #define LOL_T_FLOATING_POINT typename std::enable_if<std::is_floating_point<T>::value, T>::type | |||||
| // Mechanism to import standard cmath functions | |||||
| #define LOL_FORWARD_FP_1_ARG(f) \ | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \ | |||||
| [[nodiscard]] static inline T2 f(T x) { return std::f(x); } | |||||
| #define LOL_FORWARD_ARITH_2_ARGS(f) \ | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_ARITHMETIC> \ | |||||
| [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); } | |||||
| #define LOL_FORWARD_FP_2_ARGS(f) \ | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \ | |||||
| [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); } | |||||
| LOL_FORWARD_FP_1_ARG(sqrt) | |||||
| LOL_FORWARD_FP_1_ARG(cbrt) | |||||
| LOL_FORWARD_FP_1_ARG(exp) | |||||
| LOL_FORWARD_FP_2_ARGS(pow) | |||||
| LOL_FORWARD_FP_1_ARG(sin) | |||||
| LOL_FORWARD_FP_1_ARG(cos) | |||||
| LOL_FORWARD_FP_1_ARG(tan) | |||||
| LOL_FORWARD_FP_1_ARG(asin) | |||||
| LOL_FORWARD_FP_1_ARG(acos) | |||||
| LOL_FORWARD_FP_1_ARG(atan) | |||||
| LOL_FORWARD_FP_2_ARGS(atan2) | |||||
| LOL_FORWARD_ARITH_2_ARGS(min) | |||||
| LOL_FORWARD_ARITH_2_ARGS(max) | |||||
| LOL_FORWARD_FP_2_ARGS(fmod) | |||||
| LOL_FORWARD_FP_1_ARG(floor) | |||||
| LOL_FORWARD_FP_1_ARG(ceil) | |||||
| LOL_FORWARD_FP_1_ARG(round) | |||||
| // Our extensions | |||||
| template<typename T, typename T2 = LOL_T_FLOATING_POINT> | |||||
| [[nodiscard]] static inline T2 sincos(T x, T *s, T *c) | |||||
| { | |||||
| *s = std::sin(x); | |||||
| *c = std::cos(x); | |||||
| } | |||||
| // Inherited from GLSL | |||||
| [[nodiscard]] static inline float degrees(float radians) | |||||
| { | |||||
| return radians * (180.0f / F_PI); | |||||
| } | |||||
| [[nodiscard]] static inline double degrees(double radians) | |||||
| { | |||||
| return radians * (180.0 / D_PI); | |||||
| } | |||||
| [[nodiscard]] static inline ldouble degrees(ldouble radians) | |||||
| { | |||||
| return radians * (180.0L / LD_PI); | |||||
| } | |||||
| [[nodiscard]] static inline float radians(float degrees) | |||||
| { | |||||
| return degrees * (F_PI / 180.0f); | |||||
| } | |||||
| [[nodiscard]] static inline double radians(double degrees) | |||||
| { | |||||
| return degrees * (D_PI / 180.0); | |||||
| } | |||||
| [[nodiscard]] static inline ldouble radians(ldouble degrees) | |||||
| { | |||||
| return degrees * (LD_PI / 180.0L); | |||||
| } | |||||
| // The integer versions return floating point values. This avoids nasty | |||||
| // surprises when calling radians(180) instead of radians(180.0). | |||||
| [[nodiscard]] static inline float degrees(int8_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline float degrees(uint8_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline float degrees(int16_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline float degrees(uint16_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline double degrees(int32_t x) { return degrees(double(x)); } | |||||
| [[nodiscard]] static inline double degrees(uint32_t x) { return degrees(double(x)); } | |||||
| [[nodiscard]] static inline ldouble degrees(int64_t x) { return degrees(ldouble(x)); } | |||||
| [[nodiscard]] static inline ldouble degrees(uint64_t x) { return degrees(ldouble(x)); } | |||||
| [[nodiscard]] static inline float radians(int8_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline float radians(uint8_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline float radians(int16_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline float radians(uint16_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline double radians(int32_t x) { return radians(double(x)); } | |||||
| [[nodiscard]] static inline double radians(uint32_t x) { return radians(double(x)); } | |||||
| [[nodiscard]] static inline ldouble radians(int64_t x) { return radians(ldouble(x)); } | |||||
| [[nodiscard]] static inline ldouble radians(uint64_t x) { return radians(ldouble(x)); } | |||||
| template<typename T, typename T2 = LOL_T_FLOATING_POINT> | |||||
| [[nodiscard]] static inline T2 mix(T a, T b, T x) | |||||
| { | |||||
| return a + (b - a) * x; | |||||
| } | |||||
| // Inherited from HLSL | |||||
| template<typename T, typename T2 = LOL_T_FLOATING_POINT> | |||||
| [[nodiscard]] static inline T2 lerp(T a, T b, T x) | |||||
| { | |||||
| return mix(a, b, x); | |||||
| } | |||||
| // C++ doesn't define abs() or fmod() for all types; we add these for | |||||
| // convenience to avoid adding complexity to vector.h. | |||||
| template<typename T, typename T2 = LOL_T_SIGNED> | |||||
| [[nodiscard]] static inline T2 abs(T x) { return std::abs(x); } | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | |||||
| [[nodiscard]] static inline T2 abs(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | |||||
| [[nodiscard]] static inline T2 fmod(T x, T y) { return x % y; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | |||||
| [[nodiscard]] static inline T2 floor(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | |||||
| [[nodiscard]] static inline T2 ceil(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | |||||
| [[nodiscard]] static inline T2 round(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | |||||
| [[nodiscard]] static inline T2 sq(T x) { return x * x; } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | |||||
| [[nodiscard]] static inline T2 fract(T x) { return x - lol::floor(x); } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | |||||
| [[nodiscard]] static inline T2 clamp(T x, T y, T z) { return min(max(x, y), z); } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | |||||
| [[nodiscard]] static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | |||||
| [[nodiscard]] static inline T2 gcd(T x, T y) { return y == (T)0 ? lol::abs(x) : lol::gcd(y, lol::fmod(x, y)); } | |||||
| template<typename T, typename T2 = LOL_T_SIGNED> | |||||
| [[nodiscard]] static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); } | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | |||||
| [[nodiscard]] static inline T2 sign(T x) { return (T)((T)0 < x); } | |||||
| } /* namespace lol */ | |||||
| @@ -1,382 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2010—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| // | |||||
| // Various geometry functions | |||||
| // -------------------------- | |||||
| // | |||||
| #include <lol/base/enum.h> | |||||
| #include <algorithm> | |||||
| #include <map> | |||||
| #include <cmath> | |||||
| #include <cstdio> | |||||
| #include <cstdint> | |||||
| namespace lol | |||||
| { | |||||
| //AxisBase -------------------------------------------------------------------- | |||||
| struct AxisBase : public StructSafeEnum | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| X = 0, Y, Z, MAX, XY = 2, XYZ = 3, | |||||
| }; | |||||
| protected: | |||||
| virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map) | |||||
| { | |||||
| enum_map[X] = "X"; | |||||
| enum_map[Y] = "Y"; | |||||
| enum_map[Z] = "Z"; | |||||
| enum_map[MAX] = "MAX"; | |||||
| enum_map[XY] = "XY"; | |||||
| enum_map[XYZ] = "XYZ"; | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| typedef SafeEnum<AxisBase> Axis; | |||||
| //DirectionBase --------------------------------------------------------------- | |||||
| struct DirectionBase : public StructSafeEnum | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| Up = 0, Down, Left, Right, MAX, | |||||
| }; | |||||
| protected: | |||||
| virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map) | |||||
| { | |||||
| enum_map[Up] = "Up"; | |||||
| enum_map[Down] = "Down"; | |||||
| enum_map[Left] = "Left"; | |||||
| enum_map[Right] = "Right"; | |||||
| enum_map[MAX] = "MAX"; | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| typedef SafeEnum<DirectionBase> Direction; | |||||
| /* | |||||
| * Generic box type names | |||||
| */ | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; | |||||
| /* Idiotic hack to put "," inside a macro argument */ | |||||
| #define C_ , | |||||
| T_(box_t<, C_ 2>, box2) | |||||
| T_(box_t<, C_ 3>, box3) | |||||
| T_(box_t<, C_ 4>, box4) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| template<typename T, int N> | |||||
| struct [[nodiscard]] box_t | |||||
| { | |||||
| inline box_t() | |||||
| : aa(vec_t<T, N>(T(0))), | |||||
| bb(vec_t<T, N>(T(0))) | |||||
| {} | |||||
| inline box_t(vec_t<T,N> const &a, vec_t<T,N> const &b) | |||||
| : aa(a), | |||||
| bb(b) | |||||
| {} | |||||
| inline box_t(T const &ax, T const &ay, T const &bx, T const &by) | |||||
| : aa(ax, ay), | |||||
| bb(bx, by) | |||||
| {} | |||||
| inline box_t(T const &ax, T const &ay, T const &az, | |||||
| T const &bx, T const &by, T const &bz) | |||||
| : aa(ax, ay, az), | |||||
| bb(bx, by, bz) | |||||
| {} | |||||
| box_t<T,N> operator +(vec_t<T,N> const &v) const | |||||
| { | |||||
| return box_t<T,N>(aa + v, bb + v); | |||||
| } | |||||
| box_t<T,N> &operator +=(vec_t<T,N> const &v) | |||||
| { | |||||
| return *this = *this + v; | |||||
| } | |||||
| box_t<T,N> operator -(vec_t<T,N> const &v) const | |||||
| { | |||||
| return box_t<T,N>(aa - v, bb - v); | |||||
| } | |||||
| box_t<T,N> &operator -=(vec_t<T,N> const &v) | |||||
| { | |||||
| return *this = *this - v; | |||||
| } | |||||
| box_t<T,N> operator *(vec_t<T,N> const &v) const | |||||
| { | |||||
| return box_t<T,N>(aa * v, bb * v); | |||||
| } | |||||
| box_t<T,N> &operator *=(vec_t<T,N> const &v) | |||||
| { | |||||
| return *this = *this * v; | |||||
| } | |||||
| box_t<T,N> operator *(T const &s) const | |||||
| { | |||||
| return box_t<T,N>(aa * s, bb * s); | |||||
| } | |||||
| box_t<T,N> &operator *=(T const &s) | |||||
| { | |||||
| return *this = *this * s; | |||||
| } | |||||
| [[nodiscard]] bool operator ==(box_t<T,N> const &box) const | |||||
| { | |||||
| return aa == box.aa && bb == box.bb; | |||||
| } | |||||
| [[nodiscard]] bool operator !=(box_t<T,N> const &box) const | |||||
| { | |||||
| return aa != box.aa || bb != box.bb; | |||||
| } | |||||
| inline vec_t<T,N> center() const { return (bb + aa) / 2; } | |||||
| inline vec_t<T,N> extent() const { return bb - aa; } | |||||
| vec_t<T,N> aa, bb; | |||||
| }; | |||||
| static_assert(sizeof(box2) == 16, "sizeof(box2) == 16"); | |||||
| static_assert(sizeof(box3) == 24, "sizeof(box3) == 24"); | |||||
| static_assert(sizeof(dbox2) == 32, "sizeof(dbox2) == 32"); | |||||
| static_assert(sizeof(dbox3) == 48, "sizeof(dbox3) == 48"); | |||||
| /* | |||||
| * Helper geometry functions | |||||
| */ | |||||
| class TestEpsilon | |||||
| { | |||||
| private: | |||||
| float m_epsilon; | |||||
| float m_value; | |||||
| public: | |||||
| TestEpsilon() { m_value = 0.f; m_epsilon = .0001f; } | |||||
| static float Get(); | |||||
| static void Set(float epsilon=.0001f); | |||||
| static const TestEpsilon& F(float value); | |||||
| private: | |||||
| float Minus() const; | |||||
| float Plus() const; | |||||
| public: | |||||
| [[nodiscard]] bool operator==(float value) const; | |||||
| [[nodiscard]] bool operator!=(float value) const; | |||||
| [[nodiscard]] bool operator<(float value) const; | |||||
| [[nodiscard]] bool operator<=(float value) const; | |||||
| [[nodiscard]] bool operator>(float value) const; | |||||
| [[nodiscard]] bool operator>=(float value) const; | |||||
| }; | |||||
| [[nodiscard]] bool operator==(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator!=(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator<(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator<=(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator>(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator>=(float value, const TestEpsilon& epsilon); | |||||
| //-- | |||||
| static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) | |||||
| { | |||||
| vec2 c = b1.center() - b2.center(); | |||||
| vec2 e1 = 0.5f * b1.extent(); | |||||
| vec2 e2 = 0.5f * b2.extent(); | |||||
| return abs(c.x) <= e1.x + e2.x | |||||
| && abs(c.y) <= e1.y + e2.y; | |||||
| } | |||||
| static inline bool TestAABBVsPoint(box2 const &b1, vec2 const &p) | |||||
| { | |||||
| return TestAABBVsAABB(b1, box2(p, p)); | |||||
| } | |||||
| static inline bool TestAABBVsAABB(box3 const &b1, box3 const &b2) | |||||
| { | |||||
| vec3 c = b1.center() - b2.center(); | |||||
| vec3 e1 = 0.5f * b1.extent(); | |||||
| vec3 e2 = 0.5f * b2.extent(); | |||||
| return abs(c.x) <= e1.x + e2.x | |||||
| && abs(c.y) <= e1.y + e2.y | |||||
| && abs(c.z) <= e1.z + e2.z; | |||||
| } | |||||
| static inline bool TestAABBVsPoint(box3 const &b1, vec3 const &p) | |||||
| { | |||||
| return TestAABBVsAABB(b1, box3(p, p)); | |||||
| } | |||||
| bool TestTriangleVsTriangle(vec3 const &v00, vec3 const &v01, vec3 const &v02, | |||||
| vec3 const &v10, vec3 const &v11, vec3 const &v12, | |||||
| vec3 &ip00, vec3 &ip10); | |||||
| bool TestRayVsTriangleSide(vec3 const &v0, vec3 const &v1, vec3 const &v2, | |||||
| vec3 const &ip0, vec3 const &ip1, | |||||
| vec3 &iV0, int &iIdx0, vec3 &iV1, int &iIdx1); | |||||
| bool TestRayVsTriangle(vec3 const &ray_point, vec3 const &ray_dir, | |||||
| vec3 const &tri_p0, vec3 const &tri_p1, vec3 const &tri_p2, | |||||
| vec3 &vi); | |||||
| //RayIntersect ---------------------------------------------------------------- | |||||
| struct RayIntersectBase : public StructSafeEnum | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| Nothing, | |||||
| All, | |||||
| None, | |||||
| P0, | |||||
| P1, | |||||
| }; | |||||
| //LOL_DECLARE_ENUM_METHODS(RayIntersectBase) | |||||
| protected: | |||||
| virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map) | |||||
| { | |||||
| enum_map[Nothing] = "Nothing"; | |||||
| enum_map[All] = "All"; | |||||
| enum_map[None] = "None"; | |||||
| enum_map[P0] = "P0"; | |||||
| enum_map[P1] = "P1"; | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| typedef SafeEnum<RayIntersectBase> RayIntersect; | |||||
| #define RAY_ISECT_NOTHING 0 | |||||
| #define RAY_ISECT_ALL 1 | |||||
| #define RAY_ISECT_NONE 2 | |||||
| #define RAY_ISECT_P0 3 | |||||
| #define RAY_ISECT_P1 4 | |||||
| int TestRayVsRay(vec3 const &ray_p00, vec3 const &ray_p01, | |||||
| vec3 const &ray_p10, vec3 const &ray_p11, | |||||
| vec3 &isec_p); | |||||
| bool TestPointVsFrustum(const vec3& point, const mat4& frustum, vec3* result_point = nullptr); | |||||
| //Ray/Plane : Normal must be given normalized. returns 1 if succeeded. | |||||
| template <typename TV> | |||||
| bool TestRayVsPlane(const TV &ray_p0, const TV &ray_p1, | |||||
| const TV &plane_p, const TV &plane_n, | |||||
| TV &isec_p, bool test_line_only=false) | |||||
| { | |||||
| TV ray_dir = ray_p1 - ray_p0; | |||||
| float d = dot(ray_dir, plane_n); | |||||
| if (d > -TestEpsilon::Get() && d < TestEpsilon::Get()) | |||||
| return false; | |||||
| TV o2p1 = ray_p1 - plane_p; | |||||
| TV o2p0 = ray_p0 - plane_p; | |||||
| if (!test_line_only) | |||||
| { | |||||
| d = dot(o2p1, plane_n); | |||||
| d *= dot(o2p0, plane_n); | |||||
| //point are on the same side, so ray can intersect. | |||||
| if (d > .0f) | |||||
| return false; | |||||
| } | |||||
| float t = (dot(ProjectPointOnPlane(ray_p0, plane_p, plane_n) - ray_p0, plane_n)) / dot(ray_dir, plane_n); | |||||
| if (!test_line_only && (t < -TestEpsilon::Get() || t > 1.f + TestEpsilon::Get())) | |||||
| return false; | |||||
| isec_p = ray_p0 + t * ray_dir; | |||||
| return true; | |||||
| } | |||||
| //PlaneIntersectionBase ------------------------------------------------------- | |||||
| struct PlaneIntersectionBase : public StructSafeEnum | |||||
| { | |||||
| /* A safe enum for Primitive edge face. */ | |||||
| enum Type | |||||
| { | |||||
| Back, Front, Plane, | |||||
| }; | |||||
| protected: | |||||
| virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map) | |||||
| { | |||||
| enum_map[Back] = "Back"; | |||||
| enum_map[Front] = "Front"; | |||||
| enum_map[Plane] = "Plane"; | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| typedef SafeEnum<PlaneIntersectionBase> PlaneIntersection; | |||||
| //Point/Plane : Normal must be given normalized. | |||||
| template <typename TV> | |||||
| PlaneIntersection TestPointVsPlane(const TV &point, const TV &plane_p, const TV &plane_n) | |||||
| { | |||||
| float d = dot(normalize(point - plane_p), plane_n); | |||||
| if (d > TestEpsilon::Get()) | |||||
| return PlaneIntersection::Front; | |||||
| else if (d < -TestEpsilon::Get()) | |||||
| return PlaneIntersection::Back; | |||||
| else | |||||
| return PlaneIntersection::Plane; | |||||
| } | |||||
| /* Project point on plane */ | |||||
| template <typename TV> | |||||
| TV ProjectPointOnPlane(TV const &p, TV const &origin, TV const &normal) | |||||
| { | |||||
| return p - dot(p - origin, normal) * normal; | |||||
| } | |||||
| /* Project point on line */ | |||||
| template <typename TV> | |||||
| TV ProjectPointOnRay(TV const &p, TV const &origin, TV const &direction) | |||||
| { | |||||
| return origin + direction * dot(p - origin, direction); | |||||
| } | |||||
| /* Distance from point to plane */ | |||||
| template <typename TV> | |||||
| float PointDistToPlane(TV const &p, TV const &origin, TV const &normal) | |||||
| { | |||||
| return abs(dot(p - origin, normal)); | |||||
| } | |||||
| /* Distance from point to segment */ | |||||
| template <typename TV> | |||||
| float PointDistToSegment(TV const &p, TV const &a, TV const &b) | |||||
| { | |||||
| float d2 = sqlength(b - a); | |||||
| float u = d2 ? dot(p - a, b - a) / d2 : 0.0f; | |||||
| return distance(p, mix(a, b, clamp(u, 0.0f, 1.0f))); | |||||
| } | |||||
| } /* namespace lol */ | |||||
| @@ -1,118 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| // | |||||
| // Interpolator classes | |||||
| // -------------------- | |||||
| // | |||||
| namespace lol | |||||
| { | |||||
| template<typename T, int N = 16> class TimeInterp | |||||
| { | |||||
| public: | |||||
| inline TimeInterp() | |||||
| : m_precision(0.f), | |||||
| m_accum(0.f), | |||||
| m_pos(-N) | |||||
| {} | |||||
| inline ~TimeInterp() {} | |||||
| void SetPrecision(float seconds) | |||||
| { | |||||
| m_precision = seconds; | |||||
| } | |||||
| void Set(float seconds, T const &val) | |||||
| { | |||||
| m_accum += seconds; | |||||
| if (m_accum < m_precision) | |||||
| return; | |||||
| m_accum = 0.f; | |||||
| if (m_pos < 0) | |||||
| { | |||||
| if (m_pos > -N) | |||||
| seconds += m_key[m_pos + N - 1]; | |||||
| m_key[m_pos + N] = seconds; | |||||
| m_val[m_pos + N] = val; | |||||
| ++m_pos; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (m_pos > 0) | |||||
| seconds += m_key[m_pos - 1]; | |||||
| m_key[m_pos] = seconds; | |||||
| m_val[m_pos] = val; | |||||
| m_pos = (m_pos + 1) % N; | |||||
| } | |||||
| } | |||||
| T Get(float seconds) | |||||
| { | |||||
| if (m_pos == -N) | |||||
| return T(); | |||||
| if (m_pos == 1 - N) | |||||
| return m_val[0]; | |||||
| seconds += m_accum; | |||||
| int start = max(0, m_pos); | |||||
| int a = 0; | |||||
| int b = min(m_pos + N - 1, N - 1); | |||||
| while (a + 1 < b) | |||||
| { | |||||
| int c = (a + b) / 2; | |||||
| if (GetTime((start + c) % N) >= seconds) | |||||
| b = c; | |||||
| else | |||||
| a = c; | |||||
| } | |||||
| float ka = GetTime((start + a) % N); | |||||
| float kb = GetTime((start + b) % N); | |||||
| float u = (seconds - ka) / (kb - ka); | |||||
| return (1.f - u) * m_val[(start + a) % N] + u * m_val[(start + b) % N]; | |||||
| } | |||||
| inline void Reset() | |||||
| { | |||||
| m_pos = -N; | |||||
| } | |||||
| private: | |||||
| inline float GetTime(int i) | |||||
| { | |||||
| float k = m_key[i % N]; | |||||
| if (m_pos >= 0 && i >= m_pos) | |||||
| k -= m_key[N - 1]; | |||||
| if (m_pos != 0) | |||||
| k -= m_key[(m_pos + N - 1) % N]; | |||||
| return k; | |||||
| } | |||||
| float m_key[N]; | |||||
| T m_val[N]; | |||||
| float m_precision, m_accum; | |||||
| /* If m_pos < 0, the value indicates how many free slots | |||||
| * there are. */ | |||||
| int m_pos; | |||||
| }; | |||||
| } /* namespace lol */ | |||||
| @@ -1,95 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
| // (c) 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <functional> | |||||
| namespace lol | |||||
| { | |||||
| template<int N> | |||||
| class gradient_provider | |||||
| { | |||||
| public: | |||||
| gradient_provider(int seed = 0) | |||||
| : m_seed(seed) | |||||
| { | |||||
| } | |||||
| protected: | |||||
| vec_t<float, N> get_gradient(vec_t<int, N> origin) const | |||||
| { | |||||
| /* Quick shuffle table: | |||||
| * strings /dev/urandom | grep . -nm256 | sort -k2 -t: | sed 's|:.*|,|' | |||||
| * Then just replace “256” with “0”. */ | |||||
| static int const shuffle[256] = | |||||
| { | |||||
| 111, 14, 180, 186, 221, 114, 219, 79, 66, 46, 152, 81, 246, 200, | |||||
| 141, 172, 85, 244, 112, 92, 34, 106, 218, 205, 236, 7, 121, 115, | |||||
| 109, 131, 10, 96, 188, 148, 17, 107, 94, 182, 235, 163, 143, 63, | |||||
| 248, 202, 52, 154, 37, 241, 53, 129, 25, 159, 242, 38, 171, 213, | |||||
| 6, 203, 255, 193, 42, 209, 28, 176, 210, 60, 54, 144, 3, 71, 89, | |||||
| 116, 12, 237, 67, 216, 252, 178, 174, 164, 98, 234, 32, 26, 175, | |||||
| 24, 130, 128, 113, 99, 212, 62, 11, 75, 185, 73, 93, 31, 30, 44, | |||||
| 122, 173, 139, 91, 136, 162, 194, 41, 56, 101, 68, 69, 211, 151, | |||||
| 97, 55, 83, 33, 50, 119, 156, 149, 208, 157, 253, 247, 161, 133, | |||||
| 230, 166, 225, 204, 224, 13, 110, 123, 142, 64, 65, 155, 215, 9, | |||||
| 197, 140, 58, 77, 214, 126, 195, 179, 220, 232, 125, 147, 8, 39, | |||||
| 187, 27, 217, 100, 134, 199, 88, 206, 231, 250, 74, 2, 135, 120, | |||||
| 21, 245, 118, 243, 82, 183, 238, 150, 158, 61, 4, 177, 146, 153, | |||||
| 117, 249, 254, 233, 90, 222, 207, 48, 15, 18, 20, 16, 47, 0, 51, | |||||
| 165, 138, 127, 169, 72, 1, 201, 145, 191, 192, 239, 49, 19, 160, | |||||
| 226, 228, 84, 181, 251, 36, 87, 22, 43, 70, 45, 105, 5, 189, 95, | |||||
| 40, 196, 59, 57, 190, 80, 104, 167, 78, 124, 103, 240, 184, 170, | |||||
| 137, 29, 23, 223, 108, 102, 86, 198, 227, 35, 229, 76, 168, 132, | |||||
| }; | |||||
| /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not | |||||
| * more than 2^20 (~ 1 million). */ | |||||
| int const gradient_count = 1 << min(max(N + 2, 5), 20); | |||||
| static auto build_gradients = [&]() | |||||
| { | |||||
| array<vec_t<float, N>> ret; | |||||
| for (int k = 0; k < gradient_count; ++k) | |||||
| { | |||||
| vec_t<float, N> v; | |||||
| for (int i = 0; i < N; ++i) | |||||
| v[i] = rand(-1.f, 1.f); | |||||
| ret << normalize(v); | |||||
| } | |||||
| return ret; | |||||
| }; | |||||
| static array<vec_t<float, N>> const gradients = build_gradients(); | |||||
| int idx = m_seed; | |||||
| for (int i = 0; i < N; ++i) | |||||
| idx ^= shuffle[(idx + origin[i]) & 255]; | |||||
| idx &= (gradient_count - 1); | |||||
| #if 0 | |||||
| // DEBUG: only output a few gradients | |||||
| if (idx > 2) | |||||
| return vec_t<float, N>(0); | |||||
| #endif | |||||
| return gradients[idx]; | |||||
| } | |||||
| private: | |||||
| /* A user-provided random seed. Defaults to zero. */ | |||||
| int m_seed; | |||||
| }; | |||||
| } | |||||
| @@ -1,98 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
| // (c) 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <lol/math/noise/gradient.h> | |||||
| namespace lol | |||||
| { | |||||
| template<int N> | |||||
| class perlin_noise : public gradient_provider<N> | |||||
| { | |||||
| public: | |||||
| perlin_noise() | |||||
| : gradient_provider<N>() | |||||
| { | |||||
| } | |||||
| perlin_noise(int seed) | |||||
| : gradient_provider<N>(seed) | |||||
| { | |||||
| } | |||||
| /* Evaluate noise at a given point */ | |||||
| inline float eval(vec_t<float, N> position) const | |||||
| { | |||||
| /* Compute the containing hypercube origin */ | |||||
| vec_t<int, N> origin; | |||||
| for (int i = 0; i < N; ++i) | |||||
| origin[i] = (int)position[i] - (position[i] < 0); | |||||
| vec_t<float, N> delta = position - (vec_t<float, N>)origin; | |||||
| /* Apply a smooth step to delta and store it in “t”. */ | |||||
| vec_t<float, N> t = delta; | |||||
| t = ((6.f * t - vec_t<float, N>(15.f)) | |||||
| * t + vec_t<float, N>(10.f)) * (t * t * t); | |||||
| /* DEBUG: original Perlin noise polynomial */ | |||||
| //t = (vec_t<float, N>(3.f) - 2.f * t) * t * t; | |||||
| /* Premultiply and predivide (1-t)/t and t/(1-t) into “u” and “v”. */ | |||||
| vec_t<float, N> u, v; | |||||
| float multiplier = 1.f; | |||||
| for (int bit = 0; bit < N; ++bit) | |||||
| { | |||||
| /* Avoid divisions by zero near the hypercube boundaries. */ | |||||
| float f = clamp(t[bit], 0.001f, 0.999f); | |||||
| multiplier *= (1.f - f); | |||||
| u[bit] = (1.f - f) / f; | |||||
| v[bit] = f / (1.f - f); | |||||
| } | |||||
| float ret = 0.f; | |||||
| /* Compute all gradient contributions, for each of the 2^N corners | |||||
| * of the hypercube. */ | |||||
| for (int i = 0; ; ++i) | |||||
| { | |||||
| /* Accumulate Perlin noise */ | |||||
| ret += multiplier * dot(delta, this->get_gradient(origin)); | |||||
| /* Avoid buffer overflow below in origin[bit] */ | |||||
| if (i + 1 == (1 << N)) | |||||
| break; | |||||
| /* Don’t use the binary pattern for “i” but use its Gray code | |||||
| * “j” instead, so we know we only have one component to alter | |||||
| * in “origin” and in “delta”. We know which bit was flipped by | |||||
| * looking at “k”, the Gray code for the next value of “i”. */ | |||||
| int j = i ^ (i >> 1); | |||||
| int k = (i + 1) ^ ((i + 1) >> 1); | |||||
| int bit = 0; | |||||
| while ((j ^ k) > (1 << bit)) | |||||
| ++bit; | |||||
| origin[bit] += j > k ? -1 : 1; | |||||
| delta[bit] += j > k ? 1.f : -1.f; | |||||
| multiplier *= (j > k ? u : v)[bit]; | |||||
| } | |||||
| return sqrt(2.f) * ret; | |||||
| } | |||||
| }; | |||||
| } | |||||
| @@ -1,400 +0,0 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright © 2010—2014 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2014 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // © 2013—2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // | |||||
| // Lol Engine is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| #include <lol/math/noise/gradient.h> | |||||
| namespace lol | |||||
| { | |||||
| /* | |||||
| * Simplex noise in dimension N | |||||
| * ---------------------------- | |||||
| * | |||||
| * The N-dimensional regular hypercube can be split into N! simplices that | |||||
| * all have the main diagonal as a shared edge. | |||||
| * - number of simplices: N! | |||||
| * - number of vertices per simplex: N+1 | |||||
| * - number of edges: N(N+1)/2 | |||||
| * - minimum edge length: 1 (hypercube edges, e.g. [1,0,0,…,0]) | |||||
| * - maximum edge length: sqrt(N) (hypercube diagonal, i.e. [1,1,1,…,1]) | |||||
| * | |||||
| * We skew the simplicial grid along the main diagonal by a factor f = | |||||
| * sqrt(N+1), which means the diagonal of the initial parallelotope has | |||||
| * length sqrt(N/(N+1)). The edges of that parallelotope have length | |||||
| * sqrt(N/(N+1)), too. A formula for the maximum edge length was found | |||||
| * empirically: | |||||
| * - minimum edge length: sqrt(N/(N+1)) (parallelotope edges and diagonal) | |||||
| * - maximum edge length: sqrt(floor((N+1)²/4)/(N+1)) | |||||
| */ | |||||
| template<int N> | |||||
| class simplex_noise : public gradient_provider<N> | |||||
| { | |||||
| public: | |||||
| simplex_noise() | |||||
| : gradient_provider<N>() | |||||
| { | |||||
| #if 0 | |||||
| debugprint(); | |||||
| #endif | |||||
| } | |||||
| simplex_noise(int seed) | |||||
| : gradient_provider<N>(seed) | |||||
| { | |||||
| } | |||||
| /* Evaluate noise at a given point */ | |||||
| inline float eval(vec_t<float, N> position) const | |||||
| { | |||||
| // Retrieve the containing hypercube origin and associated decimals | |||||
| vec_t<int, N> origin; | |||||
| vec_t<float, N> pos; | |||||
| get_origin(skew(position), origin, pos); | |||||
| return get_noise(origin, pos); | |||||
| } | |||||
| /* Only for debug purposes: return the gradient vector of the given | |||||
| * point’s simplex origin. */ | |||||
| inline vec_t<float, N> gradient(vec_t<float, N> position) const | |||||
| { | |||||
| vec_t<int, N> origin; | |||||
| vec_t<float, N> pos; | |||||
| get_origin(skew(position), origin, pos); | |||||
| return get_gradient(origin); | |||||
| } | |||||
| protected: | |||||
| inline float get_noise(vec_t<int, N> origin, | |||||
| vec_t<float, N> const & pos) const | |||||
| { | |||||
| /* For a given position [0…1]^N inside a regular N-hypercube, find | |||||
| * the N-simplex which contains that position, and return a path | |||||
| * along the hypercube edges from (0,0,…,0) to (1,1,…,1) which | |||||
| * uniquely describes that simplex. */ | |||||
| vec_t<int, N> traversal_order; | |||||
| for (int i = 0; i < N; ++i) | |||||
| traversal_order[i] = i; | |||||
| /* Naïve bubble sort — enough for now since the general complexity | |||||
| * of our algorithm is O(N²). Sorting in O(N²) will not hurt more! */ | |||||
| for (int i = 0; i < N; ++i) | |||||
| for (int j = i + 1; j < N; ++j) | |||||
| if (pos[traversal_order[i]] < pos[traversal_order[j]]) | |||||
| std::swap(traversal_order[i], traversal_order[j]); | |||||
| /* Get the position in world coordinates, too */ | |||||
| vec_t<float, N> world_pos = unskew(pos); | |||||
| /* “corner” will traverse the simplex along its edges in world | |||||
| * coordinates. */ | |||||
| vec_t<float, N> world_corner(0.f); | |||||
| float result = 0.f, sum = 0.f, special = 0.f; | |||||
| UNUSED(sum, special); | |||||
| for (int i = 0; i < N + 1; ++i) | |||||
| { | |||||
| #if 1 | |||||
| /* In “Noise Hardware” (2-17) Perlin uses 0.6 - d². | |||||
| * | |||||
| * In an errata to “Simplex noise demystified”, Gustavson uses | |||||
| * 0.5 - d² instead, saying “else the noise is not continuous at | |||||
| * simplex boundaries”. | |||||
| * And indeed, the distance between any given simplex vertex and | |||||
| * the opposite hyperplane is 1/sqrt(2), so the contribution of | |||||
| * that vertex should never be > 0 for points further than | |||||
| * 1/sqrt(2). Hence 0.5 - d². | |||||
| * | |||||
| * I prefer to use 1 - 2d² and compensate for the d⁴ below by | |||||
| * dividing the final result by 2⁴, because manipulating values | |||||
| * between 0 and 1 is more convenient. */ | |||||
| float d = 1.0f - 2.f * sqlength(world_pos - world_corner); | |||||
| #else | |||||
| // DEBUG: this is the linear contribution of each vertex | |||||
| // in the skewed simplex. Unfortunately it creates artifacts. | |||||
| float d = ((i == 0) ? 1.f : pos[traversal_order[i - 1]]) | |||||
| - ((i == N) ? 0.f : pos[traversal_order[i]]); | |||||
| #endif | |||||
| #if 0 | |||||
| // DEBUG: identify simplex features: | |||||
| // -4.f: centre (-2.f), | |||||
| // -3.f: r=0.38 sphere of influence (contribution = 1/4) | |||||
| // -2.f: r=0.52 sphere of influence (contribution = 1/24) | |||||
| if (d > 0.99f) special = min(special, -4.f); | |||||
| if (d > 0.7f && d < 0.72f) special = min(special, -3.f); | |||||
| if (d > 0.44f && d < 0.46f) special = min(special, -2.f); | |||||
| #endif | |||||
| if (d > 0) | |||||
| { | |||||
| // Perlin uses 8d⁴ whereas Gustavson uses d⁴ and a final | |||||
| // multiplication factor at the end. Let’s go with | |||||
| // Gustavson, it’s a few multiplications less. | |||||
| d = d * d * d * d; | |||||
| //d = (3.f - 2.f * d) * d * d; | |||||
| //d = ((6 * d - 15) * d + 10) * d * d * d; | |||||
| result += d * dot(this->get_gradient(origin), | |||||
| world_pos - world_corner); | |||||
| sum += d; | |||||
| } | |||||
| if (i < N) | |||||
| { | |||||
| auto axis = vec_t<float, N>::axis(traversal_order[i]); | |||||
| world_corner += unskew(axis); | |||||
| origin[traversal_order[i]] += 1; | |||||
| } | |||||
| } | |||||
| #if 0 | |||||
| if (special < 0.f) | |||||
| return special; | |||||
| #endif | |||||
| return get_scale() * result; | |||||
| } | |||||
| static inline float get_scale() | |||||
| { | |||||
| /* FIXME: Gustavson uses the value 70 for dimension 2, 32 for | |||||
| * dimension 3, and 27 for dimension 4, and uses non-unit gradients | |||||
| * of length sqrt(2), sqrt(2) and sqrt(3), saying “The result is | |||||
| * scaled to stay just inside [-1,1]” which honestly is just not | |||||
| * true. | |||||
| * Experiments show that the scaling factor is remarkably close | |||||
| * to 6.7958 for all high dimensions (measured up to 12). */ | |||||
| return N == 2 ? 6.2003f | |||||
| : N == 3 ? 6.7297f | |||||
| : N == 4 ? 6.7861f | |||||
| : N == 5 ? 6.7950f | |||||
| : N == 6 ? 6.7958f | |||||
| : N == 7 ? 6.7958f | |||||
| : /* 7+ */ 6.7958f; | |||||
| } | |||||
| static inline vec_t<float, N> skew(vec_t<float, N> const &v) | |||||
| { | |||||
| /* Quoting Perlin in “Hardware Noise” (2-18): | |||||
| * The “skew factor” f should be set to f = sqrt(N+1), so that | |||||
| * the point (1,1,...1) is transformed to the point (f,f,...f). */ | |||||
| float const sum = dot(v, vec_t<float, N>(1)); | |||||
| float const f = sqrt(1.f + N); | |||||
| return v + vec_t<float, N>(sum * (f - 1) / N); | |||||
| } | |||||
| static inline vec_t<float, N> unskew(vec_t<float, N> const &v) | |||||
| { | |||||
| float const sum = dot(v, vec_t<float, N>(1)); | |||||
| float const f = sqrt(1.f + N); | |||||
| return v + vec_t<float, N>(sum * (1 / f - 1) / N); | |||||
| } | |||||
| /* For a given world position, extract grid coordinates (origin) and | |||||
| * the corresponding delta position (pos). */ | |||||
| inline void get_origin(vec_t<float, N> const & world_position, | |||||
| vec_t<int, N> & origin, vec_t<float, N> & pos) const | |||||
| { | |||||
| // Finding floor point index | |||||
| for (int i = 0; i < N; ++i) | |||||
| origin[i] = (int)world_position[i] - (world_position[i] < 0); | |||||
| // Extracting decimal part from simplex sample | |||||
| pos = world_position - (vec_t<float, N>)origin; | |||||
| } | |||||
| private: | |||||
| void debugprint() | |||||
| { | |||||
| // Print some debug information | |||||
| printf("Simplex Noise of Dimension %d\n", N); | |||||
| long long int n = 1; for (int i = 1; i <= N; ++i) n *= i; | |||||
| printf(" - each hypercube cell has %lld simplices " | |||||
| "with %d vertices and %d edges\n", n, N + 1, N * (N + 1) / 2); | |||||
| vec_t<float, N> diagonal(1.f); | |||||
| printf(" - regular hypercube:\n"); | |||||
| printf(" · edge length 1\n"); | |||||
| printf(" · diagonal length %f\n", length(diagonal)); | |||||
| printf(" - unskewed parallelotope:\n"); | |||||
| printf(" · edge length %f\n", length(unskew(diagonal))); | |||||
| printf(" · diagonal length %f\n", length(unskew(diagonal))); | |||||
| printf(" · simplex edge lengths between %f and %f\n", | |||||
| sqrt((float)N/(N+1)), sqrt((N+1)*(N+1)/4/(float)(N+1))); | |||||
| /* Generate simplex vertices */ | |||||
| vec_t<float, N> vertices[N + 1]; | |||||
| vertices[0] = vec_t<float, N>(0.f); | |||||
| for (int i = 0; i < N; ++i) | |||||
| { | |||||
| vertices[i + 1] = vertices[i]; | |||||
| vertices[i + 1][i] += 1.f; | |||||
| } | |||||
| for (int i = 0; i < N + 1; ++i) | |||||
| vertices[i] = unskew(vertices[i]); | |||||
| /* Output information for each vertex */ | |||||
| for (int i = 0; i < N + 1; ++i) | |||||
| { | |||||
| printf(" - vertex %d\n", i); | |||||
| /* Coordinates for debugging purposes */ | |||||
| #if 0 | |||||
| printf(" · ["); | |||||
| for (int k = 0; k < N; ++k) | |||||
| printf(" %f", vertices[i][k]); | |||||
| printf(" ]\n"); | |||||
| #endif | |||||
| /* Analyze edge lengths from that vertex */ | |||||
| #if 0 | |||||
| float minlength = 1.0f; | |||||
| float maxlength = 0.0f; | |||||
| for (int j = 0; j < N + 1; ++j) | |||||
| { | |||||
| if (i == j) | |||||
| continue; | |||||
| float l = length(vertices[i] - vertices[j]); | |||||
| minlength = min(minlength, l); | |||||
| maxlength = max(maxlength, l); | |||||
| } | |||||
| printf(" · edge lengths between %f and %f\n", | |||||
| minlength, maxlength); | |||||
| #endif | |||||
| /* Experimental calculation of the distance to the opposite | |||||
| * hyperplane, by picking random points. Works reasonably | |||||
| * well up to dimension 6. After that, we’d need something | |||||
| * better such as gradient walk. */ | |||||
| #if 0 | |||||
| float mindist = 1.0f; | |||||
| for (int run = 0; run < 10000000; ++run) | |||||
| { | |||||
| vec_t<float, N> p(0.f); | |||||
| float sum = 0.f; | |||||
| for (int j = 0; j < N + 1; ++j) | |||||
| { | |||||
| if (i == j) | |||||
| continue; | |||||
| float k = rand(1.f); | |||||
| p += k * vertices[j]; | |||||
| sum += k; | |||||
| } | |||||
| mindist = min(mindist, distance(vertices[i], p / sum)); | |||||
| } | |||||
| printf(" · approx. dist. to opposite hyperplane: %f\n", mindist); | |||||
| #endif | |||||
| /* Find a normal vector to the opposite hyperplane. First, pick | |||||
| * any point p(i0) on the hyperplane. We just need i0 != i. Then, | |||||
| * build a matrix where each row is p(i0)p(j) for all j != i0. | |||||
| * Multiplying this matrix by the normal vectors gives a vector | |||||
| * full of zeroes except at position i. So we build a vector | |||||
| * full of zeroes except at position i, and multiply it by the | |||||
| * matrix inverse. */ | |||||
| #if 1 | |||||
| int i0 = (i == 0) ? 1 : 0; | |||||
| mat_t<float, N, N> m; | |||||
| for (int j = 0; j < N; ++j) | |||||
| { | |||||
| auto v = vertices[j < i0 ? j : j + 1] - vertices[i0]; | |||||
| for (int k = 0; k < N; ++k) | |||||
| m[k][j] = v[k]; | |||||
| } | |||||
| auto axis = vec_t<float, N>::axis(i < i0 ? i : i - 1); | |||||
| auto normal = normalize(inverse(m) * axis); | |||||
| /* Find distance from current vertex to the opposite hyperplane. | |||||
| * Just use the projection theorem in N dimensions. */ | |||||
| auto w = vertices[i] - vertices[i0]; | |||||
| float dist = abs(dot(normal, w)); | |||||
| printf(" · distance to opposite hyperplane: %f\n", dist); | |||||
| #endif | |||||
| } | |||||
| /* Compute some statistics about the noise. TODO: histogram */ | |||||
| #if 0 | |||||
| vec_t<float, N> input(0.f); | |||||
| for (int run = 0; run < 1000000; ++run) | |||||
| { | |||||
| float t = eval(input); | |||||
| input[run % N] = rand(1000.f); | |||||
| } | |||||
| #endif | |||||
| /* Try to find max noise value by climbing gradient */ | |||||
| float minval = 0.f, maxval = 0.f; | |||||
| array<vec_t<float, N>> deltas; | |||||
| for (int i = 0; i < N; ++i) | |||||
| { | |||||
| auto v = vec_t<float, N>::axis(i); | |||||
| deltas << v << -v; | |||||
| } | |||||
| for (int run = 0; run < 1000; ++run) | |||||
| { | |||||
| /* Pick a random vector */ | |||||
| vec_t<float, N> v; | |||||
| for (int i = 0; i < N; ++i) | |||||
| v[i] = rand(-100.f, 100.f); | |||||
| float t = eval(v); | |||||
| float e = 0.1f; | |||||
| /* Climb up gradient in all dimensions */ | |||||
| while (e > 1e-6f) | |||||
| { | |||||
| int best_delta = -1; | |||||
| float best_t2 = t; | |||||
| for (int i = 0; i < deltas.count(); ++i) | |||||
| { | |||||
| float t2 = eval(v + e * deltas[i]); | |||||
| if (abs(t2) > abs(best_t2)) | |||||
| { | |||||
| best_delta = i; | |||||
| best_t2 = t2; | |||||
| } | |||||
| } | |||||
| if (best_delta == -1) | |||||
| e *= 0.5f; | |||||
| else | |||||
| { | |||||
| v += e * deltas[best_delta]; | |||||
| t = best_t2; | |||||
| } | |||||
| } | |||||
| minval = min(t, minval); | |||||
| maxval = max(t, maxval); | |||||
| } | |||||
| printf(" - noise value min/max: %f %f\n", minval, maxval); | |||||
| float newscale = 1.f / max(-minval, maxval); | |||||
| if (newscale < 1.f) | |||||
| printf(" - could replace scale %f with %f\n", | |||||
| get_scale(), newscale * get_scale()); | |||||
| else | |||||
| printf(" - scale looks OK\n"); | |||||
| printf("\n"); | |||||
| } | |||||
| }; | |||||
| } | |||||
| @@ -18,7 +18,6 @@ | |||||
| // | // | ||||
| #include <lol/base/all.h> | #include <lol/base/all.h> | ||||
| #include <lol/math/all.h> | |||||
| #include <lol/algorithm/all.h> | #include <lol/algorithm/all.h> | ||||
| #include <lol/image/all.h> | #include <lol/image/all.h> | ||||
| #include <lol/sys/all.h> | #include <lol/sys/all.h> | ||||
| @@ -15,7 +15,7 @@ | |||||
| // ------------------ | // ------------------ | ||||
| // | // | ||||
| #include <lol/math/functions.h> | |||||
| #include <../legacy/lol/math/functions.h> | |||||
| #include <cstdlib> | #include <cstdlib> | ||||
| #include <stdint.h> | #include <stdint.h> | ||||
| @@ -713,6 +713,7 @@ void Scene::render_lines(float seconds) | |||||
| buff.resize(linecount); | buff.resize(linecount); | ||||
| int real_linecount = 0; | int real_linecount = 0; | ||||
| mat4 const inv_view_proj = inverse(GetCamera()->GetProjection() * GetCamera()->GetView()); | mat4 const inv_view_proj = inverse(GetCamera()->GetProjection() * GetCamera()->GetView()); | ||||
| UNUSED(inv_view_proj); | |||||
| for (int i = 0; i < linecount; i++) | for (int i = 0; i < linecount; i++) | ||||
| { | { | ||||
| if (m_line_api.m_lines[i].m5 & m_line_api.m_debug_mask) | if (m_line_api.m_lines[i].m5 & m_line_api.m_debug_mask) | ||||
| @@ -10,8 +10,12 @@ | |||||
| // See http://www.wtfpl.net/ for more details. | // See http://www.wtfpl.net/ for more details. | ||||
| // | // | ||||
| #include <lol/engine-internal.h> | |||||
| #if HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <lol/base/lolunit.h> | #include <lol/base/lolunit.h> | ||||
| #include <lol/base/array.h> | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -2,7 +2,6 @@ | |||||
| // Lol Engine — Unit tests | // Lol Engine — Unit tests | ||||
| // | // | ||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | ||||
| // © 2013—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | |||||
| // © 2013—2015 Guillaume Bittoun <guillaume.bittoun@gmail.com> | // © 2013—2015 Guillaume Bittoun <guillaume.bittoun@gmail.com> | ||||
| // | // | ||||
| // Lol Engine is free software. It comes without any warranty, to | // Lol Engine is free software. It comes without any warranty, to | ||||
| @@ -12,8 +11,12 @@ | |||||
| // See http://www.wtfpl.net/ for more details. | // See http://www.wtfpl.net/ for more details. | ||||
| // | // | ||||
| #include <lol/engine-internal.h> | |||||
| #if HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <lol/base/lolunit.h> | #include <lol/base/lolunit.h> | ||||
| #include <../legacy/lol/base/avl_tree.h> | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -10,8 +10,12 @@ | |||||
| // See http://www.wtfpl.net/ for more details. | // See http://www.wtfpl.net/ for more details. | ||||
| // | // | ||||
| #include <lol/engine-internal.h> | |||||
| #if HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <lol/base/lolunit.h> | #include <lol/base/lolunit.h> | ||||
| #include <lol/base/enum.h> | |||||
| #include <string> | #include <string> | ||||
| #include <map> | #include <map> | ||||
| @@ -10,8 +10,12 @@ | |||||
| // See http://www.wtfpl.net/ for more details. | // See http://www.wtfpl.net/ for more details. | ||||
| // | // | ||||
| #include <lol/engine-internal.h> | |||||
| #if HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <lol/base/lolunit.h> | #include <lol/base/lolunit.h> | ||||
| #include <lol/base/utils.h> | |||||
| #include <map> | #include <map> | ||||
| @@ -10,8 +10,12 @@ | |||||
| // See http://www.wtfpl.net/ for more details. | // See http://www.wtfpl.net/ for more details. | ||||
| // | // | ||||
| #include <lol/engine-internal.h> | |||||
| #if HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <lol/base/lolunit.h> | #include <lol/base/lolunit.h> | ||||
| #include <../legacy/lol/math/interp.h> | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||