Browse Source

Add love.graphics.transformPoint and love.graphics.inverseTransformPoint.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
4c122e6581

+ 168 - 33
src/common/Matrix.cpp

@@ -27,6 +27,43 @@
 namespace love
 {
 
+//                 | e0 e4 e8  e12 |
+//                 | e1 e5 e9  e13 |
+//                 | e2 e6 e10 e14 |
+//                 | e3 e7 e11 e15 |
+// | e0 e4 e8  e12 |
+// | e1 e5 e9  e13 |
+// | e2 e6 e10 e14 |
+// | e3 e7 e11 e15 |
+
+void Matrix4::multiply(const Matrix4 &a, const Matrix4 &b, float t[16])
+{
+	t[0]  = (a.e[0]*b.e[0])  + (a.e[4]*b.e[1])  + (a.e[8]*b.e[2])  + (a.e[12]*b.e[3]);
+	t[4]  = (a.e[0]*b.e[4])  + (a.e[4]*b.e[5])  + (a.e[8]*b.e[6])  + (a.e[12]*b.e[7]);
+	t[8]  = (a.e[0]*b.e[8])  + (a.e[4]*b.e[9])  + (a.e[8]*b.e[10]) + (a.e[12]*b.e[11]);
+	t[12] = (a.e[0]*b.e[12]) + (a.e[4]*b.e[13]) + (a.e[8]*b.e[14]) + (a.e[12]*b.e[15]);
+
+	t[1]  = (a.e[1]*b.e[0])  + (a.e[5]*b.e[1])  + (a.e[9]*b.e[2])  + (a.e[13]*b.e[3]);
+	t[5]  = (a.e[1]*b.e[4])  + (a.e[5]*b.e[5])  + (a.e[9]*b.e[6])  + (a.e[13]*b.e[7]);
+	t[9]  = (a.e[1]*b.e[8])  + (a.e[5]*b.e[9])  + (a.e[9]*b.e[10]) + (a.e[13]*b.e[11]);
+	t[13] = (a.e[1]*b.e[12]) + (a.e[5]*b.e[13]) + (a.e[9]*b.e[14]) + (a.e[13]*b.e[15]);
+
+	t[2]  = (a.e[2]*b.e[0])  + (a.e[6]*b.e[1])  + (a.e[10]*b.e[2])  + (a.e[14]*b.e[3]);
+	t[6]  = (a.e[2]*b.e[4])  + (a.e[6]*b.e[5])  + (a.e[10]*b.e[6])  + (a.e[14]*b.e[7]);
+	t[10] = (a.e[2]*b.e[8])  + (a.e[6]*b.e[9])  + (a.e[10]*b.e[10]) + (a.e[14]*b.e[11]);
+	t[14] = (a.e[2]*b.e[12]) + (a.e[6]*b.e[13]) + (a.e[10]*b.e[14]) + (a.e[14]*b.e[15]);
+
+	t[3]  = (a.e[3]*b.e[0])  + (a.e[7]*b.e[1])  + (a.e[11]*b.e[2])  + (a.e[15]*b.e[3]);
+	t[7]  = (a.e[3]*b.e[4])  + (a.e[7]*b.e[5])  + (a.e[11]*b.e[6])  + (a.e[15]*b.e[7]);
+	t[11] = (a.e[3]*b.e[8])  + (a.e[7]*b.e[9])  + (a.e[11]*b.e[10]) + (a.e[15]*b.e[11]);
+	t[15] = (a.e[3]*b.e[12]) + (a.e[7]*b.e[13]) + (a.e[11]*b.e[14]) + (a.e[15]*b.e[15]);
+}
+
+void Matrix4::multiply(const Matrix4 &a, const Matrix4 &b, Matrix4 &t)
+{
+	multiply(a, b, t.e);
+}
+
 // | e0 e4 e8  e12 |
 // | e1 e5 e9  e13 |
 // | e2 e6 e10 e14 |
@@ -46,46 +83,18 @@ Matrix4::~Matrix4()
 {
 }
 
-//                 | e0 e4 e8  e12 |
-//                 | e1 e5 e9  e13 |
-//                 | e2 e6 e10 e14 |
-//                 | e3 e7 e11 e15 |
-// | e0 e4 e8  e12 |
-// | e1 e5 e9  e13 |
-// | e2 e6 e10 e14 |
-// | e3 e7 e11 e15 |
-
 Matrix4 Matrix4::operator * (const Matrix4 &m) const
 {
 	Matrix4 t;
-
-	t.e[0] = (e[0]*m.e[0]) + (e[4]*m.e[1]) + (e[8]*m.e[2]) + (e[12]*m.e[3]);
-	t.e[4] = (e[0]*m.e[4]) + (e[4]*m.e[5]) + (e[8]*m.e[6]) + (e[12]*m.e[7]);
-	t.e[8] = (e[0]*m.e[8]) + (e[4]*m.e[9]) + (e[8]*m.e[10]) + (e[12]*m.e[11]);
-	t.e[12] = (e[0]*m.e[12]) + (e[4]*m.e[13]) + (e[8]*m.e[14]) + (e[12]*m.e[15]);
-
-	t.e[1] = (e[1]*m.e[0]) + (e[5]*m.e[1]) + (e[9]*m.e[2]) + (e[13]*m.e[3]);
-	t.e[5] = (e[1]*m.e[4]) + (e[5]*m.e[5]) + (e[9]*m.e[6]) + (e[13]*m.e[7]);
-	t.e[9] = (e[1]*m.e[8]) + (e[5]*m.e[9]) + (e[9]*m.e[10]) + (e[13]*m.e[11]);
-	t.e[13] = (e[1]*m.e[12]) + (e[5]*m.e[13]) + (e[9]*m.e[14]) + (e[13]*m.e[15]);
-
-	t.e[2] = (e[2]*m.e[0]) + (e[6]*m.e[1]) + (e[10]*m.e[2]) + (e[14]*m.e[3]);
-	t.e[6] = (e[2]*m.e[4]) + (e[6]*m.e[5]) + (e[10]*m.e[6]) + (e[14]*m.e[7]);
-	t.e[10] = (e[2]*m.e[8]) + (e[6]*m.e[9]) + (e[10]*m.e[10]) + (e[14]*m.e[11]);
-	t.e[14] = (e[2]*m.e[12]) + (e[6]*m.e[13]) + (e[10]*m.e[14]) + (e[14]*m.e[15]);
-
-	t.e[3] = (e[3]*m.e[0]) + (e[7]*m.e[1]) + (e[11]*m.e[2]) + (e[15]*m.e[3]);
-	t.e[7] = (e[3]*m.e[4]) + (e[7]*m.e[5]) + (e[11]*m.e[6]) + (e[15]*m.e[7]);
-	t.e[11] = (e[3]*m.e[8]) + (e[7]*m.e[9]) + (e[11]*m.e[10]) + (e[15]*m.e[11]);
-	t.e[15] = (e[3]*m.e[12]) + (e[7]*m.e[13]) + (e[11]*m.e[14]) + (e[15]*m.e[15]);
-
+	multiply(*this, m, t);
 	return t;
 }
 
 void Matrix4::operator *= (const Matrix4 &m)
 {
-	Matrix4 t = (*this) * m;
-	memcpy(this->e, t.e, sizeof(float)*16);
+	float t[16];
+	multiply(*this, m, t);
+	memcpy(this->e, t, sizeof(float)*16);
 }
 
 const float *Matrix4::getElements() const
@@ -96,7 +105,7 @@ const float *Matrix4::getElements() const
 void Matrix4::setIdentity()
 {
 	memset(e, 0, sizeof(float)*16);
-	e[0] = e[5] = e[10] = e[15] = 1;
+	e[15] = e[10] = e[5] = e[0] = 1;
 }
 
 void Matrix4::setTranslation(float x, float y)
@@ -177,6 +186,132 @@ void Matrix4::shear(float kx, float ky)
 	this->operator *=(t);
 }
 
+Matrix4 Matrix4::inverse() const
+{
+	Matrix4 inv;
+
+	inv.e[0] = e[5]  * e[10] * e[15] -
+	           e[5]  * e[11] * e[14] -
+	           e[9]  * e[6]  * e[15] +
+	           e[9]  * e[7]  * e[14] +
+	           e[13] * e[6]  * e[11] -
+	           e[13] * e[7]  * e[10];
+
+	inv.e[4] = -e[4]  * e[10] * e[15] +
+	            e[4]  * e[11] * e[14] +
+	            e[8]  * e[6]  * e[15] -
+	            e[8]  * e[7]  * e[14] -
+	            e[12] * e[6]  * e[11] +
+	            e[12] * e[7]  * e[10];
+
+	inv.e[8] = e[4]  * e[9]  * e[15] -
+	           e[4]  * e[11] * e[13] -
+	           e[8]  * e[5]  * e[15] +
+	           e[8]  * e[7]  * e[13] +
+	           e[12] * e[5]  * e[11] -
+	           e[12] * e[7]  * e[9];
+
+	inv.e[12] = -e[4]  * e[9]  * e[14] +
+	             e[4]  * e[10] * e[13] +
+	             e[8]  * e[5]  * e[14] -
+	             e[8]  * e[6]  * e[13] -
+	             e[12] * e[5]  * e[10] +
+	             e[12] * e[6]  * e[9];
+
+	inv.e[1] = -e[1]  * e[10] * e[15] +
+	            e[1]  * e[11] * e[14] +
+	            e[9]  * e[2]  * e[15] -
+	            e[9]  * e[3]  * e[14] -
+	            e[13] * e[2]  * e[11] +
+	            e[13] * e[3]  * e[10];
+
+	inv.e[5] = e[0]  * e[10] * e[15] -
+	           e[0]  * e[11] * e[14] -
+	           e[8]  * e[2]  * e[15] +
+	           e[8]  * e[3]  * e[14] +
+	           e[12] * e[2]  * e[11] -
+	           e[12] * e[3]  * e[10];
+
+	inv.e[9] = -e[0]  * e[9]  * e[15] +
+	            e[0]  * e[11] * e[13] +
+	            e[8]  * e[1]  * e[15] -
+	            e[8]  * e[3]  * e[13] -
+	            e[12] * e[1]  * e[11] +
+	            e[12] * e[3]  * e[9];
+
+	inv.e[13] = e[0]  * e[9]  * e[14] -
+	            e[0]  * e[10] * e[13] -
+	            e[8]  * e[1]  * e[14] +
+	            e[8]  * e[2]  * e[13] +
+	            e[12] * e[1]  * e[10] -
+	            e[12] * e[2]  * e[9];
+
+	inv.e[2] = e[1]  * e[6] * e[15] -
+	           e[1]  * e[7] * e[14] -
+	           e[5]  * e[2] * e[15] +
+	           e[5]  * e[3] * e[14] +
+	           e[13] * e[2] * e[7] -
+	           e[13] * e[3] * e[6];
+
+	inv.e[6] = -e[0]  * e[6] * e[15] +
+	            e[0]  * e[7] * e[14] +
+	            e[4]  * e[2] * e[15] -
+	            e[4]  * e[3] * e[14] -
+	            e[12] * e[2] * e[7] +
+	            e[12] * e[3] * e[6];
+
+	inv.e[10] = e[0]  * e[5] * e[15] -
+	            e[0]  * e[7] * e[13] -
+	            e[4]  * e[1] * e[15] +
+	            e[4]  * e[3] * e[13] +
+	            e[12] * e[1] * e[7] -
+	            e[12] * e[3] * e[5];
+
+	inv.e[14] = -e[0]  * e[5] * e[14] +
+	             e[0]  * e[6] * e[13] +
+	             e[4]  * e[1] * e[14] -
+	             e[4]  * e[2] * e[13] -
+	             e[12] * e[1] * e[6] +
+	             e[12] * e[2] * e[5];
+
+	inv.e[3] = -e[1] * e[6] * e[11] +
+	            e[1] * e[7] * e[10] +
+	            e[5] * e[2] * e[11] -
+	            e[5] * e[3] * e[10] -
+	            e[9] * e[2] * e[7] +
+	            e[9] * e[3] * e[6];
+
+	inv.e[7] = e[0] * e[6] * e[11] -
+	           e[0] * e[7] * e[10] -
+	           e[4] * e[2] * e[11] +
+	           e[4] * e[3] * e[10] +
+	           e[8] * e[2] * e[7] -
+	           e[8] * e[3] * e[6];
+
+	inv.e[11] = -e[0] * e[5] * e[11] +
+	             e[0] * e[7] * e[9] +
+	             e[4] * e[1] * e[11] -
+	             e[4] * e[3] * e[9] -
+	             e[8] * e[1] * e[7] +
+	             e[8] * e[3] * e[5];
+
+	inv.e[15] = e[0] * e[5] * e[10] -
+	            e[0] * e[6] * e[9] -
+	            e[4] * e[1] * e[10] +
+	            e[4] * e[2] * e[9] +
+	            e[8] * e[1] * e[6] -
+	            e[8] * e[2] * e[5];
+
+	float det = e[0] * inv.e[0] + e[1] * inv.e[4] + e[2] * inv.e[8] + e[3] * inv.e[12];
+
+	float invdet = 1.0f / det;
+
+	for (int i = 0; i < 16; i++)
+		inv.e[i] *= invdet;
+
+	return inv;
+}
+
 Matrix4 Matrix4::ortho(float left, float right, float bottom, float top)
 {
 	Matrix4 m;

+ 8 - 0
src/common/Matrix.h

@@ -34,8 +34,14 @@ namespace love
  **/
 class Matrix4
 {
+private:
+
+	static void multiply(const Matrix4 &a, const Matrix4 &b, float t[16]);
+
 public:
 
+	static void multiply(const Matrix4 &a, const Matrix4 &b, Matrix4 &result);
+
 	/**
 	 * Creates a new identity matrix.
 	 **/
@@ -156,6 +162,8 @@ public:
 	template <typename V>
 	void transform(V *dst, const V *src, int size) const;
 
+	Matrix4 inverse() const;
+
 	/**
 	 * Creates a new orthographic projection matrix with depth in the range of
 	 * [-1, 1].

+ 16 - 0
src/modules/graphics/opengl/Graphics.cpp

@@ -1789,6 +1789,22 @@ void Graphics::origin()
 	pixelSizeStack.back() = 1;
 }
 
+Vector Graphics::transformPoint(Vector point)
+{
+	Vector p;
+	gl.getTransform().transform(&p, &point, 1);
+	return p;
+}
+
+Vector Graphics::inverseTransformPoint(Vector point)
+{
+	Vector p;
+	// TODO: We should probably cache the inverse transform so we don't have to
+	// re-calculate it every time this is called.
+	gl.getTransform().inverse().transform(&p, &point, 1);
+	return p;
+}
+
 } // opengl
 } // graphics
 } // love

+ 2 - 0
src/modules/graphics/opengl/Graphics.h

@@ -459,6 +459,8 @@ public:
 	void translate(float x, float y);
 	void shear(float kx, float ky);
 	void origin();
+	Vector transformPoint(Vector point);
+	Vector inverseTransformPoint(Vector point);
 
 private:
 

+ 24 - 0
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -1960,6 +1960,28 @@ int w_origin(lua_State * /*L*/)
 	return 0;
 }
 
+int w_transformPoint(lua_State *L)
+{
+	Vector p;
+	p.x = (float) luaL_checknumber(L, 1);
+	p.y = (float) luaL_checknumber(L, 2);
+	p = instance()->transformPoint(p);
+	lua_pushnumber(L, p.x);
+	lua_pushnumber(L, p.y);
+	return 2;
+}
+
+int w_inverseTransformPoint(lua_State *L)
+{
+	Vector p;
+	p.x = (float) luaL_checknumber(L, 1);
+	p.y = (float) luaL_checknumber(L, 2);
+	p = instance()->inverseTransformPoint(p);
+	lua_pushnumber(L, p.x);
+	lua_pushnumber(L, p.y);
+	return 2;
+}
+
 
 // List of functions to wrap.
 static const luaL_Reg functions[] =
@@ -2060,6 +2082,8 @@ static const luaL_Reg functions[] =
 	{ "translate", w_translate },
 	{ "shear", w_shear },
 	{ "origin", w_origin },
+	{ "transformPoint", w_transformPoint },
+	{ "inverseTransformPoint", w_inverseTransformPoint },
 
 	{ 0, 0 }
 };