Browse Source

- Adding a few methods to math vectors
- Finalizing octree

Panagiotis Christopoulos Charitos 14 years ago
parent
commit
817145f155

+ 4 - 1
CMakeLists.txt

@@ -42,7 +42,10 @@ LINK_DIRECTORIES(${ANKI_PROJ_SOURCE_DIR}/extern/lib64)
 
 
 # Lib dependencied
 # Lib dependencied
 FIND_PACKAGE(Boost 1.46 REQUIRED)
 FIND_PACKAGE(Boost 1.46 REQUIRED)
-#FIND_PACKAGE(PythonLibs 3.0 REQUIRED)
+FIND_PACKAGE(PNG 1.2 REQUIRED)
+FIND_PACKAGE(JPEG 62 REQUIRED)
+FIND_PACKAGE(Freetype 2.4.4 REQUIRED)
+FIND_PACKAGE(PythonLibs 2.6 REQUIRED)
 
 
 ADD_SUBDIRECTORY(anki)
 ADD_SUBDIRECTORY(anki)
 ADD_SUBDIRECTORY(testapp)
 ADD_SUBDIRECTORY(testapp)

+ 6 - 4
anki/collision/Aabb.cpp

@@ -1,5 +1,6 @@
 #include "anki/collision/Aabb.h"
 #include "anki/collision/Aabb.h"
 #include "anki/collision/Plane.h"
 #include "anki/collision/Plane.h"
+#include "anki/collision/Obb.h"
 #include <boost/array.hpp>
 #include <boost/array.hpp>
 
 
 
 
@@ -38,11 +39,12 @@ Aabb Aabb::getTransformed(const Transform& transform) const
 
 
 		out.set(points);*/
 		out.set(points);*/
 
 
-		// Experimental way:
+		// Fast way:
 
 
-		// obb is the rotated "this"
-		Obb obb = Obb(transform.getOrigin(), transform.getRotation(),
-			((max - min) / 2.0) * transform.getScale());
+		// obb is the transformed this
+		Vec3 c = (min + max) / 2.0;
+		Obb obb = Obb(c.getTransformed(transform), transform.getRotation(),
+			(max - c) * transform.getScale());
 
 
 		boost::array<Vec3, 8> points;
 		boost::array<Vec3, 8> points;
 		obb.getExtremePoints(points);
 		obb.getExtremePoints(points);

+ 4 - 2
anki/collision/Aabb.h

@@ -25,7 +25,9 @@ class Aabb: public CollisionShape
 		:	CollisionShape(CST_AABB),
 		:	CollisionShape(CST_AABB),
 			min(min_),
 			min(min_),
 			max(max_)
 			max(max_)
-		{}
+		{
+			ASSERT(min < max);
+		}
 
 
 		Aabb(const Aabb& b)
 		Aabb(const Aabb& b)
 		:	CollisionShape(CST_AABB),
 		:	CollisionShape(CST_AABB),
@@ -69,7 +71,7 @@ class Aabb: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 1 - 1
anki/collision/CollisionShape.h

@@ -65,7 +65,7 @@ class CollisionShape
 		/// Visitor accept
 		/// Visitor accept
 		virtual void accept(MutableVisitor& v) = 0;
 		virtual void accept(MutableVisitor& v) = 0;
 		/// Visitor accept
 		/// Visitor accept
-		virtual void accept(ConstVisitor& v) = 0;
+		virtual void accept(ConstVisitor& v) const = 0;
 
 
 		/// If the collision shape intersects with the plane then the method
 		/// If the collision shape intersects with the plane then the method
 		/// returns 0.0, else it returns the distance. If the distance is < 0.0
 		/// returns 0.0, else it returns the distance. If the distance is < 0.0

+ 1 - 1
anki/collision/LineSegment.h

@@ -70,7 +70,7 @@ class LineSegment: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 1 - 1
anki/collision/Obb.h

@@ -75,7 +75,7 @@ class Obb: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 1 - 1
anki/collision/PerspectiveCameraShape.h

@@ -46,7 +46,7 @@ class PerspectiveCameraShape: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 1 - 1
anki/collision/Plane.h

@@ -79,7 +79,7 @@ class Plane: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 1 - 1
anki/collision/Ray.h

@@ -65,7 +65,7 @@ class Ray: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 1 - 1
anki/collision/Sphere.h

@@ -65,7 +65,7 @@ class Sphere: public CollisionShape
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}
 		/// Implements CollisionShape::accept
 		/// Implements CollisionShape::accept
-		void accept(ConstVisitor& v)
+		void accept(ConstVisitor& v) const
 		{
 		{
 			v.visit(*this);
 			v.visit(*this);
 		}
 		}

+ 4 - 0
anki/math/Vec2.h

@@ -49,6 +49,10 @@ class Vec2
 		Vec2 operator-() const;
 		Vec2 operator-() const;
 		bool operator==(const Vec2& b) const;
 		bool operator==(const Vec2& b) const;
 		bool operator!=(const Vec2& b) const;
 		bool operator!=(const Vec2& b) const;
+		bool operator<(const Vec2& b) const;
+		bool operator<=(const Vec2& b) const;
+		bool operator>(const Vec2& b) const;
+		bool operator>=(const Vec2& b) const;
 		/// @}
 		/// @}
 
 
 		/// @name Operators with float
 		/// @name Operators with float

+ 1 - 2
anki/math/Vec2.inl.h

@@ -197,8 +197,7 @@ inline bool Vec2::operator==(const Vec2& b) const
 // !=
 // !=
 inline bool Vec2::operator!=(const Vec2& b) const
 inline bool Vec2::operator!=(const Vec2& b) const
 {
 {
-	return !(Math::isZero(x() - b.x()) &&
-		Math::isZero(y() - b.y()));
+	return !(*this == b);
 }
 }
 
 
 
 

+ 4 - 0
anki/math/Vec3.h

@@ -52,6 +52,10 @@ class Vec3
 		Vec3 operator-() const;
 		Vec3 operator-() const;
 		bool operator==(const Vec3& b) const;
 		bool operator==(const Vec3& b) const;
 		bool operator!=(const Vec3& b) const;
 		bool operator!=(const Vec3& b) const;
+		bool operator<(const Vec3& b) const;
+		bool operator<=(const Vec3& b) const;
+		bool operator>(const Vec3& b) const;
+		bool operator>=(const Vec3& b) const;
 		/// @}
 		/// @}
 
 
 		/// @name Operators with float
 		/// @name Operators with float

+ 28 - 0
anki/math/Vec3.inl.h

@@ -234,6 +234,34 @@ inline bool Vec3::operator!=(const Vec3& b) const
 }
 }
 
 
 
 
+// <
+inline bool Vec3::operator<(const Vec3& b) const
+{
+	return x() < b.x() && y() < b.y() && z() < b.z();
+}
+
+
+// <=
+inline bool Vec3::operator<=(const Vec3& b) const
+{
+	return x() <= b.x() && y() <= b.y() && z() <= b.z();
+}
+
+
+// >
+inline bool Vec3::operator>(const Vec3& b) const
+{
+	return x() > b.x() && y() > b.y() && z() > b.z();
+}
+
+
+// >=
+inline bool Vec3::operator>=(const Vec3& b) const
+{
+	return x() >= b.x() && y() >= b.y() && z() >= b.z();
+}
+
+
 //==============================================================================
 //==============================================================================
 // Operators with float                                                        =
 // Operators with float                                                        =
 //==============================================================================
 //==============================================================================

+ 4 - 0
anki/math/Vec4.h

@@ -62,6 +62,10 @@ class Vec4
 		Vec4 operator-() const;
 		Vec4 operator-() const;
 		bool operator==(const Vec4& b) const;
 		bool operator==(const Vec4& b) const;
 		bool operator!=(const Vec4& b) const;
 		bool operator!=(const Vec4& b) const;
+		bool operator<(const Vec4& b) const;
+		bool operator<=(const Vec4& b) const;
+		bool operator>(const Vec4& b) const;
+		bool operator>=(const Vec4& b) const;
 		/// @}
 		/// @}
 
 
 		/// @name Operators with float
 		/// @name Operators with float

+ 27 - 9
anki/renderer/CollisionDbgDrawer.cpp

@@ -7,9 +7,7 @@ namespace anki {
 
 
 
 
 //==============================================================================
 //==============================================================================
-// draw (Sphere)                                                               =
-//==============================================================================
-void CollisionDbgDrawer::draw(const Sphere& sphere)
+void CollisionDbgDrawer::visit(const Sphere& sphere)
 {
 {
 	dbg.setModelMat(Mat4(sphere.getCenter(), Mat3::getIdentity(), 1.0));
 	dbg.setModelMat(Mat4(sphere.getCenter(), Mat3::getIdentity(), 1.0));
 	dbg.drawSphere(sphere.getRadius());
 	dbg.drawSphere(sphere.getRadius());
@@ -17,9 +15,7 @@ void CollisionDbgDrawer::draw(const Sphere& sphere)
 
 
 
 
 //==============================================================================
 //==============================================================================
-// draw (Obb)                                                                  =
-//==============================================================================
-void CollisionDbgDrawer::draw(const Obb& obb)
+void CollisionDbgDrawer::visit(const Obb& obb)
 {
 {
 	Mat4 scale(Mat4::getIdentity());
 	Mat4 scale(Mat4::getIdentity());
 	scale(0, 0) = obb.getExtend().x();
 	scale(0, 0) = obb.getExtend().x();
@@ -49,9 +45,7 @@ void CollisionDbgDrawer::draw(const Obb& obb)
 
 
 
 
 //==============================================================================
 //==============================================================================
-// draw (Plane)                                                                =
-//==============================================================================
-void CollisionDbgDrawer::draw(const Plane& plane)
+void CollisionDbgDrawer::visit(const Plane& plane)
 {
 {
 	const Vec3& n = plane.getNormal();
 	const Vec3& n = plane.getNormal();
 	const float& o = plane.getOffset();
 	const float& o = plane.getOffset();
@@ -66,4 +60,28 @@ void CollisionDbgDrawer::draw(const Plane& plane)
 }
 }
 
 
 
 
+//==============================================================================
+void CollisionDbgDrawer::visit(const Aabb& aabb)
+{
+	const Vec3& min = aabb.getMin();
+	const Vec3& max = aabb.getMax();
+
+	Mat4 trf = Mat4::getIdentity();
+	// Scale
+	for(uint i = 0; i < 3; ++i)
+	{
+		trf(i, i) = max[i] - min[i];
+	}
+
+	// Translation
+	trf.setTranslationPart((max + min) / 2.0);
+
+	dbg.setModelMat(trf);
+	dbg.drawCube();
+
+	/*dbg.setModelMat(Mat4::getIdentity());
+	dbg.drawLine(min, max, Vec4(1.0, 0.0, 0.0, 1.0));*/
+}
+
+
 } // end namespace
 } // end namespace

+ 27 - 8
anki/renderer/CollisionDbgDrawer.h

@@ -1,6 +1,9 @@
 #ifndef ANKI_RENDERER_COLLISION_DBG_DRAWER_H
 #ifndef ANKI_RENDERER_COLLISION_DBG_DRAWER_H
 #define ANKI_RENDERER_COLLISION_DBG_DRAWER_H
 #define ANKI_RENDERER_COLLISION_DBG_DRAWER_H
 
 
+#include "anki/collision/CollisionShape.h"
+#include "anki/util/Assert.h"
+
 
 
 namespace anki {
 namespace anki {
 
 
@@ -12,20 +15,36 @@ class Dbg;
 
 
 
 
 /// Contains methods to render the collision shapes
 /// Contains methods to render the collision shapes
-class CollisionDbgDrawer
+class CollisionDbgDrawer: public CollisionShape::ConstVisitor
 {
 {
 	public:
 	public:
 		/// Constructor
 		/// Constructor
-		CollisionDbgDrawer(Dbg& dbg_): dbg(dbg_) {}
+		CollisionDbgDrawer(Dbg& dbg_)
+		:	dbg(dbg_)
+		{}
+
+		void visit(const LineSegment&)
+		{
+			ASSERT(0 && "ToDo");
+		}
+
+		void visit(const Obb&);
+
+		void visit(const PerspectiveCameraShape&)
+		{
+			ASSERT(0 && "ToDo");
+		}
+
+		void visit(const Plane&);
 
 
-		/// Draw Sphere
-		virtual void draw(const Sphere& sphere);
+		void visit(const Ray&)
+		{
+			ASSERT(0 && "ToDo");
+		}
 
 
-		/// Draw Obb
-		virtual void draw(const Obb& obb);
+		void visit(const Sphere&);
 
 
-		/// Draw Plane
-		virtual void draw(const Plane& plane);
+		void visit(const Aabb&);
 
 
 	private:
 	private:
 		Dbg& dbg; ///< The debug stage
 		Dbg& dbg; ///< The debug stage

+ 32 - 1
anki/renderer/Dbg.cpp

@@ -1,5 +1,6 @@
 #include "anki/renderer/Dbg.h"
 #include "anki/renderer/Dbg.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Renderer.h"
+#include "anki/renderer/CollisionDbgDrawer.h"
 #include "anki/scene/RenderableNode.h"
 #include "anki/scene/RenderableNode.h"
 #include "anki/scene/Scene.h"
 #include "anki/scene/Scene.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Camera.h"
@@ -9,9 +10,15 @@
 #include "anki/renderer/SceneDbgDrawer.h"
 #include "anki/renderer/SceneDbgDrawer.h"
 #include "anki/scene/SkinNode.h"
 #include "anki/scene/SkinNode.h"
 #include "anki/scene/SpotLight.h"
 #include "anki/scene/SpotLight.h"
+#include "anki/scene/Octree.h"
+#include "anki/scene/ModelNode.h"
+#include "anki/resource/Model.h"
 #include <boost/foreach.hpp>
 #include <boost/foreach.hpp>
 
 
 
 
+extern anki::ModelNode* horse;
+
+
 namespace anki {
 namespace anki {
 
 
 
 
@@ -362,7 +369,31 @@ void Dbg::run()
 	///////////////
 	///////////////
 
 
 
 
-	SceneSingleton::get().getPhysWorld().getWorld().debugDrawWorld();
+	/*Octree* octree = new Octree(Aabb(Vec3(-10.0), Vec3(10.0)), 10);
+
+
+	Aabb aabb(horse->getModel().getVisibilityCollisionShape());
+	aabb.transform(horse->getWorldTransform());
+
+	OctreeNode* where = octree->place(aabb);
+
+	sceneDbgDrawer.drawOctree(*octree);
+	CollisionDbgDrawer vis(*this);
+	aabb.accept(vis);
+
+	if(where)
+	{
+		setColor(Vec3(1.0, 0.0, 0.0));
+		Aabb whereaabb = where->getAabb();
+		whereaabb.transform(Transform(Vec3(0.0), Mat3::getIdentity(), 0.99));
+		whereaabb.accept(vis);
+	}
+
+	delete octree;
+
+
+	SceneSingleton::get().getPhysWorld().getWorld().debugDrawWorld();*/
+
 	// Physics
 	// Physics
 	/*glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 	/*glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 	setModelMat(Mat4::getIdentity());
 	setModelMat(Mat4::getIdentity());

+ 30 - 12
anki/renderer/SceneDbgDrawer.cpp

@@ -6,13 +6,12 @@
 #include "anki/scene/SkinNode.h"
 #include "anki/scene/SkinNode.h"
 #include "anki/scene/PerspectiveCamera.h"
 #include "anki/scene/PerspectiveCamera.h"
 #include "anki/scene/OrthographicCamera.h"
 #include "anki/scene/OrthographicCamera.h"
+#include "anki/scene/Octree.h"
 
 
 
 
 namespace anki {
 namespace anki {
 
 
 
 
-//==============================================================================
-// drawCamera                                                                  =
 //==============================================================================
 //==============================================================================
 void SceneDbgDrawer::drawCamera(const Camera& cam) const
 void SceneDbgDrawer::drawCamera(const Camera& cam) const
 {
 {
@@ -41,8 +40,6 @@ void SceneDbgDrawer::drawCamera(const Camera& cam) const
 }
 }
 
 
 
 
-//==============================================================================
-// drawPerspectiveCamera                                                       =
 //==============================================================================
 //==============================================================================
 void SceneDbgDrawer::drawPerspectiveCamera(const PerspectiveCamera& cam) const
 void SceneDbgDrawer::drawPerspectiveCamera(const PerspectiveCamera& cam) const
 {
 {
@@ -72,8 +69,6 @@ void SceneDbgDrawer::drawPerspectiveCamera(const PerspectiveCamera& cam) const
 }
 }
 
 
 
 
-//==============================================================================
-// drawOrthographicCamera                                                      =
 //==============================================================================
 //==============================================================================
 void SceneDbgDrawer::drawOrthographicCamera(
 void SceneDbgDrawer::drawOrthographicCamera(
 	const OrthographicCamera& ocam) const
 	const OrthographicCamera& ocam) const
@@ -114,8 +109,6 @@ void SceneDbgDrawer::drawOrthographicCamera(
 }
 }
 
 
 
 
-//==============================================================================
-// drawLight                                                                   =
 //==============================================================================
 //==============================================================================
 void SceneDbgDrawer::drawLight(const Light& light) const
 void SceneDbgDrawer::drawLight(const Light& light) const
 {
 {
@@ -125,8 +118,6 @@ void SceneDbgDrawer::drawLight(const Light& light) const
 }
 }
 
 
 
 
-//==============================================================================
-// drawParticleEmitter                                                         =
 //==============================================================================
 //==============================================================================
 void SceneDbgDrawer::drawParticleEmitter(const ParticleEmitterNode& pe) const
 void SceneDbgDrawer::drawParticleEmitter(const ParticleEmitterNode& pe) const
 {
 {
@@ -136,8 +127,6 @@ void SceneDbgDrawer::drawParticleEmitter(const ParticleEmitterNode& pe) const
 }
 }
 
 
 
 
-//==============================================================================
-// drawSkinNodeSkeleton                                                        =
 //==============================================================================
 //==============================================================================
 void SceneDbgDrawer::drawSkinNodeSkeleton(const SkinNode& sn) const
 void SceneDbgDrawer::drawSkinNodeSkeleton(const SkinNode& sn) const
 {
 {
@@ -154,4 +143,33 @@ void SceneDbgDrawer::drawSkinNodeSkeleton(const SkinNode& sn) const
 }
 }
 
 
 
 
+//==============================================================================
+void SceneDbgDrawer::drawOctree(const Octree& octree) const
+{
+	dbg.setColor(Vec3(1.0));
+	drawOctreeNode(octree.getRoot(), 0, octree);
+}
+
+
+//==============================================================================
+void SceneDbgDrawer::drawOctreeNode(const OctreeNode& octnode, uint depth,
+	const Octree& octree) const
+{
+	Vec3 color = Vec3(1.0 - float(depth) / float(octree.getMaxDepth()));
+	dbg.setColor(color);
+
+	CollisionDbgDrawer v(dbg);
+	octnode.getAabb().accept(v);
+
+	// Children
+	for(uint i = 0; i < 8; ++i)
+	{
+		if(octnode.getChildren()[i] != NULL)
+		{
+			drawOctreeNode(*octnode.getChildren()[i], depth + 1, octree);
+		}
+	}
+}
+
+
 } // end namespace
 } // end namespace

+ 9 - 0
anki/renderer/SceneDbgDrawer.h

@@ -1,6 +1,8 @@
 #ifndef ANKI_RENDERER_SCENE_DBG_DRAWER_H
 #ifndef ANKI_RENDERER_SCENE_DBG_DRAWER_H
 #define ANKI_RENDERER_SCENE_DBG_DRAWER_H
 #define ANKI_RENDERER_SCENE_DBG_DRAWER_H
 
 
+#include "anki/util/StdTypes.h"
+
 
 
 namespace anki {
 namespace anki {
 
 
@@ -11,6 +13,8 @@ class ParticleEmitterNode;
 class SkinNode;
 class SkinNode;
 class PerspectiveCamera;
 class PerspectiveCamera;
 class OrthographicCamera;
 class OrthographicCamera;
+class Octree;
+class OctreeNode;
 
 
 class Dbg;
 class Dbg;
 
 
@@ -36,6 +40,11 @@ class SceneDbgDrawer
 		/// Draw a skeleton
 		/// Draw a skeleton
 		virtual void drawSkinNodeSkeleton(const SkinNode& pe) const;
 		virtual void drawSkinNodeSkeleton(const SkinNode& pe) const;
 
 
+		virtual void drawOctree(const Octree& octree) const;
+
+		virtual void drawOctreeNode(const OctreeNode& octnode,
+			uint depth, const Octree& octree) const;
+
 	private:
 	private:
 		Dbg& dbg; ///< The debug stage
 		Dbg& dbg; ///< The debug stage
 
 

+ 82 - 61
anki/scene/Octree.cpp

@@ -1,5 +1,7 @@
 #include "anki/scene/Octree.h"
 #include "anki/scene/Octree.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Exception.h"
+#include "anki/core/Logger.h"
+#include "anki/core/Globals.h"
 #include "anki/collision/CollisionAlgorithmsMatrix.h"
 #include "anki/collision/CollisionAlgorithmsMatrix.h"
 
 
 
 
@@ -7,99 +9,118 @@ namespace anki {
 
 
 
 
 //==============================================================================
 //==============================================================================
-Octree::Octree(const Aabb& aabb, uchar maxDepth_)
-:	maxDepth(maxDepth_)
+Octree::Octree(const Aabb& aabb, uchar maxDepth_, float looseness_)
+:	maxDepth(maxDepth_ < 1 ? 1 : maxDepth_),
+ 	looseness(looseness_)
 {
 {
-	if(maxDepth < 1)
-	{
-		maxDepth = 1;
-	}
-
 	// Create root
 	// Create root
-	root = new OctreeNode();
-	root->aabb = aabb;
-
-	// Create children
-	//createSubTree(maxDepth, *root);
+	root = new OctreeNode(aabb, NULL);
+	nodes.push_back(root);
 }
 }
 
 
 
 
 //==============================================================================
 //==============================================================================
-OctreeNode& Octree::place(const Aabb& aabb)
+OctreeNode* Octree::place(const Aabb& aabb)
 {
 {
-	// Run the recursive
-	return place(aabb, 0, *root);
+	if(CollisionAlgorithmsMatrix::collide(aabb, root->getAabb()))
+	{
+		// Run the recursive
+		return place(aabb, 0, *root);
+	}
+	else
+	{
+		return NULL;
+	}
 }
 }
 
 
 
 
 //==============================================================================
 //==============================================================================
-OctreeNode& Octree::place(const Aabb& aabb, uint depth, OctreeNode& node)
+OctreeNode* Octree::place(const Aabb& aabb, uint depth, OctreeNode& node)
 {
 {
 	if(depth >= maxDepth)
 	if(depth >= maxDepth)
 	{
 	{
-		return node;
+		return &node;
 	}
 	}
 
 
-	uint count = 0;
-	uint last = 0;
-	for(uint i = 0; i < 8; ++i)
+
+	for(uint i = 0; i < 2; ++i)
 	{
 	{
-		if(CollisionAlgorithmsMatrix::collide(aabb, node.children[i].aabb))
+		for(uint j = 0; j < 2; ++j)
 		{
 		{
-			last = i;
-			++count;
-		}
-	}
-
-	ASSERT(count != 0);
+			for(uint k = 0; k < 2; ++k)
+			{
+				uint id = i * 4 + j * 2 + k;
+
+				Aabb childAabb;
+				if(node.getChildren()[id] != NULL)
+				{
+					childAabb = node.getChildren()[id]->getAabb();
+				}
+				else
+				{
+					calcAabb(i, j, k, node.getAabb(), childAabb);
+				}
+
+
+				// If aabb its completely inside the target
+				if(aabb.getMax() <= childAabb.getMax() &&
+					aabb.getMin() >= childAabb.getMin())
+				{
+					// Create new node if needed
+					if(node.getChildren()[id] == NULL)
+					{
+						OctreeNode* newNode = new OctreeNode(childAabb, &node);
+						node.addChild(id, *newNode);
+						nodes.push_back(newNode);
+					}
+
+					return place(aabb, depth + 1, *node.getChildren()[id]);
+				}
+			} // k
+		} // j
+	} // i
 
 
-	if(count == 1)
-	{
-		return place(aabb, depth + 1, node.children[last]);
-	}
+	return &node;
 }
 }
 
 
 
 
 //==============================================================================
 //==============================================================================
-/*void Octree::createSubTree(uint rdepth, OctreeNode& parent)
+void Octree::calcAabb(uint i, uint j, uint k, const Aabb& paabb,
+	Aabb& out) const
 {
 {
-	if(rdepth == 0)
-	{
-		return;
-	}
-
-	const Aabb& paabb = parent.getAabb();
 	const Vec3& min = paabb.getMin();
 	const Vec3& min = paabb.getMin();
 	const Vec3& max = paabb.getMax();
 	const Vec3& max = paabb.getMax();
-
 	Vec3 d = (max - min) / 2.0;
 	Vec3 d = (max - min) / 2.0;
 
 
-	// Create children
-	for(uint i = 0; i < 2; ++i)
-	{
-		for(uint j = 0; j < 2; ++j)
-		{
-			for(uint k = 0; k < 2; ++k)
-			{
-				Vec3 omin;
-				omin.x() = min.x() + d.x() * i;
-				omin.y() = min.y() + d.y() * j;
-				omin.z() = min.z() + d.z() * k;
+	Vec3 omin;
+	omin.x() = min.x() + d.x() * i;
+	omin.y() = min.y() + d.y() * j;
+	omin.z() = min.z() + d.z() * k;
 
 
-				Vec3 omax = omin + d;
+	Vec3 omax = omin + d;
 
 
-				OctreeNode* node = new OctreeNode();
-				node->parent = &parent;
-				node->aabb = Aabb(omin, omax);
+	// Scale the AABB with looseness
+	float tmp0 = (1.0 + looseness) / 2.0;
+	float tmp1 = (1.0 - looseness) / 2.0;
+	Vec3 nomin = tmp0 * omin + tmp1 * omax;
+	Vec3 nomax = tmp0 * omax + tmp1 * omin;
 
 
-				parent.children[i * 4 + j * 2 + k] = node;
-				nodes.push_back(node);
+	// Crop to fit the parent's AABB
+	for(uint n = 0; n < 3; ++n)
+	{
+		if(nomin[n] < min[n])
+		{
+			nomin[n] = min[n];
+		}
 
 
-				createSubTree(rdepth - 1, *node);
-			} // k
-		} // j
-	} // i
-}*/
+		if(nomax[n] > max[n])
+		{
+			nomax[n] = max[n];
+		}
+	}
+
+	out = Aabb(nomin, nomax);
+}
 
 
 
 
 } // end namespace
 } // end namespace

+ 48 - 14
anki/scene/Octree.h

@@ -13,16 +13,12 @@ namespace anki {
 /// XXX
 /// XXX
 class OctreeNode
 class OctreeNode
 {
 {
-	friend class Octree;
-
 	public:
 	public:
-		OctreeNode()
-		:	parent(NULL)
+		OctreeNode(const Aabb& aabb_, OctreeNode* parent_)
+		:	parent(parent_),
+		 	aabb(aabb_)
 		{
 		{
-			for(size_t i = 0; children.size(); ++i)
-			{
-				children[i] = NULL;
-			}
+			initArr();
 		}
 		}
 
 
 		/// @name Accessors
 		/// @name Accessors
@@ -48,16 +44,24 @@ class OctreeNode
 			return parent == NULL;
 			return parent == NULL;
 		}
 		}
 
 
-		/// Means no more children
-		bool isFinal() const
+		void addChild(uint pos, OctreeNode& child)
 		{
 		{
-			return children[0] == NULL;
+			child.parent = this;
+			children[pos] = &child;
 		}
 		}
 
 
 	private:
 	private:
 		boost::array<OctreeNode*, 8> children;
 		boost::array<OctreeNode*, 8> children;
 		OctreeNode* parent;
 		OctreeNode* parent;
 		Aabb aabb; ///< Including AABB
 		Aabb aabb; ///< Including AABB
+
+		void initArr()
+		{
+			for(size_t i = 0; i < children.size(); ++i)
+			{
+				children[i] = NULL;
+			}
+		}
 };
 };
 
 
 
 
@@ -65,18 +69,48 @@ class OctreeNode
 class Octree
 class Octree
 {
 {
 	public:
 	public:
-		Octree(const Aabb& aabb, uchar maxDepth);
+		Octree(const Aabb& aabb, uchar maxDepth, float looseness = 1.5);
 
 
-		OctreeNode& place(const Aabb& aabb);
+		/// @name Accessors
+		/// @{
+		const OctreeNode& getRoot() const
+		{
+			return *root;
+		}
+		OctreeNode& getRoot()
+		{
+			return *root;
+		}
+
+		uint getMaxDepth() const
+		{
+			return maxDepth;
+		}
+		/// @}
+
+		OctreeNode* place(const Aabb& aabb);
 
 
 	private:
 	private:
 		OctreeNode* root;
 		OctreeNode* root;
 		boost::ptr_vector<OctreeNode> nodes; ///< For garbage collection
 		boost::ptr_vector<OctreeNode> nodes; ///< For garbage collection
 		uint maxDepth;
 		uint maxDepth;
+		float looseness;
 
 
 		//void createSubTree(uint rdepth, OctreeNode& parent);
 		//void createSubTree(uint rdepth, OctreeNode& parent);
 
 
-		OctreeNode& place(const Aabb& aabb, uint depth, OctreeNode& node);
+		OctreeNode* place(const Aabb& aabb, uint depth, OctreeNode& node);
+
+		void createChildren(OctreeNode& parent);
+
+		/// Calculate the AABB of a child given the parent's AABB and its
+		/// position
+		/// @param[in] i 0: left, 1: right
+		/// @param[in] j 0: down, 1: up
+		/// @param[in] k 0: back, 1: front
+		/// @param[in] parentAabb The parent's AABB
+		/// @param[out] out The out AABB
+		void calcAabb(uint i, uint j, uint k, const Aabb& parentAabb,
+			Aabb& out) const;
 };
 };
 
 
 
 

+ 2 - 2
testapp/Main.cpp

@@ -145,7 +145,7 @@ void init()
 	PerspectiveCamera* cam = new PerspectiveCamera(scene, SceneNode::SNF_NONE, NULL);
 	PerspectiveCamera* cam = new PerspectiveCamera(scene, SceneNode::SNF_NONE, NULL);
 	//cam->setAll(toRad(100.0), toRad(100.0) / r::MainRendererSingleton::get().getAspectRatio(), 0.5, 200.0);
 	//cam->setAll(toRad(100.0), toRad(100.0) / r::MainRendererSingleton::get().getAspectRatio(), 0.5, 200.0);
 	ANKI_INFO(MainRendererSingleton::get().getAspectRatio());
 	ANKI_INFO(MainRendererSingleton::get().getAspectRatio());
-	cam->setAll(MainRendererSingleton::get().getAspectRatio()*Math::toRad(90.0), Math::toRad(90.0), 0.5, 200.0);
+	cam->setAll(MainRendererSingleton::get().getAspectRatio()*Math::toRad(70.0), Math::toRad(70.0), 0.5, 200.0);
 	cam->moveLocalY(3.0);
 	cam->moveLocalY(3.0);
 	cam->moveLocalZ(5.7);
 	cam->moveLocalZ(5.7);
 	cam->moveLocalX(-0.3);
 	cam->moveLocalX(-0.3);
@@ -291,7 +291,7 @@ void mainLoopExtra()
 	if(InputSingleton::get().getKey(SDL_SCANCODE_6)) mover = imp;
 	if(InputSingleton::get().getKey(SDL_SCANCODE_6)) mover = imp;
 	if(InputSingleton::get().getKey(SDL_SCANCODE_7)) mover =
 	if(InputSingleton::get().getKey(SDL_SCANCODE_7)) mover =
 		SceneSingleton::get().getParticleEmitterNodes()[0];
 		SceneSingleton::get().getParticleEmitterNodes()[0];
-	//if(InputSingleton::get().getKey(SDL_SCANCODE_M) == 1) InputSingleton::get().warpMouse = !InputSingleton::get().warpMouse;
+	if(InputSingleton::get().getKey(SDL_SCANCODE_8)) mover = horse;
 
 
 	if(InputSingleton::get().getKey(SDL_SCANCODE_A)) mover->moveLocalX(-dist);
 	if(InputSingleton::get().getKey(SDL_SCANCODE_A)) mover->moveLocalX(-dist);
 	if(InputSingleton::get().getKey(SDL_SCANCODE_D)) mover->moveLocalX(dist);
 	if(InputSingleton::get().getKey(SDL_SCANCODE_D)) mover->moveLocalX(dist);