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

问题描述 投票:0回答:1

我正在处理动作捕捉数据,我想在处理中进行“蒙皮”。因此,基本上,我从数据中获得的每两个点都必须在其间添加一个 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)));
}

现在我有点迷失了。

math processing euler-angles
1个回答
4
投票

旋转轴是盒子默认方向 (1, 0, 0) 与沿线方向 (p2 - p1) 的

叉积

旋转角度是归一化方向向量的
点积
acos

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 = PVector.lerp(p1, p2, 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();
}
© www.soinside.com 2019 - 2024. All rights reserved.