计算旋转以将对象与 3D 中的两个点对齐 space

Calculate rotation to align object with two points in 3D space

我正在处理动作捕捉数据,我想在处理过程中进行“蒙皮”。所以基本上我从我的数据中得到的每两个点我必须在它们之间添加一个 3D 对象(我现在将使用一个盒子并且放置和旋转坐标是 3D 对象的中心)并旋转它以便它在所有三个维度上与连接两点的向量对齐。

我们可以在左侧看到两点之间最初放置的框,在右侧看到现在正确旋转的框:

我知道在处理过程中旋转对象的唯一方法是使用 rotateX()、rotateY()、rotateZ() 函数,它们使用欧拉角围绕全局(?)轴旋转对象。

现在我正在努力寻找一种正确计算此旋转的方法。

我已经写了一个计算两个向量夹角的函数:

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)));
}

然后我尝试将矢量(两点之间)与每个旋转轴之一的单位矢量相结合:

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));

但是当我使用这些值旋转对象时,旋转完全关闭。

代码示例:

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)));
}

现在有点迷茫

旋转轴为方框默认方向(1,0,0)和沿线方向(p2 - p1)的Cross product
旋转的角度是归一化方向向量的Dot productacos

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));

将框绕轴旋转角度:

rotate(rotationAngle, rotationAxis.x, rotationAxis.y, rotationAxis.z);

完整示例:

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();
}