Bläddra i källkod

Merge pull request #127 from mcclure/geometry

Improvements for Matrix4, Quaternion, ScreenMesh
Ivan Safrin 13 år sedan
förälder
incheckning
1c7faf72ea

+ 24 - 2
Core/Contents/Include/PolyMatrix4.h

@@ -242,7 +242,17 @@ namespace Polycode {
 				*az = fabs(angle_z);
 
 			}
-
+		
+			/**
+			 * Returns the transpose of the matrix.
+			 */
+			inline Matrix4 transpose() const {
+				return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
+							   m[0][1], m[1][1], m[2][1], m[3][1],
+							   m[0][2], m[1][2], m[2][2], m[3][2],
+							   m[0][3], m[1][3], m[2][3], m[3][3]);
+			}
+			
 			/**
 			* Returns the inverse of the matrix.
 			*/
@@ -252,7 +262,19 @@ namespace Polycode {
 			* Returns the affine inverse of the matrix.
 			*/			
 			Matrix4 inverseAffine() const;
-	
+		
+			/**
+			* Returns the determinant of the matrix.
+			*/
+			Number determinant() const;
+		
+			/**
+			 * Returns the determinant of any general (square) matrix.
+			 * @param a A square matrix as an array of pointers to rows (or columns).
+			 * @param n The number of dimensions in matrix A.
+			 */
+			static Number generalDeterminant(Number const* const*a, int n);
+		
 		protected:
 		
 	};

+ 10 - 1
Core/Contents/Include/PolyQuaternion.h

@@ -265,7 +265,16 @@ namespace Polycode {
 			void createFromAxisAngle(Number x, Number y, Number z, Number degrees);
 			Matrix4 createMatrix() const;
 			
-			
+			/**
+			 * Rotate a Vector3 by this Quaternion.
+			 * @param v Vector to operate on.
+			 */
+			Vector3 applyTo(Vector3 v) const
+			{
+				const Quaternion &q = *this;
+				Quaternion result = q * Quaternion(0,v.x,v.y,v.z) * q.Inverse();
+				return Vector3(result.x,result.y,result.z);
+			}
 			
 			Quaternion operator *(Quaternion q);
 			

+ 6 - 5
Core/Contents/Include/PolyScreenEntity.h

@@ -124,13 +124,13 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		* Sets the width of the screen entity.
 		* @param w New height value.
 		*/									
-		void setWidth(Number w) { width = w; hitwidth = w; }
+		void setWidth(Number w) { width = w; hit.w = w; hit.x = -w/2; }
 		
 		/**
 		* Sets the height of the screen entity.
 		* @param h New height value.
 		*/									
-		void setHeight(Number h) { height = h; hitheight = h; }
+		void setHeight(Number h) { height = h; hit.h = h; hit.y = -h/2; }
 	
 		virtual void onGainFocus(){}
 		virtual void onLoseFocus(){}		
@@ -175,7 +175,9 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		bool snapToPixels;
 		bool processInputEvents;
 
-		Vector2 getHitbox();
+		Rectangle getHitbox();
+		void setHitbox(Number width, Number height);
+		void setHitbox(Number width, Number height, Number left, Number top);
 
 	protected:
 	
@@ -190,8 +192,7 @@ class _PolyExport ScreenEntity : public Entity, public EventDispatcher {
 		Number width;
 		Number height;
 
-		Number hitwidth;
-		Number hitheight;
+		Rectangle hit;
 		
 		Number xmouse;
 		Number ymouse;

+ 6 - 1
Core/Contents/Include/PolyScreenMesh.h

@@ -95,7 +95,12 @@ namespace Polycode {
 			* If true, will delete its Mesh upon destruction. (defaults to true)
 			*/ 			
 			bool ownsMesh;
-			
+		
+			/**
+			 * Updates hit.width, hit.height to coordinates of mesh.
+			 */
+			void updateHitBox();
+		
 		protected:
 		
 			Mesh *mesh;

+ 211 - 91
Core/Contents/Source/PolyMatrix4.cpp

@@ -36,107 +36,227 @@ Matrix4::Matrix4(const Number *m) {
 	memcpy(ml, m, sizeof(Number)*16);
 }
 
-	Matrix4 Matrix4::inverse() const
-    {
-        Number m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];
-        Number m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], m13 = m[1][3];
-        Number m20 = m[2][0], m21 = m[2][1], m22 = m[2][2], m23 = m[2][3];
-        Number m30 = m[3][0], m31 = m[3][1], m32 = m[3][2], m33 = m[3][3];
-
-        Number v0 = m20 * m31 - m21 * m30;
-        Number v1 = m20 * m32 - m22 * m30;
-        Number v2 = m20 * m33 - m23 * m30;
-        Number v3 = m21 * m32 - m22 * m31;
-        Number v4 = m21 * m33 - m23 * m31;
-        Number v5 = m22 * m33 - m23 * m32;
-
-        Number t00 = + (v5 * m11 - v4 * m12 + v3 * m13);
-        Number t10 = - (v5 * m10 - v2 * m12 + v1 * m13);
-        Number t20 = + (v4 * m10 - v2 * m11 + v0 * m13);
-        Number t30 = - (v3 * m10 - v1 * m11 + v0 * m12);
-
-        Number invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
-
-        Number d00 = t00 * invDet;
-        Number d10 = t10 * invDet;
-        Number d20 = t20 * invDet;
-        Number d30 = t30 * invDet;
-
-        Number d01 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
-        Number d11 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
-        Number d21 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
-        Number d31 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
-
-        v0 = m10 * m31 - m11 * m30;
-        v1 = m10 * m32 - m12 * m30;
-        v2 = m10 * m33 - m13 * m30;
-        v3 = m11 * m32 - m12 * m31;
-        v4 = m11 * m33 - m13 * m31;
-        v5 = m12 * m33 - m13 * m32;
-
-        Number d02 = + (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
-        Number d12 = - (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
-        Number d22 = + (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
-        Number d32 = - (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
-
-        v0 = m21 * m10 - m20 * m11;
-        v1 = m22 * m10 - m20 * m12;
-        v2 = m23 * m10 - m20 * m13;
-        v3 = m22 * m11 - m21 * m12;
-        v4 = m23 * m11 - m21 * m13;
-        v5 = m23 * m12 - m22 * m13;
-
-        Number d03 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
-        Number d13 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
-        Number d23 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
-        Number d33 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
-
-        return Matrix4(
-            d00, d01, d02, d03,
-            d10, d11, d12, d13,
-            d20, d21, d22, d23,
-            d30, d31, d32, d33);
-    }
-    //-----------------------------------------------------------------------
-	Matrix4 Matrix4::inverseAffine(void) const
-    {
+Matrix4 Matrix4::inverse() const
+{
+	Number m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];
+	Number m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], m13 = m[1][3];
+	Number m20 = m[2][0], m21 = m[2][1], m22 = m[2][2], m23 = m[2][3];
+	Number m30 = m[3][0], m31 = m[3][1], m32 = m[3][2], m33 = m[3][3];
+
+	Number v0 = m20 * m31 - m21 * m30;
+	Number v1 = m20 * m32 - m22 * m30;
+	Number v2 = m20 * m33 - m23 * m30;
+	Number v3 = m21 * m32 - m22 * m31;
+	Number v4 = m21 * m33 - m23 * m31;
+	Number v5 = m22 * m33 - m23 * m32;
+
+	Number t00 = + (v5 * m11 - v4 * m12 + v3 * m13);
+	Number t10 = - (v5 * m10 - v2 * m12 + v1 * m13);
+	Number t20 = + (v4 * m10 - v2 * m11 + v0 * m13);
+	Number t30 = - (v3 * m10 - v1 * m11 + v0 * m12);
+
+	Number invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
+
+	Number d00 = t00 * invDet;
+	Number d10 = t10 * invDet;
+	Number d20 = t20 * invDet;
+	Number d30 = t30 * invDet;
+
+	Number d01 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
+	Number d11 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
+	Number d21 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
+	Number d31 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
+
+	v0 = m10 * m31 - m11 * m30;
+	v1 = m10 * m32 - m12 * m30;
+	v2 = m10 * m33 - m13 * m30;
+	v3 = m11 * m32 - m12 * m31;
+	v4 = m11 * m33 - m13 * m31;
+	v5 = m12 * m33 - m13 * m32;
+
+	Number d02 = + (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
+	Number d12 = - (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
+	Number d22 = + (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
+	Number d32 = - (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
+
+	v0 = m21 * m10 - m20 * m11;
+	v1 = m22 * m10 - m20 * m12;
+	v2 = m23 * m10 - m20 * m13;
+	v3 = m22 * m11 - m21 * m12;
+	v4 = m23 * m11 - m21 * m13;
+	v5 = m23 * m12 - m22 * m13;
 
-        Number m10 = m[1][0], m11 = m[1][1], m12 = m[1][2];
-        Number m20 = m[2][0], m21 = m[2][1], m22 = m[2][2];
+	Number d03 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
+	Number d13 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
+	Number d23 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
+	Number d33 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
 
-        Number t00 = m22 * m11 - m21 * m12;
-        Number t10 = m20 * m12 - m22 * m10;
-        Number t20 = m21 * m10 - m20 * m11;
+	return Matrix4(
+		d00, d01, d02, d03,
+		d10, d11, d12, d13,
+		d20, d21, d22, d23,
+		d30, d31, d32, d33);
+}
+
+Matrix4 Matrix4::inverseAffine(void) const
+{
+
+	Number m10 = m[1][0], m11 = m[1][1], m12 = m[1][2];
+	Number m20 = m[2][0], m21 = m[2][1], m22 = m[2][2];
 
-        Number m00 = m[0][0], m01 = m[0][1], m02 = m[0][2];
+	Number t00 = m22 * m11 - m21 * m12;
+	Number t10 = m20 * m12 - m22 * m10;
+	Number t20 = m21 * m10 - m20 * m11;
 
-        Number invDet = 1 / (m00 * t00 + m01 * t10 + m02 * t20);
+	Number m00 = m[0][0], m01 = m[0][1], m02 = m[0][2];
 
-        t00 *= invDet; t10 *= invDet; t20 *= invDet;
+	Number invDet = 1 / (m00 * t00 + m01 * t10 + m02 * t20);
 
-        m00 *= invDet; m01 *= invDet; m02 *= invDet;
+	t00 *= invDet; t10 *= invDet; t20 *= invDet;
 
-        Number r00 = t00;
-        Number r01 = m02 * m21 - m01 * m22;
-        Number r02 = m01 * m12 - m02 * m11;
+	m00 *= invDet; m01 *= invDet; m02 *= invDet;
 
-        Number r10 = t10;
-        Number r11 = m00 * m22 - m02 * m20;
-        Number r12 = m02 * m10 - m00 * m12;
+	Number r00 = t00;
+	Number r01 = m02 * m21 - m01 * m22;
+	Number r02 = m01 * m12 - m02 * m11;
 
-        Number r20 = t20;
-        Number r21 = m01 * m20 - m00 * m21;
-        Number r22 = m00 * m11 - m01 * m10;
+	Number r10 = t10;
+	Number r11 = m00 * m22 - m02 * m20;
+	Number r12 = m02 * m10 - m00 * m12;
 
-        Number m03 = m[0][3], m13 = m[1][3], m23 = m[2][3];
+	Number r20 = t20;
+	Number r21 = m01 * m20 - m00 * m21;
+	Number r22 = m00 * m11 - m01 * m10;
 
-        Number r03 = - (r00 * m03 + r01 * m13 + r02 * m23);
-        Number r13 = - (r10 * m03 + r11 * m13 + r12 * m23);
-        Number r23 = - (r20 * m03 + r21 * m13 + r22 * m23);
+	Number m03 = m[0][3], m13 = m[1][3], m23 = m[2][3];
 
-        return Matrix4(
-            r00, r01, r02, r03,
-            r10, r11, r12, r13,
-            r20, r21, r22, r23,
-              0,   0,   0,   1);
+	Number r03 = - (r00 * m03 + r01 * m13 + r02 * m23);
+	Number r13 = - (r10 * m03 + r11 * m13 + r12 * m23);
+	Number r23 = - (r20 * m03 + r21 * m13 + r22 * m23);
+
+	return Matrix4(
+		r00, r01, r02, r03,
+		r10, r11, r12, r13,
+		r20, r21, r22, r23,
+		  0,   0,   0,   1);
+}
+
+Number Matrix4::determinant() const {
+	const Number *cols[4] = {m[0],m[1],m[2],m[3]};
+	return generalDeterminant(cols, 4);
+}
+
+// Determinant function by Edward Popko
+// Source: http://paulbourke.net/miscellaneous/determinant/
+//==============================================================================
+// Recursive definition of determinate using expansion by minors.
+//
+// Notes: 1) arguments:
+//             a (double **) pointer to a pointer of an arbitrary square matrix
+//             n (int) dimension of the square matrix
+//
+//        2) Determinant is a recursive function, calling itself repeatedly
+//           each time with a sub-matrix of the original till a terminal
+//           2X2 matrix is achieved and a simple determinat can be computed.
+//           As the recursion works backwards, cumulative determinants are
+//           found till untimately, the final determinate is returned to the
+//           initial function caller.
+//
+//        3) m is a matrix (4X4 in example)  and m13 is a minor of it.
+//           A minor of m is a 3X3 in which a row and column of values
+//           had been excluded.   Another minor of the submartix is also
+//           possible etc.
+//             m  a b c d   m13 . . . .
+//                e f g h       e f . h     row 1 column 3 is elminated
+//                i j k l       i j . l     creating a 3 X 3 sub martix
+//                m n o p       m n . p
+//
+//        4) the following function finds the determinant of a matrix
+//           by recursively minor-ing a row and column, each time reducing
+//           the sub-matrix by one row/column.  When a 2X2 matrix is
+//           obtained, the determinat is a simple calculation and the
+//           process of unstacking previous recursive calls begins.
+//
+//                m n
+//                o p  determinant = m*p - n*o
+//
+//        5) this function uses dynamic memory allocation on each call to
+//           build a m X m matrix  this requires **  and * pointer variables
+//           First memory allocation is ** and gets space for a list of other
+//           pointers filled in by the second call to malloc.
+//
+//        6) C++ implements two dimensional arrays as an array of arrays
+//           thus two dynamic malloc's are needed and have corresponsing
+//           free() calles.
+//
+//        7) the final determinant value is the sum of sub determinants
+//
+//==============================================================================
+Number Matrix4::generalDeterminant(Number const* const*a,int n)
+{
+    int i,j,j1,j2;                    // general loop and matrix subscripts
+    Number det = 0;                   // init determinant
+    Number **m = NULL;                // pointer to pointers to implement 2d
+	// square array
+	
+    if (n < 1)    {   }                // error condition, should never get here
+	
+    else if (n == 1) {                 // should not get here
+        det = a[0][0];
+	}
+	
+    else if (n == 2)  {                // basic 2X2 sub-matrix determinate
+		// definition. When n==2, this ends the
+        det = a[0][0] * a[1][1] - a[1][0] * a[0][1];// the recursion series
+	}
+	
+	
+	// recursion continues, solve next sub-matrix
+    else {                             // solve the next minor by building a
+		// sub matrix
+        det = 0;                      // initialize determinant of sub-matrix
+		
+		// for each column in sub-matrix
+        for (j1 = 0; j1 < n; j1++) {
+			// get space for the pointer list
+            m = new Number*[n-1];
+			
+            for (i = 0; i < n-1; i++)
+                m[i] = new Number[n-1];
+			//     i[0][1][2][3]  first malloc
+			//  m -> +  +  +  +   space for 4 pointers
+			//       |  |  |  |          j  second malloc
+			//       |  |  |  +-> _ _ _ [0] pointers to
+			//       |  |  +----> _ _ _ [1] and memory for
+			//       |  +-------> _ a _ [2] 4 doubles
+			//       +----------> _ _ _ [3]
+			//
+			//                   a[1][2]
+			// build sub-matrix with minor elements excluded
+            for (i = 1; i < n; i++) {
+                j2 = 0;               // start at first sum-matrix column position
+				// loop to copy source matrix less one column
+                for (j = 0; j < n; j++) {
+                    if (j == j1) continue; // don't copy the minor column element
+					
+                    m[i-1][j2] = a[i][j];   // copy source element into new sub-matrix
+					// i-1 because new sub-matrix is one row
+					// (and column) smaller with excluded minors
+                    j2++;                  // move to next sub-matrix column position
+				}
+			}
+			
+            det += pow(-1.0,1.0 + j1 + 1.0) * a[0][j1] * generalDeterminant(m,n-1);
+			// sum x raised to y power
+			// recursively get determinant of next
+			// sub-matrix which is now one
+			// row & column smaller
+			
+            for (i = 0 ; i < n-1 ; i++) delete[] m[i];// free the storage allocated to
+			// to this minor's set of pointers
+            delete[] m;                       // free the storage for the original
+			// pointer to pointer
+        }
     }
+    return(det) ;
+}

+ 1 - 1
Core/Contents/Source/PolySceneLine.cpp

@@ -66,7 +66,7 @@ SceneLine::SceneLine(SceneEntity *ent1, SceneEntity *ent2) : SceneEntity() {
 }
 
 SceneLine::~SceneLine() {
-
+	delete mesh;
 }
 
 void SceneLine::setStart(Vector3 start) {

+ 38 - 28
Core/Contents/Source/PolyScreenEntity.cpp

@@ -35,8 +35,7 @@ ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
 	color = Color(1.0f,1.0f,1.0f,1.0f);
 	width = 1;
 	height = 1;
-	hitwidth = 1;
-	hitheight = 1;
+	setHitbox(1, 1);
 	backfaceCulled = false;
 	positionMode = POSITION_TOPLEFT;
 	mouseOver = false;
@@ -192,25 +191,23 @@ bool ScreenEntity::hitTest(const Number x, const Number y) {
 	Polygon testPoly;
 	
 	Matrix4 transformMatrix = getConcatenatedMatrix();
-	
-	v = Vector3(-hitwidth/2.0, -hitheight/2.0,0);
-	v = transformMatrix * v;	
+	v = Vector3(hit.x, hit.y, 0);
+	v = transformMatrix * v;
 	testPoly.addVertex(v.x, v.y, 0.0);
 	
-	v = Vector3(hitwidth/2.0, -hitheight/2.0,0);
-	v = transformMatrix * v;	
+	v = Vector3(hit.x+hit.w, hit.y, 0);
+	v = transformMatrix * v;
 	testPoly.addVertex(v.x, v.y, 0.0);
 
-	v = Vector3(hitwidth/2.0, hitheight/2.0,0);
-	v = transformMatrix * v;	
+	v = Vector3(hit.x+hit.w, hit.y+hit.h, 0);
+	v = transformMatrix * v;
 	testPoly.addVertex(v.x, v.y, 0.0);
 
-	v = Vector3(-hitwidth/2.0,hitheight/2.0,0);
-	v = transformMatrix * v;	
+	v = Vector3(hit.x,hit.y+hit.h, 0);
+	v = transformMatrix * v;
 	testPoly.addVertex(v.x, v.y, 0.0);
 		
 	return isPointInsidePolygon2D(&testPoly, Vector2(x,y));
-	
 }
 
 void ScreenEntity::setPositionMode(int newPositionMode) {
@@ -249,8 +246,21 @@ void ScreenEntity::clearDragLimits() {
 	dragLimits = NULL;
 }
 
-Vector2 ScreenEntity::getHitbox() {
-	return Vector2(hitwidth, hitheight);
+Rectangle ScreenEntity::getHitbox() {
+	return hit;
+}
+
+void ScreenEntity::setHitbox(Number width, Number height) {
+	hit.w = width;
+	hit.h = height;
+	hit.x = -width/2;
+	hit.y = -height/2;
+}
+void ScreenEntity::setHitbox(Number width, Number height, Number left, Number top) {
+	hit.w = width;
+	hit.h = height;
+	hit.x = left;
+	hit.y = top;
 }
 
 Matrix4 ScreenEntity::getScreenConcatenatedMatrix() {
@@ -309,9 +319,9 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 paren
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 
 
 		
@@ -333,9 +343,9 @@ void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp, Vector2 paren
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 		
 		
 			dispatchEvent(new InputEvent(Vector2(localCoordinate.x,localCoordinate.y)-parentAdjust, timestamp), InputEvent::EVENT_MOUSEOUT);
@@ -378,9 +388,9 @@ bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 
 		
 		onMouseUp(localCoordinate.x,localCoordinate.y);		
@@ -395,9 +405,9 @@ bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 
 		
 		InputEvent *inputEvent = new InputEvent(Vector2(localCoordinate.x,localCoordinate.y)-parentAdjust, timestamp);		
@@ -441,9 +451,9 @@ void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp, Vector2 pa
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 
 		
 		onMouseWheelUp(localCoordinate.x,localCoordinate.y);
@@ -489,9 +499,9 @@ void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp, Vector2
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 
 		
 		onMouseWheelDown(localCoordinate.x,localCoordinate.y);
@@ -539,9 +549,9 @@ bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timesta
 		Matrix4 inverse = getConcatenatedMatrix().inverse();
 		localCoordinate = inverse * localCoordinate;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.x += hitwidth/2.0;
+			localCoordinate.x += hit.w/2.0;
 		if(positionMode == POSITION_TOPLEFT)
-			localCoordinate.y += hitheight/2.0;
+			localCoordinate.y += hit.h/2.0;
 
 		
 		onMouseDown(localCoordinate.x,localCoordinate.y);

+ 1 - 2
Core/Contents/Source/PolyScreenImage.cpp

@@ -65,8 +65,7 @@ void ScreenImage::setImageCoordinates(Number x, Number y, Number width, Number h
 	
 	this->width = width;
 	this->height = height;
-	hitwidth = width;
-	hitheight = height;
+	setHitbox(width, height);
 	Number whalf = floor(width/2.0f);
 	Number hhalf = floor(height/2.0f);	
 		

+ 24 - 0
Core/Contents/Source/PolyScreenMesh.cpp

@@ -33,6 +33,7 @@ ScreenMesh::ScreenMesh(Mesh *mesh) : ScreenEntity(), texture(NULL) {
 	lineSmooth = false;
 	lineWidth = 1.0;
 	ownsMesh = true;
+	updateHitBox();
 }
 
 ScreenMesh::ScreenMesh(const String& fileName) : ScreenEntity(), texture(NULL) {
@@ -90,3 +91,26 @@ void ScreenMesh::Render() {
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY);	
 	renderer->drawArrays(mesh->getMeshType());
 }
+
+void ScreenMesh::updateHitBox() {
+	Number xmin, ymin, xmax, ymax;
+	bool any = false;
+	for(int c = 0; c < mesh->getPolygonCount(); c++) {
+		Polygon *poly = mesh->getPolygon(c);
+		for(int d = 0; d < poly->getVertexCount(); d++) {
+			Vertex *v = poly->getVertex(d);
+			if (any) {
+				xmin = MIN(v->x, xmin);
+				ymin = MIN(v->y, ymin);
+				xmax = MAX(v->x, xmax);
+				ymax = MAX(v->y, ymax);
+			} else {
+				xmin = v->x; xmax = v->x;
+				ymin = v->y; ymax = v->y;
+				any = true;
+			}
+		}
+	}
+	
+	setHitbox(xmax-xmin, ymax-ymin, xmin, ymin);
+}

+ 3 - 5
Core/Contents/Source/PolyScreenShape.cpp

@@ -34,9 +34,8 @@ ScreenShape::ScreenShape(int shapeType, Number option1, Number option2, Number o
 	this->shapeType = shapeType;
 	width = option1;
 	height = option2;
-
-	hitwidth = width;
-	hitheight = height;
+	
+	setHitbox(width, height);
 
 	this->option1 = option1;
 	this->option2 = option2;
@@ -93,8 +92,7 @@ void ScreenShape::setShapeSize(Number newWidth, Number newHeight) {
 	width = newWidth;
 	height = newHeight;
 	
-	hitwidth = width;
-	hitheight = height;	
+	setHitbox(width, height);
 	
 	Number whalf = floor(width/2.0f);
 	Number hhalf = floor(height/2.0f);

+ 2 - 4
Modules/Contents/UI/Source/PolyUIBox.cpp

@@ -30,8 +30,7 @@ UIBox::UIBox(String imageFile, Number t, Number r, Number b, Number l, Number bo
 	
 	width=boxWidth;
 	height = boxHeight;
-	hitwidth = boxWidth;
-	hitheight = boxHeight;
+	setHitbox(boxWidth, boxHeight);
 	
 	tlImage = new ScreenImage(imageFile);
 	tlImage->setImageCoordinates(0,0,l,t);
@@ -106,8 +105,7 @@ void UIBox::resizeBox(Number newWidth, Number newHeight) {
 	
 	width=newWidth;
 	height = newHeight;
-	hitwidth = newWidth;
-	hitheight = newHeight;
+	setHitbox(newWidth, newHeight);
 	
 	this->rebuildTransformMatrix();
 }

+ 2 - 4
Modules/Contents/UI/Source/PolyUIScrollContainer.cpp

@@ -42,8 +42,7 @@ UIScrollContainer::UIScrollContainer(ScreenEntity *scrolledEntity, bool hScroll,
 	
 	this->width = width;
 	this->height = height;
-	this->hitwidth = width;
-	this->hitheight = height;
+	setHitbox(width, height);
 	
 	Number uiScrollPanePadding = conf->getNumericValue("Polycode", "uiScrollPanePadding");			
 	
@@ -84,8 +83,7 @@ UIScrollContainer::UIScrollContainer(ScreenEntity *scrolledEntity, bool hScroll,
 void UIScrollContainer::Resize(int x, int y) {
 	width = x;
 	height = y;
-	hitwidth = width;
-	hitheight = height;
+	setHitbox(width, height);
 	
 	maskShape->setShapeSize(x, y);
 	vScrollBar->Resize(y);

+ 1 - 2
Modules/Contents/UI/Source/PolyUITextInput.cpp

@@ -124,8 +124,7 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : ScreenEn
 	focusable = true;
 	this->width = width;
 	this->height = rectHeight;
-	hitwidth = width;
-	hitheight = rectHeight;
+	setHitbox(width, rectHeight);
 	
 	updateCaretPosition();
 }

+ 1 - 2
Modules/Contents/UI/Source/PolyUITree.cpp

@@ -259,8 +259,7 @@ void UITree::refreshTree() {
 	}
 	height = treeHeight + cellHeight;
 	width = treeWidth;
-	hitwidth = width;
-	hitheight = height;
+	setHitbox(width, height);
 	
 	selection->visible = selected;
 	dispatchEvent(new UITreeEvent(), UITreeEvent::NEED_REFRESH_EVENT);	

+ 3 - 6
Modules/Contents/UI/Source/PolyUITreeContainer.cpp

@@ -58,8 +58,7 @@ UITreeContainer::UITreeContainer(String icon, String text, Number treeWidth, Num
 	
 	width = treeWidth;
 	height = treeHeight;
-	hitwidth = width;
-	hitheight = height;
+	setHitbox(width, height);
 }
 
 void UITreeContainer::Resize(int x, int y) {
@@ -68,10 +67,8 @@ void UITreeContainer::Resize(int x, int y) {
 	mainContainer->setPositionY(0);
 
 //	width = x;
-//	height = y;
-	hitwidth = x;
-	hitheight = y;
-
+	//	height = y;
+	setHitbox(x, y);
 }
 
 void UITreeContainer::handleEvent(Event *event) {

+ 2 - 4
Modules/Contents/UI/Source/PolyUIVScrollBar.cpp

@@ -84,14 +84,12 @@ UIVScrollBar::UIVScrollBar(Number width, Number height, Number initialRatio) : S
 	this->height = height;
 	this->width = width;	
 	
-	this->hitwidth = width;
-	this->hitheight = height;	
+	setHitbox(width, height);
 }
 
 void UIVScrollBar::Resize(int newHeight) {
 	bgBox->resizeBox(width, newHeight);
-	this->height = newHeight;
-	this->hitheight = newHeight;
+	setHeight(newHeight);
 	dragRectHeight = height-(padding*2)-scrollHandleHeight;	
 	handleBox->setDragLimits(Rectangle(padding,padding,width-(padding*2)-(width-(padding*2)), dragRectHeight));	
 }

+ 1 - 2
Modules/Contents/UI/Source/PolyUIWindow.cpp

@@ -80,8 +80,7 @@ UIWindow::UIWindow(String windowName, Number width, Number height) : ScreenEntit
 	
 	this->width = width;
 	this->height = height;
-	this->hitwidth = width;
-	this->hitheight = height;
+	setHitbox(width, height);
 	
 	focusable = true;
 	blockMouseInput = true;