物理体以高速相互弹跳

2024-06-14 23:14:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python开发一个物理引擎(我知道,它主要是为了“学习”),并且运行得很好。我一直在关注很多关于这个问题的在线文档,这一系列的文章特别有用:How to Create a Custom Physics Engine

我有一些材料在工作,它们作为一个类来保存一个物体的restitutiondensity。接下来发生的事情是,具有低密度和高恢复性的物体(例如分别为0.3和0.8),它们以如此高的速度相互反弹,以至于它们不需要很长时间就射入“空洞”

我有一个测试场景,设置了4堵墙来包围身体(球)。当它们以如此高的速度前进时,碰撞永远不会被记录,因为下一次物理模拟发生在它们已经通过“墙”之后

我真正感兴趣的是为什么它们在相互弹跳时速度如此之快,而我认为它们不应该这样。在我的示例录音中,我有一个小球(红色),它是由玩家(我)控制的。它的密度为0.3,恢复率为0.8,体积为100(r*r或10*10),质量为30千克(100*0.3)。另一个较大的球(绿色)不是由玩家控制的,但可以通过用红色球击打来反弹。它具有相同的材料,因此具有相同的密度和恢复性。但是,其质量更高,因为半径更大(30)。绿球的实际质量为270(900*0.8)

在录音中很明显,球以一种不自然的方式相互反弹。小球不应该受到比大球更高的冲动吗?我试图通过交换计算冲量时使用的质量值来解决这个问题。所以小球的冲量是用大球的质量来计算的,反之亦然。你会认为这是因为更大的球有更高的质量,但对我来说,它们彼此反弹得相当快

这是我在这两个球上的密度和恢复的正常行为吗?如果需要,我将共享代码,但由于本文已经有点长,如果不需要,我不会浪费空间。我的代码几乎完全遵循文章中介绍的内容,只是“转换”为Python代码

Bouncing Balls (Red = Player)Bouncing Balls (Red = Player)

脉冲计算程序

# Relative velocity
rv = b.velocity - a.velocity

# Velocity along the normal direction
vel_along_normal = rv.dot(contact_normal)

# EPSILON (use lowest restitution value)
e = min(a.restitution, b.restitution)

# Calculate j, which will be used to get the impulse
j = -(1 + e) * vel_along_normal
j /= a_inv_mass + b_inv_mass

impulse = contact_normal * j

# Using ratio to have lighter bodies bounce with a higher impulse than heavier bodies
mass_sum = a_mass + b_mass
ratio = (b_mass / mass_sum)
a.rigid_body.velocity -= (impulse * ratio) * dt

ratio = (a_mass / mass_sum)
b.rigid_body.velocity += (impulse * ratio) * dt

Tags: to代码质量物理速度mass密度sum
2条回答

碰撞后的速度差似乎存在符号问题。它并没有减慢红球的速度,而是加快了速度

整个功能在我看来并不正确,而且由于它不能按预期工作,因此出现了一些问题。下面的代码片段将为您解决冲突问题,而不是尝试找出错误(代码中有太多未知项,dta_inv_massb_inv_masscontact_normal

// A and B are balls at time of collision
mA = A.mass
mB = B.mass
mm = mA + mB

// vector between balls
x = A.x - B.x
y = A.y - B.y  

// restitution
e1 = A.restitution
e2 = B.restitution

// distance sqr between balls
d = x * x + y * y;

// v velocities
uAB = (A.v.x * x + A.v.y * y) / d  // normal component force A into B
u2  = (A.v.y * x - A.v.x * y) / d  // tangent component force A

uBA = (B.v.x * x + B.v.y * y) / d  // normal component force B into A
u4  = (B.v.y * x - B.v.x * y) / d  // tangent component force B

// Force from B into A along normal, scaled for mass ratio and restitution
uA = ((mA - mB) / mm * uAB + (2 * mB) / mm * uBA) * e1

// Force from A into B along normal, scaled for mass ratio and restitution
uB = ((mB - mA) / mm * uBA + (2 * mA) / mm * uAB) * e2

// new velocities 
A.v.x = x * uA - y * u2
A.v.y = y * uA + x * u2

B.v.x = x * uB - y * u4
B.v.y = y * uB + x * u4

注意忽略dt(假设dt为增量时间)

注意两个对象都必须具有一定的质量。如果一个或两个质量都为0,则此操作将不起作用

相关问题 更多 >