2011-01-20 10 views
8

Już szukałem w Google problemu, ale znalazłem tylko rozwiązania 2D lub formuły, które nie działały dla mnie (znalazłem tę formułę, która wygląda ładnie: http://www.ogre3d.org/forums/viewtopic.php?f=10&t=55796, ale wydaje się, że nie jest poprawny).strzelać pociskami (trajektoria prosta) na ruchomym celu w 3 wymiarach

dałem:

Vec3 cannonPos; 
Vec3 targetPos; 
Vec3 targetVelocityVec; 
float bulletSpeed; 

co szukam jest taka, że ​​czas t

targetPos+t*targetVelocityVec 

jest intersectionpoint gdzie celować i strzelać armaty.

Szukam prostego, niedrogiego wzoru na t (przez proste i po prostu nie myśli podejmowania wielu niepotrzebnych przekształceń vectorspace i tym podobne)

dzięki!

+0

rozważa pocisk Następuje prosta trajektoria sprawia problem dość nieciekawą :-( – salva

Odpowiedz

15

Prawdziwym problemem jest ustalenie, gdzie w przestrzeni pocisk może przecinać ścieżkę celu. Prędkość pocisku jest stała, więc w pewnym czasie pokona tę samą odległość, niezależnie od kierunku, w którym ją wystrzelimy. Oznacza to, że jego pozycja po czasie t zawsze będzie leżeć na kuli. Oto brzydki ilustracja 2D:

Sfera ta może być wyrażona matematycznie jako:

(x-x_b0)^2 + (y-y_b0)^2 + (z-z_b0)^2 = (bulletSpeed * t)^2  (eq 1) 

x_b0, y_b0 i z_b0 oznaczają pozycję armaty. Można znaleźć czasu t rozwiązując to równanie dla t za pomocą równania podanego w pytaniu:

targetPos+t*targetVelocityVec         (eq 2) 

(eq 2) jest równanie wektorowych i mogą być rozłożone na trzy oddzielne równania:

x = x_t0 + t * v_x 
y = y_t0 + t * v_y 
z = z_t0 + t * v_z 

Te trzy równania mogą być wstawiane do (eq 1):

(x_t0 + t * v_x - x_b0)^2 + (y_t0 + t * v_y - y_b0)^2 + (z_t0 + t * v_z - z_b0)^2 = (bulletSpeed * t)^2 

równanie zawiera tylko znane zmienne i mogą być rozwiązane na ton. Przypisanie stałą część kwadratowego podwyrażeń do stałych można uproszczenia obliczeń:

c_1 = x_t0 - x_b0 
c_2 = y_t0 - y_b0 
c_3 = z_t0 - z_b0 
(v_b = bulletSpeed) 

(t * v_x + c_1)^2 + (t * v_y + c_2)^2 + (t * v_z + c_3)^2 = (v_b * t)^2 

Przegrupowanie jako standardowego równania kwadratowego:

(v_x^2+v_y^2+v_z^2-v_b^2)t^2 + 2*(v_x*c_1+v_y*c_2+v_z*c_3)t + (c_1^2+c_2^2+c_3^2) = 0 

To jest łatwo rozpuszczalny przy użyciu standardowego wzoru. Może to spowodować zero, jedno lub dwa rozwiązania. Rozwiązania zerowe (nie licząc złożonych rozwiązań) oznaczają, że pocisk nie może osiągnąć celu. Jedno rozwiązanie prawdopodobnie nastąpi bardzo rzadko, gdy docelowa trajektoria przecina się z samą krawędzią kuli. Najczęstszym scenariuszem będą dwa rozwiązania. Negatywne rozwiązanie oznacza, że ​​nie możesz trafić w cel, ponieważ musisz wystrzelić pocisk w przeszłość. Są to wszystkie warunki, które musisz sprawdzić.

Po rozwiązaniu równania można znaleźć pozycję t, ponownie wprowadzając ją do (eq 2).W pseudo kod:

# setup all needed variables 
c_1 = x_t0 - x_b0 
c_2 = y_t0 - y_b0 
c_3 = z_t0 - z_b0 
v_b = bulletSpeed 
# ... and so on 

a = v_x^2+v_y^2+v_z^2-v_b^2 
b = 2*(v_x*c_1+v_y*c_2+v_z*c_3) 
c = c_1^2+c_2^2+c_3^2 

if b^2 < 4*a*c: 
    # no real solutions 
    raise error 

p = -b/(2*a) 
q = sqrt(b^2 - 4*a*c)/(2*a) 

t1 = p-q 
t2 = p+q 

if t1 < 0 and t2 < 0: 
    # no positive solutions, all possible trajectories are in the past 
    raise error 

# we want to hit it at the earliest possible time 
if t1 > t2: t = t2 
else: t = t1 

# calculate point of collision 
x = x_t0 + t * v_x 
y = y_t0 + t * v_y 
z = z_t0 + t * v_z 
+2

Technicznie nie „strzelać armaty * * w przeszłości”, ale ogień armat * w * przeszłość za negatywne ' t. –

+0

@ Ben, Good point. Naprawiono –

+0

'if t1 * t2> 0': To może się zdarzyć, jeśli oba rozwiązania są pozytywne, więc błąd nie powinien zostać podniesiony bez faktycznego sprawdzenia znaku (lub stwierdzenia, dlaczego t1 i t2 nie może być zarówno pozytywny, jeśli nie może.) Po prostu użyłbym 'if t1 <0 and t2 <0', osobiście – mokus

Powiązane problemy