Pregunta

Quiero poder mover una partícula en línea recta dentro de un entorno 3D, pero no puedo pensar cómo calcular la siguiente ubicación basada en dos puntos dentro de un espacio 3D.

¿He creado una estructura que representa una partícula que tiene una ubicación y una ubicación siguiente? ¿Sería esto adecuado para calcular la siguiente ubicación para mudarse también? Sé cómo establecer inicialmente la siguiente ubicación utilizando el siguiente método:

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

Las estructuras que he usado son:

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

¿Estoy haciendo esto completamente por el camino equivocado?

Aquí está todo mi código http://pastebin.com/m469f73c2

¿Fue útil?

Solución

La otra respuesta es un poco matemática, en realidad es bastante sencilla.

Necesitas un " Velocidad " que te estás moviendo También tiene coordenadas x, y y z.

En un período de tiempo, para moverlo simplemente agregue la velocidad x a su posición x para obtener su nueva posición x, repita para y y z.

Además de eso, puede tener un " Aceleración " (también x, y, z) Por ejemplo, su aceleración z podría ser la gravedad, una constante.

Cada período de tiempo, su velocidad debe recalcularse de la misma manera, Llame a la velocidad x '' vx '', entonces vx debe convertirse en vx + ax, repita para y y z (nuevamente).

Ha pasado un tiempo desde las matemáticas, pero así es como lo recuerdo, bastante sencillo a menos que necesite hacer un seguimiento de las unidades, entonces se vuelve un poco más interesante (pero aún no está mal)

Otros consejos

Sugeriría que una partícula solo debería tener un miembro de ubicación: la ubicación actual. Además, la velocidad debería ser idealmente un vector de 3 componentes. Cree una función (llámela move , desplazar lo que sea) que tome una partícula y una duración de tiempo t . Esto calculará la posición final después de que hayan transcurrido t unidades de tiempo:

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

Recomendaría dos cosas:

  1. lea uno o dos artículos sobre matemática vectorial básica para la animación. Por ejemplo, este es un sitio que explica vectores 2D para flash.

  2. comienza simple, comienza con un punto 1d, es decir, un punto que solo se mueve a lo largo de x. Luego intente agregar una segunda dimensión (un punto 2d en un espacio 2d) y una tercera dimensión. Esto podría ayudarlo a comprender mejor la mecánica subyacente. Espero que esto ayude

Piensa en la física. Un objeto tiene una posición (x, y, z) y un vector de movimiento (a, b, c). Su objeto debe existir en su posición; tiene un vector de movimiento asociado que describe su impulso. En la ausencia de fuerzas adicionales sobre el objeto, y suponiendo que su vector de movimiento describe el movimiento durante un período de tiempo t, la posición de su objeto en el tiempo x será (x + (a t), y + ( b t), z + (c * t)).

En resumen; no almacene la posición actual y la siguiente posición. Almacene la posición actual y el impulso del objeto. Es bastante fácil " marcar el reloj " y actualice la ubicación del objeto simplemente agregando el impulso a la posición.

Almacene la velocidad como una estructura point3f, y luego tendrá algo como esto:

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

Esencialmente, la velocidad es cuánto desea que cambie la posición cada segundo / tic / lo que sea.

Desea implementar el vector math X_ {i + 1} = X_ {i} + Vt . Para los vectores X sy V que representan la posición y la velocidad respectivamente, y t que representa el tiempo. He parametrizado la distancia a lo largo de la pista por tiempo porque soy físico, pero realmente es lo más natural. Normalice el vector de velocidad si desea dar la distancia de la pista (es decir, escale V de modo que V.x * V.x + V.y * V.y + V.z * V.z = 1 ).

El uso de la struct anterior hace que sea natural acceder a los elementos, pero no es tan conveniente hacer la adición: las matrices son mejores para eso. Así:

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

// initialize

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

Con un sindicato, puede obtener las ventajas de ambos:

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;

Si desea asociar tanto la posición como la velocidad de la partícula (algo muy razonable), construya una estructura que soporte dos vectores

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

y ejecute una rutina de actualización que se parece aproximadamente a:

void update(particle *p, double dt){
  for (int i=0; i<3 ++i){
    p->position.a[i] += p->velocity.a[i]*dt;
  }
}

Afaik, existen principalmente dos formas de calcular la nueva posición. Uno es como el otro tiene una explicación para usar una velocidad explícita. La otra posibilidad es almacenar la última posición y la actual y usar la integración Verlet . Ambas formas tienen sus ventajas y desventajas. También puede echar un vistazo a esta página interesante.

Si está intentando moverse a lo largo de una línea recta entre dos puntos, puede usar la fórmula de interpolación:

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

P (t) es la posición calculada del punto, t es un escalar que varía de 0 a 1, P1 y P2 son los puntos finales, y la suma en lo anterior es la suma vectorial (por lo que aplica esta fórmula por separado al componentes x, y y z de sus puntos). Cuando t = 0, obtienes P1; cuando t = 1, obtienes P2, y para valores intermedios, obtienes un punto en parte a lo largo de la línea entre P1 y P2. Entonces t = .5 le da el punto medio entre P1 y P2, t = .333333 le da el punto 1/3 del camino de P1 a P2, etc. Los valores de t fuera del rango [0, 1] se extrapolan a puntos a lo largo la línea fuera del segmento de P1 a P2.

Usar la fórmula de interpolación puede ser mejor que calcular una velocidad y agregarla repetidamente si la velocidad es pequeña en comparación con la distancia entre los puntos, porque limita el error de redondeo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top