Home > Software engineering >  Calculate rotation to align object with two points in 3D space
Calculate rotation to align object with two points in 3D space

Time:10-23

I am working with motion capture data and I want to do "skinning" in processing. So basically with every two points I get from my data I have to add a 3D object in between (I'll be using a box for now and the placement and rotation coordinates are the center of the 3D object) and rotate it so that it is aligned in all three dimensions with the vector that connects the two points.

Here we can see on the left, the initial placed box between the two points and on the right the now correctly rotated box: split image of a white parallelepiped not aligned with a red diagonal (top left to botttom right) on the left hand side of the image and the white parallelepiped aligned with the red line on the right hand side of the image

The only way I know of to rotate an object in processing is to use the rotateX(), rotateY(), rotateZ() functions, which rotate an object around the global(?) axes using euler angles.

Now I am seriously struggling with finding a way to calculate this rotation properly.

I have already written a function for calculating the angle between two vectors:

float calcVectorAngle(PVector p1, PVector p2) {
    return acos((p1.dot(p2)) / (mag(p1.x, p1.y, p1.z) * mag(p2.x, p2.y, p2.z)));
}

And I then tried to feed the vector (between the two points) combined with a unit vector for one of each rotation axis:

float x = calcVectorAngle(vector, new PVector(1,0,0));
float y = calcVectorAngle(vector, new PVector(0,1,0));
float z = calcVectorAngle(vector, new PVector(0,0,1));

But when I use these values to rotate the object the rotation is completely off.

A code example:

PVector p1;
PVector p2;
PVector boxSize = new PVector(500, 100, 100);

void setup() {
    size(1000,1000,P3D);
    p1 = new PVector(100, 100, 0);
    p2 = new PVector(900, 900, -1000);
}

void draw() {
    background(125);
    strokeWeight(2);
    stroke(255, 0, 0);

    pushMatrix();
    
    line(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);

    PVector midPoint = calcMidPoint(p1, p2);
    translate(midPoint.x, midPoint.y, midPoint.z);

    PVector rotation = calcRotation(p1, p2);
    rotateX(rotation.x);
    rotateY(rotation.y);
    rotateZ(rotation.z);

    box(boxSize.x, boxSize.y, boxSize.z);
    popMatrix();
    
}


PVector calcMidPoint(PVector p1, PVector p2) {
    return new PVector((p1.x   p2.x) / 2, (p1.y   p2.y) / 2, (p1.z   p2.z) / 2);
}

PVector calcRotation(PVector p1, PVector p2) {
    PVector vector = new PVector();
    vector.sub(p2, p1, vector);
    float x = calcVectorAngle(vector, new PVector(1,0,0));
    float y = calcVectorAngle(vector, new PVector(0,1,0));
    float z = calcVectorAngle(vector, new PVector(0,0,1));
    return new PVector(x, y, z);
}

float calcVectorAngle(PVector p1, PVector p2) {
    return acos((p1.dot(p2)) / (mag(p1.x, p1.y, p1.z) * mag(p2.x, p2.y, p2.z)));
}

Now I am a little lost.

CodePudding user response:

Unfortunately

PVector p1, p2;
PVector boxSize = new PVector(500, 100, 100);

void setup() {
    size(1000,1000,P3D);
    p1 = new PVector(100, 100, 0);
    p2 = new PVector(900, 900, -1000);
}

void draw() {
    background(125);
    strokeWeight(2);
    stroke(255, 0, 0);

    line(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);

    PVector midPoint = p1.copy().add(p2).mult(0.5);
    PVector currentDirection = new PVector(1, 0, 0);
    PVector newDirection = p2.copy().sub(p1).normalize(); 
    PVector rotationAxis = currentDirection.cross(newDirection).normalize();
    float rotationAngle = acos(currentDirection.dot(newDirection));

    pushMatrix();
    translate(midPoint.x, midPoint.y, midPoint.z);
    Rotate(rotationAngle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
    box(boxSize.x, boxSize.y, boxSize.z);
    popMatrix();
}

void Rotate(float angle, float x, float y, float z) {
    float c = cos(angle);
    float s = sin(angle);
    applyMatrix(
        x*x*(1.0f-c) c,   x*y*(1.0f-c)-z*s, x*z*(1.0f-c) y*s, 0.0f,
        y*x*(1.0f-c) z*s, y*y*(1.0f-c) c,   y*z*(1.0f-c)-x*s, 0.0f,
        z*x*(1.0f-c)-y*s, z*y*(1.0f-c) x*s, z*z*(1.0f-c) c,   0.0f,
        0.0f,             0.0f,             0.0f,             1.0f );
}
  • Related