Search code examples
c++geometryrotationglmradians

get an angle between 2 points and rotate a point about an other point with this angle - C++


I'm basically trying to create 2D lines based on points from bezier curves. All the points of the bezier curves are well placed and everything seems in order. Starting with these points I'm creating 2 other points on the z axis which will be the border of the line :

    glm::vec3    p1 = pos[i];
    p1.z = p1.z + (size / 2);

    glm::vec3    p2 = pos[i];
    p2.z = p2.z - (size / 2);

Then I change these points positions by rotating them around the main point :

pm is the mobile point rotating around the fix point pf

    glm::vec3   rotP = glm::vec3(0.0f, 0.5f, 0.0f);

    float   co = cos(angle);
    float   si = sin(angle);

    // CLOCKWISE
    rotP.x = (pf.x - pm.x) * co + (pf.z - pm.z) * si + pm.x;
    rotP.z = -(pf.x - pm.x) * si + (pf.z - pm.z) * co + pm.z;

angle is the angle between the backward and forward point on the bezier curve :

depForward is x, glm::vec3(1.0f, 0.0f, 0.0f)

    glm::vec3 normForwardUnit = normalize(p2 - p1);
    float angle = (acos(dot(depForward, normForwardUnit)));

The problem that I get is that the rotations are wrong. Some of my lines are correct but it seems to depend on the orientation of the lines.

not correct example correct example

I think the problem comes from the format of the rotation but I'm still unable to understand. I tried to normalize the angle to different ranges :

//0 to 2PI
    if (angle < 0) { angle += 2 * PI; }
//-PI to PI
    if (angle > PI)        { angle -= 2 * PI; }
    else if (angle <= -PI) { angle += 2 * PI; }

Other ways to calculate the angle :

    float angle = atan2(p2.z - p1.z, p2.x - p1.x);

To rotate the points counter-clockwise :

//COUNTER CLOCKWISE
    rotP.x = (pf.x - pm.x) * co - (pf.z - pm.z) * si + pm.x;
    rotP.z = (pf.x - pm.x) * si + (pf.z - pm.z) * co + pm.z;

Solution

  • In case anyone needs it, here's the implementation of paddy's approach. You could use the point between backP and nextP instead of midPoint to place your new points.

    backP and nextP being the point before and the point after of the b curve

      // VEC FORWARD VECTOR
      glm::vec3 forwardVec = normalize(backP - nextP);
    
      //PERPENDICULAR VEC
      glm::vec3 perpVec = cross(forwardVec, glm::vec3(0.0f, 1.0f, 0.0f));
      perpVec = normalize(perpVec);
    
      //MID POINT
      glm::vec3 midP = midPoint(backP, nextP);
    
      // GEN POINTS
      glm::vec3 p1 = midP + (width * perpVec);
      glm::vec3 p2 = midP - (width * perpVec);