Forráskód Böngészése

Merge branch 'master' of github.com:taylor001/crown

Daniele Bartolini 10 éve
szülő
commit
8e7c9d1d6b

+ 1 - 1
README.md

@@ -95,7 +95,7 @@ To run a sample on 64-bit linux debug mode:
 
 	$ ./linux-debug-64 --source-dir <full/sample/path> --bundle-dir <full/destination/path> --compile --platform linux --continue
 
-###[01.hello-world](https://github.com/taylor001/crown/tree/master/samples/01.hello-world)
+###[00-hello-world](https://github.com/taylor001/crown/tree/master/samples/00-hello-world)
 
 Engine initialization and shutdown.
 

+ 0 - 0
samples/01.hello-world/crown.config → samples/00-hello-world/boot.config


+ 0 - 0
samples/01.hello-world/boot.package → samples/00-hello-world/boot.package


+ 0 - 0
samples/01.hello-world/camera.unit → samples/00-hello-world/camera.unit


+ 0 - 0
samples/01.hello-world/global.physics_config → samples/00-hello-world/global.physics_config


+ 0 - 0
samples/01.hello-world/lua/game.lua → samples/00-hello-world/lua/game.lua


+ 4 - 0
src/config.h

@@ -69,6 +69,10 @@
 	#define CROWN_DEFAULT_CONSOLE_PORT 10001
 #endif // CROWN_DEFAULT_CONSOLE_PORT
 
+#ifndef CROWN_BOOT_CONFIG
+	#define CROWN_BOOT_CONFIG "boot"
+#endif // CROWN_BOOT_CONFIG
+
 #ifndef CROWN_DATA_DIRECTORY
 	#define CROWN_DATA_DIRECTORY "data"
 #endif // CROWN_DATA_DIRECTORY

+ 1 - 0
src/core/math/aabb.h

@@ -18,6 +18,7 @@ namespace crown
 /// @ingroup Math
 namespace aabb
 {
+	/// Resets the AABB @a b.
 	void reset(AABB& b);
 
 	/// Returns the center of the box @a b.

+ 79 - 72
src/core/math/intersection.cpp

@@ -25,26 +25,28 @@ float ray_plane_intersection(const Vector3& from, const Vector3& dir, const Plan
 
 float ray_disc_intersection(const Vector3& from, const Vector3& dir, const Vector3& center, float radius, const Vector3& normal)
 {
-	Plane p = plane::from_point_and_normal(center, normal);
+	const Plane p = plane::from_point_and_normal(center, normal);
 	const float t = ray_plane_intersection(from, dir, p);
 
-	if (t == -1.0)
-		return -1.0;
+	if (t == -1.0f)
+		return -1.0f;
 
 	const Vector3 intersection_point = from + dir * t;
-	if (distance(intersection_point, center) < radius)
+	if (distance_squared(intersection_point, center) < radius*radius)
 		return t;
 
-	return -1.0;
+	return -1.0f;
 }
 
 float ray_sphere_intersection(const Vector3& from, const Vector3& dir, const Sphere& s)
 {
 	const Vector3 v = s.c - from;
 	const float b   = dot(v, dir);
-	const float det = (s.r * s.r) - dot(v, v) + (b * b);
+	const float rr  = s.r * s.r;
+	const float bb  = b * b;
+	const float det = rr - dot(v, v) + b;
 
-	if (det < 0.0 || b < s.r)
+	if (det < 0.0f || b < s.r)
 		return -1.0f;
 
 	return b - sqrtf(det);
@@ -56,13 +58,13 @@ float ray_obb_intersection(const Vector3& from, const Vector3& dir, const Matrix
 	float tmin = 0.0f;
 	float tmax = 100000.0f;
 
-	Vector3 obb_pos = vector3(tm.t.x, tm.t.y, tm.t.z);
-	Vector3 delta = obb_pos - from;
+	const Vector3 obb_pos = vector3(tm.t.x, tm.t.y, tm.t.z);
+	const Vector3 delta = obb_pos - from;
 
 	{
 		const Vector3 xaxis = vector3(tm.x.x, tm.x.y, tm.x.z);
-		float e = dot(xaxis, delta);
-		float f = dot(dir, xaxis);
+		const float e = dot(xaxis, delta);
+		const float f = dot(dir, xaxis);
 
 		if (fabs(f) > 0.001f)
 		{
@@ -91,8 +93,8 @@ float ray_obb_intersection(const Vector3& from, const Vector3& dir, const Matrix
 
 	{
 		const Vector3 yaxis = vector3(tm.y.x, tm.y.y, tm.y.z);
-		float e = dot(yaxis, delta);
-		float f = dot(dir, yaxis);
+		const float e = dot(yaxis, delta);
+		const float f = dot(dir, yaxis);
 
 		if (fabs(f) > 0.001f){
 
@@ -118,8 +120,8 @@ float ray_obb_intersection(const Vector3& from, const Vector3& dir, const Matrix
 
 	{
 		const Vector3 zaxis = vector3(tm.z.x, tm.z.y, tm.z.z);
-		float e = dot(zaxis, delta);
-		float f = dot(dir, zaxis);
+		const float e = dot(zaxis, delta);
+		const float f = dot(dir, zaxis);
 
 		if (fabs(f) > 0.001f){
 
@@ -149,10 +151,10 @@ float ray_obb_intersection(const Vector3& from, const Vector3& dir, const Matrix
 
 bool plane_3_intersection(const Plane& p1, const Plane& p2, const Plane& p3, Vector3& ip)
 {
-	const Vector3& n1 = p1.n;
-	const Vector3& n2 = p2.n;
-	const Vector3& n3 = p3.n;
-	const float den = -dot(cross(n1, n2), n3);
+	const Vector3 n1 = p1.n;
+	const Vector3 n2 = p2.n;
+	const Vector3 n3 = p3.n;
+	const float den  = -dot(cross(n1, n2), n3);
 
 	if (fequal(den, 0.0f))
 		return false;
@@ -190,74 +192,79 @@ bool frustum_sphere_intersection(const Frustum& f, const Sphere& s)
 
 bool frustum_box_intersection(const Frustum& f, const AABB& b)
 {
-	uint8_t out;
-
-	out = 0;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 0)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 1)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 2)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 3)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 4)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 5)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 6)) < 0.0) out++;
-	if (plane::distance_to_point(f.left, aabb::vertex(b, 7)) < 0.0) out++;
-
-	// If all vertices are outside one face, then the box doesn't intersect the frustum
+	const Vector3 v0 = aabb::vertex(b, 0);
+	const Vector3 v1 = aabb::vertex(b, 1);
+	const Vector3 v2 = aabb::vertex(b, 2);
+	const Vector3 v3 = aabb::vertex(b, 3);
+	const Vector3 v4 = aabb::vertex(b, 4);
+	const Vector3 v5 = aabb::vertex(b, 5);
+	const Vector3 v6 = aabb::vertex(b, 6);
+	const Vector3 v7 = aabb::vertex(b, 7);
+
+	uint8_t out = 0;
+	out += (plane::distance_to_point(f.left, v0) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v1) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v2) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v3) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v4) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v5) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v6) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.left, v7) < 0.0f) ? 1 : 0;
 	if (out == 8) return false;
 
 	out = 0;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 0)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 1)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 2)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 3)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 4)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 5)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 6)) < 0.0) out++;
-	if (plane::distance_to_point(f.right, aabb::vertex(b, 7)) < 0.0) out++;
+	out += (plane::distance_to_point(f.right, v0) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v1) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v2) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v3) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v4) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v5) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v6) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.right, v7) < 0.0f) ? 1 : 0;
 	if (out == 8) return false;
 
 	out = 0;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 0)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 1)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 2)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 3)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 4)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 5)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 6)) < 0.0) out++;
-	if (plane::distance_to_point(f.bottom, aabb::vertex(b, 7)) < 0.0) out++;
+	out += (plane::distance_to_point(f.bottom, v0) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v1) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v2) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v3) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v4) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v5) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v6) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.bottom, v7) < 0.0f) ? 1 : 0;
 	if (out == 8) return false;
 
 	out = 0;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 0)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 1)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 2)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 3)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 4)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 5)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 6)) < 0.0) out++;
-	if (plane::distance_to_point(f.top, aabb::vertex(b, 7)) < 0.0) out++;
+	out += (plane::distance_to_point(f.top, v0) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v1) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v2) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v3) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v4) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v5) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v6) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.top, v7) < 0.0f) ? 1 : 0;
 	if (out == 8) return false;
 
 	out = 0;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 0)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 1)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 2)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 3)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 4)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 5)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 6)) < 0.0) out++;
-	if (plane::distance_to_point(f.near, aabb::vertex(b, 7)) < 0.0) out++;
+	out += (plane::distance_to_point(f.near, v0) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v1) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v2) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v3) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v4) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v5) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v6) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.near, v7) < 0.0f) ? 1 : 0;
 	if (out == 8) return false;
 
 	out = 0;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 0)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 1)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 2)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 3)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 4)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 5)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 6)) < 0.0) out++;
-	if (plane::distance_to_point(f.far, aabb::vertex(b, 7)) < 0.0) out++;
+	out += (plane::distance_to_point(f.far, v0) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v1) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v2) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v3) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v4) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v5) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v6) < 0.0f) ? 1 : 0;
+	out += (plane::distance_to_point(f.far, v7) < 0.0f) ? 1 : 0;
 	if (out == 8) return false;
 
 	// If we are here, it is because either the box intersects or it is contained in the frustum

+ 3 - 0
src/core/math/intersection.h

@@ -9,6 +9,8 @@
 
 namespace crown
 {
+/// @addtogroup Math
+/// @{
 
 /// Returns the distance along ray (from, dir) to intersection point with plane @a p
 /// or -1.0 if no intersection.
@@ -30,4 +32,5 @@ bool plane_3_intersection(const Plane& p1, const Plane& p2, const Plane& p3, Vec
 bool frustum_sphere_intersection(const Frustum& f, const Sphere& s);
 bool frustum_box_intersection(const Frustum& f, const AABB& b);
 
+/// @}
 } // namespace crown

+ 10 - 10
src/core/math/matrix3x3.h

@@ -129,11 +129,11 @@ inline Matrix3x3 operator/(Matrix3x3 a, float k)
 /// Multiplies the matrix @a a by the vector @a v and returns the result.
 inline Vector3 operator*(const Vector3& v, const Matrix3x3& a)
 {
-	Vector3 res;
-	res.x = v.x*a.x.x + v.y*a.y.x + v.z*a.z.x;
-	res.y = v.x*a.x.y + v.y*a.y.y + v.z*a.z.y;
-	res.z = v.x*a.x.z + v.y*a.y.z + v.z*a.z.z;
-	return res;
+	Vector3 r;
+	r.x = v.x*a.x.x + v.y*a.y.x + v.z*a.z.x;
+	r.y = v.x*a.x.y + v.y*a.y.y + v.z*a.z.y;
+	r.z = v.x*a.x.z + v.y*a.y.z + v.z*a.z.z;
+	return r;
 }
 
 /// Multiplies the matrix @a a by @a b and returns the result. (i.e. transforms first by @a a then by @a b)
@@ -238,11 +238,11 @@ inline Vector3 scale(const Matrix3x3& m)
 	const float sx = length(m.x);
 	const float sy = length(m.y);
 	const float sz = length(m.z);
-	Vector3 res;
-	res.x = sx;
-	res.y = sy;
-	res.z = sz;
-	return res;
+	Vector3 v;
+	v.x = sx;
+	v.y = sy;
+	v.z = sz;
+	return v;
 }
 
 /// Sets the scale of the matrix @a m.

+ 41 - 20
src/core/math/matrix4x4.h

@@ -15,10 +15,11 @@ namespace crown
 /// @addtogroup Math
 /// @{
 
-inline Matrix4x4 matrix4x4(float r1c1, float r2c1, float r3c1, float r4c1,
-	float r1c2, float r2c2, float r3c2, float r4c2,
-	float r1c3, float r2c3, float r3c3, float r4c3,
-	float r1c4, float r2c4, float r3c4, float r4c4)
+inline Matrix4x4 matrix4x4(float r1c1, float r2c1, float r3c1, float r4c1
+	, float r1c2, float r2c2, float r3c2, float r4c2
+	, float r1c3, float r2c3, float r3c3, float r4c3
+	, float r1c4, float r2c4, float r3c4, float r4c4
+	)
 {
 	Matrix4x4 m;
 	m.x.x = r1c1;
@@ -246,22 +247,22 @@ inline Matrix4x4 operator/(Matrix4x4 a, float k)
 /// Multiplies the matrix @a a by the vector @a v and returns the result.
 inline Vector3 operator*(const Vector3& v, const Matrix4x4& a)
 {
-	Vector3 res;
-	res.x = v.x*a.x.x + v.y*a.y.x + v.z*a.z.x + a.t.x;
-	res.y = v.x*a.x.y + v.y*a.y.y + v.z*a.z.y + a.t.y;
-	res.z = v.x*a.x.z + v.y*a.y.z + v.z*a.z.z + a.t.z;
-	return res;
+	Vector3 r;
+	r.x = v.x*a.x.x + v.y*a.y.x + v.z*a.z.x + a.t.x;
+	r.y = v.x*a.x.y + v.y*a.y.y + v.z*a.z.y + a.t.y;
+	r.z = v.x*a.x.z + v.y*a.y.z + v.z*a.z.z + a.t.z;
+	return r;
 }
 
 /// Multiplies the matrix @a by the vector @a v and returns the result.
 inline Vector4 operator*(const Vector4& v, const Matrix4x4& a)
 {
-	Vector4 res;
-	res.x = v.x*a.x.x + v.y*a.y.x + v.z*a.z.x + v.w*a.t.x;
-	res.y = v.x*a.x.y + v.y*a.y.y + v.z*a.z.y + v.w*a.t.y;
-	res.z = v.x*a.x.z + v.y*a.y.z + v.z*a.z.z + v.w*a.t.z;
-	res.w = v.x*a.x.w + v.y*a.y.w + v.z*a.z.w + v.w*a.t.w;
-	return res;
+	Vector4 r;
+	r.x = v.x*a.x.x + v.y*a.y.x + v.z*a.z.x + v.w*a.t.x;
+	r.y = v.x*a.x.y + v.y*a.y.y + v.z*a.z.y + v.w*a.t.y;
+	r.z = v.x*a.x.z + v.y*a.y.z + v.z*a.z.z + v.w*a.t.z;
+	r.w = v.x*a.x.w + v.y*a.y.w + v.z*a.z.w + v.w*a.t.w;
+	return r;
 }
 
 /// Multiplies the matrix @a a by @a b and returns the result. (i.e. transforms first by @a a then by @a b)
@@ -506,19 +507,31 @@ inline void set_identity(Matrix4x4& m)
 /// Returns the x asis of the matrix @a m.
 inline Vector3 x(const Matrix4x4& m)
 {
-	return vector3(m.x.x, m.x.y, m.x.z);
+	Vector3 v;
+	v.x = m.x.x;
+	v.y = m.x.y;
+	v.z = m.x.z;
+	return v;
 }
 
 /// Returns the y asis of the matrix @a m.
 inline Vector3 y(const Matrix4x4& m)
 {
-	return vector3(m.y.x, m.y.y, m.y.z);
+	Vector3 v;
+	v.x = m.y.x;
+	v.y = m.y.y;
+	v.z = m.y.z;
+	return v;
 }
 
 /// Returns the z asis of the matrix @a m.
 inline Vector3 z(const Matrix4x4& m)
 {
-	return vector3(m.z.x, m.z.y, m.z.z);
+	Vector3 v;
+	v.x = m.z.x;
+	v.y = m.z.y;
+	v.z = m.z.z;
+	return v;
 }
 
 /// Sets the x axis of the matrix @a m.
@@ -548,7 +561,11 @@ inline void set_z(Matrix4x4& m, const Vector3& z)
 /// Returns the translation portion of the matrix @a m.
 inline Vector3 translation(const Matrix4x4& m)
 {
-	return vector3(m.t.x, m.t.y, m.t.z);
+	Vector3 v;
+	v.x = m.t.x;
+	v.y = m.t.y;
+	v.z = m.t.z;
+	return v;
 }
 
 /// Sets the translation portion of the matrix @a m.
@@ -611,7 +628,11 @@ inline Vector3 scale(const Matrix4x4& m)
 	const float sx = length(to_vector3(m.x));
 	const float sy = length(to_vector3(m.y));
 	const float sz = length(to_vector3(m.z));
-	return vector3(sx, sy, sz);
+	Vector3 v;
+	v.x = sx;
+	v.y = sy;
+	v.z = sz;
+	return v;
 }
 
 /// Sets the scale of the matrix @æ m.

+ 31 - 28
src/core/math/quaternion.h

@@ -26,11 +26,14 @@ inline Quaternion quaternion(float x, float y, float z, float w)
 
 inline Quaternion quaternion(const Vector3& axis, float angle)
 {
+	const float ha = angle * 0.5f;
+	const float sa = sinf(ha);
+	const float ca = cosf(ha);
 	Quaternion q;
-	q.x = axis.x * sinf(angle * 0.5f);
-	q.y = axis.y * sinf(angle * 0.5f);
-	q.z = axis.z * sinf(angle * 0.5f);
-	q.w = cosf(angle * 0.5f);
+	q.x = axis.x * sa;
+	q.y = axis.y * sa;
+	q.z = axis.z * sa;
+	q.w = ca;
 	return q;
 }
 
@@ -52,12 +55,12 @@ inline Quaternion& operator*=(Quaternion& a, const Quaternion& b)
 /// Negates the quaternion @a q and returns the result.
 inline Quaternion operator-(const Quaternion& q)
 {
-	Quaternion res;
-	res.x = -q.x;
-	res.y = -q.y;
-	res.z = -q.z;
-	res.w = -q.w;
-	return res;
+	Quaternion r;
+	r.x = -q.x;
+	r.y = -q.y;
+	r.z = -q.z;
+	r.w = -q.w;
+	return r;
 }
 
 /// Multiplies the quaternions @a a and @a b. (i.e. rotates first by @a a then by @a b).
@@ -70,12 +73,12 @@ inline Quaternion operator*(Quaternion a, const Quaternion& b)
 /// Multiplies the quaternion @a a by the scalar @a k.
 inline Quaternion operator*(const Quaternion& q, float k)
 {
-	Quaternion res;
-	res.x = q.x * k;
-	res.y = q.y * k;
-	res.z = q.z * k;
-	res.w = q.w * k;
-	return res;
+	Quaternion r;
+	r.x = q.x * k;
+	r.y = q.y * k;
+	r.z = q.z * k;
+	r.w = q.w * k;
+	return r;
 }
 
 /// Returns the dot product between quaternions @a a and @a b.
@@ -105,12 +108,12 @@ inline Quaternion& normalize(Quaternion& q)
 /// Returns the conjugate of quaternion @a q.
 inline Quaternion conjugate(const Quaternion& q)
 {
-	Quaternion res;
-	res.x = -q.x;
-	res.y = -q.y;
-	res.z = -q.z;
-	res.w = q.w;
-	return res;
+	Quaternion r;
+	r.x = -q.x;
+	r.y = -q.y;
+	r.z = -q.z;
+	r.w = q.w;
+	return r;
 }
 
 /// Returns the inverse of quaternion @a q.
@@ -130,12 +133,12 @@ inline Quaternion power(const Quaternion& q, float exp)
 		const float new_alpha = alpha * exp;
 		const float mult = sinf(new_alpha) / sinf(alpha);
 
-		Quaternion tmp;
-		tmp.w = cosf(new_alpha);
-		tmp.x = q.x * mult;
-		tmp.y = q.y * mult;
-		tmp.z = q.z * mult;
-		return tmp;
+		Quaternion r;
+		r.w = cosf(new_alpha);
+		r.x = q.x * mult;
+		r.y = q.y * mult;
+		r.z = q.z * mult;
+		return r;
 	}
 
 	return q;

+ 6 - 0
src/core/math/sphere.h

@@ -11,10 +11,16 @@
 
 namespace crown
 {
+
+/// Functions to manipulate Sphere.
+///
+/// @ingroup Math
 namespace sphere
 {
+	/// Resets the sphere @a s.
 	void reset(Sphere& s);
 
+	/// Returns the volume of the sphere @a s.
 	float volume(const Sphere& s);
 
 	/// Adds @a num @a points to the sphere @a s, expanding its bounds if necessary.

+ 6 - 3
src/core/memory/linear_allocator.cpp

@@ -31,18 +31,21 @@ LinearAllocator::~LinearAllocator()
 	if (_backing)
 		_backing->deallocate(_physical_start);
 
-	CE_ASSERT(_offset == 0, "Memory leak of %d bytes, maybe you forgot to call clear()?", _offset);
+	CE_ASSERT(_offset == 0
+		, "Memory leak of %d bytes, maybe you forgot to call clear()?"
+		, _offset
+		);
 }
 
 void* LinearAllocator::allocate(uint32_t size, uint32_t align)
 {
 	const uint32_t actual_size = size + align;
 
-	// Memory exhausted
+	// Out of memory
 	if (_offset + actual_size > _total_size)
 		return NULL;
 
-	void* user_ptr = memory::align_top((char*) _physical_start + _offset, align);
+	void* user_ptr = memory::align_top((char*)_physical_start + _offset, align);
 
 	_offset += actual_size;
 

+ 5 - 3
src/core/memory/linear_allocator.h

@@ -10,15 +10,18 @@
 namespace crown
 {
 
-/// Allocates memory linearly from a predefined chunk
-/// and frees all the allocations with a single call to clear()
+/// Allocates memory linearly from a fixed chunk of memory
+/// and frees all the allocations with a single call to clear().
 ///
 /// @ingroup Memory
 class LinearAllocator : public Allocator
 {
 public:
 
+	/// Allocates @a size bytes from @a backing.
 	LinearAllocator(Allocator& backing, uint32_t size);
+
+	/// Uses @a size bytes of memory from @a start.
 	LinearAllocator(void* start, uint32_t size);
 	~LinearAllocator();
 
@@ -44,7 +47,6 @@ public:
 private:
 
 	Allocator* _backing;
-
 	void* _physical_start;
 	uint32_t _total_size;
 	uint32_t _offset;

+ 167 - 25
src/core/memory/memory.cpp

@@ -36,6 +36,40 @@ namespace crown
 {
 namespace memory
 {
+	// Header stored at the beginning of a memory allocation to indicate the
+	// size of the allocated data.
+	struct Header {
+		uint32_t size;
+	};
+
+	// If we need to align the memory allocation we pad the header with this
+	// value after storing the size. That way we can
+	const uint32_t HEADER_PAD_VALUE = 0xffffffffu;
+
+	// Given a pointer to the header, returns a pointer to the data that follows it.
+	inline void *data_pointer(Header *header, uint32_t align) {
+		void *p = header + 1;
+		return memory::align_top(p, align);
+	}
+
+	// Given a pointer to the data, returns a pointer to the header before it.
+	inline Header *header(const void *data)
+	{
+		uint32_t *p = (uint32_t *)data;
+		while (p[-1] == HEADER_PAD_VALUE)
+			--p;
+		return (Header *)p - 1;
+	}
+
+	// Stores the size in the header and pads with HEADER_PAD_VALUE up to the
+	// data pointer.
+	inline void fill(Header *header, void *data, uint32_t size)
+	{
+		header->size = size;
+		uint32_t *p = (uint32_t *)(header + 1);
+		while (p < data)
+			*p++ = HEADER_PAD_VALUE;
+	}
 	/// Allocator based on C malloc().
 	class HeapAllocator : public Allocator
 	{
@@ -115,40 +149,18 @@ namespace memory
 
 	private:
 
-		// Holds the number of bytes of an allocation
-		struct Header
-		{
-			uint32_t size;
-		};
-
 		uint32_t actual_allocation_size(uint32_t size, uint32_t align)
 		{
 			return size + align + sizeof(Header);
 		}
 
-		Header* header(const void* data)
-		{
-			const uint32_t* ptr = (uint32_t*)data;
-			ptr--;
-
-			while (*ptr == memory::PADDING_VALUE)
-				ptr--;
-
-			return (Header*)ptr;
-		}
-
-		void* data(Header* header, uint32_t align)
-		{
-			return memory::align_top(header + 1, align);
-		}
-
 		void pad(Header* header, void* data)
 		{
 			uint32_t* p = (uint32_t*)(header + 1);
 
 			while (p != data)
 			{
-				*p = memory::PADDING_VALUE;
+				*p = HEADER_PAD_VALUE;
 				p++;
 			}
 		}
@@ -159,22 +171,147 @@ namespace memory
 		uint32_t _allocated_size;
 		uint32_t _allocation_count;
 	};
+
+	// Copyright (C) 2012 Bitsquid AB
+	// License: https://bitbucket.org/bitsquid/foundation/src/default/LICENCSE
+	//
+	// An allocator used to allocate temporary "scratch" memory. The allocator
+	// uses a fixed size ring buffer to services the requests.
+	//
+	// Memory is always always allocated linearly. An allocation pointer is
+	// advanced through the buffer as memory is allocated and wraps around at
+	// the end of the buffer. Similarly, a free pointer is advanced as memory
+	// is freed.
+	//
+	// It is important that the scratch allocator is only used for short-lived
+	// memory allocations. A long lived allocator will lock the "free" pointer
+	// and prevent the "allocate" pointer from proceeding past it, which means
+	// the ring buffer can't be used.
+	//
+	// If the ring buffer is exhausted, the scratch allocator will use its backing
+	// allocator to allocate memory instead.
+	class ScratchAllocator : public Allocator
+	{
+		Allocator &_backing;
+
+		// Start and end of the ring buffer.
+		char *_begin, *_end;
+
+		// Pointers to where to allocate memory and where to free memory.
+		char *_allocate, *_free;
+
+	public:
+		/// Creates a ScratchAllocator. The allocator will use the backing
+		/// allocator to create the ring buffer and to service any requests
+		/// that don't fit in the ring buffer.
+		///
+		/// size specifies the size of the ring buffer.
+		ScratchAllocator(Allocator &backing, uint32_t size) : _backing(backing) {
+			_begin = (char *)_backing.allocate(size);
+			_end = _begin + size;
+			_allocate = _begin;
+			_free = _begin;
+		}
+
+		~ScratchAllocator() {
+			CE_ASSERT(_free == _allocate, "Memory leak");
+			_backing.deallocate(_begin);
+		}
+
+		bool in_use(void *p)
+		{
+			if (_free == _allocate)
+				return false;
+			if (_allocate > _free)
+				return p >= _free && p < _allocate;
+			return p >= _free || p < _allocate;
+		}
+
+		virtual void *allocate(uint32_t size, uint32_t align) {
+			CE_ASSERT(align % 4 == 0, "Must be 4-byte aligned");
+			size = ((size + 3)/4)*4;
+
+			char *p = _allocate;
+			Header *h = (Header *)p;
+			char *data = (char *)data_pointer(h, align);
+			p = data + size;
+
+			// Reached the end of the buffer, wrap around to the beginning.
+			if (p > _end) {
+				h->size = (_end - (char *)h) | 0x80000000u;
+
+				p = _begin;
+				h = (Header *)p;
+				data = (char *)data_pointer(h, align);
+				p = data + size;
+			}
+
+			// If the buffer is exhausted use the backing allocator instead.
+			if (in_use(p))
+				return _backing.allocate(size, align);
+
+			fill(h, data, p - (char *)h);
+			_allocate = p;
+			return data;
+		}
+
+		virtual void deallocate(void *p) {
+			if (!p)
+				return;
+
+			if (p < _begin || p >= _end) {
+				_backing.deallocate(p);
+				return;
+			}
+
+			// Mark this slot as free
+			Header *h = header(p);
+			CE_ASSERT((h->size & 0x80000000u) == 0, "Not free");
+			h->size = h->size | 0x80000000u;
+
+			// Advance the free pointer past all free slots.
+			while (_free != _allocate) {
+				Header *h = (Header *)_free;
+				if ((h->size & 0x80000000u) == 0)
+					break;
+
+				_free += h->size & 0x7fffffffu;
+				if (_free == _end)
+					_free = _begin;
+			}
+		}
+
+		virtual uint32_t allocated_size(const void *p) {
+			Header *h = header(p);
+			return h->size - ((char *)p - (char *)h);
+		}
+
+		virtual uint32_t total_allocated() {
+			return _end - _begin;
+		}
+	};
 } // namespace memory
 
 namespace memory_globals
 {
 	using namespace memory;
-	// Create default allocators
-	char _buffer[1024];
+
+	static const uint32_t SIZE = sizeof(HeapAllocator)
+		+ sizeof(ScratchAllocator)
+		;
+	char _buffer[SIZE];
 	HeapAllocator* _default_allocator = NULL;
+	ScratchAllocator* _default_scratch_allocator = NULL;
 
 	void init()
 	{
 		_default_allocator = new (_buffer) HeapAllocator();
+		_default_scratch_allocator = new (_buffer + sizeof(HeapAllocator)) ScratchAllocator(*_default_allocator, 1024*1024);
 	}
 
 	void shutdown()
 	{
+		_default_scratch_allocator->~ScratchAllocator();
 		_default_allocator->~HeapAllocator();
 	}
 } // namespace memory_globals
@@ -184,4 +321,9 @@ Allocator& default_allocator()
 	return *memory_globals::_default_allocator;
 }
 
+Allocator& default_scratch_allocator()
+{
+	return *memory_globals::_default_scratch_allocator;
+}
+
 } // namespace crown

+ 1 - 3
src/core/memory/memory.h

@@ -15,13 +15,11 @@ namespace crown
 {
 
 Allocator& default_allocator();
+Allocator& default_scratch_allocator();
 
 /// @defgroup Memory Memory
 namespace memory
 {
-	/// Value used to fill unused memory
-	const uint32_t PADDING_VALUE = 0xffffffffu;
-
 	/// Returns the pointer @a p aligned to the desired @a align byte
 	inline void* align_top(void* p, uint32_t align)
 	{

+ 1 - 1
src/core/memory/temp_allocator.h

@@ -29,7 +29,7 @@ public:
 
 	/// Uses the @a backing allocator when internal memory is exahusted
 	/// or the allocation size exceeds the remaining storage.
-	TempAllocator(Allocator& backing = default_allocator());
+	TempAllocator(Allocator& backing = default_scratch_allocator());
 	~TempAllocator();
 
 	/// @copydoc Allocator::allocate()

+ 1 - 1
src/device.cpp

@@ -426,7 +426,7 @@ void Device::read_config()
 		project_path += '/';
 	}
 
-	project_path += "crown";
+	project_path += CROWN_BOOT_CONFIG;
 
 	const StringId64 config_name(project_path.c_str());