Browse Source

Octree WIP

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
f50645b598
2 changed files with 159 additions and 0 deletions
  1. 75 0
      src/anki/scene/Octree.cpp
  2. 84 0
      src/anki/scene/Octree.h

+ 75 - 0
src/anki/scene/Octree.cpp

@@ -0,0 +1,75 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/scene/Octree.h>
+
+namespace anki
+{
+
+OctreeLeaf& Octree::newLeaf()
+{
+	OctreeLeaf* out = nullptr;
+
+	// Try find one in the storages
+	for(LeafStorage& storage : m_leafStorages)
+	{
+		if(storage.m_unusedLeafCount > 0)
+		{
+			// Pop an element
+			--storage.m_unusedLeafCount;
+			out = &storage.m_leafs[storage.m_unusedLeafCount];
+			break;
+		}
+	}
+
+	if(out == nullptr)
+	{
+		// Need to create a new storage
+
+		m_leafStorages.resize(m_alloc, m_leafStorages.getSize() + 1);
+		LeafStorage& storage = m_leafStorages.getBack();
+
+		storage.m_leafs = {m_alloc.newArray<OctreeLeaf>(LEAFES_PER_STORAGE), LEAFES_PER_STORAGE};
+		storage.m_unusedLeafCount = LEAFES_PER_STORAGE;
+
+		storage.m_unusedLeafsStack = {m_alloc.newArray<U16>(LEAFES_PER_STORAGE), LEAFES_PER_STORAGE};
+		for(U i = 0; i < LEAFES_PER_STORAGE; ++i)
+		{
+			storage.m_unusedLeafsStack[i] = LEAFES_PER_STORAGE - (i + 1);
+		}
+
+		// Allocate one
+		out = &storage.m_leafs[0];
+		--storage.m_unusedLeafCount;
+	}
+
+	// Init the leaf
+	zeroMemory(*out);
+
+	ANKI_ASSERT(out);
+	return *out;
+}
+
+void Octree::releaseLeaf(OctreeLeaf* leaf)
+{
+	ANKI_ASSERT(leaf);
+
+	for(LeafStorage& storage : m_leafStorages)
+	{
+		if(leaf >= &storage.m_leafs.getFront() && leaf <= &storage.m_leafs.getBack())
+		{
+			// Found its storage
+
+			const U idx = leaf - storage.m_leafs.getBegin();
+			storage.m_unusedLeafsStack[storage.m_unusedLeafCount] = idx;
+			++storage.m_unusedLeafCount;
+			return;
+		}
+	}
+
+	ANKI_ASSERT(!"Not found");
+}
+
+} // end namespace anki

+ 84 - 0
src/anki/scene/Octree.h

@@ -0,0 +1,84 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/scene/Common.h>
+#include <anki/Math.h>
+#include <anki/collision/Forward.h>
+#include <anki/util/WeakArray.h>
+
+namespace anki
+{
+
+// Forward
+class OctreeLeaf;
+
+/// @addtogroup scene
+/// @{
+
+/// XXX
+class OctreeElement
+{
+protected:
+	OctreeElement* m_prev = nullptr;
+	OctreeElement* m_next = nullptr;
+	OctreeLeaf* m_leaf = nullptr;
+};
+
+/// XXX
+/// @warning Keept its size as small as possible.
+/// @warning Watch the members. Should be be able to zero its memory to initialize it.
+class OctreeLeaf
+{
+public:
+	OctreeElement* m_first;
+	OctreeElement* m_last;
+	Array<OctreeLeaf*, 8> m_leafs;
+	Vec3 m_aabbMin;
+	Vec3 m_aabbMax;
+};
+
+/// Octree for visibility tests.
+class Octree
+{
+public:
+	Octree(SceneAllocator<U8> alloc)
+		: m_alloc(alloc)
+	{
+	}
+
+	~Octree();
+
+	/// Place or re-place an element in the tree.
+	/// @note It's thread-safe.
+	void placeElement(const Aabb& volume, OctreeElement& element);
+
+	/// Remove an element from the tree.
+	/// @note It's thread-safe.
+	void removeElement(OctreeElement& element);
+
+private:
+	SceneAllocator<U8> m_alloc;
+
+	/// Keep the allocations of leafes tight because we want quite alot of them.
+	class LeafStorage
+	{
+	public:
+		WeakArray<OctreeLeaf> m_leafs;
+		WeakArray<U16> m_unusedLeafsStack;
+		U16 m_unusedLeafCount = MAX_U16;
+	};
+
+	static constexpr U LEAFES_PER_STORAGE = 256;
+
+	DynamicArray<LeafStorage> m_leafStorages;
+
+	OctreeLeaf& newLeaf();
+	void releaseLeaf(OctreeLeaf* leaf);
+};
+/// @}
+
+} // end namespace anki