制作2D物理引擎:质量,惯性和力(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/making-a-d-physics-engine-mass-inertia-and-forces-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 8 分钟阅读 - 3684 个词 阅读量 0制作2D物理引擎:质量,惯性和力(译文)
原文地址:https://www.codeproject.com/Articles/1215961/Making-a-D-Physics-Engine-Mass-Inertia-and-Forces
原文作者:Arav Singhal
译文由本站 robot-v1.0 翻译
前言
Calculating the mass and inertia of a body and applying forces to it
计算物体的质量和惯性并对其施加力
制作2D物理引擎:系列(Making a 2D Physics Engine: The Series)
这是该文章的第四篇(This is the fourth article in the)制作2D物理引擎(Making a 2D Physics Engine)系列.如果您尚未阅读本系列之前的所有文章,我强烈建议您绕道而过.(Series. If you haven’t already read all the articles in the series before this one, I strongly recommend that you take a detour and skim through them.)
- 制作2D物理引擎:数学(Making a 2D Physics Engine: The Math)
- 制作2D物理引擎:空间与物体(Making a 2D Physics Engine: Spaces and Bodies)
- 制作2D物理引擎:形状,世界和整合(Making a 2D Physics Engine: Shapes, Worlds and Integration)
- 制作2D物理引擎:质量,惯性和力(Making a 2D Physics Engine: Mass, Inertia and Forces)
介绍(Introduction)
每个物理对象都有一些质量和惯性矩,这取决于其形状和密度.在本文中,我们将根据物体的质量和惯性为其分配(Every physical object has some mass and moment of inertia which is determined by its shape and density. In this article, we will assign mass and inertia to our bodies based on its) Shape
并提供密度以使交互更加逼真.为了简单起见,我们假设对象具有统一的密度.(and provided density to make interactions more realistic. To keep things simple, we assume that objects have uniform density.)
我们还将学习在现实生活中如何应用力,并在我们的物理引擎中模拟它们.(We will also learn how forces are applied in real life and emulate them in our physics engine.)
本文的内容包含在(The contents of this article are contained in the history of) 这个提交(this commit) 的(of the) 2D物理引擎(2D physics engine) 我将与本系列文章一起在Rust中构建.(I am building in Rust along with this article series.)
不要怕!碰撞即将来临.(Do not fear! Collisions are coming soon.)
质量和惯性计算(Mass and Inertia Calculation)
前处理(Preprocessing)
在开始之前,我们必须确保身体的质心是其局部空间的原点.对于密度均匀的形状,质心只是质心.(Before we begin, we must make sure that the center of mass of our body is the origin in its local space. For shapes with uniform density, the center of mass is simply the centroid.)
界(Circles)
根据我们的定义(By our definition of a) Circle
,圆心已经是它的质心.我们在这里不需要做任何事情.(, the centre of the circle is already its centroid. We do not need to do anything here.)
多边形(Polygons)
一种(A) Polygon
但是,可以是任意的.我们必须找到顶点的质心并将其从每个顶点中减去,以使多边形顶点相对于质心为中心.(, however, can be arbitrary. We must find the centroid of the vertices and subtract it from each vertex so that the polygon vertices are relative to the centroid as the center.)
多边形的质心是(The centroid of the polygon is a) 多边形顶点的加权平均值(weighted average of the vertices of the polygon) ,由脸部三角形区域加权.本文稍后将给出用于计算面部三角形面积和多边形面积的公式(及其解释).(, weighted by face triangle area. The formulas (and their explanation) for calculating face triangle area and polygon area are given later on in the article.)
重心计算如下:(The centroid is calculated as follows:)
centroid = Vec2::ZERO;
for face in polygon {
face_area = 0.5 * face.vertex_a.cross(face.vertex_b);
centroid += (face.vertex_a + face.vertex_b) * face_area / (3.0 * polygon_area);
}
// Make the centroid the origin
for vertex in vertices {
vertex -= centroid;
}
弥撒(Mass)
根据质量的定义,(By the definition of mass,) mass = density * volume
.作为加法量(. Being an additive quantity,) volume
(二维区域)可以通过将给定形状分解为较小的形状来计算.((area in 2D) can be calculated by breaking the given shape into smaller shapes.)
界(Circles)
圆的面积是(The area of a circle is)(\ pi r ^ 2 )((\pi r^2))要么(or) PI * radius * radius
,这使我们的质量定义非常简单:(, which makes our mass definition very simple:)
mass = density * PI * radius * radius;
多边形(Polygons)
任意凸多边形的面积没有固定的公式,但是我们可以将多边形细分为在顶点处具有顶点的三角形.多边形的面积是细分三角形面积的总和.(The area of an arbitrary convex polygon does not have a fixed formula, but we can subdivide the polygon into triangles with a vertex at the centroid. The area of the polygon is the sum of the areas of the subdivided triangles.)
每个细分的三角形在原点(质心)都有一个顶点,并且有两个顶点作为多边形的一个面的顶点.(Each subdivided triangle has a vertex at the origin (centroid), and two vertices as the vertices of a face of the polygon.)
具有边向量的三角形的面积(The area of a triangle with side vectors) A
和(and) B
是(谁)给的(is given by) 0.5 * abs(A.cross(B))
.这是一个众所周知的结果,可以轻松地在网上找到其推导.因此,对于顶点(. This is a well known result whose derivation can easily be found online. Thus, for the vertices) A
和(and) B
,对应的细分三角形的边向量为(, the side vectors of the corresponding subdivided triangle are) A
和(and) B
而面积是(and the area is) 0.5 * abs(A.cross(B))
.我们多边形的面积就是这些面积的总和.(. The area of our polygon is simply the sum of the areas of these areas.)
area = 0;
for face in polygon {
area += 0.5 * abs(face.vertex_a.cross(face.vertex_b));
}
大众现在(The mass is now) density * area
.(.)
惯性(Inertia)
2D旋转是围绕垂直于2D平面的轴,即Z轴.就这样(Rotations in 2D are about the axis perpendicular to the 2D plane, i.e. the Z-axis. Thus, the) 惯性矩(moment of inertia) 2D形状的"转角"是形状绕Z轴通过原点的惯性矩.它类似于质量,它是人体对扭矩或旋转运动的抵抗力的度量.像质量一样,惯性是可加的,任何形状的惯性都可以通过将构成它的较小形状的惯性相加而得出.(of a 2D shape is the moment of inertia of the shape about the Z-axis passing through the origin. It is analogous to mass in that it is a measure of the resistance a body offers to torque or rotational motion. Like mass, inertia is additive and the inertia of any shape can be calculated by summing the inertia of smaller shapes that constitute it.)
界(Circles)
圆绕垂直于其中心的垂直轴的惯性为(The inertia of a circle about a perpendicular axis passing through its center is)(\ frac {1} {2} m r ^ 2 )((\frac{1}{2} m r^2)):(:)
inertia = 0.5 * mass * radius * radius;
多边形(Polygons)
任意凸多边形的惯性没有固定的公式,但是像质量一样,我们可以通过将多边形细分为以顶点为原点的三角形并找到其惯性来计算惯性.(The inertia of an arbitrary convex polygon does not have a fixed formula, but like mass we can compute the inertia by subdividing the polygon into triangles with a vertex at the origin and finding their inertia.)
在原点和边向量处具有顶点的三角形的惯性(The inertia of a triangle with a vertex at the origin and side vectors) A
和(and) B
绕过原点的垂直轴为(about a perpendicular axis passing through the origin is given by) mass * (A.sqrLength() + B.sqrLength() + A.dot(B)) / 6
.该公式的推导是不平凡的,为简洁起见,此处将不包括在内.如果您要挑战(a(. The derivation of this formula is non-trivial and will not be included here for the sake of brevity. If you are up for a challenge (a)**冗长(lengthy)**一个),不过,您可以尝试通过将三角形分成与不包含原点的边平行的细矩形(即由(one), however, you can try proving this result yourself by breaking the triangle up into thin rectangles parallel to the edge that does not contain the origin, i.e., the edge formed by) A
和(and) B
.(.)
现在可以如下计算多边形的惯量:(The inertia for the polygon can now be computed as follows:)
inertia = 0;
for face in polygon {
A = face.vertex_a, B = face.vertex_b;
mass_tri = density * 0.5 * abs(A.cross(B));
inertia_tri = mass_tri * (A.sqrLength() + B.sqrLength() + A.dot(B)) / 6;
inertia += inertia_tri;
}
施加力(Application of Forces)
本节假定您具有有关什么是力和扭矩,它们如何相互关联以及它们与加速度如何相关的基本知识.力量在上一篇文章中进行了简要讨论,但此处讨论的要点将再次进行讨论以求相关.(This section assumes that you have basic knowledge on what forces and torques are, how they are related to each other, and how they relate to acceleration. Forces were briefly discussed in the previous article, but the points covered there will be discussed again for relevance.) 外部因素(包括物理引擎)与人体的主要相互作用机制将是通过力(和间接转矩).但是,与身体的所有交互都应基于每个帧或每个时间步.这样,施加到物体上的所有力和扭矩应仅对当前框架有效.力量也是在现实生活中发挥作用的方式,但是由于我们的世界是连续的,不是分散的并且没有任何"时间步伐"的,因此尚不清楚.(The main interaction mechanism of external agents (including the physics engine) with a body is going to be through forces (and indirectly torque). However, any and all interactions with a body should be on a per-frame or per-timestep basis. As such, all forces and torques applied to a body should be valid only for the current frame. This is how forces work in real life too, but it is not evident because our world is continuous, not discrete, and does not have any “timesteps”.) 当在某个点向身体施加力时,它会在质心产生线性加速度以及扭矩.但是,有两种特殊情况需要考虑:(When a force is applied on a body at a certain point, it produces a linear acceleration at the center of mass as well as a torque. However, there are two special cases to consider:)
- 施加的扭矩为零:根据扭矩的定义,(Torque applied is zero: By the definition of torque,)(\ vec {\ tau} =\ vec {r} \ times \ vec {F} )((\vec{\tau} = \vec{r} \times \vec{F})).因此,当在质心处施加力时,合成转矩将为零.(. Thus, when the force is applied at the center of mass, the resultant torque will be zero.)
- 施加的力为零:使用一对力(一对力大小相等但方向相反的力)来产生扭矩而不产生线性加速度.质心上相等但相反的线性力相互抵消.(Force applied is zero: A couple (a pair of forces equal in magnitude but opposite in direction) is used to generate torque without generating linear acceleration. The equal but opposite linear forces at the center of mass cancel each other out.) 在我们的刚体结构中,由于我们具有独立的力(在质心)和扭矩变量,因此我们可以首先实现每种情况,然后使用这些实现在任意点施加力.(In our rigidbody structure, since we have independent force (at center of mass) and torque variables, we can implement each of these cases first and use these implementations to apply a force at an arbitrary point.)
pub fn add_force(&mut self, force: Vec2) {
self.force += force;
}
pub fn add_torque(&mut self, torque: f32) {
self.torque += torque;
}
pub fn add_force_at_pos(&mut self, force: Vec2, pos: Vec2) {
self.add_force(force);
self.add_torque(pos.cross(force));
}
冲动(Impulses)
冲动是动量的有限变化.它们也可以看作是在很短的时间内施加的巨大力量.但是,我们将它们视为动量的变化,并在施加脉冲时直接修改线速度和角速度:(Impulses are finite changes in momentum. They can also be considered as large forces applied over very short periods. However, we will consider them as momentum changes and directly modify the linear and angular velocities when an impulse is applied:)
pub fn add_impulse_at_pos(&mut self, impulse: Vec2, pos: Vec2) {
self.velocity += impulse * self.inv_mass;
self.angular_vel += pos.cross(impulse) * self.inv_inertia;
}
未来的步骤(Future Steps)
恭喜你!我们已经研究了物理引擎的枯燥基础,现在可以继续进行更有趣(更困难)的事情:碰撞.我建议您在下一篇文章之前及时复习线性代数.相信我,您将需要它.(Congratulations! We have gone through the boring foundations of a physics engine and now can move on to something widely more interesting (and difficult): collisions. I advise you to brush up your linear algebra in time for the next article. Trust me, you will need it.)
历史(History)
- 28(28)日(th)2018年1月:初始职位(January, 2018: Initial post)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
physics 2D mathematics 新闻 翻译