Browse Source

Working on collision, replacing a lot of Vec3 with SIMD Vec4

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
31fe55a4ed
60 changed files with 719 additions and 1862 deletions
  1. 1 1
      include/anki/Collision.h
  2. 24 25
      include/anki/collision/Aabb.h
  3. 0 142
      include/anki/collision/CollisionAlgorithms.h
  4. 16 11
      include/anki/collision/CollisionShape.h
  5. 18 1
      include/anki/collision/ConvexShape.h
  6. 0 1
      include/anki/collision/Forward.h
  7. 1 1
      include/anki/collision/GjkEpa.h
  8. 35 33
      include/anki/collision/LineSegment.h
  9. 25 27
      include/anki/collision/Obb.h
  10. 37 36
      include/anki/collision/Plane.h
  11. 0 119
      include/anki/collision/Ray.h
  12. 15 15
      include/anki/collision/Sphere.h
  13. 1 1
      include/anki/event/AnimationEvent.h
  14. 6 5
      include/anki/event/MoveEvent.h
  15. 1 0
      include/anki/math/Forward.h
  16. 5 0
      include/anki/math/Mat.h
  17. 61 40
      include/anki/math/Mat3x4.h
  18. 22 7
      include/anki/math/Mat4.h
  19. 15 4
      include/anki/math/Quat.h
  20. 53 48
      include/anki/math/Transform.h
  21. 13 1
      include/anki/math/Vec.h
  22. 0 103
      include/anki/math/Vec3.h
  23. 1 1
      include/anki/math/Vec4.h
  24. 4 4
      include/anki/math/Vec4.inl.h
  25. 3 3
      include/anki/physics/Converters.h
  26. 0 5
      include/anki/renderer/DebugDrawer.h
  27. 1 1
      include/anki/scene/Camera.h
  28. 1 1
      include/anki/scene/FrustumComponent.h
  29. 2 2
      include/anki/scene/Light.h
  30. 1 1
      include/anki/scene/Misc.h
  31. 1 1
      include/anki/scene/ModelNode.h
  32. 29 29
      include/anki/scene/MoveComponent.h
  33. 6 6
      include/anki/scene/ParticleEmitter.h
  34. 1 1
      include/anki/scene/SpatialComponent.h
  35. 2 2
      include/anki/scene/StaticGeometryNode.h
  36. 2 2
      include/anki/scene/Visibility.h
  37. 24 11
      src/collision/Aabb.cpp
  38. 0 669
      src/collision/CollisionAlgorithms.cpp
  39. 1 1
      src/collision/CompoundShape.cpp
  40. 23 22
      src/collision/Frustum.cpp
  41. 1 1
      src/collision/GjkEpa.cpp
  42. 7 8
      src/collision/LineSegment.cpp
  43. 92 42
      src/collision/Obb.cpp
  44. 17 20
      src/collision/Plane.cpp
  45. 0 57
      src/collision/Ray.cpp
  46. 13 17
      src/collision/Sphere.cpp
  47. 0 232
      src/collision/TestsObbObb.cpp
  48. 8 8
      src/event/AnimationEvent.cpp
  49. 5 4
      src/event/MoveEvent.cpp
  50. 35 0
      src/renderer/Dbg.cpp
  51. 12 16
      src/renderer/DebugDrawer.cpp
  52. 3 4
      src/renderer/Drawer.cpp
  53. 9 9
      src/renderer/Is.cpp
  54. 1 1
      src/renderer/Lf.cpp
  55. 10 8
      src/renderer/Tiler.cpp
  56. 9 7
      src/scene/Camera.cpp
  57. 10 10
      src/scene/MoveComponent.cpp
  58. 19 19
      src/scene/ParticleEmitter.cpp
  59. 3 3
      src/scene/Visibility.cpp
  60. 14 13
      testapp/Main.cpp

+ 1 - 1
include/anki/Collision.h

@@ -12,12 +12,12 @@
 #include "anki/collision/Plane.h"
 #include "anki/collision/Sphere.h"
 #include "anki/collision/Obb.h"
-#include "anki/collision/Ray.h"
 #include "anki/collision/LineSegment.h"
 #include "anki/collision/Frustum.h"
 #include "anki/collision/Aabb.h"
 #include "anki/collision/CompoundShape.h"
 
+#include "anki/collision/GjkEpa.h"
 #include "anki/collision/Functions.h"
 
 #endif

+ 24 - 25
include/anki/collision/Aabb.h

@@ -6,7 +6,7 @@
 #ifndef ANKI_COLLISION_AABB_H
 #define ANKI_COLLISION_AABB_H
 
-#include "anki/collision/CollisionShape.h"
+#include "anki/collision/ConvexShape.h"
 #include "anki/math/Vec3.h"
 
 namespace anki {
@@ -15,52 +15,54 @@ namespace anki {
 /// @{
 
 /// Axis align bounding box collision shape
-class Aabb: public CollisionShape
+class Aabb: public ConvexShape
 {
 public:
+	using Base = ConvexShape;
+
 	/// @name Constructors
 	/// @{
 	Aabb()
-		: CollisionShape(Type::AABB)
+		: Base(Type::AABB)
 	{}
 
-	Aabb(const Vec3& min, const Vec3& max)
-		: CollisionShape(Type::AABB), m_min(min), m_max(max)
+	Aabb(const Vec4& min, const Vec4& max)
+		: Base(Type::AABB), m_min(min), m_max(max)
 	{
-		ANKI_ASSERT(m_min < m_max);
+		ANKI_ASSERT(m_min.xyz() < m_max.xyz());
 	}
 
 	Aabb(const Aabb& b)
-		:	CollisionShape(Type::AABB), 
-			m_min(b.m_min), 
-			m_max(b.m_max)
-	{}
+		: Base(Type::AABB)
+	{
+		operator=(b);
+	}
 	/// @}
 
 	/// @name Accessors
 	/// @{
-	const Vec3& getMin() const
+	const Vec4& getMin() const
 	{
 		return m_min;
 	}
-	Vec3& getMin()
+	Vec4& getMin()
 	{
 		return m_min;
 	}
-	void setMin(const Vec3& x)
+	void setMin(const Vec4& x)
 	{
 		m_min = x;
 	}
 
-	const Vec3& getMax() const
+	const Vec4& getMax() const
 	{
 		return m_max;
 	}
-	Vec3& getMax()
+	Vec4& getMax()
 	{
 		return m_max;
 	}
-	void setMax(const Vec3& x)
+	void setMax(const Vec4& x)
 	{
 		m_max = x;
 	}
@@ -70,19 +72,13 @@ public:
 	/// @{
 	Aabb& operator=(const Aabb& b)
 	{
+		Base::operator=(b);
 		m_min = b.m_min;
 		m_max = b.m_max;
 		return *this;
 	}
 	/// @}
 
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
-	{
-		return detail::collide(*this, x);
-	}
-
 	/// Implements CollisionShape::accept
 	void accept(MutableVisitor& v)
 	{
@@ -109,6 +105,9 @@ public:
 		b = *this;
 	}
 
+	/// Implements CompoundShape::computeSupport
+	Vec4 computeSupport(const Vec4& dir) const;
+
 	/// It uses a nice trick to avoid unwanted calculations 
 	Aabb getTransformed(const Transform& transform) const;
 
@@ -123,8 +122,8 @@ public:
 private:
 	/// @name Data
 	/// @{
-	Vec3 m_min;
-	Vec3 m_max;
+	Vec4 m_min;
+	Vec4 m_max;
 	/// @}
 };
 /// @}

+ 0 - 142
include/anki/collision/CollisionAlgorithms.h

@@ -1,142 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#ifndef ANKI_COLLISION_COLLISION_ALGORITHMS_H
-#define ANKI_COLLISION_COLLISION_ALGORITHMS_H
-
-#include "anki/collision/Forward.h"
-#include "anki/util/StdTypes.h"
-
-namespace anki {
-namespace detail {
-
-/// @addtogroup Collision
-/// @{
-/// @addtogroup Algorithms
-/// Provides the collision algorithms that detect collision between various
-/// shapes
-/// @code
-/// +------+------+------+------+------+------+------+
-/// |      | LS   | OBB  | P    | R    | S    | AABB |
-/// +------+------+------+------+------+------+------+
-/// | LS   | N/A  | OK   | OK   | N/A  | OK   | OK   |
-/// +------+------+------+------+------+------+------+
-/// | OBB  |      | OK   | OK   | OK   | OK   | OK   |
-/// +------+------+------+------+------+------+------+
-/// | P    |      |      | OK   | OK   | OK   | OK   |
-/// +------+------+------+------+------+------+------+
-/// | R    |      |      |      | N/A  | OK   | OK   |
-/// +------+------+------+------+------+------+------+
-/// | S    |      |      |      |      | OK   | OK   |
-/// +------+------+------+------+------+------+------+
-/// | AABB |      |      |      |      |      | OK   |
-/// +------+------+------+------+------+------+------+
-/// @endcode
-/// @{
-
-/// Generic collide function. It doesn't uses visitor pattern for
-/// speed reasons
-extern Bool collide(const CollisionShape& a, const CollisionShape& b);
-
-// 1st line (LS)
-extern Bool collide(const LineSegment& a, const LineSegment& b);
-extern Bool collide(const LineSegment& a, const Obb& b);
-extern Bool collide(const LineSegment& a, const Plane& b);
-extern Bool collide(const LineSegment& a, const Ray& b);
-extern Bool collide(const LineSegment& a, const Sphere& b);
-extern Bool collide(const LineSegment& a, const Aabb& b);
-
-// 2nd line (OBB)
-inline Bool collide(const Obb& a, const LineSegment& b)
-{
-	return collide(b, a);
-}
-extern Bool collide(const Obb& a, const Obb& b);
-extern Bool collide(const Obb& a, const Plane& b);
-extern Bool collide(const Obb& a, const Ray& b);
-extern Bool collide(const Obb& a, const Sphere& b);
-extern Bool collide(const Obb& a, const Aabb& b);
-
-// 4th line (P)
-inline Bool collide(const Plane& a, const LineSegment& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Plane& a, const Obb& b)
-{
-	return collide(b, a);
-}
-extern Bool collide(const Plane& a, const Plane& b);
-extern Bool collide(const Plane& a, const Ray& b);
-extern Bool collide(const Plane& a, const Sphere& b);
-extern Bool collide(const Plane& a, const Aabb& b);
-
-// 5th line (R)
-inline Bool collide(const Ray& a, const LineSegment& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Ray& a, const Obb& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Ray& a, const Plane& b)
-{
-	return collide(b, a);
-}
-extern Bool collide(const Ray& a, const Ray& b);
-extern Bool collide(const Ray& a, const Sphere& b);
-extern Bool collide(const Ray& a, const Aabb& b);
-
-// 6th line (S)
-inline Bool collide(const Sphere& a, const LineSegment& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Sphere& a, const Obb& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Sphere& a, const Plane& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Sphere& a, const Ray& b)
-{
-	return collide(b, a);
-}
-extern Bool collide(const Sphere& a, const Sphere& b);
-extern Bool collide(const Sphere& a, const Aabb& b);
-
-// 7th line (AABB)
-inline Bool collide(const Aabb& a, const LineSegment& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Aabb& a, const Obb& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Aabb& a, const Plane& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Aabb& a, const Ray& b)
-{
-	return collide(b, a);
-}
-inline Bool collide(const Aabb& a, const Sphere& b)
-{
-	return collide(b, a);
-}
-extern Bool collide(const Aabb& a, const Aabb& b);
-
-/// @}
-/// @}
-
-} // end namespace detail
-} // end namespace anki
-
-#endif

+ 16 - 11
include/anki/collision/CollisionShape.h

@@ -7,7 +7,6 @@
 #define ANKI_COLLISION_COLLISION_SHAPE_H
 
 #include "anki/collision/Forward.h"
-#include "anki/collision/CollisionAlgorithms.h"
 #include "anki/Math.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Visitor.h"
@@ -26,7 +25,6 @@ public:
 	enum class Type: U8
 	{
 		LINE_SEG,
-		RAY,
 		PLANE,
 		SPHERE,
 		AABB,
@@ -44,7 +42,6 @@ public:
 		virtual void visit(LineSegment&) = 0;
 		virtual void visit(Obb&) = 0;
 		virtual void visit(Plane&) = 0;
-		virtual void visit(Ray&) = 0;
 		virtual void visit(Sphere&) = 0;
 		virtual void visit(Aabb&) = 0;
 		virtual void visit(CompoundShape&) = 0;
@@ -60,7 +57,6 @@ public:
 		virtual void visit(const LineSegment&) = 0;
 		virtual void visit(const Obb&) = 0;
 		virtual void visit(const Plane&) = 0;
-		virtual void visit(const Ray&) = 0;
 		virtual void visit(const Sphere&) = 0;
 		virtual void visit(const Aabb&) = 0;
 		virtual void visit(const CompoundShape&) = 0;
@@ -72,24 +68,33 @@ public:
 		: m_cid(cid)
 	{}
 
+	CollisionShape(const CollisionShape& b)
+		: m_cid(b.m_cid)
+	{
+		operator=(b);
+	}
+
 	virtual ~CollisionShape()
 	{}
 	/// @}
 
-	/// @name Accessors
+	/// @name Operators
 	/// @{
-	Type getType() const
+	CollisionShape& operator=(const CollisionShape& b)
 	{
-		return m_cid;
+		ANKI_ASSERT(b.m_cid == m_cid);
+		(void)b;
+		return *this;
 	}
 	/// @}
 
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
+	/// @name Accessors
+	/// @{
+	Type getType() const
 	{
-		return detail::collide(*this, x);
+		return m_cid;
 	}
+	/// @}
 
 	/// 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

+ 18 - 1
include/anki/collision/ConvexShape.h

@@ -17,11 +17,28 @@ namespace anki {
 class ConvexShape: public CollisionShape
 {
 public:
+	using Base = CollisionShape;
+
 	/// @name Constructors & destructor
 	/// @{
 	ConvexShape(Type cid)
-		: CollisionShape(cid)
+		: Base(cid)
 	{}
+
+	ConvexShape(const ConvexShape& b)
+		: Base(b)
+	{
+		operator=(b);
+	}
+	/// @}
+
+	/// @name Operators
+	/// @{
+	ConvexShape& operator=(const ConvexShape& b)
+	{
+		Base::operator=(b);
+		return *this;
+	}
 	/// @}
 
 	/// Get a support vector for the GJK algorithm

+ 0 - 1
include/anki/collision/Forward.h

@@ -14,7 +14,6 @@ class LineSegment;
 class Obb;
 class Frustum;
 class Plane;
-class Ray;
 class Sphere;
 class Aabb;
 class CompoundShape;

+ 1 - 1
include/anki/collision/GjkEpa.h

@@ -39,7 +39,7 @@ private:
 	/// Helper of axbxa
 	static Vec4 crossAba(const Vec4& a, const Vec4& b)
 	{
-		return a.cross(b).cross(a);
+		return (a.cross(b)).cross(a);
 	}
 };
 

+ 35 - 33
include/anki/collision/LineSegment.h

@@ -19,51 +19,59 @@ namespace anki {
 class LineSegment: public CollisionShape
 {
 public:
+	using Base = CollisionShape;
+
 	/// @name Constructors
 	/// @{
 	LineSegment()
-		: CollisionShape(Type::LINE_SEG)
+		:	Base(Type::LINE_SEG),
+			m_origin(0.0),
+			m_dir(0.0)
 	{}
 
-	LineSegment(const Vec3& origin_, const Vec3& direction)
-		:	CollisionShape(Type::LINE_SEG), 
-			origin(origin_), 
-			dir(direction)
+	LineSegment(const Vec4& origin, const Vec4& direction)
+		:	Base(Type::LINE_SEG), 
+			m_origin(origin), 
+			m_dir(direction)
 	{}
 
 	LineSegment(const LineSegment& b)
-		:	CollisionShape(Type::LINE_SEG), 
-			origin(b.origin), 
-			dir(b.dir)
-	{}
+		:	Base(Type::LINE_SEG)
+	{
+		operator=(b);
+	}
 	/// @}
 
 	/// @name Accessors
 	/// @{
-	const Vec3& getOrigin() const
+	const Vec4& getOrigin() const
 	{
-		return origin;
+		return m_origin;
 	}
-	Vec3& getOrigin()
+
+	Vec4& getOrigin()
 	{
-		return origin;
+		return m_origin;
 	}
-	void setOrigin(const Vec3& x)
+
+	void setOrigin(const Vec4& x)
 	{
-		origin = x;
+		m_origin = x;
 	}
 
-	const Vec3& getDirection() const
+	const Vec4& getDirection() const
 	{
-		return dir;
+		return m_dir;
 	}
-	Vec3& getDirection()
+
+	Vec4& getDirection()
 	{
-		return dir;
+		return m_dir;
 	}
-	void setDirection(const Vec3& x)
+
+	void setDirection(const Vec4& x)
 	{
-		dir = x;
+		m_dir = x;
 	}
 	/// @}
 
@@ -71,19 +79,13 @@ public:
 	/// @{
 	LineSegment& operator=(const LineSegment& b)
 	{
-		origin = b.origin;
-		dir = b.dir;
+		Base::operator=(b);
+		m_origin = b.m_origin;
+		m_dir = b.m_dir;
 		return *this;
 	}
 	/// @}
 
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
-	{
-		return detail::collide(*this, x);
-	}
-
 	/// Implements CollisionShape::accept
 	void accept(MutableVisitor& v)
 	{
@@ -112,12 +114,12 @@ public:
 private:
 	/// @name Data
 	/// @{
-	Vec3 origin; ///< P0
-	Vec3 dir; ///< P1 = origin+dir so dir = P1-origin
+	Vec4 m_origin; ///< P0
+	Vec4 m_dir; ///< P1 = origin+dir so dir = P1-origin
 	/// @}
 };
 /// @}
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 25 - 27
include/anki/collision/Obb.h

@@ -6,7 +6,7 @@
 #ifndef ANKI_COLLISION_OBB_H
 #define ANKI_COLLISION_OBB_H
 
-#include "anki/collision/CollisionShape.h"
+#include "anki/collision/ConvexShape.h"
 #include "anki/Math.h"
 #include "anki/util/Array.h"
 
@@ -16,57 +16,59 @@ namespace anki {
 /// @{
 
 /// Object oriented bounding box
-class Obb: public CollisionShape
+class Obb: public ConvexShape
 {
 public:
+	using Base = ConvexShape;
+
 	/// @name Constructors
 	/// @{
 	Obb();
 
 	Obb(const Obb& b);
 
-	Obb(const Vec3& center, const Mat3& rotation, const Vec3& extends);
+	Obb(const Vec4& center, const Mat3x4& rotation, const Vec4& extend);
 	/// @}
 
 	/// @name Accessors
 	/// @{
-	const Vec3& getCenter() const
+	const Vec4& getCenter() const
 	{
 		return m_center;
 	}
-	Vec3& getCenter()
+	Vec4& getCenter()
 	{
 		return m_center;
 	}
-	void setCenter(const Vec3& x)
+	void setCenter(const Vec4& x)
 	{
 		m_center = x;
 	}
 
-	const Mat3& getRotation() const
+	const Mat3x4& getRotation() const
 	{
 		return m_rotation;
 	}
-	Mat3& getRotation()
+	Mat3x4& getRotation()
 	{
 		return m_rotation;
 	}
-	void setRotation(const Mat3& x)
+	void setRotation(const Mat3x4& x)
 	{
 		m_rotation = x;
 	}
 
-	const Vec3& getExtend() const
+	const Vec4& getExtend() const
 	{
-		return m_extends;
+		return m_extend;
 	}
-	Vec3& getExtend()
+	Vec4& getExtend()
 	{
-		return m_extends;
+		return m_extend;
 	}
-	void setExtend(const Vec3& x)
+	void setExtend(const Vec4& x)
 	{
-		m_extends = x;
+		m_extend = x;
 	}
 	/// @}
 
@@ -76,18 +78,11 @@ public:
 	{
 		m_center = b.m_center;
 		m_rotation = b.m_rotation;
-		m_extends = b.m_extends;
+		m_extend = b.m_extend;
 		return *this;
 	}
 	/// @}
 
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
-	{
-		return detail::collide(*this, x);
-	}
-
 	/// Implements CollisionShape::accept
 	void accept(MutableVisitor& v)
 	{
@@ -122,16 +117,19 @@ public:
 		const void* buff, U count, PtrSize stride, PtrSize buffSize);
 
 	/// Get extreme points in 3D space
-	void getExtremePoints(Array<Vec3, 8>& points) const;
+	void getExtremePoints(Array<Vec4, 8>& points) const;
+
+	/// Implements ConvexShape::computeSupport
+	Vec4 computeSupport(const Vec4& dir) const;
 
 public:
 	/// @name Data
 	/// @{
-	Vec3 m_center;
-	Mat3 m_rotation;
+	Vec4 m_center;
+	Mat3x4 m_rotation;
 	/// With identity rotation this points to max (front, right, top in
 	/// our case)
-	Vec3 m_extends;
+	Vec4 m_extend;
 	/// @}
 };
 

+ 37 - 36
include/anki/collision/Plane.h

@@ -18,6 +18,8 @@ namespace anki {
 class Plane: public CollisionShape
 {
 public:
+	using Base = CollisionShape;
+
 	/// @name Constructors
 	/// @{
 
@@ -27,10 +29,14 @@ public:
 	{}
 
 	/// Copy constructor
-	Plane(const Plane& b);
+	Plane(const Plane& b)
+		: CollisionShape(Type::PLANE)
+	{
+		operator=(b);
+	}
 
 	/// Constructor
-	Plane(const Vec3& normal_, F32 offset_);
+	Plane(const Vec4& normal, F32 offset);
 
 	/// @see setFrom3Points
 	Plane(const Vec3& p0, const Vec3& p1, const Vec3& p2)
@@ -47,52 +53,46 @@ public:
 	}
 	/// @}
 
+	/// @name Operators
+	/// @{
+	Plane& operator=(const Plane& b)
+	{
+		Base::operator=(b);
+		m_normal = b.m_normal;
+		m_offset = b.m_offset;
+		return *this;
+	}
+	/// @}
+
 	/// @name Accessors
 	/// @{
-	const Vec3& getNormal() const
+	const Vec4& getNormal() const
 	{
-		return normal;
+		return m_normal;
 	}
-	Vec3& getNormal()
+	Vec4& getNormal()
 	{
-		return normal;
+		return m_normal;
 	}
-	void setNormal(const Vec3& x)
+	void setNormal(const Vec4& x)
 	{
-		normal = x;
+		m_normal = x;
 	}
 
 	F32 getOffset() const
 	{
-		return offset;
+		return m_offset;
 	}
 	F32& getOffset()
 	{
-		return offset;
+		return m_offset;
 	}
 	void setOffset(const F32 x)
 	{
-		offset = x;
+		m_offset = x;
 	}
 	/// @}
 
-	/// @name Operators
-	/// @{
-	Plane& operator=(const Plane& b)
-	{
-		normal = b.normal;
-		offset = b.offset;
-		return *this;
-	}
-	/// @}
-
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
-	{
-		return detail::collide(*this, x);
-	}
-
 	/// Implements CollisionShape::accept
 	void accept(MutableVisitor& v)
 	{
@@ -122,22 +122,23 @@ public:
 	/// It gives the distance between a point and a plane. if returns >0
 	/// then the point lies in front of the plane, if <0 then it is behind
 	/// and if =0 then it is co-planar
-	F32 test(const Vec3& point) const
+	F32 test(const Vec4& point) const
 	{
-		return normal.dot(point) - offset;
+		ANKI_ASSERT(isZero<F32>(point.w()));
+		return m_normal.dot(point) - m_offset;
 	}
 
 	/// Get the distance from a point to this plane
-	F32 getDistance(const Vec3& point) const
+	F32 getDistance(const Vec4& point) const
 	{
 		return fabs(test(point));
 	}
 
 	/// Returns the perpedicular point of a given point in this plane.
 	/// Plane's normal and returned-point are perpedicular
-	Vec3 getClosestPoint(const Vec3& point) const
+	Vec4 getClosestPoint(const Vec4& point) const
 	{
-		return point - normal * test(point);
+		return point - m_normal * test(point);
 	}
 
 	/// Test a CollisionShape
@@ -150,8 +151,8 @@ public:
 private:
 	/// @name Data
 	/// @{
-	Vec3 normal;
-	F32 offset;
+	Vec4 m_normal;
+	F32 m_offset;
 	/// @}
 
 	/// Set the plane from 3 points
@@ -162,6 +163,6 @@ private:
 };
 /// @}
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 0 - 119
include/anki/collision/Ray.h

@@ -1,119 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#ifndef ANKI_COLLISION_RAY_H
-#define ANKI_COLLISION_RAY_H
-
-#include "anki/collision/CollisionShape.h"
-#include "anki/Math.h"
-
-namespace anki {
-
-/// @addtogroup Collision
-/// @{
-
-/// Ray collision shape. It has a starting point but the end extends to infinity
-class Ray: public CollisionShape
-{
-public:
-	/// @name Constructors
-	/// @{
-
-	/// Default constructor
-	Ray()
-		: CollisionShape(Type::RAY)
-	{}
-
-	/// Copy constructor
-	Ray(const Ray& b)
-		: CollisionShape(Type::RAY), origin(b.origin), dir(b.dir)
-	{}
-
-	/// Constructor
-	Ray(const Vec3& origin_, const Vec3& direction_)
-		: CollisionShape(Type::RAY), origin(origin_), dir(direction_)
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-	const Vec3& getOrigin() const
-	{
-		return origin;
-	}
-	Vec3& getOrigin()
-	{
-		return origin;
-	}
-	void setOrigin(const Vec3& x)
-	{
-		origin = x;
-	}
-
-	const Vec3& getDirection() const
-	{
-		return dir;
-	}
-	Vec3& getDirection()
-	{
-		return dir;
-	}
-	void setDirection(const Vec3& x)
-	{
-		dir = x;
-	}
-	/// @}
-
-	/// @name Operators
-	/// @{
-	Ray& operator=(const Ray& b)
-	{
-		origin = b.origin;
-		dir = b.dir;
-		return *this;
-	}
-	/// @}
-
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
-	{
-		return detail::collide(*this, x);
-	}
-
-	/// Implements CollisionShape::accept
-	void accept(MutableVisitor& v)
-	{
-		v.visit(*this);
-	}
-	/// Implements CollisionShape::accept
-	void accept(ConstVisitor& v) const
-	{
-		v.visit(*this);
-	}
-
-	/// Implements CollisionShape::testPlane
-	F32 testPlane(const Plane& p) const;
-
-	/// Implements CollisionShape::transform
-	void transform(const Transform& trf)
-	{
-		*this = getTransformed(trf);
-	}
-
-	/// Implements CollisionShape::computeAabb
-	void computeAabb(Aabb& aabb) const;
-
-	Ray getTransformed(const Transform& transform) const;
-
-private:
-	Vec3 origin;
-	Vec3 dir;
-};
-/// @}
-
-} // end namespace
-
-#endif

+ 15 - 15
include/anki/collision/Sphere.h

@@ -18,24 +18,26 @@ namespace anki {
 class Sphere: public ConvexShape
 {
 public:
+	using Base = ConvexShape;
+
 	/// @name Constructors
 	/// @{
 
 	/// Default constructor
 	Sphere()
-		: ConvexShape(Type::SPHERE)
+		: Base(Type::SPHERE)
 	{}
 
 	/// Copy constructor
 	Sphere(const Sphere& b)
-		:	ConvexShape(Type::SPHERE)
+		: Base(Type::SPHERE)
 	{
 		operator=(b);
 	}
 
 	/// Constructor
-	Sphere(const Vec3& center, F32 radius)
-		:	ConvexShape(Type::SPHERE), 
+	Sphere(const Vec4& center, F32 radius)
+		:	Base(Type::SPHERE), 
 			m_center(center), 
 			m_radius(radius)
 	{}
@@ -43,15 +45,17 @@ public:
 
 	/// @name Accessors
 	/// @{
-	const Vec3& getCenter() const
+	const Vec4& getCenter() const
 	{
 		return m_center;
 	}
-	Vec3& getCenter()
+
+	Vec4& getCenter()
 	{
 		return m_center;
 	}
-	void setCenter(const Vec3& x)
+
+	void setCenter(const Vec4& x)
 	{
 		m_center = x;
 	}
@@ -60,10 +64,12 @@ public:
 	{
 		return m_radius;
 	}
+
 	F32& getRadius()
 	{
 		return m_radius;
 	}
+
 	void setRadius(const F32 x)
 	{
 		m_radius = x;
@@ -74,19 +80,13 @@ public:
 	/// @{
 	Sphere& operator=(const Sphere& b)
 	{
+		Base::operator=(b);
 		m_center = b.m_center;
 		m_radius = b.m_radius;
 		return *this;
 	}
 	/// @}
 
-	/// Check for collision
-	template<typename T>
-	Bool collide(const T& x) const
-	{
-		return detail::collide(*this, x);
-	}
-
 	/// Implements CollisionShape::accept
 	void accept(MutableVisitor& v)
 	{
@@ -124,7 +124,7 @@ public:
 	Vec4 computeSupport(const Vec4& dir) const;
 
 private:
-	Vec3 m_center;
+	Vec4 m_center;
 	F32 m_radius;
 };
 /// @}

+ 1 - 1
include/anki/event/AnimationEvent.h

@@ -22,7 +22,7 @@ public:
 	void update(F32 prevUpdateTime, F32 crntTime) override;
 
 private:
-	AnimationResourcePointer anim;
+	AnimationResourcePointer m_anim;
 };
 /// @}
 

+ 6 - 5
include/anki/event/MoveEvent.h

@@ -18,10 +18,11 @@ class SceneNode;
 /// @{
 
 /// Helper class
-struct MoveEventData
+class MoveEventData
 {
-	Vec3 posMin;
-	Vec3 posMax;
+public:
+	Vec4 m_posMin;
+	Vec4 m_posMax;
 };
 
 /// An event for simple movable animations
@@ -40,8 +41,8 @@ public:
 	void update(F32 prevUpdateTime, F32 crntTime);
 
 private:
-	Vec3 originalPos;
-	Vec3 newPos;
+	Vec4 m_originalPos;
+	Vec4 m_newPos;
 };
 /// @}
 

+ 1 - 0
include/anki/math/Forward.h

@@ -22,6 +22,7 @@ template<typename T, U J, U I, typename TSimd, typename TM, typename TVJ,
 	typename TVI>
 class TMat;
 template<typename T> class TMat3;
+template<typename T> class TMat3x4;
 template<typename T> class TMat4;
 
 template<typename T> class TQuat;

+ 5 - 0
include/anki/math/Mat.h

@@ -662,6 +662,11 @@ public:
 
 	void setTranslationPart(const TVI& v)
 	{
+		if(ROW_SIZE == 4)
+		{
+			ANKI_ASSERT(isZero<T>(v[3] - static_cast<T>(1))
+				&& "w should be 1");
+		}
 		setColumn(3, v);
 	}
 

+ 61 - 40
include/anki/math/Mat3x4.h

@@ -50,21 +50,47 @@ public:
 		: Base()
 	{}
 
+	TMat3x4(const TMat3x4& b)
+		: Base(b)
+	{}
+
+	explicit TMat3x4(T m00, T m01, T m02, T m03, T m10, T m11, T m12, T m13, 
+		T m20, T m21, T m22, T m23)
+	{
+		TMat3x4& m = *this;
+		m(0, 0) = m00;
+		m(0, 1) = m01;
+		m(0, 2) = m02;
+		m(0, 3) = m03;
+		m(1, 0) = m10;
+		m(1, 1) = m11;
+		m(1, 2) = m12;
+		m(1, 3) = m13;
+		m(2, 0) = m20;
+		m(2, 1) = m21;
+		m(2, 2) = m22;
+		m(2, 3) = m23;
+	}
+
+	explicit TMat3x4(const T f)
+		: Base(f)
+	{}
+
 	explicit TMat3x4(const TMat3<T>& m3)
 	{
 		TMat3x4& m = *this;
 		m(0, 0) = m3(0, 0);
 		m(0, 1) = m3(0, 1);
 		m(0, 2) = m3(0, 2);
-		m(0, 3) = 0.0;
+		m(0, 3) = static_cast<T>(0);
 		m(1, 0) = m3(1, 0);
 		m(1, 1) = m3(1, 1);
 		m(1, 2) = m3(1, 2);
-		m(1, 3) = 0.0;
+		m(1, 3) = static_cast<T>(0);
 		m(2, 0) = m3(2, 0);
 		m(2, 1) = m3(2, 1);
 		m(2, 2) = m3(2, 2);
-		m(2, 3) = 0.0;
+		m(2, 3) = static_cast<T>(0);
 	}
 
 	explicit TMat3x4(const TMat4<T>& m3)
@@ -84,59 +110,59 @@ public:
 		m(2, 3) = m3(2, 3);
 	}
 
-	explicit TMat3x4(T m00, T m01, T m02, T m03, T m10, T m11, T m12, T m13, 
-		T m20, T m21, T m22, T m23)
-	{
-		TMat3x4& m = *this;
-		m(0, 0) = m00;
-		m(0, 1) = m01;
-		m(0, 2) = m02;
-		m(0, 3) = m03;
-		m(1, 0) = m10;
-		m(1, 1) = m11;
-		m(1, 2) = m12;
-		m(1, 3) = m13;
-		m(2, 0) = m20;
-		m(2, 1) = m21;
-		m(2, 2) = m22;
-		m(2, 3) = m23;
-	}
-
 	explicit TMat3x4(const TVec3<T>& v)
 	{
 		TMat3x4& m = *this;
-		m(0, 0) = 1.0;
-		m(0, 1) = 0.0;
-		m(0, 2) = 0.0;
+		m(0, 0) = static_cast<T>(1);
+		m(0, 1) = static_cast<T>(0);
+		m(0, 2) = static_cast<T>(0);
 		m(0, 3) = v.x();
-		m(1, 0) = 0.0;
-		m(1, 1) = 1.0;
-		m(1, 2) = 0.0;
+		m(1, 0) = static_cast<T>(0);
+		m(1, 1) = static_cast<T>(1);
+		m(1, 2) = static_cast<T>(0);
 		m(1, 3) = v.y();
-		m(2, 0) = 0.0;
-		m(2, 1) = 0.0;
-		m(2, 2) = 1.0;
+		m(2, 0) = static_cast<T>(0);
+		m(2, 1) = static_cast<T>(0);
+		m(2, 2) = static_cast<T>(1);
 		m(2, 3) = v.z();
 	}
 
+	explicit TMat3x4(const TQuat<T>& q)
+	{
+		Base::setRotationPart(TMat3<T>(q));
+		Base::setTranslationPart(TVec3<T>(static_cast<T>(0)));
+	}
+
+	explicit TMat3x4(const TEuler<T>& b)
+	{
+		Base::setRotationPart(TMat3<T>(b));
+		Base::setTranslationPart(TVec3<T>(static_cast<T>(0)));
+	}
+
+	explicit TMat3x4(const TAxisang<T>& b)
+	{
+		Base::setRotationPart(TAxisang<T>(b));
+		Base::setTranslationPart(TVec3<T>(static_cast<T>(0)));
+	}
+
 	explicit TMat3x4(const TVec3<T>& transl, const TMat3<T>& rot)
 	{
-		setRotationPart(rot);
-		setTranslationPart(transl);
+		Base::setRotationPart(rot);
+		Base::setTranslationPart(transl);
 	}
 
 	explicit TMat3x4(const TVec3<T>& transl, const TMat3<T>& rot, const T scale)
 	{
-		if(isZero<T>(scale - 1.0))
+		if(isZero<T>(scale - static_cast<T>(1)))
 		{
-			setRotationPart(rot);
+			Base::setRotationPart(rot);
 		}
 		else
 		{
 			setRotationPart(rot * scale);
 		}
 
-		setTranslationPart(transl);
+		Base::setTranslationPart(transl);
 	}
 
 	explicit TMat3x4(const TTransform<T>& t)
@@ -185,11 +211,6 @@ public:
 		return c;
 	}
 
-	void transform(const TMat3x4& b)
-	{
-		*this = combineTransformations(b);
-	}
-
 	void setIdentity()
 	{
 		(*this) = getIdentity();

+ 22 - 7
include/anki/math/Mat4.h

@@ -158,15 +158,15 @@ public:
 		m(3, 3) = v.w();
 	}
 
-	explicit TMat4(const TVec3<T>& transl, const TMat3<T>& rot)
+	explicit TMat4(const TVec4<T>& transl, const TMat3<T>& rot)
 	{
 		setRotationPart(rot);
-		setTranslationPart(TVec4<T>(transl, 1.0));
+		setTranslationPart(transl);
 		TMat4& m = *this;
 		m(3, 0) = m(3, 1) = m(3, 2) = 0.0;
 	}
 
-	explicit TMat4(const TVec3<T>& transl, const TMat3<T>& rot, const T scale)
+	explicit TMat4(const TVec4<T>& transl, const TMat3<T>& rot, const T scale)
 	{
 		if(isZero<T>(scale - 1.0))
 		{
@@ -177,16 +177,17 @@ public:
 			setRotationPart(rot * scale);
 		}
 
-		setTranslationPart(TVec4<T>(transl, 1.0));
+		setTranslationPart(transl);
 
 		TMat4& m = *this;
 		m(3, 0) = m(3, 1) = m(3, 2) = 0.0;
 	}
 
 	explicit TMat4(const TTransform<T>& t)
-	{
-		(*this) = TMat4(t.getOrigin(), t.getRotation(), t.getScale());
-	}
+		: TMat4(TVec4<T>(t.getOrigin().xyz(), 1.0), 
+			t.getRotation().getRotationPart(), 
+			t.getScale())
+	{}
 	/// @}
 
 	/// @name Other
@@ -372,6 +373,20 @@ public:
 
 		return m4;
 	}
+
+	/// @note 9 muls, 9 adds
+	TVec3<T> transform(const TVec3<T>& v) const
+	{
+		const TMat4& m = *this;
+
+		return TVec3<T>(
+			m(0, 0) * v.x() + m(0, 1) * v.y() 
+			+ m(0, 2) * v.z() + m(0, 3),
+			m(1, 0) * v.x() + m(1, 1) * v.y() 
+			+ m(1, 2) * v.z() + m(1, 3),
+			m(2, 0) * v.x() + m(2, 1) * v.y() 
+			+ m(2, 2) * v.z() + m(2, 3));
+	}
 	/// @}
 };
 

+ 15 - 4
include/anki/math/Quat.h

@@ -108,6 +108,13 @@ public:
 		}
 	}
 
+	explicit TQuat(const TMat3x4<T>& m)
+		: TQuat(m.getRotationPart())
+	{
+		ANKI_ASSERT(isZero<T>(m(0, 3)) && isZero<T>(m(1, 3)) 
+			&& isZero<T>(m(2, 3)));
+	}
+
 	explicit TQuat(const TEuler<T>& eu)
 	{
 		T cx, sx;
@@ -238,7 +245,7 @@ public:
 	}
 
 	/// @note 16 muls, 12 adds
-	TQuat getRotated(const TQuat& b) const 
+	TQuat combineRotations(const TQuat& b) const 
 	{
 		// XXX See if this can be optimized
 		TQuat out;
@@ -249,10 +256,14 @@ public:
 		return out;
 	}
 
-	/// @see getRotated
-	void rotate(const TQuat& b)
+	/// Returns q * this * q.Conjucated() aka returns a rotated this.
+	/// 18 muls, 12 adds
+	TVec3<T> rotate(const TVec3<T>& v) const
 	{
-		*this = getRotated(b);
+		ANKI_ASSERT(isZero<T>(1.0 - Base::getLength())); // Not normalized quat
+		TVec3<T> qXyz(Base::xyz());
+		return 
+			v + qXyz.cross(qXyz.cross(v) + v * Base::w()) * 2.0;
 	}
 
 	void setIdentity()

+ 53 - 48
include/anki/math/Transform.h

@@ -6,12 +6,12 @@
 #ifndef ANKI_MATH_TRANSFORM_H
 #define ANKI_MATH_TRANSFORM_H
 
-#include "anki/math/Vec3.h"
-#include "anki/math/Mat3.h"
 #include "anki/math/CommonIncludes.h"
 
 namespace anki {
 
+#define ANKI_CHECK_W() ANKI_ASSERT(m_origin.w() == 0.0)
+
 /// @addtogroup math
 /// @{
 
@@ -27,49 +27,55 @@ public:
 
 	TTransform(const TTransform& b)
 		: m_origin(b.m_origin), m_rotation(b.m_rotation), m_scale(b.m_scale)
-	{}
+	{
+		ANKI_CHECK_W();
+	}
 
 	explicit TTransform(const Mat4& m4)
 	{
 		m_rotation = m4.getRotationPart();
-		m_origin = m4.getTranslationPart().xyz();
+		m_origin = m4.getTranslationPart();
 		m_scale = 1.0;
+		ANKI_CHECK_W();
 	}
 
-	explicit TTransform(const TVec3<T>& origin, const TMat3<T>& rotation,
+	explicit TTransform(const TVec4<T>& origin, const TMat3x4<T>& rotation,
 		const T scale)
 		: m_origin(origin), m_rotation(rotation), m_scale(scale)
-	{}
+	{
+		ANKI_CHECK_W();
+	}
 	/// @}
 
 	/// @name Accessors
 	/// @{
-	const TVec3<T>& getOrigin() const
+	const TVec4<T>& getOrigin() const
 	{
 		return m_origin;
 	}
 
-	TVec3<T>& getOrigin()
+	TVec4<T>& getOrigin()
 	{
 		return m_origin;
 	}
 
-	void setOrigin(const TVec3<T>& o)
+	void setOrigin(const TVec4<T>& o)
 	{
 		m_origin = o;
+		ANKI_CHECK_W();
 	}
 
-	const TMat3<T>& getRotation() const
+	const TMat3x4<T>& getRotation() const
 	{
 		return m_rotation;
 	}
 
-	TMat3<T>& getRotation()
+	TMat3x4<T>& getRotation()
 	{
 		return m_rotation;
 	}
 
-	void setRotation(const TMat3<T>& r)
+	void setRotation(const TMat3x4<T>& r)
 	{
 		m_rotation = r;
 	}
@@ -97,6 +103,7 @@ public:
 		m_origin = b.m_origin;
 		m_rotation = b.m_rotation;
 		m_scale = b.m_scale;
+		ANKI_CHECK_W();
 		return *this;
 	}
 
@@ -122,38 +129,21 @@ public:
 	static const TTransform& getIdentity()
 	{
 		static const TTransform ident(
-			TVec3<T>(0.0), TMat3<T>::getIdentity(), 1.0);
+			TVec4<T>(0.0), TMat3x4<T>::getIdentity(), 1.0);
 		return ident;
 	}
 
-	static void combineTransformations(
-		const TVec3<T>& t0, const TMat3<T>& r0, const T s0,
-		const TVec3<T>& t1, const TMat3<T>& r1, const T s1,
-		TVec3<T>& tf, TMat3<T>& rf, T& sf)
-	{
-		tf = t1.getTransformed(t0, r0, s0);
-		rf = r0 * r1;
-		sf = s0 * s1;
-	}
-
-	static void combineTransformations(
-		const TVec3<T>& t0, const TMat3<T>& r0,
-		const TVec3<T>& t1, const TMat3<T>& r1,
-		TVec3<T>& tf, TMat3<T>& rf)
-	{
-		tf = t1.getTransformed(t0, r0);
-		rf = r0 * r1;
-	}
-
 	/// @copybrief combineTTransformations
-	static TTransform combineTransformations(const TTransform& a,
-		const TTransform& b)
+	TTransform combineTransformations(const TTransform& b) const
 	{
+		ANKI_CHECK_W();
+		const TTransform& a = *this;
 		TTransform out;
 
 		out.m_origin = 
-			b.m_origin.getTransformed(a.m_origin, a.m_rotation, a.m_scale);
-		out.m_rotation = a.m_rotation * b.m_rotation;
+			TVec4<T>(a.m_rotation * (b.m_origin * a.m_scale), 0.0) + a.m_origin;
+
+		out.m_rotation = a.m_rotation.combineTransformations(b.m_rotation);
 		out.m_scale = a.m_scale * b.m_scale;
 
 		return out;
@@ -162,37 +152,50 @@ public:
 	/// Get the inverse transformation. Its faster that inverting a Mat4
 	TTransform getInverse() const
 	{
+		ANKI_CHECK_W();
 		TTransform o;
-		o.m_rotation = m_rotation.getTransposed(); // Rotation
-		o.m_scale = 1.0 / m_scale; // Apply scale
-		o.m_origin = -((o.m_rotation * o.m_scale) * m_origin); // Translation
+		o.m_rotation = m_rotation;
+		o.m_rotation.transposeRotationPart();
+		o.m_scale = 1.0 / m_scale;
+		o.m_origin = -((o.m_rotation * o.m_scale) * m_origin).xyz0();
 		return o;
 	}
 
 	void invert()
 	{
-		*this = getInverse();
+		m_rotation.transposeRotationPart();
+		m_scale = 1.0 / m_scale;
+		m_origin = -((m_rotation * m_scale) * m_origin);
 	}
 
-	void transform(const TTransform& b)
+	/// Transform a TVec3
+	TVec3<T> transform(const TVec3<T>& b) const
 	{
-		m_origin = b.m_origin.getTransformed(m_origin, m_rotation, m_scale);
-		m_rotation = m_rotation * b.m_rotation;
-		m_scale *= b.m_scale;
+		ANKI_CHECK_W();
+		return (m_rotation.getRotationPart() * (b * m_scale)) + m_origin.xyz();
+	}
+
+	/// Transform a TVec4. SIMD optimized
+	TVec4<T> transform(const TVec4<T>& b) const
+	{
+		ANKI_CHECK_W();
+		TVec4<T> out = TVec4<T>(m_rotation * (b * m_scale), 0.0) + m_origin;
+		return out;
 	}
 
 	std::string toString() const
 	{
-		return m_origin.toString() + " " + m_rotation.toString() + " " + 
-			std::to_string(m_scale);
+		return "t: " + m_origin.toString() 
+			+ "\n\nr: " + m_rotation.toString() 
+			+ "\ns: " + std::to_string(m_scale);
 	}
 	/// @}
 
 private:
 	/// @name Data
 	/// @{
-	TVec3<T> m_origin; ///< The rotation
-	TMat3<T> m_rotation; ///< The translation
+	TVec4<T> m_origin; ///< The rotation
+	TMat3x4<T> m_rotation; ///< The translation
 	T m_scale; ///< The uniform scaling
 	/// @}
 };
@@ -202,6 +205,8 @@ typedef TTransform<F32> Transform;
 
 /// @}
 
+#undef ANKI_CHECK_W
+
 } // end namespace anki
 
 #endif

+ 13 - 1
include/anki/math/Vec.h

@@ -1846,7 +1846,19 @@ public:
 	{
 		static_assert(N > 3, "Wrong vector");
 		return TVec4<T>(w(), w(), w(), w());
-	}	
+	}
+
+	TVec4<T> xyz1() const
+	{
+		static_assert(N > 2, "Wrong vector");
+		return TVec4<T>(x(), y(), z(), static_cast<T>(1));
+	}
+
+	TVec4<T> xyz0() const
+	{
+		static_assert(N > 2, "Wrong vector");
+		return TVec4<T>(x(), y(), z(), static_cast<T>(0));
+	}
 
 	T& operator[](const U i)
 	{

+ 0 - 103
include/anki/math/Vec3.h

@@ -65,15 +65,6 @@ public:
 	{}
 	/// @}
 
-	/// @name Operators with other types
-	/// @{
-	TVec3 operator*(const TMat3<T>& m3) const
-	{
-		ANKI_ASSERT(0 && "TODO");
-		return TVec3(0.0);
-	}
-	/// @}
-
 	/// @name Other
 	/// @{
 
@@ -89,100 +80,6 @@ public:
 	{
 		return toThis * ((*this).dot(toThis) / (toThis.dot(toThis)));
 	}
-
-	/// Returns q * this * q.Conjucated() aka returns a rotated this.
-	/// 18 muls, 12 adds
-	TVec3 getRotated(const TQuat<T>& q) const
-	{
-		ANKI_ASSERT(isZero<T>(1.0 - q.getLength())); // Not normalized quat
-		TVec3 qXyz(q.x(), q.y(), q.z());
-		return 
-			(*this) + qXyz.cross(qXyz.cross((*this)) + (*this) * q.w()) * 2.0;
-	}
-
-	void rotate(const TQuat<T>& q)
-	{
-		(*this) = getRotated(q);
-	}
-	/// @}
-
-	/// @name Transformations
-	/// The faster way is by far the TMat4 * TVec3 or the
-	/// getTransformed(const TVec3&, const TMat3&)
-	/// @{
-	TVec3 getTransformed(const TVec3& translate, const TMat3<T>& rotate,
-		T scale) const
-	{
-		return (rotate * ((*this) * scale)) + translate;
-	}
-
-	void transform(const TVec3& translate, const TMat3<T>& rotate, T scale)
-	{
-		(*this) = getTransformed(translate, rotate, scale);
-	}
-
-	TVec3 getTransformed(const TVec3& translate, const TMat3<T>& rotate) const
-	{
-		return (rotate * (*this)) + translate;
-	}
-
-	void transform(const TVec3& translate, const TMat3<T>& rotate)
-	{
-		(*this) = getTransformed(translate, rotate);
-	}
-
-	TVec3 getTransformed(const TVec3& translate, const TQuat<T>& rotate,
-		T scale) const
-	{
-		return ((*this) * scale).getRotated(rotate) + translate;
-	}
-
-	void transform(const TVec3& translate, const TQuat<T>& rotate, T scale)
-	{
-		(*this) = getTransformed(translate, rotate, scale);
-	}
-
-	TVec3 getTransformed(const TVec3& translate, const TQuat<T>& rotate) const
-	{
-		return getRotated(rotate) + translate;
-	}
-
-	void transform(const TVec3& translate, const TQuat<T>& rotate)
-	{
-		(*this) = getTransformed(translate, rotate);
-	}
-
-	/// Transform the vector
-	/// @param transform A transformation matrix
-	///
-	/// @note 9 muls, 9 adds
-	TVec3 getTransformed(const TMat4<T>& transform) const
-	{
-		return TVec3(
-			transform(0, 0) * x() + transform(0, 1) * y() 
-			+ transform(0, 2) * z() + transform(0, 3),
-			transform(1, 0) * x() + transform(1, 1) * y() 
-			+ transform(1, 2) * z() + transform(1, 3),
-			transform(2, 0) * x() + transform(2, 1) * y() 
-			+ transform(2, 2) * z() + transform(2, 3));
-	}
-
-	void transform(const TMat4<T>& transform)
-	{
-		(*this) = getTransformed(transform);
-	}
-
-	/// 12 muls, 9 adds
-	TVec3 getTransformed(const TTransform<T>& transform) const
-	{
-		return (transform.getRotation() * ((*this) * transform.getScale())) 
-			+ transform.getOrigin();
-	}
-
-	void transform(const TTransform<T>& transform)
-	{
-		(*this) = getTransformed(transform);
-	}
 	/// @}
 };
 

+ 1 - 1
include/anki/math/Vec4.h

@@ -105,7 +105,7 @@ public:
 	{
 		ANKI_ASSERT(isZero<T>(Base::w()));
 		ANKI_ASSERT(isZero<T>(b.w()));
-		return TVec4(Base::xyz().template cross(b.xyz(), static_cast<T>(0)));
+		return TVec4(Base::xyz().cross(b.xyz()), static_cast<T>(0));
 	}
 	/// @{
 

+ 4 - 4
include/anki/math/Vec4.inl.h

@@ -159,8 +159,8 @@ inline TVec4<F32>& TVec4<F32>::Base::operator/=(const TVec4<F32>& b)
 template<>
 inline TVec4<F32> TVec4<F32>::cross(const TVec4<F32>& b) const
 {
-	ANKI_ASSERT(isZero<F32>(Base::w()));
-	ANKI_ASSERT(isZero<F32>(b.w()));
+	ANKI_ASSERT(Base::w() == 0.0);
+	ANKI_ASSERT(b.w() == 0.0);
 
 	const auto& a = *this;
 	const auto mask0 = _MM_SHUFFLE(3, 0, 2, 1);
@@ -168,8 +168,8 @@ inline TVec4<F32> TVec4<F32>::cross(const TVec4<F32>& b) const
 
 	__m128 tmp0 = _mm_mul_ps(_mm_shuffle_ps(a.m_simd, a.m_simd, mask0), 
 		_mm_shuffle_ps(b.m_simd, b.m_simd, mask1));
-	__m128 tmp1 = _mm_mul_ps(_mm_shuffle_ps(a.m_simd, a.m_simd, mask0), 
-		_mm_shuffle_ps(b.m_simd, b.m_simd, mask1));
+	__m128 tmp1 = _mm_mul_ps(_mm_shuffle_ps(a.m_simd, a.m_simd, mask1), 
+		_mm_shuffle_ps(b.m_simd, b.m_simd, mask0));
 
 	return TVec4<F32>(_mm_sub_ps(tmp0, tmp1));	
 }

+ 3 - 3
include/anki/physics/Converters.h

@@ -41,8 +41,8 @@ inline Quat toAnki(const btQuaternion& q)
 inline Transform toAnki(const btTransform& t)
 {
 	Transform out;
-	out.setRotation(toAnki(t.getBasis()));
-	out.setOrigin(toAnki(t.getOrigin()));
+	out.setRotation(Mat3x4(toAnki(t.getBasis())));
+	out.setOrigin(Vec4(toAnki(t.getOrigin()), 0.0));
 	out.setScale(1.0);
 	return out;
 }
@@ -86,7 +86,7 @@ inline btTransform toBt(const Transform& trf)
 {
 	btTransform r;
 	r.setOrigin(toBt(trf.getOrigin()));
-	r.setBasis(toBt(trf.getRotation()));
+	r.setBasis(toBt(trf.getRotation().getRotationPart()));
 	return r;
 }
 

+ 0 - 5
include/anki/renderer/DebugDrawer.h

@@ -111,11 +111,6 @@ public:
 
 	void visit(const Plane&);
 
-	void visit(const Ray&)
-	{
-		ANKI_ASSERT(0 && "ToDo");
-	}
-
 	void visit(const Sphere&);
 
 	void visit(const Aabb&);

+ 1 - 1
include/anki/scene/Camera.h

@@ -72,7 +72,7 @@ public:
 
 	/// @name SpatialComponent virtuals
 	/// @{
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return getWorldTransform().getOrigin();
 	}

+ 1 - 1
include/anki/scene/FrustumComponent.h

@@ -76,7 +76,7 @@ public:
 	}
 
 	/// Get the origin for sorting and visibility tests
-	const Vec3& getFrustumOrigin() const
+	const Vec4& getFrustumOrigin() const
 	{
 		return getFrustum().getTransform().getOrigin();
 	}

+ 2 - 2
include/anki/scene/Light.h

@@ -184,7 +184,7 @@ public:
 
 	/// @name SpatialComponent virtuals
 	/// @{
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return getWorldTransform().getOrigin();
 	}
@@ -256,7 +256,7 @@ public:
 	/// @}
 
 public:
-	Sphere sphereW = Sphere(Vec3(0.0), 1.0);
+	Sphere sphereW = Sphere(Vec4(0.0), 1.0);
 };
 
 /// Spot light

+ 1 - 1
include/anki/scene/Misc.h

@@ -27,7 +27,7 @@ struct ObbSpatialComponent: public SpatialComponent
 	}
 
 	/// Implement SpatialComponent::getSpatialOrigin
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return obb.getCenter();
 	}

+ 1 - 1
include/anki/scene/ModelNode.h

@@ -64,7 +64,7 @@ public:
 	}
 
 	/// Implement SpatialComponent::getSpatialOrigin
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return m_obb.getCenter();
 	}

+ 29 - 29
include/anki/scene/MoveComponent.h

@@ -51,49 +51,49 @@ public:
 	/// @{
 	const Transform& getLocalTransform() const
 	{
-		return lTrf;
+		return m_ltrf;
 	}
 	void setLocalTransform(const Transform& x)
 	{
-		lTrf = x;
+		m_ltrf = x;
 		markForUpdate();
 	}
-	void setLocalOrigin(const Vec3& x)
+	void setLocalOrigin(const Vec4& x)
 	{
-		lTrf.setOrigin(x);
+		m_ltrf.setOrigin(x);
 		markForUpdate();
 	}
-	const Vec3& getLocalOrigin() const
+	const Vec4& getLocalOrigin() const
 	{
-		return lTrf.getOrigin();
+		return m_ltrf.getOrigin();
 	}
-	void setLocalRotation(const Mat3& x)
+	void setLocalRotation(const Mat3x4& x)
 	{
-		lTrf.setRotation(x);
+		m_ltrf.setRotation(x);
 		markForUpdate();
 	}
-	const Mat3& getLocalRotation() const
+	const Mat3x4& getLocalRotation() const
 	{
-		return lTrf.getRotation();
+		return m_ltrf.getRotation();
 	}
 	void setLocalScale(F32 x)
 	{
-		lTrf.setScale(x);
+		m_ltrf.setScale(x);
 		markForUpdate();
 	}
 	F32 getLocalScale() const
 	{
-		return lTrf.getScale();
+		return m_ltrf.getScale();
 	}
 
 	const Transform& getWorldTransform() const
 	{
-		return wTrf;
+		return m_wtrf;
 	}
 
 	const Transform& getPrevWorldTransform() const
 	{
-		return prevWTrf;
+		return m_prevWTrf;
 	}
 	/// @}
 
@@ -112,40 +112,40 @@ public:
 	/// @{
 	void rotateLocalX(F32 angDegrees)
 	{
-		lTrf.getRotation().rotateXAxis(angDegrees);
+		m_ltrf.getRotation().rotateXAxis(angDegrees);
 		markForUpdate();
 	}
 	void rotateLocalY(F32 angDegrees)
 	{
-		lTrf.getRotation().rotateYAxis(angDegrees);
+		m_ltrf.getRotation().rotateYAxis(angDegrees);
 		markForUpdate();
 	}
 	void rotateLocalZ(F32 angDegrees)
 	{
-		lTrf.getRotation().rotateZAxis(angDegrees);
+		m_ltrf.getRotation().rotateZAxis(angDegrees);
 		markForUpdate();
 	}
 	void moveLocalX(F32 distance)
 	{
-		Vec3 x_axis = lTrf.getRotation().getColumn(0);
-		lTrf.getOrigin() += x_axis * distance;
+		Vec3 x_axis = m_ltrf.getRotation().getColumn(0);
+		m_ltrf.getOrigin() += Vec4(x_axis, 0.0) * distance;
 		markForUpdate();
 	}
 	void moveLocalY(F32 distance)
 	{
-		Vec3 y_axis = lTrf.getRotation().getColumn(1);
-		lTrf.getOrigin() += y_axis * distance;
+		Vec3 y_axis = m_ltrf.getRotation().getColumn(1);
+		m_ltrf.getOrigin() += Vec4(y_axis, 0.0) * distance;
 		markForUpdate();
 	}
 	void moveLocalZ(F32 distance)
 	{
-		Vec3 z_axis = lTrf.getRotation().getColumn(2);
-		lTrf.getOrigin() += z_axis * distance;
+		Vec3 z_axis = m_ltrf.getRotation().getColumn(2);
+		m_ltrf.getOrigin() += Vec4(z_axis, 0.0) * distance;
 		markForUpdate();
 	}
 	void scale(F32 s)
 	{
-		lTrf.getScale() *= s;
+		m_ltrf.getScale() *= s;
 		markForUpdate();
 	}
 	/// @}
@@ -156,24 +156,24 @@ public:
 	}
 
 private:
-	SceneNode* node;
+	SceneNode* m_node;
 
 	/// The transformation in local space
-	Transform lTrf = Transform::getIdentity();
+	Transform m_ltrf = Transform::getIdentity();
 
 	/// The transformation in world space (local combined with parent's
 	/// transformation)
-	Transform wTrf = Transform::getIdentity();
+	Transform m_wtrf = Transform::getIdentity();
 
 	/// Keep the previous transformation for checking if it moved
-	Transform prevWTrf = Transform::getIdentity();
+	Transform m_prevWTrf = Transform::getIdentity();
 
 	void markForUpdate()
 	{
 		enableBits(MF_MARKED_FOR_UPDATE);
 	}
 
-	/// Called every frame. It updates the @a wTrf if @a shouldUpdateWTrf
+	/// Called every frame. It updates the @a m_wtrf if @a shouldUpdateWTrf
 	/// is true. Then it moves to the children.
 	void updateWorldTransform();
 };

+ 6 - 6
include/anki/scene/ParticleEmitter.h

@@ -83,7 +83,7 @@ public:
 		(void)crntTime;
 	}
 
-	virtual const Vec3& getPosition() const = 0;
+	virtual const Vec4& getPosition() const = 0;
 
 protected:
 	F32 m_timeOfBirth; ///< Keep the time of birth for nice effects
@@ -105,16 +105,16 @@ public:
 	void simulate(const ParticleEmitter& pe, F32 prevUpdateTime, 
 		F32 crntTime) override;
 
-	const Vec3& getPosition() const
+	const Vec4& getPosition() const
 	{
 		return m_position;
 	}
 
 private:
 	/// The velocity
-	Vec3 m_velocity = Vec3(0.0);
-	Vec3 m_acceleration = Vec3(0.0);
-	Vec3 m_position;
+	Vec4 m_velocity = Vec4(0.0);
+	Vec4 m_acceleration = Vec4(0.0);
+	Vec4 m_position;
 };
 
 /// Particle for bullet simulations
@@ -176,7 +176,7 @@ public:
 		return m_obb;
 	}
 
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return m_obb.getCenter();
 	}

+ 1 - 1
include/anki/scene/SpatialComponent.h

@@ -73,7 +73,7 @@ public:
 
 	/// Used for sorting spatials. In most object the origin is the center of
 	/// mess but for cameras the origin is the eye point
-	virtual Vec3 getSpatialOrigin() = 0;
+	virtual Vec4 getSpatialOrigin() = 0;
 	/// @}
 
 	/// The derived class has to manually call this method when the collision 

+ 2 - 2
include/anki/scene/StaticGeometryNode.h

@@ -27,7 +27,7 @@ public:
 		return *m_obb;
 	}
 
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return m_obb->getCenter();
 	}
@@ -57,7 +57,7 @@ public:
 		return *m_obb;
 	}
 
-	Vec3 getSpatialOrigin()
+	Vec4 getSpatialOrigin()
 	{
 		return m_obb->getCenter();
 	}

+ 2 - 2
include/anki/scene/Visibility.h

@@ -102,7 +102,7 @@ public:
 class DistanceSortFunctor
 {
 public:
-	Vec3 m_origin;
+	Vec4 m_origin;
 
 	Bool operator()(const VisibleNode& a, const VisibleNode& b)
 	{
@@ -136,7 +136,7 @@ class DistanceSortJob: public ThreadpoolTask
 public:
 	U32 m_nodesCount;
 	VisibilityTestResults::Container::iterator m_nodes;
-	Vec3 m_origin;
+	Vec4 m_origin;
 
 	void operator()(ThreadId /*threadId*/, U /*threadsCount*/)
 	{

+ 24 - 11
src/collision/Aabb.cpp

@@ -11,19 +11,19 @@
 namespace anki {
 
 //==============================================================================
-Aabb Aabb::getTransformed(const Transform& transform) const
+Aabb Aabb::getTransformed(const Transform& trf) const
 {
-	Mat3 absM;
-	for(U i = 0; i < 9; ++i)
+	Mat3x4 absM;
+	for(U i = 0; i < 12; ++i)
 	{
-		absM[i] = fabs(transform.getRotation()[i]);
+		absM[i] = fabs(trf.getRotation()[i]);
 	}
 
-	Vec3 center = (m_min + m_max) * 0.5;
-	Vec3 extend = (m_max - m_min) * 0.5;
+	Vec4 center = (m_min + m_max) * 0.5;
+	Vec4 extend = (m_max - m_min) * 0.5;
 
-	Vec3 newC = center.getTransformed(transform);
-	Vec3 newE = absM * (extend * transform.getScale());
+	Vec4 newC = trf.transform(center);
+	Vec4 newE = Vec4(absM * (extend * trf.getScale()), 0.0);
 
 	return Aabb(newC - newE, newC + newE);
 }
@@ -32,7 +32,7 @@ Aabb Aabb::getTransformed(const Transform& transform) const
 F32 Aabb::testPlane(const Plane& p) const
 {
 	const Aabb& aabb = *this;
-	Vec3 diagMin, diagMax;
+	Vec4 diagMin(0.0), diagMax(0.0);
 	// set min/max values for x,y,z direction
 	for(U i = 0; i < 3; i++)
 	{
@@ -72,6 +72,7 @@ F32 Aabb::testPlane(const Plane& p) const
 Aabb Aabb::getCompoundShape(const Aabb& b) const
 {
 	Aabb out;
+	out.m_min.w() = out.m_max.w() = 0.0;
 
 	for(U i = 0; i < 3; i++)
 	{
@@ -86,8 +87,8 @@ Aabb Aabb::getCompoundShape(const Aabb& b) const
 void Aabb::setFromPointCloud(
 	const void* buff, U count, PtrSize stride, PtrSize buffSize)
 {
-	m_min = Vec3(MAX_F32);
-	m_max = Vec3(MIN_F32);
+	m_min = Vec4(Vec3(MAX_F32), 0.0);
+	m_max = Vec4(Vec3(MIN_F32), 0.0);
 
 	iteratePointCloud(buff, count, stride, buffSize, [&](const Vec3& pos)
 	{
@@ -105,4 +106,16 @@ void Aabb::setFromPointCloud(
 	});
 }
 
+//==============================================================================
+Vec4 Aabb::computeSupport(const Vec4& dir) const
+{
+	Vec4 ret(0.0);
+ 
+	ret.x() = dir.x() >= 0.0 ? m_max.x() : m_min.x();
+	ret.y() = dir.y() >= 0.0 ? m_max.y() : m_min.y();
+	ret.z() = dir.z() >= 0.0 ? m_max.z() : m_min.z();
+ 
+	return ret;
+}
+
 } // end namespace anki

+ 0 - 669
src/collision/CollisionAlgorithms.cpp

@@ -1,669 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/collision/CollisionAlgorithms.h"
-#include "anki/Collision.h"
-#include "anki/util/Assert.h"
-#include "anki/Math.h"
-#include <limits>
-
-namespace anki {
-namespace detail {
-
-//==============================================================================
-template<typename T>
-static Bool tcollide(const CollisionShape& a, const CollisionShape& b)
-{
-	const T& t = static_cast<const T&>(a);
-	Bool out = false;
-
-	switch(b.getType())
-	{
-	case CollisionShape::Type::LINE_SEG:
-		out = collide(t, static_cast<const LineSegment&>(b));
-		break;
-	case CollisionShape::Type::RAY:
-		out = collide(t, static_cast<const Ray&>(b));
-		break;
-	case CollisionShape::Type::PLANE:
-		out = collide(t, static_cast<const Plane&>(b));
-		break;
-	case CollisionShape::Type::SPHERE:
-		out = collide(t, static_cast<const Sphere&>(b));
-		break;
-	case CollisionShape::Type::AABB:
-		out = collide(t, static_cast<const Aabb&>(b));
-		break;
-	case CollisionShape::Type::OBB:
-		out = collide(t, static_cast<const Obb&>(b));
-		break;
-	default:
-		ANKI_ASSERT(0 && "Forgot something");
-		break;
-	}
-
-	return out;
-}
-
-//==============================================================================
-Bool collide(const CollisionShape& a, const CollisionShape& b)
-{
-	Bool out = false;
-
-	switch(a.getType())
-	{
-	case CollisionShape::Type::LINE_SEG:
-		out = tcollide<LineSegment>(a, b);
-		break;
-	case CollisionShape::Type::RAY:
-		out = tcollide<Ray>(a, b);
-		break;
-	case CollisionShape::Type::PLANE:
-		out = tcollide<Plane>(a, b);
-		break;
-	case CollisionShape::Type::SPHERE:
-		out = tcollide<Sphere>(a, b);
-		break;
-	case CollisionShape::Type::AABB:
-		out = tcollide<Aabb>(a, b);
-		break;
-	case CollisionShape::Type::OBB:
-		out = tcollide<Obb>(a, b);
-		break;
-	default:
-		ANKI_ASSERT(0 && "Forgot something");
-		break;
-	}
-
-	return out;
-}
-
-//==============================================================================
-// 1st row                                                                     =
-//==============================================================================
-
-//==============================================================================
-Bool collide(const LineSegment& /*a*/, const LineSegment& /*b*/)
-{
-	ANKI_ASSERT(0 && "N/A");
-	return false;
-}
-
-//==============================================================================
-Bool collide(const LineSegment& ls, const Obb& obb)
-{
-	F32 maxS = std::numeric_limits<F32>::min();
-	F32 minT = std::numeric_limits<F32>::max();
-
-	// compute difference vector
-	Vec3 diff = obb.getCenter() - ls.getOrigin();
-
-	// for each axis do
-	for(U i = 0; i < 3; ++i)
-	{
-		// get axis i
-		Vec3 axis = obb.getRotation().getColumn(i);
-
-		// project relative vector onto axis
-		F32 e = axis.dot(diff);
-		F32 f = ls.getDirection().dot(axis);
-
-		// ray is parallel to plane
-		if(isZero(f))
-		{
-			// ray passes by box
-			if(-e - obb.getExtend()[i] > 0.0 || -e + obb.getExtend()[i] > 0.0)
-			{
-				return false;
-			}
-			continue;
-		}
-
-		F32 s = (e - obb.getExtend()[i]) / f;
-		F32 t = (e + obb.getExtend()[i]) / f;
-
-		// fix order
-		if(s > t)
-		{
-			F32 temp = s;
-			s = t;
-			t = temp;
-		}
-
-		// adjust min and max values
-		if(s > maxS)
-		{
-			maxS = s;
-		}
-		if(t < minT)
-		{
-			minT = t;
-		}
-
-		// check for intersection failure
-		if(minT < 0.0 || maxS > 1.0 || maxS > minT)
-		{
-			return false;
-		}
-	}
-
-	// done, have intersection
-	return true;
-}
-
-//==============================================================================
-Bool collide(const LineSegment& ls, const Plane& p)
-{
-	return ls.testPlane(p) == 0.0;
-}
-
-//==============================================================================
-Bool collide(const LineSegment& /*a*/, const Ray& /*b*/)
-{
-	ANKI_ASSERT(0 && "N/A");
-	return false;
-}
-
-//==============================================================================
-Bool collide(const LineSegment& ls, const Sphere& s)
-{
-	const Vec3& v = ls.getDirection();
-	Vec3 w0 = s.getCenter() - ls.getOrigin();
-	F32 w0dv = w0.dot(v);
-	F32 rsq = s.getRadius() * s.getRadius();
-
-	if(w0dv < 0.0) // if the ang is >90
-	{
-		return w0.getLengthSquared() <= rsq;
-	}
-
-	Vec3 w1 = w0 - v; // aka center - P1, where P1 = seg.origin + seg.dir
-	F32 w1dv = w1.dot(v);
-
-	if(w1dv > 0.0) // if the ang is <90
-	{
-		return w1.getLengthSquared() <= rsq;
-	}
-
-	// the big parenthesis is the projection of w0 to v
-	Vec3 tmp = w0 - (v * (w0.dot(v) / v.getLengthSquared()));
-	return tmp.getLengthSquared() <= rsq;
-}
-
-//==============================================================================
-Bool collide(const LineSegment& ls, const Aabb& aabb)
-{
-	F32 maxS = std::numeric_limits<F32>::min();
-	F32 minT = std::numeric_limits<F32>::max();
-
-	// do tests against three sets of planes
-	for(U i = 0; i < 3; ++i)
-	{
-		// segment is parallel to plane
-		if(isZero(ls.getDirection()[i]))
-		{
-			// segment passes by box
-			if(ls.getOrigin()[i] < aabb.getMin()[i] 
-				|| ls.getOrigin()[i] > aabb.getMax()[i])
-			{
-				return false;
-			}
-		}
-		else
-		{
-			// compute intersection parameters and sort
-			F32 s = (aabb.getMin()[i] - ls.getOrigin()[i]) 
-				/ ls.getDirection()[i];
-			F32 t = (aabb.getMax()[i] - ls.getOrigin()[i]) 
-				/ ls.getDirection()[i];
-			if(s > t)
-			{
-				F32 temp = s;
-				s = t;
-				t = temp;
-			}
-
-			// adjust min and max values
-			if(s > maxS)
-			{
-				maxS = s;
-			}
-			if(t < minT)
-			{
-				minT = t;
-			}
-
-			// check for intersection failure
-			if(minT < 0.0 || maxS > 1.0 || maxS > minT)
-			{
-				return false;
-			}
-		}
-	}
-
-	// done, have intersection
-	return true;
-}
-
-//==============================================================================
-// 2nd row                                                                     =
-//==============================================================================
-
-//==============================================================================
-Bool collide(const Obb& o0, const Obb& o1)
-{
-	// extent vectors
-	const Vec3& a = o0.getExtend();
-	const Vec3& b = o1.getExtend();
-
-	// test factors
-	F32 cTest, aTest, bTest;
-	Bool parallelAxes = false;
-
-	// transpose of rotation of B relative to A, i.e. (R_b^T * R_a)^T
-	Mat3 rt = o0.getRotation().getTransposed() * o1.getRotation();
-
-	// absolute value of relative rotation matrix
-	Mat3 rabs;
-	for(U i = 0; i < 3; ++i)
-	{
-		for(U j = 0; j < 3; ++j)
-		{
-			rabs(i, j) = fabs(rt(i, j));
-			// if magnitude of dot product between axes is close to one
-			if(rabs(i, j) + getEpsilon<F32>() >= 1.0)
-			{
-				// then box A and box B have near-parallel axes
-				parallelAxes = true;
-			}
-		}
-	}
-
-	// relative translation (in A's frame)
-	Vec3 c = o0.getRotation().getTransposed() 
-		* (o1.getCenter() - o0.getCenter());
-
-	// separating axis A0
-	cTest = fabs(c.x());
-	aTest = a.x();
-	bTest = b.x() * rabs(0, 0) + b.y() * rabs(0, 1) + b.z() * rabs(0, 2);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A1
-	cTest = fabs(c.y());
-	aTest = a.y();
-	bTest = b.x() * rabs(1, 0) + b.y() * rabs(1, 1) + b.z() * rabs(1, 2);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A2
-	cTest = fabs(c.z());
-	aTest = a.z();
-	bTest = b.x() * rabs(2, 0) + b.y() * rabs(2, 1) + b.z() * rabs(2, 2);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis B0
-	cTest = fabs(c.x() * rt(0, 0) + c.y() * rt(1, 0) + c.z() * rt(2, 0));
-	aTest = a.x() * rabs(0, 0) + a.y() * rabs(1, 0) + a.z() * rabs(2, 0);
-	bTest = b.x();
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis B1
-	cTest = fabs(c.x() * rt(0, 1) + c.y() * rt(1, 1) + c.z() * rt(2, 1));
-	aTest = a.x() * rabs(0, 1) + a.y() * rabs(1, 1) + a.z() * rabs(2, 1);
-	bTest = b.y();
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis B2
-	cTest = fabs(c.x() * rt(0, 2) + c.y() * rt(1, 2) + c.z() * rt(2, 2));
-	aTest = a.x() * rabs(0, 2) + a.y() * rabs(1, 2) + a.z() * rabs(2, 2);
-	bTest = b.z();
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// if the two boxes have parallel axes, we're done, intersection
-	if(parallelAxes)
-	{
-		return true;
-	}
-
-	// separating axis A0 x B0
-	cTest = fabs(c.z() * rt(1, 0) - c.y() * rt(2, 0));
-	aTest = a.y() * rabs(2, 0) + a.z() * rabs(1, 0);
-	bTest = b.y() * rabs(0, 2) + b.z() * rabs(0, 1);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A0 x B1
-	cTest = fabs(c.z() * rt(1, 1) - c.y() * rt(2, 1));
-	aTest = a.y() * rabs(2, 1) + a.z() * rabs(1, 1);
-	bTest = b.x() * rabs(0, 2) + b.z() * rabs(0, 0);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A0 x B2
-	cTest = fabs(c.z() * rt(1, 2) - c.y() * rt(2, 2));
-	aTest = a.y() * rabs(2, 2) + a.z() * rabs(1, 2);
-	bTest = b.x() * rabs(0, 1) + b.y() * rabs(0, 0);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A1 x B0
-	cTest = fabs(c.x() * rt(2, 0) - c.z() * rt(0, 0));
-	aTest = a.x() * rabs(2, 0) + a.z() * rabs(0, 0);
-	bTest = b.y() * rabs(1, 2) + b.z() * rabs(1, 1);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A1 x B1
-	cTest = fabs(c.x() * rt(2, 1) - c.z() * rt(0, 1));
-	aTest = a.x() * rabs(2, 1) + a.z() * rabs(0, 1);
-	bTest = b.x() * rabs(1, 2) + b.z() * rabs(1, 0);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A1 x B2
-	cTest = fabs(c.x() * rt(2, 2) - c.z() * rt(0, 2));
-	aTest = a.x() * rabs(2, 2) + a.z() * rabs(0, 2);
-	bTest = b.x() * rabs(1, 1) + b.y() * rabs(1, 0);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A2 x B0
-	cTest = fabs(c.y() * rt(0, 0) - c.x() * rt(1, 0));
-	aTest = a.x() * rabs(1, 0) + a.y() * rabs(0, 0);
-	bTest = b.y() * rabs(2, 2) + b.z() * rabs(2, 1);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A2 x B1
-	cTest = fabs(c.y() * rt(0, 1) - c.x() * rt(1, 1));
-	aTest = a.x() * rabs(1, 1) + a.y() * rabs(0, 1);
-	bTest = b.x() * rabs(2, 2) + b.z() * rabs(2, 0);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// separating axis A2 x B2
-	cTest = fabs(c.y() * rt(0, 2) - c.x() * rt(1, 2));
-	aTest = a.x() * rabs(1, 2) + a.y() * rabs(0, 2);
-	bTest = b.x() * rabs(2, 1) + b.y() * rabs(2, 0);
-	if(cTest > aTest + bTest)
-	{
-		return false;
-	}
-
-	// all tests failed, have intersection
-	return true;
-}
-
-//==============================================================================
-Bool collide(const Obb& a, const Plane& b)
-{
-	return a.testPlane(b) == 0.0;
-}
-
-//==============================================================================
-Bool collide(const Obb& obb, const Ray& r)
-{
-	Aabb aabb_(-obb.getExtend(), obb.getExtend());
-	Ray newray;
-	Mat3 rottrans = obb.getRotation().getTransposed();
-
-	newray.getOrigin() = rottrans * (r.getOrigin() - obb.getCenter());
-	newray.getDirection() = rottrans * r.getDirection();
-
-	return collide(newray, aabb_);
-}
-
-//==============================================================================
-Bool collide(const Obb& obb, const Sphere& s)
-{
-	Aabb aabb_(-obb.getExtend(), obb.getExtend()); // aabb_ is in "this" frame
-	Vec3 newCenter = obb.getRotation().getTransposed() 
-		* (s.getCenter() - obb.getCenter());
-	Sphere sphere_(newCenter, s.getRadius()); // sphere1 to "this" fame
-
-	return collide(sphere_, aabb_);
-}
-
-//==============================================================================
-Bool collide(const Obb& obb, const Aabb& aabb)
-{
-	Vec3 center_ = (aabb.getMax() + aabb.getMin()) * 0.5;
-	Vec3 extends_ = (aabb.getMax() - aabb.getMin()) * 0.5;
-	Obb obb_(center_, Mat3::getIdentity(), extends_);
-
-	return collide(obb, obb_);
-}
-
-//==============================================================================
-// 4th line (P)                                                                =
-//==============================================================================
-
-//==============================================================================
-Bool collide(const Plane& p0, const Plane& p1)
-{
-	return p0.getNormal() != p1.getNormal();
-}
-
-//==============================================================================
-Bool collide(const Plane& p, const Ray& r)
-{
-	return r.testPlane(p) == 0.0;
-}
-
-//==============================================================================
-Bool collide(const Plane& p, const Sphere& s)
-{
-	return s.testPlane(p) == 0.0;
-}
-
-//==============================================================================
-Bool collide(const Plane& p, const Aabb& aabb)
-{
-	return aabb.testPlane(p) == 0.0;
-}
-
-//==============================================================================
-// 5th line (R)                                                                =
-//==============================================================================
-
-//==============================================================================
-Bool collide(const Ray& a, const Ray& b)
-{
-	ANKI_ASSERT(0 && "N/A");
-	return false;
-}
-
-//==============================================================================
-Bool collide(const Ray& r, const Sphere& s)
-{
-	Vec3 w(s.getCenter() - r.getOrigin());
-	const Vec3& v = r.getDirection();
-	F32 proj = v.dot(w);
-	F32 wsq = w.getLengthSquared();
-	F32 rsq = s.getRadius() * s.getRadius();
-
-	if(proj < 0.0 && wsq > rsq)
-	{
-		return false;
-	}
-
-	F32 vsq = v.getLengthSquared();
-
-	return (vsq * wsq - proj * proj <= vsq * rsq);
-}
-
-//==============================================================================
-Bool collide(const Ray& r, const Aabb& aabb)
-{
-	F32 maxS = std::numeric_limits<F32>::min();
-	F32 minT = std::numeric_limits<F32>::max();
-
-	// do tests against three sets of planes
-	for(U i = 0; i < 3; ++i)
-	{
-		// ray is parallel to plane
-		if(isZero(r.getDirection()[i]))
-		{
-			// ray passes by box
-			if(r.getOrigin()[i] < aabb.getMin()[i] ||
-				r.getOrigin()[i] > aabb.getMax()[i])
-			{
-				return false;
-			}
-		}
-		else
-		{
-			// compute intersection parameters and sort
-			F32 s = (aabb.getMin()[i] - r.getOrigin()[i]) /
-				r.getDirection()[i];
-			F32 t = (aabb.getMax()[i] - r.getOrigin()[i]) /
-				r.getDirection()[i];
-			if(s > t)
-			{
-				F32 temp = s;
-				s = t;
-				t = temp;
-			}
-
-			// adjust min and max values
-			if(s > maxS)
-			{
-				maxS = s;
-			}
-
-			if(t < minT)
-			{
-				minT = t;
-			}
-
-			// check for intersection failure
-			if(minT < 0.0 || maxS > minT)
-			{
-				return false;
-			}
-		}
-	}
-
-	// done, have intersection
-	return true;
-}
-
-//==============================================================================
-// 6th line (S)                                                                =
-//==============================================================================
-
-//==============================================================================
-Bool collide(const Sphere& a, const Sphere& b)
-{
-	F32 tmp = a.getRadius() + b.getRadius();
-	return (a.getCenter() - b.getCenter()).getLengthSquared() <= tmp * tmp;
-}
-
-//==============================================================================
-Bool collide(const Sphere& s, const Aabb& aabb)
-{
-	const Vec3& c = s.getCenter();
-
-	// find the box's closest point to the sphere
-	Vec3 cp; // Closest Point
-	for(U i = 0; i < 3; i++)
-	{
-		// if the center is greater than the max then the closest
-		// point is the max
-		if(c[i] > aabb.getMax()[i])
-		{
-			cp[i] = aabb.getMax()[i];
-		}
-		else if(c[i] < aabb.getMin()[i]) // relative to the above
-		{
-			cp[i] = aabb.getMin()[i];
-		}
-		else
-		{
-			// the c lies between min and max
-			cp[i] = c[i];
-		}
-	}
-
-	F32 rsq = s.getRadius() * s.getRadius();
-
-	// if the c lies totally inside the box then the sub is the zero,
-	// this means that the length is also zero and thus its always smaller
-	// than rsq
-	Vec3 sub = c - cp;
-
-	if(sub.getLengthSquared() <= rsq)
-	{
-		return true;
-	}
-
-	return false;
-}
-
-//==============================================================================
-// 7th line (AABB)                                                             =
-//==============================================================================
-
-//==============================================================================
-Bool collide(const Aabb& a, const Aabb& b)
-{
-	// if separated in x direction
-	if(a.getMin().x() > b.getMax().x() || b.getMin().x() > a.getMax().x())
-	{
-		return false;
-	}
-
-	// if separated in y direction
-	if(a.getMin().y() > b.getMax().y() || b.getMin().y() > a.getMax().y())
-	{
-		return false;
-	}
-
-	// if separated in z direction
-	if(a.getMin().z() > b.getMax().z() || b.getMin().z() > a.getMax().z())
-	{
-		return false;
-	}
-
-	// no separation, must be intersecting
-	return true;
-}
-
-} // end namespace detail
-} // end namespace anki

+ 1 - 1
src/collision/CompoundShape.cpp

@@ -71,7 +71,7 @@ void CompoundShape::transform(const Transform& trf)
 //==============================================================================
 void CompoundShape::computeAabb(Aabb& out) const
 {
-	Vec3 min(MAX_F32), max(MIN_F32);
+	Vec4 min(Vec3(MAX_F32), 0.0), max(Vec3(MIN_F32), 0.0);
 
 	iterateShapes([&](const CollisionShape& cs)
 	{

+ 23 - 22
src/collision/Frustum.cpp

@@ -65,7 +65,7 @@ void Frustum::transform(const Transform& trf)
 		useTrf = &trf;
 	}
 
-	m_trf.transform(trf);
+	m_trf = m_trf.combineTransformations(trf);
 
 	// Transform the compound
 	CompoundShape::transform(*useTrf);
@@ -127,24 +127,24 @@ void PerspectiveFrustum::recalculate()
 
 	sinCos(getPi<F32>() + m_fovX / 2.0, s, c);
 	// right
-	m_planes[(U)PlaneType::RIGHT] = Plane(Vec3(c, 0.0, s), 0.0);
+	m_planes[(U)PlaneType::RIGHT] = Plane(Vec4(c, 0.0, s, 0.0), 0.0);
 	// left
-	m_planes[(U)PlaneType::LEFT] = Plane(Vec3(-c, 0.0, s), 0.0);
+	m_planes[(U)PlaneType::LEFT] = Plane(Vec4(-c, 0.0, s, 0.0), 0.0);
 
 	sinCos((getPi<F32>() + m_fovY) * 0.5, s, c);
 	// bottom
-	m_planes[(U)PlaneType::BOTTOM] = Plane(Vec3(0.0, s, c), 0.0);
+	m_planes[(U)PlaneType::BOTTOM] = Plane(Vec4(0.0, s, c, 0.0), 0.0);
 	// top
-	m_planes[(U)PlaneType::TOP] = Plane(Vec3(0.0, -s, c), 0.0);
+	m_planes[(U)PlaneType::TOP] = Plane(Vec4(0.0, -s, c, 0.0), 0.0);
 
 	// near
-	m_planes[(U)PlaneType::NEAR] = Plane(Vec3(0.0, 0.0, -1.0), m_near);
+	m_planes[(U)PlaneType::NEAR] = Plane(Vec4(0.0, 0.0, -1.0, 0.0), m_near);
 	// far
-	m_planes[(U)PlaneType::FAR] = Plane(Vec3(0.0, 0.0, 1.0), -m_far);
+	m_planes[(U)PlaneType::FAR] = Plane(Vec4(0.0, 0.0, 1.0, 0.0), -m_far);
 
 	// Rest
 	//
-	Vec3 eye = Vec3(0.0, 0.0, -m_near);
+	Vec4 eye = Vec4(0.0, 0.0, -m_near, 0.0);
 	for(LineSegment& ls : m_segments)
 	{
 		ls.setOrigin(eye);
@@ -154,10 +154,10 @@ void PerspectiveFrustum::recalculate()
 	F32 y = tan(m_fovY / 2.0) * m_far;
 	F32 z = -m_far;
 
-	m_segments[0].setDirection(Vec3(x, y, z - m_near)); // top right
-	m_segments[1].setDirection(Vec3(-x, y, z - m_near)); // top left
-	m_segments[2].setDirection(Vec3(-x, -y, z - m_near)); // bottom left
-	m_segments[3].setDirection(Vec3(x, -y, z - m_near)); // bottom right
+	m_segments[0].setDirection(Vec4(x, y, z - m_near, 0.0)); // top right
+	m_segments[1].setDirection(Vec4(-x, y, z - m_near, 0.0)); // top left
+	m_segments[2].setDirection(Vec4(-x, -y, z - m_near, 0.0)); // bottom left
+	m_segments[3].setDirection(Vec4(x, -y, z - m_near, 0.0)); // bottom right
 }
 
 //==============================================================================
@@ -269,19 +269,20 @@ Mat4 OrthographicFrustum::calculateProjectionMatrix() const
 void OrthographicFrustum::recalculate()
 {
 	// Planes
-	m_planes[(U)PlaneType::LEFT] = Plane(Vec3(1.0, 0.0, 0.0), m_left);
-	m_planes[(U)PlaneType::RIGHT] = Plane(Vec3(-1.0, 0.0, 0.0), -m_right);
-	m_planes[(U)PlaneType::NEAR] = Plane(Vec3(0.0, 0.0, -1.0), m_near);
-	m_planes[(U)PlaneType::FAR] = Plane(Vec3(0.0, 0.0, 1.0), -m_far);
-	m_planes[(U)PlaneType::TOP] = Plane(Vec3(0.0, -1.0, 0.0), -m_top);
-	m_planes[(U)PlaneType::BOTTOM] = Plane(Vec3(0.0, 1.0, 0.0), m_bottom);
+	m_planes[(U)PlaneType::LEFT] = Plane(Vec4(1.0, 0.0, 0.0, 0.0), m_left);
+	m_planes[(U)PlaneType::RIGHT] = Plane(Vec4(-1.0, 0.0, 0.0, 0.0), -m_right);
+	m_planes[(U)PlaneType::NEAR] = Plane(Vec4(0.0, 0.0, -1.0, 0.0), m_near);
+	m_planes[(U)PlaneType::FAR] = Plane(Vec4(0.0, 0.0, 1.0, 0.0), -m_far);
+	m_planes[(U)PlaneType::TOP] = Plane(Vec4(0.0, -1.0, 0.0, 0.0), -m_top);
+	m_planes[(U)PlaneType::BOTTOM] = Plane(Vec4(0.0, 1.0, 0.0, 0.0), m_bottom);
 
 	// OBB
-	Vec3 c((m_right + m_left) * 0.5, 
+	Vec4 c((m_right + m_left) * 0.5, 
 		(m_top + m_bottom) * 0.5, 
-		-(m_far + m_near) * 0.5);
-	Vec3 e = Vec3(m_right, m_top, -m_far) - c;
-	m_obb = Obb(c, Mat3::getIdentity(), e);
+		-(m_far + m_near) * 0.5,
+		0.0);
+	Vec4 e = Vec4(m_right, m_top, -m_far, 0.0) - c;
+	m_obb = Obb(c, Mat3x4::getIdentity(), e);
 }
 
 } // end namespace anki

+ 1 - 1
src/collision/GjkEpa.cpp

@@ -60,7 +60,7 @@ Bool Gjk::update(const Vec4& a)
 			m_c = m_b;
 			m_b = a;
 		 
-			m_dir = crossAba(ab,ao);
+			m_dir = crossAba(ab, ao);
 		 
 			return false;
 		}

+ 7 - 8
src/collision/LineSegment.cpp

@@ -13,9 +13,8 @@ namespace anki {
 //==============================================================================
 F32 LineSegment::testPlane(const Plane& p) const
 {
-	const LineSegment& ls = *this;
-	const Vec3& p0 = ls.getOrigin();
-	Vec3 p1 = ls.getOrigin() + ls.getDirection();
+	const Vec4& p0 = m_origin;
+	Vec4 p1 = m_origin + m_dir;
 
 	F32 dist0 = p.test(p0);
 	F32 dist1 = p.test(p1);
@@ -45,19 +44,19 @@ F32 LineSegment::testPlane(const Plane& p) const
 }
 
 //==============================================================================
-LineSegment LineSegment::getTransformed(const Transform& transform) const
+LineSegment LineSegment::getTransformed(const Transform& trf) const
 {
 	LineSegment out;
-	out.origin = origin.getTransformed(transform);
-	out.dir = transform.getRotation() * (dir * transform.getScale());
+	out.m_origin = trf.transform(m_origin);
+	out.m_dir = Vec4(trf.getRotation() * (m_dir * trf.getScale()), 0.0);
 	return out;
 }
 
 //==============================================================================
 void LineSegment::computeAabb(Aabb& aabb) const
 {
-	Vec3 min = origin;
-	Vec3 max = origin + dir;
+	Vec4 min = m_origin;
+	Vec4 max = m_origin + m_dir;
 
 	for(U i = 0; i < 3; ++i)
 	{

+ 92 - 42
src/collision/Obb.cpp

@@ -11,41 +11,41 @@ namespace anki {
 
 //==============================================================================
 Obb::Obb()
-	:	CollisionShape(Type::OBB),
-		m_center(Vec3(0.0)),
-		m_rotation(Mat3::getIdentity()),
-		m_extends(Vec3(getEpsilon<F32>()))
+	:	Base(Type::OBB),
+		m_center(Vec4(0.0)),
+		m_rotation(Mat3x4::getIdentity()),
+		m_extend(Vec3(getEpsilon<F32>()), 0.0)
 {}
 
 //==============================================================================
 Obb::Obb(const Obb& b)
-	: 	CollisionShape(Type::OBB), 
-		m_center(b.m_center), 
-		m_rotation(b.m_rotation),
-		m_extends(b.m_extends)
-{}
+	: 	Base(Type::OBB)
+{
+	operator=(b);
+}
 
 //==============================================================================
-Obb::Obb(const Vec3& center, const Mat3& rotation, const Vec3& extends)
-	:	CollisionShape(Type::OBB), 
-		m_center(center), 
+Obb::Obb(const Vec4& center, const Mat3x4& rotation, const Vec4& extend)
+	:	Base(Type::OBB), 
+		m_center(center),
 		m_rotation(rotation),
-		m_extends(extends)
+		m_extend(extend)
 {}
 
 //==============================================================================
 F32 Obb::testPlane(const Plane& p) const
 {
-	const Obb& obb = *this;
-	Vec3 xNormal = obb.getRotation().getTransposed() * p.getNormal();
+	Mat3x4 rot = m_rotation;
+	rot.transposeRotationPart();
+	Vec3 xNormal = rot * p.getNormal();
 
 	// maximum extent in direction of plane normal
 	F32 r =
-		fabs(obb.getExtend().x() * xNormal.x()) +
-		fabs(obb.getExtend().y() * xNormal.y()) +
-		fabs(obb.getExtend().z() * xNormal.z());
+		abs(m_extend.x() * xNormal.x()) +
+		abs(m_extend.y() * xNormal.y()) +
+		abs(m_extend.z() * xNormal.z());
 	// signed distance between box center and plane
-	F32 d = p.test(obb.getCenter());
+	F32 d = p.test(m_center);
 
 	// return signed distance
 	if(fabs(d) < r)
@@ -63,12 +63,12 @@ F32 Obb::testPlane(const Plane& p) const
 }
 
 //==============================================================================
-Obb Obb::getTransformed(const Transform& transform) const
+Obb Obb::getTransformed(const Transform& trf) const
 {
 	Obb out;
-	out.m_extends = m_extends * transform.getScale();
-	out.m_center = m_center.getTransformed(transform);
-	out.m_rotation = transform.getRotation() * m_rotation;
+	out.m_extend = m_extend * trf.getScale();
+	out.m_center = trf.transform(m_center);
+	out.m_rotation = trf.getRotation().combineTransformations(m_rotation);
 	return out;
 }
 
@@ -77,26 +77,26 @@ Obb Obb::getCompoundShape(const Obb& b) const
 {
 	Obb out;
 
-	Array<Vec3, 8> points0;
-	Array<Vec3, 8> points1;
+	Array<Vec4, 8> points0;
+	Array<Vec4, 8> points1;
 
 	getExtremePoints(points0);
 	b.getExtremePoints(points1);
 
-	Array<Vec3, 16> points;
+	Array<Vec4, 16> points;
 	for(U i = 0; i < 8; i++)
 	{
 		points[i] = points0[i];
 		points[i + 8] = points1[i];
 	}
 
-	out.setFromPointCloud(&points[0], points.size(), sizeof(Vec3), 
-		sizeof(Vec3) * points.size());
+	out.setFromPointCloud(&points[0], points.size(), sizeof(Vec4), 
+		sizeof(Vec4) * points.size());
 	return out;
 }
 
 //==============================================================================
-void Obb::getExtremePoints(Array<Vec3, 8>& points) const
+void Obb::getExtremePoints(Array<Vec4, 8>& points) const
 {
 	// L: left, R: right, T: top, B: bottom, F: front, B: back
 	enum
@@ -111,14 +111,15 @@ void Obb::getExtremePoints(Array<Vec3, 8>& points) const
 		RBB
 	};
 
-	Vec3 er = m_rotation * m_extends; // extend rotated
+	Vec3 er3 = m_rotation * m_extend; // extend rotated
+	Vec4 er(er3, 0.0);
 
 	points[RTF] = er;
 	points[LBB] = -er;
 
-	Vec3 xAxis = m_rotation.getColumn(0);
-	Vec3 yAxis = m_rotation.getColumn(1);
-	Vec3 zAxis = m_rotation.getColumn(2);
+	Vec4 xAxis = Vec4(m_rotation.getColumn(0), 0.0);
+	Vec4 yAxis = Vec4(m_rotation.getColumn(1), 0.0);
+	Vec4 zAxis = Vec4(m_rotation.getColumn(2), 0.0);
 
 	// Reflection: x1' = 2n|x1.n| - x1
 
@@ -130,7 +131,7 @@ void Obb::getExtremePoints(Array<Vec3, 8>& points) const
 	points[RTB] = 2.0f * points[LTF].dot(yAxis) * yAxis - points[LTF];
 	points[RBF] = 2.0f * points[LTF].dot(zAxis) * zAxis - points[LTF];
 
-	for(Vec3& point : points)
+	for(Vec4& point : points)
 	{
 		point += m_center;
 	}
@@ -139,25 +140,26 @@ void Obb::getExtremePoints(Array<Vec3, 8>& points) const
 //==============================================================================
 void Obb::computeAabb(Aabb& aabb) const
 {
-	Mat3 absM;
-	for(U i = 0; i < 9; ++i)
+	Mat3x4 absM;
+	for(U i = 0; i < 12; ++i)
 	{
 		absM[i] = fabs(m_rotation[i]);
 	}
 
-	Vec3 newE = absM * m_extends;
+	Vec4 newE = Vec4(absM * m_extend, 0.0);
 
 	// Add a small epsilon to avoid some assertions
+	Vec4 epsilon(Vec3(getEpsilon<F32>() * 100.0), 0.0);
 	aabb = Aabb(m_center - newE, 
-		m_center + newE + Vec3(getEpsilon<F32>() * 100.0));
+		m_center + newE + epsilon);
 }
 
 //==============================================================================
 void Obb::setFromPointCloud(
 	const void* buff, U count, PtrSize stride, PtrSize buffSize)
 {
-	Vec3 min = Vec3(MAX_F32);
-	Vec3 max = Vec3(MIN_F32);
+	Vec4 min = Vec4(Vec3(MAX_F32), 0.0);
+	Vec4 max = Vec4(Vec3(MIN_F32), 0.0);
 
 	iteratePointCloud(buff, count, stride, buffSize, [&](const Vec3& pos)
 	{
@@ -176,8 +178,56 @@ void Obb::setFromPointCloud(
 
 	// Set the locals
 	m_center = (max + min) / 2.0;
-	m_rotation = Mat3::getIdentity();
-	m_extends = max - m_center;
+	m_rotation = Mat3x4::getIdentity();
+	m_extend = max - m_center;
+}
+
+//==============================================================================
+Vec4 Obb::computeSupport(const Vec4& dir) const
+{
+	Vec4 out(0.0);
+
+	Vec3 er3 = m_rotation * m_extend; // extend rotated
+	Vec4 er(er3, 0.0);
+
+	Vec4 xAxis = Vec4(m_rotation.getColumn(0), 0.0);
+	Vec4 yAxis = Vec4(m_rotation.getColumn(1), 0.0);
+	Vec4 zAxis = Vec4(m_rotation.getColumn(2), 0.0);
+
+	if(dir.dot(xAxis) >= 0.0)
+	{
+		// Right side of the box
+
+		out.x() = er.x();
+	}
+	else
+	{
+		out.x() = -er.x();
+	}
+
+	if(dir.dot(yAxis) >= 0.0)
+	{
+		// Top side
+
+		out.y() = er.y();
+	}
+	else
+	{
+		out.y() = -er.y();
+	}
+
+	if(dir.dot(zAxis) >= 0.0)
+	{
+		// Front side
+
+		out.z() = er.z();
+	}
+	else
+	{
+		out.z() = -er.z();
+	}
+
+	return out;
 }
 
 } // end namespace anki

+ 17 - 20
src/collision/Plane.cpp

@@ -9,13 +9,8 @@
 namespace anki {
 
 //==============================================================================
-Plane::Plane(const Plane& b)
-	: CollisionShape(Type::PLANE), normal(b.normal), offset(b.offset)
-{}
-
-//==============================================================================
-Plane::Plane(const Vec3& normal_, F32 offset_)
-	: CollisionShape(Type::PLANE), normal(normal_), offset(offset_)
+Plane::Plane(const Vec4& normal, F32 offset)
+	: CollisionShape(Type::PLANE), m_normal(normal), m_offset(offset)
 {}
 
 //==============================================================================
@@ -29,27 +24,27 @@ F32 Plane::testPlane(const Plane& /*p*/) const
 void Plane::setFrom3Points(const Vec3& p0, const Vec3& p1, const Vec3& p2)
 {
 	// get plane vectors
-	Vec3 u = p1 - p0;
-	Vec3 v = p2 - p0;
+	Vec4 u = Vec4(p1 - p0, 0.0);
+	Vec4 v = Vec4(p2 - p0, 0.0);
 
-	normal = u.cross(v);
+	m_normal = u.cross(v);
 
 	// length of normal had better not be zero
-	ANKI_ASSERT(!isZero(normal.getLengthSquared()));
+	ANKI_ASSERT(!isZero(m_normal.getLengthSquared()));
 
-	normal.normalize();
-	offset = normal.dot(p0); // XXX: correct??
+	m_normal.normalize();
+	m_offset = m_normal.dot(Vec4(p0, 0.0)); // XXX: correct??
 }
 
 //==============================================================================
 void Plane::setFromPlaneEquation(F32 a, F32 b, F32 c, F32 d)
 {
-	normal = Vec3(a, b, c);
+	m_normal = Vec4(a, b, c, 0.0);
 
 	// length of normal had better not be zero
-	ANKI_ASSERT(isZero(normal.getLength() - 1.0));
+	ANKI_ASSERT(isZero(m_normal.getLength() - 1.0));
 
-	offset = d;
+	m_offset = d;
 }
 
 //==============================================================================
@@ -57,12 +52,14 @@ Plane Plane::getTransformed(const Transform& trf) const
 {
 	Plane plane;
 
-	// the normal
-	plane.normal = trf.getRotation() * normal;
+	// Rotate the normal
+	plane.m_normal = Vec4(trf.getRotation() * m_normal, 0.0);
 
 	// the offset
-	Vec3 newTrans = trf.getRotation().getTransposed() * trf.getOrigin();
-	plane.offset = offset * trf.getScale() + newTrans.dot(normal);
+	Mat3x4 rot = trf.getRotation();
+	rot.transposeRotationPart();
+	Vec4 newTrans(rot * trf.getOrigin(), 0.0);
+	plane.m_offset = m_offset * trf.getScale() + newTrans.dot(m_normal);
 
 	return plane;
 }

+ 0 - 57
src/collision/Ray.cpp

@@ -1,57 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/collision/Ray.h"
-#include "anki/collision/Plane.h"
-
-namespace anki {
-
-//==============================================================================
-Ray Ray::getTransformed(const Transform& transform) const
-{
-	Ray out;
-	out.origin = origin.getTransformed(transform);
-	out.dir = transform.getRotation() * dir;
-	return out;
-}
-
-//==============================================================================
-F32 Ray::testPlane(const Plane& p) const
-{
-	const Ray& r = *this;
-	F32 dist = p.test(r.getOrigin());
-	F32 cos_ = p.getNormal().dot(r.getDirection());
-
-	if(cos_ > 0.0) // the ray points to the same half-space as the plane
-	{
-		if(dist < 0.0) // the ray's origin is behind the plane
-		{
-			return 0.0;
-		}
-		else
-		{
-			return dist;
-		}
-	}
-	else
-	{
-		if(dist > 0.0)
-		{
-			return 0.0;
-		}
-		else
-		{
-			return dist;
-		}
-	}
-}
-
-//==============================================================================
-void Ray::computeAabb(Aabb&) const
-{
-	ANKI_ASSERT(0 && "Can't do that");
-}
-
-} // end namespace

+ 13 - 17
src/collision/Sphere.cpp

@@ -36,16 +36,12 @@ F32 Sphere::testPlane(const Plane& p) const
 }
 
 //==============================================================================
-Sphere Sphere::getTransformed(const Transform& transform) const
+Sphere Sphere::getTransformed(const Transform& trf) const
 {
 	Sphere newSphere;
 
-	newSphere.m_center = m_center.getTransformed(
-		transform.getOrigin(),
-		transform.getRotation(),
-		transform.getScale());
-
-	newSphere.m_radius = m_radius * transform.getScale();
+	newSphere.m_center = trf.transform(m_center);
+	newSphere.m_radius = m_radius * trf.getScale();
 	return newSphere;
 }
 
@@ -81,7 +77,7 @@ Sphere Sphere::getCompoundShape(const Sphere& b) const
 	}
 	*/
 
-	Vec3 c = b.getCenter() - a.getCenter(); // Vector from one center to the
+	Vec4 c = b.getCenter() - a.getCenter(); // Vector from one center to the
 	                                        // other
 	F32 cLen = c.getLength();
 
@@ -94,10 +90,10 @@ Sphere Sphere::getCompoundShape(const Sphere& b) const
 		return b;
 	}
 
-	Vec3 bnorm = c / cLen;
+	Vec4 bnorm = c / cLen;
 
-	Vec3 ca = (-bnorm) * a.getRadius() + a.getCenter();
-	Vec3 cb = (bnorm) * b.getRadius() + b.getCenter();
+	Vec4 ca = (-bnorm) * a.getRadius() + a.getCenter();
+	Vec4 cb = (bnorm) * b.getRadius() + b.getCenter();
 
 	return Sphere((ca + cb) / 2.0, (ca - cb).getLength() / 2.0);
 }
@@ -105,8 +101,8 @@ Sphere Sphere::getCompoundShape(const Sphere& b) const
 //==============================================================================
 void Sphere::computeAabb(Aabb& aabb) const
 {
-	aabb.setMin((m_center - m_radius).xyz());
-	aabb.setMax((m_center + m_radius).xyz());
+	aabb.setMin(m_center - m_radius);
+	aabb.setMax(m_center + m_radius);
 }
 
 //==============================================================================
@@ -114,8 +110,8 @@ void Sphere::setFromPointCloud(
 	const void* buff, U count, PtrSize stride, PtrSize buffSize)
 {
 	// Calc min/max
-	Vec3 min(MAX_F32);
-	Vec3 max(MIN_F32);
+	Vec4 min(Vec3(MAX_F32), 0.0);
+	Vec4 max(Vec3(MIN_F32), 0.0);
 	
 	iteratePointCloud(buff, count, stride, buffSize, [&](const Vec3& pos)
 	{
@@ -139,7 +135,7 @@ void Sphere::setFromPointCloud(
 
 	iteratePointCloud(buff, count, stride, buffSize, [&](const Vec3& pos)
 	{
-		F32 dist = (pos - m_center).getLengthSquared();
+		F32 dist = (Vec4(pos, 0.0) - m_center).getLengthSquared();
 		if(dist > maxDist)
 		{
 			maxDist = dist;
@@ -152,7 +148,7 @@ void Sphere::setFromPointCloud(
 //==============================================================================
 Vec4 Sphere::computeSupport(const Vec4& dir) const
 {
-	//return s.center + v.getNormalized() * s.radius;
+	return m_center + dir.getNormalized() * m_radius;
 }
 
 } // end namespace anki

+ 0 - 232
src/collision/TestsObbObb.cpp

@@ -10,238 +10,6 @@
 namespace anki {
 namespace detail {
 
-//==============================================================================
-static F32 calcVectorDot3Internal(const F32* a, const F32* b, U stepA, U stepB)
-{
-	return a[0] * b[0] + a[stepA] * b[stepB] + a[2 * stepA] * b[2 * stepB];
-}
-
-static F32 calcVectorDot313(const F32* a, const F32* b)
-{ 
-	return calcVectorDot3Internal(a, b, 1, 3); 
-}
-static F32 calcVectorDot331(const F32* a, const F32* b) 
-{ 
-	return calcVectorDot3Internal(a, b, 3, 1); 
-}
-static F32 calcVectorDot333(const F32* a, const F32* b) 
-{ 
-	return calcVectorDot3Internal(a, b, 3, 3); 
-}
-static F32 calcVectorDot314(const F32* a, const F32* b) 
-{ 
-	return calcVectorDot3Internal(a, b, 1, 4); 
-}
-static F32 calcVectorDot341(const F32* a, const F32* b) 
-{ 
-	return calcVectorDot3Internal(a, b, 4, 1); 
-}
-static F32 calcVectorDot344(const F32* a, const F32* b) 
-{ 
-	return calcVectorDot3Internal(a, b, 4, 4); 
-}
-
-static void lineClosestApproach(
-	const Vec3& pa, const Vec3& ua,
-	const Vec3& pb, const Vec3& ub,
-	F32* alpha, F32* beta)
-{
-	Vec3 p;
-	p = pb - pa;
-	F32 uaub = ua.dot(ub);
-	F32 q1 =  ua.dot(p);
-	F32 q2 = -ub.dot(p);
-	F32 d = 1.0 - uaub * uaub;
-
-	if(d <= 0.0001)
-	{
-		*alpha = 0.0;
-		*beta = 0.0;
-	}
-	else 
-	{
-		d = 1.0 / d;
-		*alpha = (q1 + uaub * q2) * d;
-		*beta = (uaub * q1 + q2) * d;
-	}
-}
-
-// find all the intersection points between the 2D rectangle with vertices
-// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
-// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
-//
-// the intersection points are returned as x,y pairs in the 'ret' array.
-// the number of intersection points is returned by the function (this will
-// be in the range 0 to 8).
-static U intersectRectQuad(F32 h[2], F32 p[8], F32 ret[16])
-{
-	// q (and r) contain nq (and nr) coordinate points for the current (and
-	// chopped) polygons
-	I nq = 4;
-	U nr;
-	F32 buffer[16];
-	F32* q = p;
-	F32* r = ret;
-
-	for(I dir = 0; dir <= 1; dir++) 
-	{
-		// direction notation: xy[0] = x axis, xy[1] = y axis
-		for(I sign=-1; sign <= 1; sign += 2) 
-		{
-			// chop q along the line xy[dir] = sign*h[dir]
-			F32* pq = q;
-			F32* pr = r;
-			nr = 0;
-
-			for(I i = nq; i > 0; i--) 
-			{
-				// Go through all points in q and all lines between adjacent 
-				// points
-				if(sign * pq[dir] < h[dir]) 
-				{
-					// this point is inside the chopping line
-					pr[0] = pq[0];
-					pr[1] = pq[1];
-					pr += 2;
-					nr++;
-
-					if(nr & 8) 
-					{
-						q = r;
-						goto done;
-					}
-				}
-
-				F32* nextq = (i > 1) ? pq + 2 : q;
-
-				if((sign * pq[dir] < h[dir]) ^ (sign * nextq[dir] < h[dir])) 
-				{
-					// this line crosses the chopping line
-					pr[1 - dir] = pq[1 - dir] + (nextq[1 - dir] - pq[1 - dir]) 
-						/ (nextq[dir] - pq[dir]) * (sign * h[dir] - pq[dir]);
-					pr[dir] = sign * h[dir];
-					pr += 2;
-					++nr;
-					if(nr & 8) 
-					{
-						q = r;
-						goto done;
-					}
-				}
-				pq += 2;
-			}
-
-			q = r;
-			r = (q == ret) ? buffer : ret;
-			nq = nr;
-		}
-	}
-	
-done:
-	if(q != ret)
-	{
-		std::memcpy(ret, q, nr * 2 * sizeof(F32));
-	}
-
-	return nr;
-}
-
-// given n points in the plane (array p, of size 2*n), generate m points that
-// best represent the whole set. the definition of 'best' here is not
-// predetermined - the idea is to select points that give good box-box
-// collision detection behavior. the chosen point indexes are returned in the
-// array iret (of size m). 'i0' is always the first entry in the array.
-// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
-// in the range [0..n-1].
-static void cullPoints(I n, F32 p[], I m, I i0, I iret[])
-{
-	// compute the centroid of the polygon in cx,cy
-	I i, j;
-	F32 a, cx, cy, q;
-
-	if(n == 1) 
-	{
-		cx = p[0];
-		cy = p[1];
-	}
-	else if(n == 2) 
-	{
-		cx = 0.5 * (p[0] + p[2]);
-		cy = 0.5 * (p[1] + p[3]);
-	}
-	else 
-	{
-		a = 0.0;
-		cx = 0.0;
-		cy = 0.0;
-
-		for (i = 0; i < (n - 1); i++) 
-		{
-			q = p[i * 2] * p[i * 2 + 3] - p[ i * 2 + 2] * p[ i * 2 + 1];
-			a += q;
-			cx += q * (p[i * 2] + p[i * 2 + 2]);
-			cy += q * (p[i * 2 + 1] + p[i * 2 + 3]);
-		}
-
-		q = p[n * 2 - 2] * p[1] - p[0] * p[n * 2 - 1];
-		a = 1.0 / (3.0 * (a + q));
-		cx = a * (cx + q * (p[n * 2 - 2] + p[0]));
-		cy = a * (cy + q * (p[n * 2 - 1] + p[1]));
-	}
-
-	// compute the angle of each point w.r.t. the centroid
-	F32 A[8];
-	for(i = 0; i < n; i++) 
-	{
-		A[i] = atan2(p[i * 2 + 1] - cy, p[i * 2] - cx);
-	}
-
-	// search for points that have angles closest to A[i0] + i*(2*pi/m).
-	I avail[8];
-	for(i = 0; i < n; i++) 
-	{
-		avail[i] = 1;
-	}
-
-	avail[i0] = 0;
-	iret[0] = i0;
-	iret++;
-
-	for(j = 1; j < m; j++) 
-	{
-		a = (F32(j) * (2 * getPi<F32>() / m) + A[i0]);
-
-		if(a > getPi<F32>()) 
-		{
-			a -= 2.0 * getPi<F32>();
-		}
-
-		F32 maxdiff = MAX_F32, diff;
-		for(i = 0; i < n; i++) 
-		{
-			if(avail[i]) 
-			{
-				diff = abs(A[i] - a);
-
-				if(diff > getPi<F32>()) 
-				{
-					diff = 2.0 * getPi<F32>() - diff;
-				}
-
-				if(diff < maxdiff) 
-				{
-					maxdiff = diff;
-					*iret = i;
-				}
-			}
-		}
-
-		ANKI_ASSERT(maxdiff != MAX_F32);
-		avail[*iret] = 0;
-		iret++;
-	}
-}
-
 //==============================================================================
 U test(const Obb& a, const Obb& b, CollisionTempVector<ContactPoint>& points)
 {

+ 8 - 8
src/event/AnimationEvent.cpp

@@ -12,16 +12,16 @@ namespace anki {
 
 //==============================================================================
 AnimationEvent::AnimationEvent(EventManager* manager, 
-	const AnimationResourcePointer& anim_, SceneNode* movableSceneNode)
+	const AnimationResourcePointer& anim, SceneNode* movableSceneNode)
 	:	Event(manager, 0.0, 0.0, movableSceneNode),
-		anim(anim_)
+		m_anim(anim)
 {
 	ANKI_ASSERT(movableSceneNode);
 
-	startTime = anim->getStartingTime();
-	duration = anim->getDuration();
+	startTime = m_anim->getStartingTime();
+	duration = m_anim->getDuration();
 
-	enableBits(EF_REANIMATE, anim->getRepeat());
+	enableBits(EF_REANIMATE, m_anim->getRepeat());
 }
 
 //==============================================================================
@@ -33,11 +33,11 @@ void AnimationEvent::update(F32 prevUpdateTime, F32 crntTime)
 	Vec3 pos;
 	Quat rot;
 	F32 scale = 1.0;
-	anim->interpolate(0, crntTime, pos, rot, scale);
+	m_anim->interpolate(0, crntTime, pos, rot, scale);
 
 	Transform trf;
-	trf.setOrigin(pos);
-	trf.setRotation(Mat3(rot));
+	trf.setOrigin(pos.xyz0());
+	trf.setRotation(Mat3x4(rot));
 	trf.setScale(scale);
 	move.setLocalTransform(trf);
 }

+ 5 - 4
src/event/MoveEvent.cpp

@@ -20,13 +20,14 @@ MoveEvent::MoveEvent(EventManager* manager, F32 startTime, F32 duration,
 
 	const MoveComponent& move = node->getComponent<MoveComponent>();
 
-	originalPos = move.getLocalTransform().getOrigin();
+	m_originalPos = move.getLocalTransform().getOrigin();
 
 	for(U i = 0; i < 3; i++)
 	{
-		newPos[i] = randRange(posMin[i], posMax[i]);
+		m_newPos[i] = randRange(m_posMin[i], m_posMax[i]);
 	}
-	newPos += move.getLocalTransform().getOrigin();
+	m_newPos[3] = 0.0;
+	m_newPos += move.getLocalTransform().getOrigin();
 }
 
 //==============================================================================
@@ -41,7 +42,7 @@ void MoveEvent::update(F32 prevUpdateTime, F32 crntTime)
 
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
 
-	trf.getOrigin() = interpolate(originalPos, newPos, factor);
+	trf.getOrigin() = interpolate(m_originalPos, m_newPos, factor);
 
 	move.setLocalTransform(trf);
 }

+ 35 - 0
src/renderer/Dbg.cpp

@@ -181,6 +181,41 @@ void Dbg::run(GlJobChainHandle& jobs)
 	// XXX
 #endif
 
+#if 1
+	{
+		Vec4 pos0 = scene.findSceneNode("shape0").
+			getComponent<MoveComponent>().getWorldTransform().getOrigin();
+
+		Vec4 pos1 = scene.findSceneNode("shape1").
+			getComponent<MoveComponent>().getWorldTransform().getOrigin();
+		Mat3x4 rot1 = scene.findSceneNode("shape1").
+			getComponent<MoveComponent>().getWorldTransform().getRotation();
+
+
+		Aabb s0(pos0 - Vec4(1.01, 1.0, 2.02, 0.0), pos0 + Vec4(1.0, 1.0, 2.0, 0.0));
+		Obb s1(pos1, rot1, Vec4(1.01, 0.501, 2.51, 0.0));
+
+		CollisionDebugDrawer dr(m_drawer.get());
+
+		Gjk gjk;
+
+		Bool intersect = gjk.intersect(s1, s0);
+
+
+		if(intersect)
+		{
+			m_drawer->setColor(Vec4(1.0, 0.0, 0.0, 1.0));
+		}
+		else
+		{
+			m_drawer->setColor(Vec4(1.0, 1.0, 1.0, 1.0));
+		}
+
+		s0.accept(dr);
+		s1.accept(dr);
+	}
+#endif
+
 	m_drawer->flush();
 	m_drawer->finishDraw();
 

+ 12 - 16
src/renderer/DebugDrawer.cpp

@@ -226,7 +226,8 @@ void DebugDrawer::drawSphere(F32 radius, I complexity)
 	Mat4 oldMMat = m_mMat;
 	Mat4 oldVpMat = m_vpMat;
 
-	setModelMatrix(m_mMat * Mat4(Vec3(0.0), Mat3::getIdentity(), radius));
+	setModelMatrix(m_mMat * Mat4(Vec4(0.0, 0.0, 0.0, 1.0), 
+		Mat3::getIdentity(), radius));
 
 	begin();
 	for(const Vec3& p : *sphereLines)
@@ -276,7 +277,8 @@ void DebugDrawer::drawCube(F32 size)
 //==============================================================================
 void CollisionDebugDrawer::visit(const Sphere& sphere)
 {
-	m_dbg->setModelMatrix(Mat4(sphere.getCenter(), Mat3::getIdentity(), 1.0));
+	m_dbg->setModelMatrix(
+		Mat4(sphere.getCenter().xyz1(), Mat3::getIdentity(), 1.0));
 	m_dbg->drawSphere(sphere.getRadius());
 }
 
@@ -288,28 +290,22 @@ void CollisionDebugDrawer::visit(const Obb& obb)
 	scale(1, 1) = obb.getExtend().y();
 	scale(2, 2) = obb.getExtend().z();
 
-	Mat4 rot(obb.getRotation());
+	Mat4 tsl(Transform(obb.getCenter(), obb.getRotation(), 1.0));
 
-	Mat4 trs(obb.getCenter());
-
-	Mat4 tsl;
-	tsl = Mat4::combineTransformations(rot, scale);
-	tsl = Mat4::combineTransformations(trs, tsl);
-
-	m_dbg->setModelMatrix(tsl);
+	m_dbg->setModelMatrix(tsl * scale);
 	m_dbg->drawCube(2.0);
 }
 
 //==============================================================================
 void CollisionDebugDrawer::visit(const Plane& plane)
 {
-	const Vec3& n = plane.getNormal();
+	Vec3 n = plane.getNormal().xyz();
 	const F32& o = plane.getOffset();
 	Quat q;
 	q.setFrom2Vec3(Vec3(0.0, 0.0, 1.0), n);
 	Mat3 rot(q);
 	rot.rotateXAxis(getPi<F32>() / 2.0);
-	Mat4 trf(n * o, rot);
+	Mat4 trf(Vec4(n * o, 1.0), rot);
 
 	m_dbg->setModelMatrix(trf);
 	m_dbg->drawGrid();
@@ -320,16 +316,16 @@ void CollisionDebugDrawer::visit(const LineSegment& ls)
 {
 	m_dbg->setModelMatrix(Mat4::getIdentity());
 	m_dbg->begin();
-	m_dbg->pushBackVertex(ls.getOrigin());
-	m_dbg->pushBackVertex(ls.getOrigin() + ls.getDirection());
+	m_dbg->pushBackVertex(ls.getOrigin().xyz());
+	m_dbg->pushBackVertex((ls.getOrigin() + ls.getDirection()).xyz());
 	m_dbg->end();
 }
 
 //==============================================================================
 void CollisionDebugDrawer::visit(const Aabb& aabb)
 {
-	const Vec3& min = aabb.getMin();
-	const Vec3& max = aabb.getMax();
+	Vec3 min = aabb.getMin().xyz();
+	Vec3 max = aabb.getMax().xyz();
 
 	Mat4 trf = Mat4::getIdentity();
 	// Scale

+ 3 - 4
src/renderer/Drawer.cpp

@@ -72,8 +72,7 @@ public:
 		switch(rvar.getBuildinId())
 		{
 		case BuildinMaterialVariableId::NO_BUILDIN:
-			uniSet<DataType>(
-				glvar, rvar.begin(), arraySize);
+			uniSet<DataType>(glvar, rvar.begin(), arraySize);
 			break;
 		case BuildinMaterialVariableId::MVP_MATRIX:
 			if(hasWorldTrfs)
@@ -166,7 +165,7 @@ public:
 				{
 					Transform trf;
 					m_renderable->getRenderWorldTransform(i, trf);
-					trf.setRotation(rot);
+					trf.setRotation(Mat3x4(rot));
 					bmvp[i] = vp * Mat4(trf);
 				}
 
@@ -320,7 +319,7 @@ void RenderableDrawer::render(SceneNode& frsn, VisibleNode& visibleNode)
 	// Calculate the key
 	RenderingKey key;
 
-	Vec3 camPos = fr.getFrustumOrigin();
+	Vec4 camPos = fr.getFrustumOrigin();
 
 	F32 dist = (visibleNode.m_node->getComponent<SpatialComponent>().
 		getSpatialOrigin() - camPos).getLength();

+ 9 - 9
src/renderer/Is.cpp

@@ -159,10 +159,10 @@ public:
 		const Camera* cam = m_is->m_cam;
 		ANKI_ASSERT(cam);
 	
-		Vec3 pos = light.getWorldTransform().getOrigin().getTransformed(
-			cam->getViewMatrix());
+		Vec4 pos = 
+			cam->getViewMatrix() * light.getWorldTransform().getOrigin().xyz1();
 
-		slight.m_posRadius = Vec4(pos, -1.0 / light.getRadius());
+		slight.m_posRadius = Vec4(pos.xyz(), -1.0 / light.getRadius());
 		slight.m_diffuseColorShadowmapId = light.getDiffuseColor();
 		slight.m_specularColorTexId = light.getSpecularColor();
 
@@ -222,9 +222,9 @@ public:
 		ANKI_ASSERT(baseslight);
 
 		// Pos & dist
-		Vec3 pos = light.getWorldTransform().getOrigin().getTransformed(
-				cam->getViewMatrix());
-		baseslight->m_posRadius = Vec4(pos, -1.0 / light.getDistance());
+		Vec4 pos = 
+			cam->getViewMatrix() * light.getWorldTransform().getOrigin().xyz1();
+		baseslight->m_posRadius = Vec4(pos.xyz(), -1.0 / light.getDistance());
 
 		// Diff color and shadowmap ID now
 		baseslight->m_diffuseColorShadowmapId = 
@@ -250,11 +250,11 @@ public:
 
 		for(U i = 0; i < 4; i++)
 		{
-			Vec3 extendPoint = light.getWorldTransform().getOrigin() 
+			Vec4 extendPoint = light.getWorldTransform().getOrigin() 
 				+ frustum.getLineSegments()[i].getDirection();
 
-			extendPoint.transform(cam->getViewMatrix());
-			baseslight->m_extendPoints[i] = Vec4(extendPoint, 1.0);
+			extendPoint = cam->getViewMatrix() * extendPoint.xyz1();
+			baseslight->m_extendPoints[i] = extendPoint;
 		}
 
 		return i;

+ 1 - 1
src/renderer/Lf.cpp

@@ -224,7 +224,7 @@ void Lf::run(GlJobChainHandle& jobs)
 			const U depth = tex.getDepth();
 
 			// Transform
-			Vec3 posWorld = light.getWorldTransform().getOrigin();
+			Vec3 posWorld = light.getWorldTransform().getOrigin().xyz();
 			Vec4 posClip = cam.getViewProjectionMatrix() * Vec4(posWorld, 1.0);
 
 			if(posClip.x() > posClip.w() || posClip.x() < -posClip.w()

+ 10 - 8
src/renderer/Tiler.cpp

@@ -159,16 +159,17 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadpoolTask
 	/// Calculate and set a top looking plane
 	void calcPlaneI(U i, const F32 o6)
 	{
-		Vec3 a, b;
+		Vec4 a, b;
 		const F32 n = m_cam->getNear();
 		Plane& plane = m_tiler->m_planesY[i];
 		CHECK_PLANE_PTR(&plane);
 
-		a = Vec3(0.0, 
+		a = Vec4(0.0, 
 			(I(i + 1) - I(m_tiler->m_r->getTilesCount().y()) / 2) * o6,
-			-n);
+			-n,
+			0.0);
 
-		b = Vec3(1.0, 0.0, 0.0).cross(a);
+		b = Vec4(1.0, 0.0, 0.0, 0.0).cross(a);
 		b.normalize();
 
 		plane = Plane(b, 0.0);
@@ -177,16 +178,17 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadpoolTask
 	/// Calculate and set a right looking plane
 	void calcPlaneJ(U j, const F32 l6)
 	{
-		Vec3 a, b;
+		Vec4 a, b;
 		const F32 n = m_cam->getNear();
 		Plane& plane = m_tiler->m_planesX[j];
 		CHECK_PLANE_PTR(&plane);
 
-		a = Vec3((I(j + 1) - I(m_tiler->m_r->getTilesCount().x()) / 2) * l6,
+		a = Vec4((I(j + 1) - I(m_tiler->m_r->getTilesCount().x()) / 2) * l6,
 			0.0, 
-			-n);
+			-n,
+			0.0);
 
-		b = a.cross(Vec3(0.0, 1.0, 0.0));
+		b = a.cross(Vec4(0.0, 1.0, 0.0, 0.0));
 		b.normalize();
 
 		plane = Plane(b, 0.0);

+ 9 - 7
src/scene/Camera.cpp

@@ -36,13 +36,14 @@ void Camera::lookAtPoint(const Vec3& point)
 {
 	MoveComponent& move = *this;
 
-	const Vec3& j = Vec3(0.0, 1.0, 0.0);
-	Vec3 vdir = (point - move.getLocalTransform().getOrigin()).getNormalized();
-	Vec3 vup = j - vdir * j.dot(vdir);
-	Vec3 vside = vdir.cross(vup);
-
-	Mat3 rot = move.getLocalTransform().getRotation();
-	rot.setColumns(vside, vup, -vdir);
+	Vec4 j = Vec4(0.0, 1.0, 0.0, 0.0);
+	Vec4 vdir = 
+		(point.xyz0() - move.getLocalTransform().getOrigin()).getNormalized();
+	Vec4 vup = j - vdir * j.dot(vdir);
+	Vec4 vside = vdir.cross(vup);
+
+	Mat3x4 rot = move.getLocalTransform().getRotation();
+	rot.setColumns(vside.xyz(), vup.xyz(), (-vdir).xyz());
 	move.setLocalRotation(rot);
 }
 
@@ -65,6 +66,7 @@ void Camera::moveUpdate(MoveComponent& move)
 {
 	// Frustum
 	FrustumComponent& fr = *this;
+
 	fr.setViewMatrix(Mat4(move.getWorldTransform().getInverse()));
 	fr.setViewProjectionMatrix(fr.getProjectionMatrix() * fr.getViewMatrix());
 	fr.markForUpdate();

+ 10 - 10
src/scene/MoveComponent.cpp

@@ -9,11 +9,11 @@
 namespace anki {
 
 //==============================================================================
-MoveComponent::MoveComponent(SceneNode* node_, U32 flags)
-	:	SceneComponent(MOVE_COMPONENT, node_),
-		Base(nullptr, node_->getSceneAllocator()),
+MoveComponent::MoveComponent(SceneNode* node, U32 flags)
+	:	SceneComponent(MOVE_COMPONENT, node),
+		Base(nullptr, node->getSceneAllocator()),
 		Bitset<U8>(flags),
-		node(node_)
+		m_node(node)
 {
 	markForUpdate();
 }
@@ -38,7 +38,7 @@ Bool MoveComponent::update(SceneNode&, F32, F32, UpdateType uptype)
 //==============================================================================
 void MoveComponent::updateWorldTransform()
 {
-	prevWTrf = wTrf;
+	m_prevWTrf = m_wtrf;
 	const Bool dirty = bitsEnabled(MF_MARKED_FOR_UPDATE);
 
 	// If dirty then update world transform
@@ -50,20 +50,20 @@ void MoveComponent::updateWorldTransform()
 		{
 			if(bitsEnabled(MF_IGNORE_LOCAL_TRANSFORM))
 			{
-				wTrf = parent->getWorldTransform();
+				m_wtrf = parent->getWorldTransform();
 			}
 			else
 			{
-				wTrf = Transform::combineTransformations(
-					parent->getWorldTransform(), lTrf);
+				m_wtrf = 
+					parent->getWorldTransform().combineTransformations(m_ltrf);
 			}
 		}
 		else
 		{
-			wTrf = lTrf;
+			m_wtrf = m_ltrf;
 		}
 
-		node->componentUpdated(*this, ASYNC_UPDATE);
+		m_node->componentUpdated(*this, ASYNC_UPDATE);
 		timestamp = getGlobTimestamp();
 
 		// Now it's a good time to cleanse parent

+ 19 - 19
src/scene/ParticleEmitter.cpp

@@ -78,8 +78,8 @@ void ParticleSimple::simulate(const ParticleEmitter& pe,
 		static_cast<const ParticleEmitterProperties&>(pe).
 		m_particle.m_gravity.getLength() > 0.0);
 
-	Vec3 xp = m_position;
-	Vec3 xc = m_acceleration * (dt * dt) + m_velocity * dt + xp;
+	Vec4 xp = m_position;
+	Vec4 xc = m_acceleration * (dt * dt) + m_velocity * dt + xp;
 
 	m_position = xc;
 
@@ -91,16 +91,16 @@ void ParticleSimple::revive(const ParticleEmitter& pe,
 	F32 prevUpdateTime, F32 crntTime)
 {
 	ParticleBase::revive(pe, prevUpdateTime, crntTime);
-	m_velocity = Vec3(0.0);
+	m_velocity = Vec4(0.0);
 
 	const ParticleEmitterProperties& props = pe;
 
 	m_acceleration = getRandom(props.m_particle.m_gravity,
-			props.m_particle.m_gravityDeviation);
+			props.m_particle.m_gravityDeviation).xyz0();
 
 	// Set the initial position
 	m_position = getRandom(props.m_particle.m_startingPos,
-		props.m_particle.m_startingPosDeviation);
+		props.m_particle.m_startingPosDeviation).xyz0();
 
 	m_position += pe.getWorldTransform().getOrigin();
 }
@@ -214,9 +214,9 @@ ParticleEmitter::ParticleEmitter(
 	addComponent(static_cast<SpatialComponent*>(this));
 	addComponent(static_cast<RenderComponent*>(this));
 
-	m_obb.setCenter(Vec3(0.0));
-	m_obb.setExtend(Vec3(1.0));
-	m_obb.setRotation(Mat3::getIdentity());
+	m_obb.setCenter(Vec4(0.0));
+	m_obb.setExtend(Vec4(1.0, 1.0, 1.0, 0.0));
+	m_obb.setRotation(Mat3x4::getIdentity());
 
 	// Load resource
 	m_particleEmitterResource.load(filename);
@@ -323,7 +323,7 @@ void ParticleEmitter::componentUpdated(SceneComponent& comp,
 	if(comp.getType() == MoveComponent::getClassType())
 	{
 		m_identityRotation =
-			getWorldTransform().getRotation() == Mat3::getIdentity();
+			getWorldTransform().getRotation() == Mat3x4::getIdentity();
 	}
 }
 
@@ -387,8 +387,8 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime,
 	// - Calc the AABB
 	// - Calc the instancing stuff
 	//
-	Vec3 aabbmin(MAX_F32);
-	Vec3 aabbmax(MIN_F32);
+	Vec4 aabbmin(MAX_F32, MAX_F32, MAX_F32, 0.0);
+	Vec4 aabbmax(MIN_F32, MIN_F32, MIN_F32, 0.0);
 	m_aliveParticlesCount = 0;
 
 	F32* verts = (F32*)(m_vertBuffMapping 
@@ -420,7 +420,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime,
 			// This will calculate a new world transformation
 			p->simulate(*this, prevUpdateTime, crntTime);
 
-			const Vec3& origin = p->getPosition();
+			const Vec4& origin = p->getPosition();
 
 			for(U i = 0; i < 3; i++)
 			{
@@ -455,15 +455,15 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime,
 
 	if(m_aliveParticlesCount != 0)
 	{
-		Vec3 min = aabbmin - m_particle.m_size;
-		Vec3 max = aabbmax + m_particle.m_size;
-		Vec3 center = (min + max) / 2.0;
+		Vec4 min = aabbmin - m_particle.m_size;
+		Vec4 max = aabbmax + m_particle.m_size;
+		Vec4 center = (min + max) / 2.0;
 
-		m_obb = Obb(center, Mat3::getIdentity(), max - center);
+		m_obb = Obb(center, Mat3x4::getIdentity(), max - center);
 	}
 	else
 	{
-		m_obb = Obb(Vec3(0.0), Mat3::getIdentity(), Vec3(0.001));
+		m_obb = Obb(Vec4(0.0), Mat3x4::getIdentity(), Vec4(0.001));
 	}
 	SpatialComponent::markForUpdate();
 
@@ -581,7 +581,7 @@ void ParticleEmitter::doInstancingCalcs()
 					staticCastPtr<ObbSpatialComponent*>(&sp);
 		
 				Obb aobb = m_obb;
-				aobb.setCenter(Vec3(0.0));
+				aobb.setCenter(Vec4(0.0));
 				msp->obb = aobb.getTransformed(m_transforms[count - 1]);
 
 				msp->markForUpdate();
@@ -626,7 +626,7 @@ void ParticleEmitter::getRenderWorldTransform(U index, Transform& trf)
 		// The particle positions are already in word space. Move them back to
 		// local space
 		Transform invTrf = getWorldTransform().getInverse();
-		trf = Transform::combineTransformations(m_transforms[index], invTrf);
+		trf = m_transforms[index].combineTransformations(invTrf);
 	}
 }
 

+ 3 - 3
src/scene/Visibility.cpp

@@ -98,12 +98,12 @@ public:
 			}
 
 			// Sort spatials
-			Vec3 origin = testedFr.getFrustumOrigin();
+			Vec4 origin = testedFr.getFrustumOrigin();
 			std::sort(sps.begin(), sps.begin() + count, 
 				[&](const SpatialTemp& a, const SpatialTemp& b) -> Bool
 			{
-				Vec3 spa = a.sp->getSpatialOrigin();
-				Vec3 spb = b.sp->getSpatialOrigin();
+				Vec4 spa = a.sp->getSpatialOrigin();
+				Vec4 spb = b.sp->getSpatialOrigin();
 
 				F32 dist0 = origin.getDistanceSquared(spa);
 				F32 dist1 = origin.getDistanceSquared(spb);

+ 14 - 13
testapp/Main.cpp

@@ -49,7 +49,7 @@ void initPhysics()
 
 	Transform groundTransform;
 	groundTransform.setIdentity();
-	groundTransform.setOrigin(Vec3(0, -50, 0));
+	groundTransform.setOrigin(Vec4(0, -50, 0, 0));
 
 	RigidBody::Initializer init;
 	init.mass = 0.0;
@@ -130,8 +130,8 @@ void init()
 	cam->setAll(
 		MainRendererSingleton::get().getAspectRatio() * toRad(ang),
 		toRad(ang), 0.5, 500.0);
-	cam->setLocalTransform(Transform(Vec3(17.0, 5.2, 0.0),
-		Mat3(Euler(toRad(-10.0), toRad(90.0), toRad(0.0))),
+	cam->setLocalTransform(Transform(Vec4(17.0, 5.2, 0.0, 0),
+		Mat3x4(Euler(toRad(-10.0), toRad(90.0), toRad(0.0))),
 		1.0));
 	scene.setActiveCamera(cam);
 
@@ -190,9 +190,10 @@ void init()
 	F32 z = 2.49;
 	Array<Vec3, 4> vaseLightPos = {{Vec3(x, y, -z - 1.4), Vec3(x, y, z),
 		Vec3(-x - 2.3, y, z), Vec3(-x - 2.3, y, -z - 1.4)}};
-	for(U i = 0; i < vaseLightPos.getSize(); i++)
+	//for(U i = 0; i < vaseLightPos.getSize(); i++)
+	for(U i = 0; i < 0; i++)
 	{
-		Vec3 lightPos = vaseLightPos[i];
+		Vec4 lightPos = vaseLightPos[i].xyz0();
 
 		PointLight* point = scene.newSceneNode<PointLight>(
 			("vase_plight" + std::to_string(i)).c_str());
@@ -215,8 +216,8 @@ void init()
 		event->enableBits(Event::EF_REANIMATE);
 
 		MoveEventData moveData;
-		moveData.posMin = Vec3(-0.5, 0.0, -0.5);
-		moveData.posMax = Vec3(0.5, 0.0, 0.5);
+		moveData.m_posMin = Vec4(-0.5, 0.0, -0.5, 0);
+		moveData.m_posMax = Vec4(0.5, 0.0, 0.5, 0);
 		MoveEvent* mevent;
 		scene.getEventManager().newEvent(mevent, 0.0, 2.0, point, moveData);
 		mevent->enableBits(Event::EF_REANIMATE);
@@ -326,13 +327,13 @@ void init()
 
 	horse = scene.newSceneNode<ModelNode>("shape0", 
 		"models/collision_test/Cube_Material-material.ankimdl");
-	horse->setLocalTransform(Transform(Vec3(0.0, 0, 0), Mat3::getIdentity(),
-		1.0));
+	horse->setLocalTransform(Transform(Vec4(0.0, 0, 0, 0), 
+		Mat3x4::getIdentity(), 0.1));
 
 	horse = scene.newSceneNode<ModelNode>("shape1", 
 		"models/collision_test/Cube.001_Material_001-material.ankimdl");
-	horse->setLocalTransform(Transform(Vec3(0, 3, 0), Mat3::getIdentity(),
-		1.0));
+	horse->setLocalTransform(Transform(Vec4(0, 3, 0, 0), Mat3x4::getIdentity(),
+		0.1));
 }
 
 //==============================================================================
@@ -395,11 +396,11 @@ void mainLoopExtra()
 	}
 	if(in.getKey(KeyCode::_6))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("vase_plight0").getComponent<MoveComponent>();
+		mover = &SceneGraphSingleton::get().findSceneNode("shape0").getComponent<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_7))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("red_barrel").getComponent<MoveComponent>();
+		mover = &SceneGraphSingleton::get().findSceneNode("shape1").getComponent<MoveComponent>();
 	}
 
 	/*if(in.getKey(KeyCode::L) == 1)