top of page
Search
cedarcantab

Studying Box2D-Lite in Javascript, Part 8: Collision Detection - Polygon vs Circle

Updated: Mar 1



Polygon vs Circle



function b2CollidePolygonAndCircle(manifold, polygonA, xfA, circleB, xfB) {
	
	manifold.pointCount = 0;

	// Compute circle position in the frame of the polygon.
	
	
	let c = b2Mul(xfB, circleB.m_p); //b2Vec2 
	let cLocal = b2MulT(xfA, c); //b2Vec2 

	// Find the min separating edge.
	let normalIndex = 0;
	let separation = Number.NEGATIVE_INFINITY; //-b2_maxFloat;
	let radius = polygonA.m_radius + circleB.m_radius;
	let vertexCount = polygonA.m_count;
	const vertices = polygonA.m_vertices; //b2Vec2*
	const normals = polygonA.m_normals; //b2Vec2*

	for (let i = 0; i < vertexCount; ++i)	{
		let s = Vec2.b2Dot(normals[i], Vec2.Subtract(cLocal, vertices[i]));

		if (s > radius) {
			// Early out.
			return;
		}

		if (s > separation)		{
			separation = s;
			normalIndex = i;
		}
	}

	// Vertices that subtend the incident face.
	let vertIndex1 = normalIndex;
	let vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
	let v1 = vertices[vertIndex1]; //b2Vec2
	let v2 = vertices[vertIndex2]; //b2Vec2

	// If the center is inside the polygon ...
	if (separation < b2_epsilon) {
		manifold.pointCount = 1;
		manifold.type = b2Manifold.e_faceA;
		manifold.localNormal = normals[normalIndex];
		manifold.localPoint = Vec2.Scale(0.5, Vec2.Add(v1, v2));
		manifold.points[0].localPoint = circleB.m_p;
		manifold.points[0].id.key = 0;
		return;
	}

	// Compute barycentric coordinates
	let u1 = Vec2.b2Dot(Vec2.Subtract(cLocal, v1), Vec2.Subtract(v2, v1));
	let u2 = Vec2.b2Dot(Vec2.Subtract(cLocal, v2), Vec2.Subtract(v1, v2));
	if (u1 <= 0.0) {
		if (Vec2.DistanceSquared(cLocal, v1) > radius  radius)		{
			return;
		}

		manifold.pointCount = 1;
		manifold.type = b2Manifold.e_faceA;
		manifold.localNormal = Vec2.Subtract(cLocal, v1);
		manifold.localNormal.normalize();
		manifold.localPoint = v1;
		manifold.points[0].localPoint = circleB.m_p;
		manifold.points[0].id.key = 0;
	}
	else if (u2 <= 0.0) {
		if (Vec2.DistanceSquared(cLocal, v2) > radius  radius)		{
			return;
		}

		manifold.pointCount = 1;
		manifold.type = b2Manifold.e_faceA;
		manifold.localNormal = Vec2.Subtract(cLocal, v2);
		manifold.localNormal.normalize();
		manifold.localPoint = v2;
		manifold.points[0].localPoint = circleB.m_p;
		manifold.points[0].id.key = 0;
	}
	else
	{
		let faceCenter = Vec2.Scale(0.5, Vec2.Add(v1, v2)); //b2Vec2
		let s = Vec2.b2Dot(Vec2.Subtract(cLocal, faceCenter), normals[vertIndex1]);
		if (s > radius) {
			return;
		}

		manifold.pointCount = 1;
		manifold.type = b2Manifold.e_faceA;
		manifold.localNormal = normals[vertIndex1];
		manifold.localPoint = faceCenter;
		manifold.points[0].localPoint = circleB.m_p;
		manifold.points[0].id.key = 0;
	}

}

2 views0 comments

Recent Posts

See All

p2 naive broadphase

var Broadphase = require('../collision/Broadphase'); module.exports = NaiveBroadphase; /** * Naive broadphase implementation. Does N^2...

sopiro motor constranit

import { Matrix2, Vector2 } from "./math.js"; import { RigidBody } from "./rigidbody.js"; import { Settings } from "./settings.js";...

Comments


記事: Blog2_Post
bottom of page