我目前正在做一个三维刚体模拟程序。我目前已经设法使刚体碰撞地板和弹跳正确地利用冲力。然而,我的问题是,一旦他们反弹,他们不断地加速,尽管使用摩擦矢量试图减缓他们。
Rvector fDirection(m_Bodies[i].Vel.x,0.0,m_Bodies[i].Vel.z);
Rvector relativeVelocities = m_Bodies[i].Vel - floorVelocity;
fDirection.normalize();
Real impulse = -(1+e) * (Rvector::dotProduct(relativeVelocities,floorNormal))
/ (1/m_Bodies[i].mass + floorMass);
Rvector friction = fDirection*mu*gravity.length()*m_Bodies[i].mass;
Rvector collision_forces = Rvector(0,1,0)*impulse;
collision_forces += friction ;
m_Bodies[i].Vel += (collision_forces/m_Bodies[i].mass);
谢谢
编辑:这里是集成代码。
void RigidBodySimulation::eulerIntegration(float dTime)
{
Rvector newVel;
Rvector newPos;
Rvector zero(0.0, 0.0, 0.0);
Real one_over_mass;
Rvector accel;
for( unsigned int i = 0 ; i < m_Bodies.size(); i++)
{
one_over_mass = 1/m_Bodies[i].mass;
newVel = m_Bodies[i].Vel + m_Bodies[i].force*one_over_mass*dTime;
newPos = m_Bodies[i].Pos + m_Bodies[i].Vel*dTime;
accel = m_Bodies[i].force / m_Bodies[i].mass;
m_Bodies[i].acceleration = accel;
m_Bodies[i].newPos = newPos;
m_Bodies[i].Vel = newVel;
m_Bodies[i].Pos = newPos;
}
}
我不得不说,这是一段非常糟糕的代码,我已经做了10多年了。你应该得到一本关于动力学的基本教科书(像Hibbeler那样)。
Real impulse = -(1+e) * (Rvector::dotProduct(relativeVelocities,floorNormal))
/ (1/m_Bodies[i].mass + floorMass);
这个方程式看起来像是在计算撞击的恢复冲量(尽管计算是错误的)。首先,你必须明白,冲动和力不是一回事。冲量是力在一定时间间隔上的积分。在撞击过程中,你可以假设这段时间非常小,这就是为什么你会执行瞬时速度变化。这就是为什么你应该指定积分代码与碰撞计算无关,因为它在那一瞬间是绕过的,或者至少,如果你做基于冲量的计算,它应该是绕过的。实际计算应该是这样的:
Real momentum_before = Rvector::dotProduct(m_Bodies[i].Vel * m_Bodies[i].mass + floorVelocity * floorMass, floorNormal);
Real rel_vel_after = -e * Rvector::dotProduct(relativeVelocities,floorNormal);
// conservation of momentum in normal direction gives this:
Real body_vel_after = (momentum_before + floorMass * rel_vel_after) / (m_Bodies[i].mass + floorMass);
Real floor_vel_after = body_vel_after - rel_vel_after;
这实际上简化为一行,如下所示:
Real body_vel_after = ( (m_Bodies[i].mass - e * floorMass) * Rvector::dotProduct(m_Bodies[i].Vel, floorNormal)
+ (1.0 + e) * floorMass * Rvector::dotProduct(floorVelocity, floorNormal)
) / (m_Bodies[i].mass + floorMass);
Real body_rel_vel_after = -e * Rvector::dotProduct(relativeVelocities, floorNormal);
Real body_vel_after = Rvector::dotProduct(floorVelocity, floorNormal) + body_rel_vel_after;
Real impulse = m_Bodies[i].mass * (body_vel_after - Rvector::dotProduct(m_Bodies[i].Vel, floorNormal));
现在,因为恢复冲量是法向力在撞击的小时间段内的积分,所以撞击过程中摩擦产生的冲量可以从恢复冲量中计算出来。摩擦力等于“mu”乘以法向力,即ff=mu*fn
,这也适用于冲量,即if=mu*in
。因此,您可以直接计算:
Real friction_impulse = mu * fabs(impulse);
但那只是摩擦冲量的大小。其方向与相对切向速度相反,即:
Rvector tangent_rel_vel = relativeVelocities - Rvector::dotProduct(relativeVelocities, floorNormal) * floorNormal;
它的方向是:
Rvector dir_rel_vel = tangent_rel_vel;
dir_rel_vel.normalize();
Rvector tangent_rel_vel_after = tangent_rel_vel - dir_rel_vel * friction_impulse / m_Bodies[i].mass;
Real tang_rel_vel_change = friction_impulse / mBodies[i].mass;
Rvector tangent_rel_vel_after = tangent_rel_vel - dir_rel_vel * tang_rel_vel_change;
if ( tang_rel_vel_change > tangent_rel_vel.length() )
tangent_rel_vel_after = Rvector(0.0, 0.0, 0.0); // stop relative motion.
此时,你所需要做的就是将两个最终的速度结合起来:
m_Bodies[i].Vel = floorVelocity + tangent_rel_vel_after + body_rel_vel_after * floorNormal;
至少,对于这个非常简单的问题(无限大的地板质量)来说,就是这样。在现实中,这种基于脉冲的方法变得越来越难处理,因为你把事情复杂化了:两个有限质量的物体,多个物体,以及实际的刚体动力学(因为你在这里只是做粒子动力学)。这种基于脉冲的方法很少见到,除了简单的校园里的球在地板上弹跳的例子。顺便说一句,你不应该把它叫做“刚体”模拟器,因为你实际上是在做一个粒子动力学(而三维刚体动力学要比这个复杂得多)。还有,你的积分法很糟糕,但那是完全不同的故事。
流氓和静态刚体 一般当我们创建一个刚体并将它添加到空间上后,空间就开始对之进行模拟,包括了对刚体位置、速度、受力以及重力影响等的模拟。没被添加到空间(没有被模拟)的刚体我们把它称之为流氓刚体。流氓刚体最重要的用途就是用来当作静态刚体,但是你仍然可以使用它来实现如移动平台这样的直接受控物体。 内存管理函数 cpBody *cpBodyAlloc(void) cpBody *cpBodyInit(cp
刚体是组成物理世界的基本对象,可以让一个节点受到物理影响并产生反应。该组件在使用 Builtin 物理引擎时无效。 点击 属性检查器 下方的 添加组件 -> 物理组件 -> Rigid Body 3D,即可添加刚体组件到节点上。 刚体属性 属性 功能说明 Mass 刚体的质量 Linear Damping 线性阻尼,用于减小刚体的线性速率,值越大物体移动越慢 Angular Damping 角阻尼
刚体是组成物理世界的基本对象,你可以将刚体想象成一个你不能看到(绘制)也不能摸到(碰撞)的带有属性的物体。 刚体属性 质量 刚体的质量是通过碰撞组件的 密度 与 大小 自动计算得到的。 当你需要计算物体应该受到多大的力时可能需要使用到这个属性。 var mass = rigidbody.getMass(); 移动速度 // 获取移动速度 var velocity = rigidbody.line
获取刚体组件 TypeScript的代码示例:const rigidBody = this.getComponent(RigidBody); 刚体类型 刚体一般分为三种类型,static,dynamic,kinematic. static,表示静态刚体,犹如质量巨大无比的石头,具体为质量为0的,或者只有碰撞组件的物理元素。 dynamic,表示动力学刚体,能够受到力的作用,具体为质量大于0并且is
如何模拟AsNoTracking方法? 在下面的示例中,DbContext已经注入到服务类中,如果我从GetOrderedProducts方法中移除AsNoTracking扩展方法,它可以正常工作,但是with AsNoTracking测试失败,因为它返回null。我还试图模拟AsNoTracking以返回正确的值,但它不起作用。
我有一个模型类和一个控制器。我在post man的正文中发布json类型的数据。但每次我都会收到一个不受支持的媒体类型415错误。这是我的模型课: 我的控制器是: 我已经用HttpServletRequest代替@RequestBody,它起到了作用。但为什么在我使用@RequestBody时它不工作呢? 这是邮递员的快照。这是邮递员请求的图片 这是请求中使用的标题的屏幕截图