0

my math isnt too great but im trying to learn though..

What im trying to do is give my games missiles a helix rocket effect, but i dont know how to work the Sin and Cos to make the helix play out in the right direction..

This is a 3D game by the way:

The problem is, depending on which direction the missile faces, the helix looks warped or flat..

Whats the best way to mathematically calculate a helix based on the missiles X,Y,Z/direction?, ive been trying to figure it out for a long time :/

Thanks alot!

            double x = radius * Math.cos(theta);
            double y = radius * Math.sin(theta);
            double z = radius * Math.cos(theta);
            location.add(x,y,z);
            missile.shootFlame(location,2);
            location.subtract(x,y,z);
Spektre
  • 49,595
  • 11
  • 110
  • 380
Jakeinzah
  • 25
  • 1
  • 6
  • Direct in a 3D world cannot be defined by just one angle - you need two angles. – Erwin Bolwidt Dec 13 '16 at 07:25
  • im sorry, could you explain further? – Jakeinzah Dec 13 '16 at 07:37
  • 1
    Think about it (and note that this purely a mathematics question, not programming) - in a 2D world, like a piece of paper, you can specify a point with a radius from the origin and and angle from some reference. In a 3D world, you need 3 pieces of information - in your case, likely one radius and two angles. Search for geometry with google, not for Java programming. – Erwin Bolwidt Dec 13 '16 at 08:21

1 Answers1

1

Basis vectors

you need the overall direction of missile as 3D vector let call it W. From it you need to get 2 another vectors U,V which are all perpendicular to each other. To get them you can exploit cross product. So:

  1. make W unit vector

    Just W = W/|W| so:

    l=sqrt(Wx*Wx+Wy*Wy+Wz*Wz);
    Wx/=l;
    Wy/=l;
    Wz/=l;
    
  2. choose U as any direction non parallel to W

    so start with U=(1.0,0.0,0.0) and if U==W choose U=(0.0,1.0,0.0). If you got anything to lock to use that as U direction so the coordinate system will not rotate with time (like Up,North,Sun ...)

    U should be unit so if not normalize it just like in #1

  3. compute V

    It should be perpendicular to U,W so use cross product:

    V = W x U
    

    Cross product of unit vectors is also unit vector so no need to normalize.

  4. recompute U

    As we choose the U manually we need to make sure it is also perpendicular to V,W so:

    U = V x W
    

Now we have 3 perpendicular basis vectors where U,V lies in plane of the helix screws and W is the overall movement direction.

If you do not know how to compute the cross product see:

Now the Helix is easy:

  1. Defines

    so we have U,V,W on top of that we need radius r [units], movement speed v [units/s], angular speed o [rad/s] time t>=0.0 [s] and start position P0.

  2. Helix equation

    What we need is equation returning actual position for time so:

    ang = o*t;
    P(t) = P0 + U*r*cos(ang) + V*r*sin(ang) + W*v*t;
    

    rewritten to scalars:

    ang = o*t;
    x = P0x + Ux*r*cos(ang) + Vx*r*sin(ang) + Wx*v*t;
    y = P0y + Uy*r*cos(ang) + Vy*r*sin(ang) + Wy*v*t;
    z = P0z + Uz*r*cos(ang) + Vz*r*sin(ang) + Wz*v*t;
    

[edit1] as you are incompetent to copy paste and or changing my code correctly...

Vector w = loc.getDirection();

double wX = w.getX();
double wY = w.getY();
double wZ = w.getZ();
double l = Math.sqrt((wX * wX) + (wY * wY) + (wZ * wZ));
wX = wX / l;
wY = wY / l;
wZ = wZ / l;
w = new Vector(wX,wY,wZ); // you forget to change W and use it latter ...

Vector u = new Vector(0, 1.0, 0);  
if (Math.abs(wX)<1e-3) // if U and W are the same chose different U
 if (Math.abs(wZ)<1e-3)
  u = new Vector(1.0, 0.0, 0);

Vector v = w.crossProduct(u);
u = v.crossProduct(w);

double radius = 10; // helix radius [units]
double speed = 2.00; // movement speed [unit/s]
double omega = 0.628; // angular speed [rad/s]
//double omega = 36.0; // angular speed [deg/s]
for (double i = 0; i < 100; i += 1.0) // time [s]
 {
 double angle = omega * i; // actual screw position [rad] or [deg]
 double x = u.getX() * radius * Math.cos(angle) + v.getX() * radius * Math.sin(angle) + wX * speed * i;
 double y = u.getY() * radius * Math.cos(angle) + v.getY() * radius * Math.sin(angle) + wY * speed * i;
 double z = u.getZ() * radius * Math.cos(angle) + v.getZ() * radius * Math.sin(angle) + wZ * speed * i;
 loc.add(x,y,z); // What is this? should not you set the x,y,z instead of adding?
 //do work
 loc.subtract(x,y,z); // what is this?
 }

This should provide you with helix points with traveled linear distance

speed*imax = 2.0*100.0 = 200.0 units 

And screws:

omega*imax/(2*Pi) ~= 0.628*100.0/6.28 ~= 10 screws // in case of sin,cos want [rad]
omega*imax/360.0 = 36.0*100.0/360 = 10.0 screws // in case of sin,cos want [deg]

Do not forget to rem in/out the correct omega line (I choose [rad] as that is what I am used that my math libs use). Not sure If I translated to your environment correctly there may be bugs like abs has different name or u = new Vector(1.0, 0.0, 0); can be done on intermediate or declaration of variable only etc which I do not know as I do not code in it.

Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Still having problems, I seem to only be able to get it to draw straight beams rather than helixes, i guess this is a starting point :D Heres what ive gotten so far, but im not sure where i went wrong? http://pastebin.com/PALJNbDM – Jakeinzah Dec 13 '16 at 15:06
  • @Jake1996 you are multiplying doubles with int and I think this is your main problem: first `o= * i;` is really what? `O` should be angle dependent on time (mine `ang=o*t;` where `o` is rotation speed or screws per distance if you want) and you are setting it with pointer to `int`? and use that for `cos,sin` that is wrong. And the part `wX * v * i;` I would feel safer with `wX * v * double(i);` – Spektre Dec 13 '16 at 15:27
  • Hi, i think im still doing something wrong here.. i changed the ints to doubles just as a test but i know thats not the problem, I dont know, its weird.. it looks like it should work, is there another way to do this? http://pastebin.com/43NkyCEx – Jakeinzah Dec 13 '16 at 22:21
  • @Jake1996 1. you are iterating 10 times that means `10` points per whole helix I would go for `100` 2. you are using `speed=2` for both movement and rotation that is wrong. `double angle = speed * i;` should be different then `wX * speed * i;`. The rotational speed is in degrees or radians per second so try `double angle = 0.01 * i;` instead. In my code the speeds are `o` and `v` you are using `speed` for booth – Spektre Dec 13 '16 at 22:48
  • @Jake1996 added edit1 btw what is the output trajectory like? (not working can mean anything) – Spektre Dec 14 '16 at 08:56