Browse Source

Allow vertices in either clockwise or counter-clockwise order for newPolygonShape (fixes issue #326)

Bill Meltsner 13 years ago
parent
commit
e482f32da3
1 changed files with 49 additions and 11 deletions
  1. 49 11
      src/modules/physics/box2d/Physics.cpp

+ 49 - 11
src/modules/physics/box2d/Physics.cpp

@@ -93,29 +93,67 @@ namespace box2d
 	int Physics::newPolygonShape(lua_State * L)
 	int Physics::newPolygonShape(lua_State * L)
 	{
 	{
 		int argc = lua_gettop(L);
 		int argc = lua_gettop(L);
-		int vcount = (int)argc/2;
-		// 3 vertices
-		love::luax_assert_argc(L, 2 * 3);
+		if (argc%2 != 0)
+			return luaL_error(L, "Number of vertices must be a multiple of two.");
+		// 3 to 8 (b2_maxPolygonVertices) vertices
+		int vcount = argc / 2;
+		if (vcount < 3)
+			luaL_error(L, "Expected a minimum of 3 vertices, got %d.", vcount);
+		else if (vcount > b2_maxPolygonVertices)
+			luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount);
 
 
 		b2PolygonShape* s = new b2PolygonShape();
 		b2PolygonShape* s = new b2PolygonShape();
 
 
-		b2Vec2 * vecs = new b2Vec2[vcount];
+		bool reverse = false;
+		b2Vec2 edge1;
+		b2Vec2 vecs[b2_maxPolygonVertices];
 
 
-		for (int i = 0;i<vcount;i++)
+		for (int i = 0; i < vcount; i++)
 		{
 		{
-			float x = (float)lua_tonumber(L, -2);
-			float y = (float)lua_tonumber(L, -1);
-			vecs[i] = (Physics::scaleDown(b2Vec2(x, y)));
+			float x = (float)luaL_checknumber(L, -2);
+			float y = (float)luaL_checknumber(L, -1);
+			vecs[i] = Physics::scaleDown(b2Vec2(x, y));
 			lua_pop(L, 2);
 			lua_pop(L, 2);
+
+			if (!reverse)
+			{
+				// Detect clockwise winding.
+				if (i == 1)
+				{
+					edge1 = vecs[1] - vecs[0];
+				}
+				else if (i == vcount - 1)
+				{
+					b2Vec2 edge2 = vecs[i] - vecs[i-1];
+					// Also check the edge from the last and first point.
+					b2Vec2 edge3 = vecs[0] - vecs[i];
+					if (b2Cross(edge1, edge2) < 0.0f || b2Cross(edge2, edge3) < 0.0f)
+						reverse = true;
+				}
+				else if (i > 1)
+				{
+					b2Vec2 edge2 = vecs[i] - vecs[i-1];
+					if (b2Cross(edge1, edge2) < 0.0f)
+						reverse = true;
+					edge1 = edge2;
+				}
+			}
 		}
 		}
 
 
-		s->Set(vecs, vcount);
+		if (reverse)
+		{
+			for (int i = 0, j = vcount-1; i < j; ++i, --j)
+			{
+				b2Vec2 swap = vecs[i];
+				vecs[i] = vecs[j];
+				vecs[j] = swap;
+			}
+		}
 
 
+		s->Set(vecs, vcount);
 		PolygonShape * p = new PolygonShape(s);
 		PolygonShape * p = new PolygonShape(s);
-		delete[] vecs;
 
 
 		luax_newtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, (void*)p);
 		luax_newtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, (void*)p);
-
 		return 1;
 		return 1;
 	}
 	}