Browse Source

Refactor several headers, slowly migrating to include-what-you-use.

wip/submodule
Sam Hocevar 5 years ago
parent
commit
f9d97f6340
40 changed files with 74 additions and 3189 deletions
  1. +3
    -2
      doc/samples/simplex.cpp
  2. +1
    -0
      doc/tutorial/16_movie.cpp
  3. +1
    -1
      lol-core
  4. +3
    -10
      src/Makefile.am
  5. +0
    -14
      src/lol-core.vcxproj
  6. +0
    -42
      src/lol-core.vcxproj.filters
  7. +0
    -402
      src/lol/algorithm/aabb_tree.h
  8. +9
    -7
      src/lol/algorithm/all.h
  9. +2
    -0
      src/lol/algorithm/portal.h
  10. +2
    -0
      src/lol/algorithm/sort.h
  11. +3
    -3
      src/lol/base/all.h
  12. +1
    -1
      src/lol/base/array.h
  13. +0
    -156
      src/lol/base/assert.h
  14. +0
    -646
      src/lol/base/avl_tree.h
  15. +2
    -0
      src/lol/base/enum.h
  16. +0
    -55
      src/lol/base/map.h
  17. +10
    -8
      src/lol/base/tuple.h
  18. +0
    -160
      src/lol/base/types.h
  19. +3
    -0
      src/lol/debug/lines.h
  20. +1
    -1
      src/lol/image/all.h
  21. +2
    -3
      src/lol/image/image.h
  22. +1
    -1
      src/lol/image/movie.h
  23. +0
    -79
      src/lol/image/pixel.h
  24. +3
    -3
      src/lol/image/resource.h
  25. +0
    -27
      src/lol/math/all.h
  26. +0
    -282
      src/lol/math/arraynd.h
  27. +0
    -185
      src/lol/math/functions.h
  28. +0
    -382
      src/lol/math/geometry.h
  29. +0
    -118
      src/lol/math/interp.h
  30. +0
    -95
      src/lol/math/noise/gradient.h
  31. +0
    -98
      src/lol/math/noise/perlin.h
  32. +0
    -400
      src/lol/math/noise/simplex.h
  33. +0
    -1
      src/lol/public.h
  34. +1
    -1
      src/numeric.h
  35. +1
    -0
      src/scene.cpp
  36. +5
    -1
      src/t/base/array.cpp
  37. +5
    -2
      src/t/base/avl_tree.cpp
  38. +5
    -1
      src/t/base/enum.cpp
  39. +5
    -1
      src/t/base/map.cpp
  40. +5
    -1
      src/t/math/interp.cpp

+ 3
- 2
doc/samples/simplex.cpp View File

@@ -1,8 +1,8 @@
//
// 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>
// © 20132014 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
@@ -16,6 +16,7 @@
#endif

#include <lol/engine.h>
#include <../legacy/lol/math/noise/simplex.h>

using namespace lol;



+ 1
- 0
doc/tutorial/16_movie.cpp View File

@@ -16,6 +16,7 @@

#include <lol/engine.h>
#include <lol/image/movie.h>
#include <../legacy/lol/math/noise/perlin.h>
#include "loldebug.h"

int main(int argc, char **argv)


+ 1
- 1
lol-core

@@ -1 +1 @@
Subproject commit f65ab0fa1e93fe8268a9511095d8a4ea71ae777c
Subproject commit 2235ce1635fa404fc8e7f700258de7c0a903136a

+ 3
- 10
src/Makefile.am View File

@@ -31,18 +31,11 @@ liblol_core_headers = \
lol/lua.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/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/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/audio.h lol/audio/sample.h \
@@ -54,7 +47,7 @@ liblol_core_headers = \
lol/sys/init.h lol/sys/file.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/net/all.h \


+ 0
- 14
src/lol-core.vcxproj View File

@@ -235,7 +235,6 @@
<ClInclude Include="loldebug.h" />
<ClInclude Include="lolgl.h" />
<ClInclude Include="lolua\baselua.h" />
<ClInclude Include="lol\algorithm\aabb_tree.h" />
<ClInclude Include="lol\algorithm\all.h" />
<ClInclude Include="lol\algorithm\portal.h" />
<ClInclude Include="lol\algorithm\sort.h" />
@@ -244,11 +243,8 @@
<ClInclude Include="lol\audio\sample.h" />
<ClInclude Include="lol\base\all.h" />
<ClInclude Include="lol\base\array.h" />
<ClInclude Include="lol\base\assert.h" />
<ClInclude Include="lol\base\enum.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\debug\all.h" />
<ClInclude Include="lol\debug\lines.h" />
@@ -268,20 +264,10 @@
<ClInclude Include="lol\gpu\texture.h" />
<ClInclude Include="lol\gpu\vertexbuffer.h" />
<ClInclude Include="lol\image\all.h" />
<ClInclude Include="lol\image\color.h" />
<ClInclude Include="lol\image\image.h" />
<ClInclude Include="lol\image\movie.h" />
<ClInclude Include="lol\image\pixel.h" />
<ClInclude Include="lol\image\resource.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\http.h" />
<ClInclude Include="lol\public.h" />


+ 0
- 42
src/lol-core.vcxproj.filters View File

@@ -305,9 +305,6 @@
<ClInclude Include="lolua\baselua.h">
<Filter>lolua</Filter>
</ClInclude>
<ClInclude Include="lol\algorithm\aabb_tree.h">
<Filter>lol\algorithm</Filter>
</ClInclude>
<ClInclude Include="lol\algorithm\all.h">
<Filter>lol\algorithm</Filter>
</ClInclude>
@@ -320,21 +317,12 @@
<ClInclude Include="lol\base\array.h">
<Filter>lol\base</Filter>
</ClInclude>
<ClInclude Include="lol\base\assert.h">
<Filter>lol\base</Filter>
</ClInclude>
<ClInclude Include="lol\base\enum.h">
<Filter>lol\base</Filter>
</ClInclude>
<ClInclude Include="lol\base\log.h">
<Filter>lol\base</Filter>
</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">
<Filter>lol\base</Filter>
</ClInclude>
@@ -392,45 +380,18 @@
<ClInclude Include="lol\image\all.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\image\color.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\image\image.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\image\movie.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\image\pixel.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\image\resource.h">
<Filter>lol\image</Filter>
</ClInclude>
<ClInclude Include="lol\lua.h">
<Filter>lol</Filter>
</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">
<Filter>lol\net</Filter>
</ClInclude>
@@ -485,9 +446,6 @@
</ClInclude>
<ClInclude Include="utils.h" />
<ClInclude Include="video.h" />
<ClInclude Include="lol\math\all.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\base\all.h">
<Filter>lol\base</Filter>
</ClInclude>


+ 0
- 402
src/lol/algorithm/aabb_tree.h View File

@@ -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 */


+ 9
- 7
src/lol/algorithm/all.h View File

@@ -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

#include <lol/algorithm/sort.h>
#include <lol/algorithm/aabb_tree.h>
#include <../legacy/lol/algorithm/aabb_tree.h>
#include <lol/algorithm/portal.h>


+ 2
- 0
src/lol/algorithm/portal.h View File

@@ -14,6 +14,8 @@
#pragma once

#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/image/color.h>



+ 2
- 0
src/lol/algorithm/sort.h View File

@@ -14,6 +14,8 @@
#pragma once

#include <lol/base/array.h>
#include <lol/math/rand.h>
#include <../legacy/lol/math/functions.h> // lol::max

namespace lol
{


+ 3
- 3
src/lol/base/all.h View File

@@ -12,12 +12,12 @@

#pragma once

#include <lol/base/types.h>
#include <../legacy/lol/base/types.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/array.h>
#include <lol/base/avl_tree.h>
#include <../legacy/lol/base/avl_tree.h>
#include <lol/base/utils.h>
#include <lol/base/enum.h>


+ 1
- 1
src/lol/base/array.h View File

@@ -20,7 +20,7 @@
// 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 <new> /* for placement new */


+ 0
- 156
src/lol/base/assert.h View File

@@ -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 */


+ 0
- 646
src/lol/base/avl_tree.h View File

@@ -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;
};

}


+ 2
- 0
src/lol/base/enum.h View File

@@ -13,6 +13,8 @@

#pragma once

#include <lol/base/utils.h> // has_key()

#include <string>
#include <map>



+ 0
- 55
src/lol/base/map.h View File

@@ -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 */


+ 10
- 8
src/lol/base/tuple.h View File

@@ -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
@@ -17,7 +19,7 @@
// A very simple tuple class.
//

#include <lol/base/assert.h>
#include <../legacy/lol/base/assert.h>

#include <tuple>



+ 0
- 160
src/lol/base/types.h View File

@@ -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 */


+ 3
- 0
src/lol/debug/lines.h View File

@@ -15,6 +15,9 @@
// ---------------------
//

#include <../legacy/lol/math/geometry.h> // box3
#include <lol/math/vector.h> // vec3, vec4 etc.

#include <stdint.h>

namespace lol


+ 1
- 1
src/lol/image/all.h View File

@@ -12,6 +12,6 @@

#pragma once

#include <lol/image/pixel.h>
#include <../legacy/lol/image/pixel.h>
#include <lol/image/resource.h>


+ 2
- 3
src/lol/image/image.h View File

@@ -17,10 +17,9 @@
// ---------------
//

#include <lol/math/arraynd.h>
#include <../legacy/lol/math/arraynd.h>
#include <lol/math/vector.h>
#include <lol/math/geometry.h>
#include <lol/image/pixel.h>
#include <../legacy/lol/image/pixel.h>

#include <string>



+ 1
- 1
src/lol/image/movie.h View File

@@ -17,7 +17,7 @@
// ---------------
//

#include <lol/image/pixel.h>
#include <../legacy/lol/image/pixel.h>
#include <lol/image/image.h>

extern "C" struct AVFormatContext;


+ 0
- 79
src/lol/image/pixel.h View File

@@ -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 */


+ 3
- 3
src/lol/image/resource.h View File

@@ -18,11 +18,11 @@
// ——————————————————
//

#include <lol/math/arraynd.h>
#include <../legacy/lol/math/arraynd.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/pixel.h>
#include <../legacy/lol/image/pixel.h>

namespace lol
{


+ 0
- 27
src/lol/math/all.h View File

@@ -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>


+ 0
- 282
src/lol/math/arraynd.h View File

@@ -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 */


+ 0
- 185
src/lol/math/functions.h View File

@@ -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 */


+ 0
- 382
src/lol/math/geometry.h View File

@@ -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 */


+ 0
- 118
src/lol/math/interp.h View File

@@ -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 */


+ 0
- 95
src/lol/math/noise/gradient.h View File

@@ -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;
};

}


+ 0
- 98
src/lol/math/noise/perlin.h View File

@@ -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;
}
};

}


+ 0
- 400
src/lol/math/noise/simplex.h View File

@@ -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");
}
};

}


+ 0
- 1
src/lol/public.h View File

@@ -18,7 +18,6 @@
//

#include <lol/base/all.h>
#include <lol/math/all.h>
#include <lol/algorithm/all.h>
#include <lol/image/all.h>
#include <lol/sys/all.h>


+ 1
- 1
src/numeric.h View File

@@ -15,7 +15,7 @@
// ------------------
//

#include <lol/math/functions.h>
#include <../legacy/lol/math/functions.h>

#include <cstdlib>
#include <stdint.h>


+ 1
- 0
src/scene.cpp View File

@@ -713,6 +713,7 @@ void Scene::render_lines(float seconds)
buff.resize(linecount);
int real_linecount = 0;
mat4 const inv_view_proj = inverse(GetCamera()->GetProjection() * GetCamera()->GetView());
UNUSED(inv_view_proj);
for (int i = 0; i < linecount; i++)
{
if (m_line_api.m_lines[i].m5 & m_line_api.m_debug_mask)


+ 5
- 1
src/t/base/array.cpp View File

@@ -10,8 +10,12 @@
// 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/array.h>

namespace lol
{


+ 5
- 2
src/t/base/avl_tree.cpp View File

@@ -2,7 +2,6 @@
// Lol Engine — Unit tests
//
// 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>
//
// Lol Engine is free software. It comes without any warranty, to
@@ -12,8 +11,12 @@
// 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 <../legacy/lol/base/avl_tree.h>

namespace lol
{


+ 5
- 1
src/t/base/enum.cpp View File

@@ -10,8 +10,12 @@
// 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/enum.h>

#include <string>
#include <map>


+ 5
- 1
src/t/base/map.cpp View File

@@ -10,8 +10,12 @@
// 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/utils.h>

#include <map>



+ 5
- 1
src/t/math/interp.cpp View File

@@ -10,8 +10,12 @@
// 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 <../legacy/lol/math/interp.h>

namespace lol
{


Loading…
Cancel
Save