Example #1
0
static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count)
{
	b2Assert(count >= 2);

	b2Vec2 c; c.Set(0.0f, 0.0f);
	float32 area = 0.0f;

	if (count == 2)
	{
		c = 0.5f * (vs[0] + vs[1]);
		return c;
	}

	// pRef is the reference point for forming triangles.
	// It's location doesn't change the result (except for rounding error).
	b2Vec2 pRef(0.0f, 0.0f);
#if 0
	// This code would put the reference point inside the polygon.
	for (int32 i = 0; i < count; ++i)
	{
		pRef += vs[i];
	}
	pRef *= 1.0f / count;
#endif

	const float32 inv3 = 1.0f / 3.0f;

	for (int32 i = 0; i < count; ++i)
	{
		// Triangle vertices.
		b2Vec2 p1 = pRef;
		b2Vec2 p2 = vs[i];
		b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];

		b2Vec2 e1 = p2 - p1;
		b2Vec2 e2 = p3 - p1;

		float32 D = b2Cross(e1, e2);

		float32 triangleArea = 0.5f * D;
		area += triangleArea;

		// Area weighted centroid
		c += triangleArea * inv3 * (p1 + p2 + p3);
	}

	// Centroid
	b2Assert(area > b2_epsilon);
	c *= 1.0f / area;
	return c;
}
//Taken from b2PolygonShape.cpp
b2Vec2 CustomContactListener::ComputeCentroid(vector<b2Vec2> vs, float& area)
{
    int count = (int)vs.size();
    b2Assert(count >= 3);

    b2Vec2 c;
    c.Set(0.0f, 0.0f);
    area = 0.0f;

    // pRef is the reference point for forming triangles.
    // Its location doesnt change the result (except for rounding error).
    b2Vec2 pRef(0.0f, 0.0f);

    const float32 inv3 = 1.0f / 3.0f;

    for (int32 i = 0; i < count; ++i)
    {
        // Triangle vertices.
        b2Vec2 p1 = pRef;
        b2Vec2 p2 = vs[i];
        b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];

        b2Vec2 e1 = p2 - p1;
        b2Vec2 e2 = p3 - p1;

        float32 D = b2Cross(e1, e2);

        float32 triangleArea = 0.5f * D;
        area += triangleArea;

        // Area weighted centroid
        c += triangleArea * inv3 * (p1 + p2 + p3);
    }

    // Centroid
    if (area > b2_epsilon)
        c *= 1.0f / area;
    else
        area = 0;
    return c;
}
Example #3
0
bool LHBodyShape::LHValidateCentroid(b2Vec2* vs, int count)
{
    if(count > b2_maxPolygonVertices)
        return false;
    
    if(count < 3)
        return false;
    
    b2Vec2 c; c.Set(0.0f, 0.0f);
    float32 area = 0.0f;
    
    // pRef is the reference point for forming triangles.
    // It's location doesn't change the result (except for rounding error).
    b2Vec2 pRef(0.0f, 0.0f);
#if 0
    // This code would put the reference point inside the polygon.
    for (int32 i = 0; i < count; ++i)
    {
        pRef += vs[i];
    }
    pRef *= 1.0f / count;
#endif
    
    const float32 inv3 = 1.0f / 3.0f;
    
    for (int32 i = 0; i < count; ++i)
    {
        // Triangle vertices.
        b2Vec2 p1 = pRef;
        b2Vec2 p2 = vs[i];
        b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];
        
        b2Vec2 e1 = p2 - p1;
        b2Vec2 e2 = p3 - p1;
        
        float32 D = b2Cross(e1, e2);
        
        float32 triangleArea = 0.5f * D;
        area += triangleArea;
        
        // Area weighted centroid
        c += triangleArea * inv3 * (p1 + p2 + p3);
    }
    
    // Centroid
    if(area < b2_epsilon)
    {
        return false;
    }
    

	
	int32 n = b2Min(count, b2_maxPolygonVertices);
    
	// Perform welding and copy vertices into local buffer.
	b2Vec2 ps[b2_maxPolygonVertices];
	int32 tempCount = 0;
	for (int32 i = 0; i < n; ++i)
	{
		b2Vec2 v = vs[i];
        
		bool unique = true;
		for (int32 j = 0; j < tempCount; ++j)
		{
			if (b2DistanceSquared(v, ps[j]) < 0.5f * b2_linearSlop)
			{
				unique = false;
				break;
			}
		}
        
		if (unique)
		{
			ps[tempCount++] = v;
		}
	}
    
	n = tempCount;
	if (n < 3)
	{
		return false;
	}

    
    return true;
    
}
Example #4
0
void b2PolygonShape::ComputeMass(b2MassData* massData, float32 density) const
{
	// Polygon mass, centroid, and inertia.
	// Let rho be the polygon density in mass per unit area.
	// Then:
	// mass = rho * int(dA)
	// centroid.x = (1/mass) * rho * int(x * dA)
	// centroid.y = (1/mass) * rho * int(y * dA)
	// I = rho * int((x*x + y*y) * dA)
	//
	// We can compute these integrals by summing all the integrals
	// for each triangle of the polygon. To evaluate the integral
	// for a single triangle, we make a change of variables to
	// the (u,v) coordinates of the triangle:
	// x = x0 + e1x * u + e2x * v
	// y = y0 + e1y * u + e2y * v
	// where 0 <= u && 0 <= v && u + v <= 1.
	//
	// We integrate u from [0,1-v] and then v from [0,1].
	// We also need to use the Jacobian of the transformation:
	// D = cross(e1, e2)
	//
	// Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
	//
	// The rest of the derivation is handled by computer algebra.

	b2Assert(m_vertexCount >= 2);

	// A line segment has zero mass.
	if (m_vertexCount == 2)
	{
		massData->center = 0.5f * (m_vertices[0] + m_vertices[1]);
		massData->mass = 0.0f;
		massData->I = 0.0f;
		return;
	}

	b2Vec2 center; center.Set(0.0f, 0.0f);
	float32 area = 0.0f;
	float32 I = 0.0f;

	// pRef is the reference point for forming triangles.
	// It's location doesn't change the result (except for rounding error).
	b2Vec2 pRef(0.0f, 0.0f);
#if 0
	// This code would put the reference point inside the polygon.
	for (int32 i = 0; i < m_vertexCount; ++i)
	{
		pRef += m_vertices[i];
	}
	pRef *= 1.0f / count;
#endif

	const float32 k_inv3 = 1.0f / 3.0f;

	for (int32 i = 0; i < m_vertexCount; ++i)
	{
		// Triangle vertices.
		b2Vec2 p1 = pRef;
		b2Vec2 p2 = m_vertices[i];
		b2Vec2 p3 = i + 1 < m_vertexCount ? m_vertices[i+1] : m_vertices[0];

		b2Vec2 e1 = p2 - p1;
		b2Vec2 e2 = p3 - p1;

		float32 D = b2Cross(e1, e2);

		float32 triangleArea = 0.5f * D;
		area += triangleArea;

		// Area weighted centroid
		center += triangleArea * k_inv3 * (p1 + p2 + p3);

		float32 px = p1.x, py = p1.y;
		float32 ex1 = e1.x, ey1 = e1.y;
		float32 ex2 = e2.x, ey2 = e2.y;

		float32 intx2 = k_inv3 * (0.25f * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5f*px*px;
		float32 inty2 = k_inv3 * (0.25f * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5f*py*py;

		I += D * (intx2 + inty2);
	}

	// Total mass
	massData->mass = density * area;

	// Center of mass
	b2Assert(area > b2_epsilon);
	center *= 1.0f / area;
	massData->center = center;

	// Inertia tensor relative to the local origin.
	massData->I = density * I;
}
Example #5
0
bool Box2dHelper::areVerticesAcceptable(b2Vec2* vertices, int count)
{
	if (count < 3)
		return false;

	if (count > b2_maxPolygonVertices){
		return false;
	}

	int32 i;
	for (i = 0; i < count; i++){
		int32 i1 = i;
		int32 i2 = i + 1 < count ? i + 1 : 0;
		b2Vec2 edge = vertices[i2] - vertices[i1];
		if (edge.LengthSquared() <= b2_epsilon * b2_epsilon){
			return false;
		}
	}

	float32 area = 0.0f;
	b2Vec2 pRef(0.0f, 0.0f);
	for (i = 0; i < count; i++){
		b2Vec2 p1 = pRef;
		b2Vec2 p2 = vertices[i];
		b2Vec2 p3 = i + 1 < count ? vertices[i + 1] : vertices[0];

		b2Vec2 e1 = p2 - p1;
		b2Vec2 e2 = p3 - p1;

		float32 D = b2Cross(e1, e2);

		float32 triangleArea = 0.5f * D;
		area += triangleArea;
	}

	if (area <= 0.0001f)
	{
		return false;
	}

	float determinant;
	float referenceDeterminant;
	b2Vec2 v1 = vertices[0] - vertices[count - 1];
	b2Vec2 v2 = vertices[1] - vertices[0];
	referenceDeterminant = calculate_determinant_2x2(v1.x, v1.y, v2.x, v2.y);

	for (i = 1; i < count - 1; i++)
	{
		v1 = v2;
		v2 = vertices[i + 1] - vertices[i];
		determinant = calculate_determinant_2x2(v1.x, v1.y, v2.x, v2.y);

		if (referenceDeterminant * determinant < 0.0f)
		{
			return false;
		}
	}
	v1 = v2;
	v2 = vertices[0] - vertices[count - 1];
	determinant = calculate_determinant_2x2(v1.x, v1.y, v2.x, v2.y);
	if (referenceDeterminant * determinant < 0.0f)
	{
		return false;
	}
	return true;
}
Example #6
0
// ============================================================================
/// Checks shape validity. Returns 0 if valid.
///\author Erin Catto, Daid
///\note Taken from Boxcuter, licensed n Box2D license.
int CheckPolyShape(const b2PolygonDef* poly)
{
	if (!(3 <= poly->vertexCount && poly->vertexCount <= b2_maxPolygonVertices))
		return -1;

	b2Vec2 m_normals[poly->vertexCount];

	// Compute normals. Ensure the edges have non-zero length.
	for (int32 i = 0; i < poly->vertexCount; ++i)
	{
		int32 i1 = i;
		int32 i2 = i + 1 < poly->vertexCount ? i + 1 : 0;
		b2Vec2 edge = poly->vertices[i2] - poly->vertices[i1];
		if (!(edge.LengthSquared() > B2_FLT_EPSILON * B2_FLT_EPSILON))
			return -1;
		m_normals[i] = b2Cross(edge, 1.0f);
		m_normals[i].Normalize();
	}

	// Ensure the polygon is convex.
	for (int32 i = 0; i < poly->vertexCount; ++i)
	{
		for (int32 j = 0; j < poly->vertexCount; ++j)
		{
			// Don't check vertices on the current edge.
			if (j == i || j == (i + 1) % poly->vertexCount)
			{
				continue;
			}
			
			// Your polygon is non-convex (it has an indentation).
			// Or your polygon is too skinny.
			float32 s = b2Dot(m_normals[i], poly->vertices[j] - poly->vertices[i]);
			if (!(s < -b2_linearSlop))
				return -1;
		}
	}

	// Ensure the polygon is counter-clockwise.
	for (int32 i = 1; i < poly->vertexCount; ++i)
	{
		float32 cross = b2Cross(m_normals[i-1], m_normals[i]);

		// Keep asinf happy.
		cross = b2Clamp(cross, -1.0f, 1.0f);

		// You have consecutive edges that are almost parallel on your polygon.
		float32 angle = asinf(cross);
		if (!(angle > b2_angularSlop))
			return -1;
	}

	// Compute the polygon centroid.
	b2Vec2 m_centroid; m_centroid.Set(0.0f, 0.0f);
	float32 area = 0.0f;

	// pRef is the reference point for forming triangles.
	// It's location doesn't change the result (except for rounding error).
	b2Vec2 pRef(0.0f, 0.0f);

	const float32 inv3 = 1.0f / 3.0f;

	for (int32 i = 0; i < poly->vertexCount; ++i)
	{
		// Triangle vertices.
		b2Vec2 p1 = pRef;
		b2Vec2 p2 = poly->vertices[i];
		b2Vec2 p3 = i + 1 < poly->vertexCount ? poly->vertices[i+1] : poly->vertices[0];

		b2Vec2 e1 = p2 - p1;
		b2Vec2 e2 = p3 - p1;

		float32 D = b2Cross(e1, e2);

		float32 triangleArea = 0.5f * D;
		area += triangleArea;

		// Area weighted centroid
		m_centroid += triangleArea * inv3 * (p1 + p2 + p3);
	}

	// Centroid
	if (!(area > B2_FLT_EPSILON))
		return -1;
	m_centroid *= 1.0f / area;

	// Compute the oriented bounding box.
	//ComputeOBB(&m_obb, m_vertices, m_vertexCount);

	// Create core polygon shape by shifting edges inward.
	// Also compute the min/max radius for CCD.
	for (int32 i = 0; i < poly->vertexCount; ++i)
	{
		int32 i1 = i - 1 >= 0 ? i - 1 : poly->vertexCount - 1;
		int32 i2 = i;

		b2Vec2 n1 = m_normals[i1];
		b2Vec2 n2 = m_normals[i2];
		b2Vec2 v = poly->vertices[i] - m_centroid;

		b2Vec2 d;
		d.x = b2Dot(n1, v) - b2_toiSlop;
		d.y = b2Dot(n2, v) - b2_toiSlop;

		// Shifting the edge inward by b2_toiSlop should
		// not cause the plane to pass the centroid.

		// Your shape has a radius/extent less than b2_toiSlop.
		if (!(d.x >= 0.0f))
			return -1;
		if (!(d.y >= 0.0f))
			return -1;
	}
	
	return 0;
}
Example #7
0
// Polygon mass, centroid, and inertia.
// Let rho be the polygon density in mass per unit area.
// Then:
// mass = rho * int(dA)
// centroid.x = (1/mass) * rho * int(x * dA)
// centroid.y = (1/mass) * rho * int(y * dA)
// I = rho * int((x*x + y*y) * dA)
//
// We can compute these integrals by summing all the integrals
// for each triangle of the polygon. To evaluate the integral
// for a single triangle, we make a change of variables to
// the (u,v) coordinates of the triangle:
// x = x0 + e1x * u + e2x * v
// y = y0 + e1y * u + e2y * v
// where 0 <= u && 0 <= v && u + v <= 1.
//
// We integrate u from [0,1-v] and then v from [0,1].
// We also need to use the Jacobian of the transformation:
// D = cross(e1, e2)
//
// Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
//
// The rest of the derivation is handled by computer algebra.
static void PolyMass(b2MassData* massData, const b2Vec2* vs, int32 count, float32 rho)
{
	b2Assert(count >= 3);

	b2Vec2 center; center.Set(0.0f, 0.0f);
	float32 area = 0.0f;
	float32 I = 0.0f;

	// pRef is the reference point for forming triangles.
	// It's location doesn't change the result (except for rounding error).
	b2Vec2 pRef(0.0f, 0.0f);
#if 0
	// This code would put the reference point inside the polygon.
	for (int32 i = 0; i < count; ++i)
	{
		pRef += vs[i];
	}
	pRef *= 1.0f / count;
#endif

	const float32 inv3 = 1.0f / 3.0f;

	for (int32 i = 0; i < count; ++i)
	{
		// Triangle vertices.
		b2Vec2 p1 = pRef;
		b2Vec2 p2 = vs[i];
		b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];

		b2Vec2 e1 = p2 - p1;
		b2Vec2 e2 = p3 - p1;

		float32 D = b2Cross(e1, e2);

		float32 triangleArea = 0.5f * D;
		area += triangleArea;

		// Area weighted centroid
		center += triangleArea * inv3 * (p1 + p2 + p3);

		float32 px = p1.x, py = p1.y;
		float32 ex1 = e1.x, ey1 = e1.y;
		float32 ex2 = e2.x, ey2 = e2.y;

		float32 intx2 = inv3 * (0.25f * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5f*px*px;
		float32 inty2 = inv3 * (0.25f * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5f*py*py;

		I += D * (intx2 + inty2);
	}

	// Total mass
	massData->mass = rho * area;

	// Center of mass
	b2Assert(area > FLT_EPSILON);
	center *= 1.0f / area;
	massData->center = center;

	// Inertia tensor relative to the center.
	I = rho * (I - area * b2Dot(center, center));
	massData->I = I;
}