Box2D-Lite源码阅读笔记(11)

  • 简介
    这次我来看详细的运动处理函数。
  • 计算准备工作
    看下面的这个函数里的实现。
void World::Step(float dt)
{
	...
	for (ArbIter arb = arbiters.begin(); arb != arbiters.end(); ++arb)
	{
		arb->second.PreStep(inv_dt);
	}
	...
}

代码如下,注释和后面都会有说明

void Arbiter::PreStep(float inv_dt)
{
	//补偿系数参数
	const float k_allowedPenetration = 0.01f;
	//补偿系数参数
	float k_biasFactor = World::positionCorrection ? 0.2f : 0.0f;
	for (int i = 0; i < numContacts; ++i)
	{
		//获取一个碰撞点
		Contact* c = contacts + i;
		//获取碰撞点到每个物体中心的向量
		Vec2 r1 = c->position - body1->position;
		Vec2 r2 = c->position - body2->position;

		//碰撞方向的冲量
		float rn1 = Dot(r1, c->normal);
		float rn2 = Dot(r2, c->normal);
		//这里的冲量计算公式
		float kNormal = body1->invMass + body2->invMass;
		kNormal += body1->invI * (Dot(r1, r1) - rn1 * rn1) + body2->invI * (Dot(r2, r2) - rn2 * rn2);
		c->massNormal = 1.0f / kNormal;

		//我推测这里是计算摩擦力方向上的冲量
		Vec2 tangent = Cross(c->normal, 1.0f);//旋转90的向量
		float rt1 = Dot(r1, tangent);
		float rt2 = Dot(r2, tangent);
		//这里是冲量计算公式
		float kTangent = body1->invMass + body2->invMass;
		kTangent += body1->invI * (Dot(r1, r1) - rt1 * rt1) + body2->invI * (Dot(r2, r2) - rt2 * rt2);
		c->massTangent = 1.0f /  kTangent;
		//补偿系数计算
		c->bias = -k_biasFactor * inv_dt * Min(0.0f, c->separation + k_allowedPenetration);
		//如果支持冲量累加
		if (World::accumulateImpulses)
		{
			// Apply normal + friction impulse
			Vec2 P = c->Pn * c->normal + c->Pt * tangent;//计算各个分量上的冲量总和
			//将冲量作用在速度和角速度上
			body1->velocity -= body1->invMass * P;
			body1->angularVelocity -= body1->invI * Cross(r1, P);

			body2->velocity += body2->invMass * P;
			body2->angularVelocity += body2->invI * Cross(r2, P);
		}
	}
}

这个里面用到了一个计算总冲量的公式。

∣ J ∣ = − ( v r ⋅ n ⃗ ) ( e + 1 ) 1 m 1 + 1 m 2 + n ⃗ ⋅ ( ( r 1 × n ⃗ ) / I 1 ) × r 1 + n ⃗ ⋅ ( ( r 2 × n ⃗ ) / I 2 ) × r 2 |J|=\frac{-(v_{r}\cdot{\vec{n}})(e+1)}{\frac{1}{m_{1}}+\frac{1}{m_{2}}+\vec{n}\cdot{((r_{1}\times{\vec{n}})/I_{1})\times{r_{1}}+\vec{n}\cdot((r_{2}\times{\vec{n}})/I_{2})\times{r_{2}}}} J=m11+m21+n ((r1×n )/I1)×r1+n ((r2×n )/I2)×r2(vrn )(e+1)
实际代码中的式子这里只写这一块了。
r 1 ⋅ r 1 − r 1 ⋅ n ⃗ ⋅ r 1 ⋅ n ⃗ r_{1}\cdot{r_{1}}-r_{1}\cdot{\vec{n}}\cdot{r_{1}\cdot{\vec{n}}} r1r1r1n r1n

n ⃗ ( ( r 1 × n ⃗ ) × r 1 ) \vec{n}((r_{1}\times{\vec{n}})\times{r_{1}}) n ((r1×n )×r1)
其中n为分离轴方向向量,r为碰撞点到物体中心的向量,I为转动惯量,m为物体质量,e+1是补偿系数,没有在这段代码里体现,vr是两个物体的相对速度。
实际上是一回事,经过一系列整理就可以达到,这里就不展开说明了。
实际上预计算就是计算总冲量公式总的分母部分,后面的迭代中,分母是不变的,所以这里先计算好。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Box2D-js是Box2D物理引擎的JavaScript端口,可以在Vue中使用。你需要先安装Box2D-js库。你可以通过npm安装,使用以下命令: ``` npm install box2d-js ``` 然后在Vue组件中使用Box2D-js,你需要引入Box2D-js库并创建Box2D世界。以下是一个简单的示例: ```html <template> <div> <canvas ref="canvas" width="800" height="600"></canvas> </div> </template> <script> import { b2Vec2, b2World, b2BodyDef, b2BodyType, b2PolygonShape, b2FixtureDef } from 'box2d-js' export default { mounted() { const canvas = this.$refs.canvas const ctx = canvas.getContext('2d') // 创建Box2D世界 const gravity = new b2Vec2(0, 10) const world = new b2World(gravity) // 创建地面刚体 const groundBodyDef = new b2BodyDef() groundBodyDef.position.Set(400 / 30, 550 / 30) const groundBody = world.CreateBody(groundBodyDef) const groundShape = new b2PolygonShape() groundShape.SetAsBox(400 / 30, 10 / 30) const groundFixtureDef = new b2FixtureDef() groundFixtureDef.shape = groundShape groundFixtureDef.density = 0 groundFixtureDef.friction = 0.5 groundFixtureDef.restitution = 0.2 groundBody.CreateFixture(groundFixtureDef) // 创建方块刚体 const boxBodyDef = new b2BodyDef() boxBodyDef.type = b2BodyType.b2_dynamicBody boxBodyDef.position.Set(200 / 30, 50 / 30) const boxBody = world.CreateBody(boxBodyDef) const boxShape = new b2PolygonShape() boxShape.SetAsBox(50 / 30, 50 / 30) const boxFixtureDef = new b2FixtureDef() boxFixtureDef.shape = boxShape boxFixtureDef.density = 1 boxFixtureDef.friction = 0.5 boxFixtureDef.restitution = 0.2 boxBody.CreateFixture(boxFixtureDef) // 模拟世界 setInterval(() => { world.Step(1 / 60, 10, 10) ctx.clearRect(0, 0, canvas.width, canvas.height) // 绘制地面 ctx.beginPath() ctx.moveTo(0, 550) ctx.lineTo(800, 550) ctx.stroke() // 绘制方块 ctx.save() ctx.translate(boxBody.GetPosition().x * 30, boxBody.GetPosition().y * 30) ctx.rotate(boxBody.GetAngle()) ctx.fillRect(-50, -50, 100, 100) ctx.restore() }, 1000 / 60) } } </script> ``` 这个示例创建了一个Box2D世界并在Canvas上绘制了一个方块和地面。你可以根据自己的需求修改这个示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值