Rotate point around vector 3d

丶灬走出姿态 提交于 2020-01-03 02:00:10

问题


I want to rotate a P3 (that is somewhere near) around a vector (that intersects P1 and P2) by x degrees.

P1 and P2 are 2 points that are intersected by vector(line) e from image. I've researched and searched a lot and found some good materials, but my trigonometry skills are so poor. I need this for PAWN (small), here i have some code, but doesn't really work as intended. If anyone can help me, i'll be very thankful :)

Image link: http://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Euler_AxisAngle.png/220px-Euler_AxisAngle.png

P1 / P2 / P3 = (x,y,z)

float vec[3];
SubtractVectors(P1, P2, vec);

float newp[3];
float rotation[4][4];
SetupMatrix(90.0, vec, rotation);
MultiplyMatrix(P3, rotation, newp);

//---------------------------------

stock void MultiplyMatrix(float input[3], float rotation[4][4], float output[3])
{
    float input2[4];
    input2[0] = input[0];
    input2[1] = input[1];
    input2[2] = input[2];
    input2[3] = 1.0;

    float output2[4];
    for(int i = 0 ; i < 4 ; i++)
    {
        for(int j = 0 ; j < 4 ; j++)
        {
            output2[i] += rotation[i][j] * input2[j];
        }
    }

    output[0] = output2[0];
    output[1] = output2[1];
    output[2] = output2[2];
}

stock void SetupMatrix(float angle, float vector[3], float rotation[4][4])
{
    float L = (vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]);
    angle = angle * M_PI / 180.0;
    float u2 = vector[0] * vector[0];
    float v2 = vector[1] * vector[1];
    float w2 = vector[2] * vector[2];

    rotation[0][0] = (u2 + (v2 + w2) * Cosine(angle)) / L;
    rotation[0][1] = (vector[0] * vector[1] * (1 - Cosine(angle)) - vector[2] * SquareRoot(L) * Sine(angle)) / L;
    rotation[0][2] = (vector[0] * vector[2] * (1 - Cosine(angle)) + vector[1] * SquareRoot(L) * Sine(angle)) / L;
    rotation[0][3] = 0.0; 

    rotation[1][0] = (vector[0] * vector[1] * (1 - Cosine(angle)) + vector[2] * SquareRoot(L) * Sine(angle)) / L;
    rotation[1][1] = (v2 + (u2 + w2) * Cosine(angle)) / L;
    rotation[1][2] = (vector[1] * vector[2] * (1 - Cosine(angle)) - vector[0] * SquareRoot(L) * Sine(angle)) / L;
    rotation[1][3] = 0.0; 

    rotation[2][0] = (vector[0] * vector[2] * (1 - Cosine(angle)) - vector[1] * SquareRoot(L) * Sine(angle)) / L;
    rotation[2][1] = (vector[1] * vector[2] * (1 - Cosine(angle)) + vector[0] * SquareRoot(L) * Sine(angle)) / L;
    rotation[2][2] = (w2 + (u2 + v2) * Cosine(angle)) / L;
    rotation[2][3] = 0.0; 

    rotation[3][0] = 0.0;
    rotation[3][1] = 0.0;
    rotation[3][2] = 0.0;
    rotation[3][3] = 1.0;
}

回答1:


look at quaternions they do exactly what you need. if you do not use them like me then:

  1. construct transform matrix M representing your rotational axis coordinate system

    first look here: transform matrix anatomy. For example origin is the point P1 So X axis is P2-P1 (rotation axis). Let Q = (1.0,0.0,0.0) or (0.0,1.0,0.0) choose one that is not parallel to X axis vector so

    X = P2-P1
    Q = (1.0,0.0,0.0) or (0.0,1.0,0.0)
    Y = cros(X,Q)
    Z = cros(X,Y)
    

    now you can negate axises or change their cross product operands order to match the axises direction you need (if desired). Also do not forget to make all the axises unit vectors

  2. so now do local coordinate system (LCS) rotation

    look here LCS transforms and here LCS rotation around X axis lrotx C++ implementation search for lrotx at the end of answer

  3. so now

    take GCS point P you want to rotate get its LCS coordinates (for unrotated transform matrix M)

    Q = inverse(M)*P // if `M` before rotation was one then you can do Q=P instead
    

    rotate:

    M = inverse(inverse(M)*rotation)
    

    convert Q back to GCS

    Q = M*Q
    

    that it is all ...

[Notes]

if you have wrong rotation direction then just negate one of the axises ... or use negated angle



来源:https://stackoverflow.com/questions/26561355/rotate-point-around-vector-3d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!