Domanda

Voglio essere in grado di spostare una particella in linea retta all'interno di un ambiente 3D ma non riesco a pensare a come elaborare la posizione successiva in base a due punti all'interno di uno spazio 3D?

Ho creato una struttura che rappresenta una particella che ha una posizione e una posizione successiva? Sarebbe adatto a lavorare anche nella prossima posizione per spostarsi? So come impostare inizialmente la posizione successiva usando il seguente metodo:

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

Le strutture che ho usato sono:

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

Sto andando in questo modo completamente sbagliato?

ecco tutto il mio codice http://pastebin.com/m469f73c2

È stato utile?

Soluzione

L'altra risposta è un po 'matematica, in realtà è piuttosto semplice.

È necessaria una "Velocità" che stai spostando. Ha anche coordinate x, ye z.

In un periodo di tempo, per muoverti basta aggiungere la velocità x alla posizione x per ottenere la nuova posizione x, ripetere per ye z.

Inoltre, puoi avere un " Acceleration " (anche x, y, z) Ad esempio, l'accelerazione z potrebbe essere la gravità, una costante.

Ogni periodo di tempo in cui la tua velocità deve essere ricalcolata allo stesso modo, Chiama velocità x "vx", quindi vx dovrebbe diventare vx + ax, ripetere per y e z (di nuovo).

È passato un po 'di tempo dalla matematica, ma è così che me lo ricordo, piuttosto semplice a meno che non sia necessario tenere traccia delle unità, quindi diventa un po' più interessante (ma comunque non male)

Altri suggerimenti

Suggerirei che una particella dovrebbe avere un solo membro della posizione - la posizione corrente. Inoltre, la velocità dovrebbe idealmente essere un vettore di 3 componenti stessi. Crea una funzione (chiamala sposta , sposta qualunque cosa) che prende una particella e una durata t . Questo calcolerà la posizione finale dopo che t è trascorso:

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

Consiglierei due cose:

  1. leggi uno o due articoli sulla matematica vettoriale di base per l'animazione. Ad esempio, questo è un sito che spiega i vettori 2D per il flash.

  2. inizia in modo semplice, inizia con un punto 1d, ovvero un punto che si sposta solo lungo x. Quindi prova ad aggiungere una seconda dimensione (un punto 2d in uno spazio 2d) e una terza dimensione. Ciò potrebbe aiutarti a comprendere meglio la meccanica di base. spero che questo aiuti

Pensa alla fisica. Un oggetto ha una posizione (x, y, z) e un vettore di movimento (a, b, c). Il tuo oggetto dovrebbe esistere nella sua posizione; ha un vettore di movimento associato ad esso che descrive il suo momento. In mancanza di forze addizionali sull'oggetto, e supponendo che il tuo vettore di movimento descriva il movimento per un periodo di tempo t, la posizione del tuo oggetto al momento x sarà (x + (a t), y + ( b t), z + (c * t)).

In breve; non memorizzare la posizione corrente e la posizione successiva. Memorizza la posizione corrente e lo slancio dell'oggetto. È abbastanza facile " spuntare l'orologio " e aggiorna la posizione dell'oggetto semplicemente aggiungendo lo slancio alla posizione.

Memorizza la velocity come struct point3f, e quindi hai qualcosa del genere:

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

Essenzialmente la velocità è quanto vuoi che la posizione cambi ogni secondo / tick / qualunque cosa.

Desideri implementare la matematica vettoriale X_ {i + 1} = X_ {i} + Vt . Per i vettori X se V che rappresentano rispettivamente posizione e velocità e t che rappresentano il tempo. Ho parametrizzato la distanza lungo la pista per tempo perché sono un fisico, ma è davvero la cosa naturale da fare. Normalizza il vettore di velocità se vuoi fornire la distanza della traccia (cioè scala V tale che V.x * V.x + V.y * V.y + V.z * V.z = 1 ).

L'uso della struct sopra rende naturale l'accesso agli elementi, ma non è così conveniente fare l'aggiunta: gli array sono migliori per questo. In questo modo:

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

// initialize

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

Con un sindacato, puoi ottenere i vantaggi di entrambi:

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;

Se vuoi associare sia la posizione che la velocità della particella (una cosa molto ragionevole da fare) costruisci una struttura che supporti due vettori

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

ed esegui una routine di aggiornamento che assomiglia approssimativamente a:

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

Dopo tutto, ci sono principalmente due modi per calcolare la nuova posizione. Uno è come l'altro ha spiegato per usare una velocità esplicita. L'altra possibilità è quella di memorizzare l'ultima e la posizione corrente e di utilizzare Integrazione di Verlet . Entrambi i modi hanno i loro vantaggi e svantaggi. Puoi anche dare un'occhiata a questa pagina .

Se stai provando a muoverti lungo una linea retta tra due punti, puoi usare la formula di interpolazione:

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

P (t) è la posizione calcolata del punto, t è uno scalare compreso tra 0 e 1, P1 e P2 sono i punti finali e l'aggiunta di cui sopra è l'aggiunta vettoriale (quindi si applica questa formula separatamente al componenti x, ye z dei tuoi punti). Quando t = 0, ottieni P1; quando t = 1, ottieni P2, e per valori intermedi, ottieni un punto a metà della linea tra P1 e P2. Quindi t = .5 ti dà il punto medio tra P1 e P2, t = .333333 ti dà il punto 1/3 della strada da P1 a P2, ecc. I valori di t al di fuori dell'intervallo [0, 1] estrapolano ai punti lungo la linea esterna al segmento da P1 a P2.

Usare la formula di interpolazione può essere meglio che calcolare una velocità e aggiungerla ripetutamente se la velocità è piccola rispetto alla distanza tra i punti, perché si limita l'errore di arrotondamento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top