Matrix 在jsc3d中围绕上方向向量旋转场景

Matrix 在jsc3d中围绕上方向向量旋转场景,matrix,rotation,jsc3d,Matrix,Rotation,Jsc3d,我使用jsc3d在画布上加载和显示一些3d对象。查看器已经有一个内置功能,可以通过拖动鼠标围绕Y轴旋转“视图坐标”(如果我错了,请更正我) 通过经典旋转矩阵执行旋转,最后将变换矩阵乘以该旋转矩阵 围绕Y轴的totation的计算方式类似于围绕加载对象的整个场景的圆周运动: JSC3D.Matrix3x4.prototype.rotateAboutYAxis = function(angle) { if(angle != 0) { angle *= Math.PI / 18

我使用jsc3d在画布上加载和显示一些3d对象。查看器已经有一个内置功能,可以通过拖动鼠标围绕Y轴旋转“视图坐标”(如果我错了,请更正我)

通过经典旋转矩阵执行旋转,最后将变换矩阵乘以该旋转矩阵

围绕Y轴的totation的计算方式类似于围绕加载对象的整个场景的圆周运动:

JSC3D.Matrix3x4.prototype.rotateAboutYAxis = function(angle) {
    if(angle != 0) {
        angle *= Math.PI / 180;
        var c = Math.cos(angle);
        var s = Math.sin(angle);

        var m00 = c * this.m00 + s * this.m20;
        var m01 = c * this.m01 + s * this.m21;
        var m02 = c * this.m02 + s * this.m22;
        var m03 = c * this.m03 + s * this.m23;
        var m20 = c * this.m20 - s * this.m00;
        var m21 = c * this.m21 - s * this.m01;
        var m22 = c * this.m22 - s * this.m02;
        var m23 = c * this.m23 - s * this.m03;

        this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
        this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
    }
};
现在,拖动鼠标将在整个世界上围绕Y轴应用此旋转,如下图左侧所示。有没有一种方法,可以围绕上方向向量进行旋转,使其保持在初始位置,就像它出现在右侧一样

我试过这样的方法:

var rotY = (x - viewer.mouseX) * 360 / viewer.canvas.height;       
var rotMat = new JSC3D.Matrix3x4; // identity
rotMat.rotateAboutYAxis(rotY);
viewer.rotMatrix.multiply(rotMat);
但它没有效果

我的旋转矩阵应该应用什么操作来实现关于上方向向量的旋转


示例:

此3D库已经有一些内置函数,允许场景围绕X、Y和Z轴旋转,因此不需要为此实现新的矩阵运算,我们可以使用现有函数RotateAoutXays、RotateAoutYaxis和RotateAoutZaxis,应用所需旋转角度(以度为单位)的就地矩阵乘法

JSC3D中的场景通过3x4矩阵进行变换,其中旋转存储在每行的前3个值中。 在应用场景旋转和/或平移后,应用关于上方向向量的后续旋转是计算关于任意轴的旋转的问题

这里描述了如何解决这个问题的一个非常清晰的说教性解释:

  • 将P 0(x 0,y 0,z 0)轴点平移到坐标系的原点
  • 执行适当的旋转,使旋转轴与轴重合 z坐标轴
  • 绕z轴旋转角度θ
  • 执行组合旋转变换的反转
  • 执行与翻译相反的操作
  • 现在,为它编写函数很容易,因为我们使用了JSC3D中已有的函数(这里省略了翻译部分)

    由于上述所有函数都使用度数,我们需要从旋转矩阵(简化)中获取实际的欧拉角:

    这里棘手的部分是,我们总是需要返回当前的旋转角度,因为它们是应用旋转的结果,所以每次旋转应用到场景时,必须使用单独的函数来存储当前的Euler角度

    为此,我们可以使用非常简单的结构:

    JSC3D.Viewer.prototype.rpy = [0, 0, 0];
    
    这将是最终结果:

    JSC3D.Viewer.prototype.calcRollPitchYaw = function() {
        var m = this.rotMatrix;
        var radians = 180 / Math.PI;
    
        var angleX = Math.atan2(-m.m12, m.m22) * radians;
        var angleY = Math.asin(m.m01) * radians;
        var angleZ = Math.atan2(-m.m01, m.m00) * radians;
    
        this.rpy[0] = angleX;
        this.rpy[1] = angleY;
        this.rpy[2] = angleZ;
    }
    
    JSC3D.Viewer.prototype.rpy = [0, 0, 0];