在 C 和 OpenGL 中移动粒子

发布于 2024-07-18 10:27:28 字数 1196 浏览 2 评论 0原文

我希望能够在 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

I want to be able to move a particle in a straight line within a 3D environment but I can't think how to work out the next location based on two points within a 3D space?

I have created a struct which represents a particle which has a location and a next location? Would this be suitable to work out the next location to move too? I know how to initially set the next location using the following method:

// 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;
}

The structs I have used are:

// 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;
};

Am I going about this completely the wrong way?

here's all my code http://pastebin.com/m469f73c2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

绿萝 2024-07-25 10:27:28

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

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

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

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

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

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

The other answer is a little mathish, it's actually pretty straight forward.

You need a "Velocity" which you are moving. It also has x, y and z coordinates.

In one time period, to move you just add the x velocity to your x position to get your new x position, repeat for y and z.

On top of that, you can have an "Acceleration" (also x,y,z) For instance, your z acceleration could be gravity, a constant.

Every time period your velocity should be recalcualted in the same way, Call velocity x "vx", so vx should become vx + ax, repeat for y and z (again).

It's been a while since math, but that's how I remember it, pretty straight forward unless you need to keep track of units, then it gets a little more interesting (but still not bad)

残疾 2024-07-25 10:27:28

我建议粒子应该只有一个位置成员——当前位置。 此外,理想情况下速度本身应该是由 3 个分量组成的向量。 创建一个采用粒子和持续时间t的函数(将其称为movedisplace等)。 这将计算经过 t 个时间单位后的最终位置:

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;
}

I'd suggest that a particle should only have one location member -- the current location. Also, the velocity should ideally be a vector of 3 components itself. Create a function (call it move, displace whatever) that takes a particle and a time duration t. This will compute the final position after t units of time has elapsed:

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;
}
寻找我们的幸福 2024-07-25 10:27:28

我推荐两件事:

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

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

I would recomend two things:

  1. read an article or two on basic vector math for animation. For instance, this is a site that explains 2d vectors for flash.

  2. start simple, start with a 1d point, ie a point only moving along x. Then try adding a second dimension (a 2d point in a 2d space) and third dimension. This might help you get a better understanding of the underlying mechanics.
    hope this helps

自演自醉 2024-07-25 10:27:28

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

简而言之; 不存储当前位置和下一个位置。 存储当前位置和物体的动量。 只需将动量添加到位置,即可轻松“滴答作响”并更新对象的位置。

Think of physics. An object has a position (x, y, z) and a movement vector (a, b, c). Your object should exist at its position; it has a movement vector associated with it that describes its momentum. In the lack of any additional forces on the object, and assuming that your movement vector describes the movement over a time period t, the position of your object at time x will be (x + (at), y + (bt), z + (c*t)).

In short; don't store the current position and the next position. Store the current position and the object's momentum. It's easy enough to "tick the clock" and update the location of the object by simply adding the momentum to the position.

梦毁影碎の 2024-07-25 10:27:28

将速度存储为 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;
}

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

Store velocity as a struct point3f, and then you have something like this:

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

Essentially the velocity is how much you want the position to change each second/tick/whatever.

旧伤慢歌 2024-07-25 10:27:28

您想要实现向量数学 X_{i+1} = X_{i} + Vt。 对于Xs和V向量分别表示位置和速度,t表示时间。 因为我是一名物理学家,所以我按照时间参数化了沿轨道的距离,但这确实是很自然的事情。 如果您想给出轨迹距离(即缩放V,使得Vx*Vx + Vy*Vy + Vz*Vz = 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;
  }
}

You want to implement the vector math X_{i+1} = X_{i} + Vt. For the Xs and V vectors representing position and velocity respectively, and t representing time. I've parameterized the distance along the track by time because I'm a physicist, but it really is the natural thing to do. Normalize the velocity vector if you want to give track distance (i.e. scale V such that V.x*V.x + V.y*V.y + V.z*V.z = 1).

Using the struct above makes it natural to access the elements, but not so convenient to do the addition: arrays are better for that. Like this:

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

// initialize

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

With a union, you can get the advantages of both:

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;

If you want to associate both the position and the velocity of with the particle (a very reasonable thing to do) you construct a structure that support two vectors

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

and run an update routine that looks roughly like:

void update(particle *p, double dt){
  for (int i=0; i<3 ++i){
    p->position.a[i] += p->velocity.a[i]*dt;
  }
}
栀子花开つ 2024-07-25 10:27:28

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

Afaik, there are mainly two ways on how you can calculate the new position. One is like the other have explaint to use an explicit velocity. The other possibility is to store the last and the current position and to use the Verlet integration. Both ways have their advantages and disadvantages. You might also take a look on this interresting page.

凤舞天涯 2024-07-25 10:27:28

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

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 的线段外部的线。

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

If you are trying to move along a straight line between two points, you can use the interpolation formula:

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

P(t) is the calculated position of the point, t is a scalar ranging from 0 to 1, P1 and P2 are the endpoints, and the addition in the above is vector addition (so you apply this formula separately to the x, y and z components of your points). When t=0, you get P1; when t=1, you get P2, and for intermediate values, you get a point part way along the line between P1 and P2. So t=.5 gives you the midpoint between P1 and P2, t=.333333 gives you the point 1/3 of the way from P1 to P2, etc. Values of t outside the range [0, 1] extrapolate to points along the line outside the segment from P1 to P2.

Using the interpolation formula can be better than computing a velocity and repeatedly adding it if the velocity is small compared to the distance between the points, because you limit the roundoff error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文