2

I have a spaceship model that I want to move along a circular path. I want the nose of the ship to always point in the direction it is moving in.

Here is the code I have to move it in a circle right now:

glm::mat4 m = glm::mat4(1.0f);

        //time
        long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::
                                                                                                                                          high_resolution_clock::now())
                                                                                  .time_since_epoch())
                            .count();
        //translate 
        m = glm::translate(m, translate);
        m = glm::translate(m, glm::vec3(-50, 0, -20));
        m = glm::scale(m, glm::vec3(0.025f, 0.025f, 0.025f));
        m = glm::translate(m, glm::vec3(1800, 0, 3000));

        float speed = .002;
        float x = 100 * cos(value_ms * speed); // + 1800;
        float y = 0;
        float z = 100 * sin(value_ms * speed); // + 3000;
        m = glm::translate(m, glm::vec3(x, y, z));

How would I move it so the nose always points ahead? I tried doing glm::rotate with the rotation axis set as x or y or z but I cannot get it to work properly.

genpfault
  • 51,148
  • 11
  • 85
  • 139
steph
  • 323
  • 1
  • 9
  • A hint: Your circular path is in x-z plane. => The rotation axis should be **y** (not _x or y or z_). ;-) – Scheff's Cat Jun 26 '19 at 05:59
  • Not all transformations are commutative. Translations are (i.e. any order of multiple translations results in the same final transformation). That's not the case for rotation nor for scaling. – Scheff's Cat Jun 26 '19 at 06:00

1 Answers1

0

First see Understanding 4x4 homogenous transform matrices as I am using terminology and stuff from there...

Its usual to use a transform matrix of object for its navigation purposes and not the other way around ... So you should have a transform matrix M for your space ship that represents its position and orientation in [GCS] (global coordinate system). On top of that is sometimes multiplied another matrix M0 that align your space ship mesh to the first matrix (you know some meshes are not centered around (0,0,0) nor axis aligned...)

Now when you are moving your object you just do local transformations on the M so moving forward is just translating M origin position by a multiple of forward axis basis vector. The same goes for sliding to sides (just use different basis vector) resulting in that the object is alway aligned to where it supposed to be (in respect to movement). The same goes for turns. So going in circle is just moving forward and turning at constant speeds per time iteration step (timer).

You are doing this backwards first you compute position and orientation and then you are trying to make operations resulting in matrix that would do the same... In such case is much much easier to construct the matrix M instead of creating transformations that will create it... So what you need is:

  • origin position
  • 3 perpendicular (most likely unit) basis vectors

So the origin is your x,y,z position. 2 basis vectors can be obtained from the circle so forward is tangent (or position-last_position) and vector towards circle center cen be used as (right or left). The 3th vector can be obtained by cross product so let assume:

  • +X axis is right
  • +Y axis is up
  • +Z axis is forward

you got:

r=100.0
a=speed*t
pos = (r*cos(a),0.0,r*sin(a))
center = (0.0,0.0,0.0)

so:

Z = (cos(a-0.5*M_PI),0.0,sin(a-0.5*M_PI))
X = (cos(a),0.0,sin(a))-ceneter
Y = cross(X,Z)
O = pos

normalize:

X /= length(X)
Y /= length(Y)
Z /= length(Z)

So now just feed your X,Y,Z,O to your matrix (depending on the conventions you use like multiplication order, direct/inverse matrix, row-major or column-major matrices ...)

so for example like this:

double M[16]=
 {
 X[0],X[1],X[2],0.0,
 Y[0],Y[1],Y[2],0.0,
 Z[0],Z[1],Z[2],0.0,
 O[0],O[1],O[2],1.0,
 };

or:

double M[16]=
 {
 X[0],Y[0],Z[0],O[0],
 X[1],Y[1],Z[1],O[1],
 X[2],Y[2],Z[2],O[2],
 0.0 ,0.0 ,0.0 ,1.0,
 };

And that is all ... The matrix might be transposed, inverted etc based on the conventions you use. Sorry I do not use GLM but the syntax should be very siilar ... the matrix feeding might be even simpler if rows or columns are loadable by a vector ...

Spektre
  • 49,595
  • 11
  • 110
  • 380