1

我希望能够在 3D 环境中沿直线移动粒子,但我想不出如何根据 3D 空间中的两个点计算出下一个位置?

我创建了一个结构,它代表一个具有位置和下一个位置的粒子?这也适合计算下一个移动位置吗?我知道如何使用以下方法初始设置下一个位置:

// Set particle's direction to a random direction
void setDirection(struct particle *p)
{
    float xnm = (p->location.x * -1) - p->velocity;
    float xnp = p->location.x + p->velocity;
    float ynm = (p->location.y * -1) - p->velocity;
    float ynp = p->location.y + p->velocity;
    float znm = (p->location.z * -1) - p->velocity;
    float znp = p->location.z + p->velocity;

    struct point3f nextLocation = { randFloat(xnm, xnp), randFloat(ynm, ynp), randFloat(znm, znp) };
    p->nextLocation = nextLocation;
}

我使用的结构是:

// Represents a 3D point
struct point3f
{
    float x;
    float y;
    float z;
};

// Represents a particle
struct particle
{
    enum TYPES type;
    float radius;
    float velocity;
    struct point3f location;
    struct point3f nextLocation;
    struct point3f colour;
};

我会以完全错误的方式解决这个问题吗?

这是我所有的代码http://pastebin.com/m469f73c2

4

8 回答 8

3

我建议一个粒子应该只有一个位置成员——当前位置。此外,理想情况下,速度本身应该是 3 个分量的向量。创建一个需要 a和 time duration的函数(调用它move,无论如何) 。这将计算单位时间过去后的最终位置:displaceparticlett

struct point3f move(struct *particle, int time) {
    particle->location->x = particle->velocity->x * t;
    /* and so on for the other 2 dimensions */
    return particle->location;
}
于 2009-04-29T21:14:40.517 回答
3

另一个答案有点数学,实际上很简单。

你需要一个你正在移动的“速度”。它还具有 x、y 和 z 坐标。

在一个时间段内,要移动您只需将 x 速度添加到您的 x 位置以获得新的 x 位置,重复 y 和 z。

最重要的是,你可以有一个“加速度”(也是 x,y,z)例如,你的 z 加速度可以是重力,一个常数。

每个时间段你的速度都应该以同样的方式重新计算,调用速度 x“vx”,所以 vx 应该变成 vx + ax,对 y 和 z 重复(再次)。

自从数学以来已经有一段时间了,但这就是我记得的方式,非常简单,除非你需要跟踪单位,然后它会变得更有趣(但仍然不错)

于 2009-04-29T21:17:15.520 回答
2

我会推荐两件事:

  1. 阅读一两篇关于动画基本矢量数学的文章。例如,是一个解释 flash 的 2d 矢量的网站。

  2. 开始简单,从一维点开始,即仅沿 x 移动的点。然后尝试添加第二维(二维空间中的二维点)和第三维。这可能有助于您更好地了解底层机制。希望这可以帮助

于 2009-04-29T21:41:25.727 回答
1

想想物理学。一个对象有一个位置 (x, y, z) 和一个运动向量 (a, b, c)。你的对象应该存在于它的位置;它有一个与之关联的运动矢量来描述它的动量。在物体上没有任何附加力的情况下,并假设您的运动矢量描述了时间段 t 内的运动,您的物体在时间 x 的位置将是 (x + (a t), y + (b t) , z + (c*t))。

简而言之; 不要存储当前位置和下一个位置。存储当前位置和对象的动量。只需将动量添加到位置,就可以很容易地“计时”并更新对象的位置。

于 2009-04-29T21:13:38.943 回答
1

将velocity存储为struct point3f,然后你有这样的东西:

void move(struct particle * p)
{
  p->position.x += p->velocity.x;
  p->position.y += p->velocity.y;
  p->position.z += p->velocity.z;
}

本质上,速度是您希望位置每秒/滴答声/任何改变的程度。

于 2009-04-29T21:14:04.233 回答
0

你想实现向量数学X_{i+1} = X_{i} + Vt。对于Xs和Vvectors,分别代表位置和速度,t代表时间。因为我是物理学家,所以我已经按时间参数化了沿轨道的距离,但这确实是很自然的事情。如果你想给出轨道距离(即比例VV.x*V.x + V.y*V.y + V.z*V.z = 1),则归一化速度矢量。

使用struct上面的方法可以很自然地访问元素,但做加法并不那么方便:数组更适合这个。像这样:

double X[3];
double V[3];

// initialize

for (int i=0; i<3 ++1){
  X[i] = X[i] + V[i]*t;
}

使用联合,您可以获得两者的优势:

struct vector_s{
  double x;
  double y;
  double z;
}
typedef
union vector_u {
  struct vector_s s; // s for struct
  double a[3];       // a for array
} vector;

如果您想将 的位置和速度与粒子相关联(这是一件非常合理的事情),您可以构建一个支持两个向量的结构

typedef
struct particle_s {
  vector position;
  vector velocity;
  //...
} particle_t;

并运行一个大致如下所示的更新例程:

void update(particle *p, double dt){
  for (int i=0; i<3 ++i){
    p->position.a[i] += p->velocity.a[i]*dt;
  }
}
于 2009-04-29T21:09:33.680 回答
0

Afaik,主要有两种方法可以计算新位置。一个就像另一个解释使用显式速度一样。另一种可能性是存储最后和当前位置并使用Verlet 集成。两种方式都有其优点和缺点。你也可以看看这个有趣的页面

于 2009-04-30T08:29:55.793 回答
0

如果您试图沿着两点之间的直线移动,您可以使用插值公式:

P(t) = P1*(1-t) + P2*t

P(t)是点的计算位置,t是0到1的标量,P1和P2是端点,上面的加法是向量加法(所以你把这个公式分别应用到x,y和你的点的z分量)。当 t=0 时,得到 P1;当 t=1 时,您会得到 P2,对于中间值,您会在 P1 和 P2 之间的连线上得到一个点。因此 t=.5 为您提供 P1 和 P2 之间的中点,t=.333333 为您提供从 P1 到 P2 的 1/3 点,依此类推。 [0, 1] 范围之外的 t 值外推到沿线的点从 P1 到 P2 的线段外的线。

如果速度与点之间的距离相比较小,则使用插值公式可能比计算速度并重复添加它更好,因为您限制了舍入误差。

于 2009-05-01T18:45:26.787 回答