Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matrix 如何在THREE.js中找到两组3D点之间的旋转矩阵_Matrix_Three.js_Rotation_Quaternions - Fatal编程技术网

Matrix 如何在THREE.js中找到两组3D点之间的旋转矩阵

Matrix 如何在THREE.js中找到两组3D点之间的旋转矩阵,matrix,three.js,rotation,quaternions,Matrix,Three.js,Rotation,Quaternions,我的问题是这个问题的延伸: 如果我有一个向量3,一个垂直于它的向量3,描述了一个3D对象的方向,我如何找到这个向量组和这个向量组的变换之间的旋转矩阵,作为已经转换的向量组,我可以使用它 这里有一个视觉效果可以让它更清晰: 我想使用适当的THREE.js实用程序查找四元数,该四元数将v1和v1n描述的组的旋转旋转为v1'和v1n'描述的相同组的旋转。这些状态的旋转枢轴由点p1和p1'描述 从上面的答案中,我知道如何获得从一个矢量3到另一个矢量3的旋转,但是如果我在我的用例中使用该方法,我将不会处

我的问题是这个问题的延伸:

如果我有一个向量3,一个垂直于它的向量3,描述了一个3D对象的方向,我如何找到这个向量组和这个向量组的变换之间的旋转矩阵,作为已经转换的向量组,我可以使用它

这里有一个视觉效果可以让它更清晰:

我想使用适当的THREE.js实用程序查找四元数,该四元数将v1和v1n描述的组的旋转旋转为v1'和v1n'描述的相同组的旋转。这些状态的旋转枢轴由点p1和p1'描述


从上面的答案中,我知道如何获得从一个矢量3到另一个矢量3的旋转,但是如果我在我的用例中使用该方法,我将不会处理旋转的第三自由度(假设使用偏航、俯仰、滚动来描述旋转)。

假设v1和v1n在组1中,v2和v2n在组2中。 如果我们可以假设两个组都是以相同的向量配置开始的,比如(0,1,0)和(0,0,1),这似乎是合乎逻辑的:

首先,将group1移动到其原始方向

var qtmp1 = group1.quaternion.clone().conjugate();
group1.applyQuaternion(qtmp1);
然后,将组1移动到组2的方向

var qtmp2 = group2.quaternion.clone();
group1.applyQuaternion(qtmp2);
在一次轮换中:

group1.applyQuaternion(qtmp2.multiply(qtmp1));
这个假设可能不正确

编辑:更简单:

group1.quaternion.slerp(group2.quaternion, 1);

假设v1和v1n在组1中,v2和v2n在组2中。 如果我们可以假设两个组都是以相同的向量配置开始的,比如(0,1,0)和(0,0,1),这似乎是合乎逻辑的:

首先,将group1移动到其原始方向

var qtmp1 = group1.quaternion.clone().conjugate();
group1.applyQuaternion(qtmp1);
然后,将组1移动到组2的方向

var qtmp2 = group2.quaternion.clone();
group1.applyQuaternion(qtmp2);
在一次轮换中:

group1.applyQuaternion(qtmp2.multiply(qtmp1));
这个假设可能不正确

编辑:更简单:

group1.quaternion.slerp(group2.quaternion, 1);
我的答案是#2:不依赖于两个群体的定位

让我们再次假设我们想要将v1和v1n旋转到v2和v2n。我们可以使用.setFromUnitVectors(v1,v2)获得四元数Q1,将v1旋转到v2。v1n将旋转为v1nrot1,这与v2正常,但不是v2n。我们可以再次使用.setFromUnitVectors(v1nrot1,v2n)得到四元数Q2,将v1nrot1旋转到v2n。第二次旋转不会影响v1rot(=v2),因为v1rot与v1nrot1和v2n垂直。如果这些都不是正常的,那么就需要额外的步骤来获得正常值。最后,v1rot点v2=1和v1nrot2点v2n=1显示Q2Q1旋转工作。代码被注释

<!doctype html>
<html><!-- https://stackoverflow.com/questions/61619752/ -->
  <head>
    <title> SO.html </title>
    <style type="text/css">
* { font-family:monospace; font-size:16px; }
    </style>
    <script src="http://threejs.org/build/three.js"></script>
    <script type="text/javascript">
  "use strict";
  const k57=180/Math.PI;
  var div1elt;
window.onload = function() {
  div1elt = document.getElementById("div1");
  // get v1 and v1n
  print("  --  v1 and v1n");
  var v1 = new THREE.Vector3(1,2,3).normalize();
  var vtmp = new THREE.Quaternion(1,0,0).normalize();
  var v1n = v1.clone().cross(vtmp).normalize(); 
  printv("v1", v1);
  printv("v1n", v1n);
  print("v1 dot v1n", v1.dot(v1n));
  // get v2 and v2n
  print("  --  v2 and v2n");
  var v2 = new THREE.Vector3(4,3,2).normalize();
  var vtmp = new THREE.Quaternion(0,0,1).normalize();
  var v2n = v2.clone().cross(vtmp).normalize(); 
  printv("v2", v2);
  printv("v2n", v2n);
  print("v2 dot v2n", v2.dot(v2n));
  // get Q1 that rotates v1 to v1rot (and v1n to v1nrot1)
  var Q1 = new THREE.Quaternion().setFromUnitVectors(v1, v2);
  // get Q2 that rotates v1nrot1 to v1nrot2
  // Q2 will not rotate v1rot because v1nrot1 and v2n are normal to v1rot
  var v1nrot1 = v1n.clone().applyQuaternion(Q1); // 
  var Q2 = new THREE.Quaternion().setFromUnitVectors(v1nrot1, v2n);
  var Q12 = new THREE.Quaternion().multiplyQuaternions(Q2,Q1);
  // print Q12
  printq("  --  Q12  --",Q12);
  // now see if Q12 works
  print("  --  check results");
  var v1rot = v1.clone().applyQuaternion(Q12);
  print("v1rot dot v2", v1rot.dot(v2).dd(1,5));
  var v1nrot2 = v1n.clone().applyQuaternion(Q12);
  print("v1nrot2 dot v2n", v1nrot2.dot(v2n).dd(1,5));  
};
Number.prototype.dd = function(b4, af) { // formats nn.nnn
  // usage: string = n.dd(2,3) or (2).dd(2,3)
  if (isNaN(parseFloat(this)) || !isFinite(this)) return this;
  var pfx = "", pos, b4s, b4v, afs, afv;
  var s = String(this+.5*Math.pow(10,-af));
  if (s.substring(0,1) == "-") { pfx = "-"; s = s.substring(1); b4-=1; }
  if (s.substring(0,1) == "0") s = s.substring(1);
  if ((pos = s.indexOf("."))==-1) s+=".";
  b4s = s.substring(0,pos); b4v = b4s.length;
  afs = s.substring(pos+1); afv = afs.length;
  if (b4>b4v) pfx+= "0".repeat(b4-b4v);
  if (af>afv) afs +="0".repeat(af-afv);
  if (af<afv) afs = afs.substring(0,af);
  return pfx+b4s+((af!=0)?".":"")+afs;
};
function printq(txt, q) { // print q
  var ang = Math.atan2(Math.sqrt(q.x*q.x+q.y*q.y+q.z*q.z), q.w);
  var len = Math.sqrt(q.w*q.w+q.x*q.x+q.y*q.y+q.z*q.z);
  print(txt, q.w.dd(2,5),q.x.dd(2,5),q.y.dd(2,5),q.z.dd(2,5),
        "[len="+len.dd(2,5)+", ang="+(ang*k57).dd(4,1)+"]");
}
function printv(txt, v) { // print v
  var len = Math.sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
  print(txt, v.x.dd(2,5),v.y.dd(2,5),v.z.dd(2,5),
        "[len="+len.dd(2,5)+"]");
}
function print(what) { // print
  var s="";
  for (var i1=0; i1<arguments.length; i1+=1) {
    if (s != "") s += ", ";
    s+= arguments[i1];
  }
  div1elt.innerHTML += s + "<br />";
}
    </script>
  </head>
  <body>
    <div id="div1"></div>
  </body>
</html>

SO.html
*{字体系列:单空格;字体大小:16px;}
“严格使用”;
常数k57=180/Math.PI;
var div1elt;
window.onload=函数(){
div1elt=document.getElementById(“div1”);
//获取v1和v1n
打印(“--v1和v1n”);
var v1=新的3.Vector3(1,2,3).normalize();
var vtmp=新的三个四元数(1,0,0).normalize();
var v1n=v1.clone().cross(vtmp.normalize();
printv(“v1”,v1);
printv(“v1n”,v1n);
打印(“v1点v1n”,v1.dot(v1n));
//获取v2和v2n
打印(“--v2和v2n”);
var v2=新的3.Vector3(4,3,2).normalize();
var vtmp=新的三个四元数(0,0,1).normalize();
var v2n=v2.clone().cross(vtmp.normalize();
printv(“v2”,v2);
printv(“v2n”,v2n);
打印(“v2点v2n”,v2点(v2n));
//获取将v1旋转到v1rot(以及将v1n旋转到v1nrot1)的Q1
var Q1=新的三个.Quaternion().setFromUnitVectors(v1,v2);
//获取将v1nrot1旋转到v1nrot2的Q2
//Q2不会旋转v1rot,因为v1nrot1和v2n与v1rot垂直
var v1nrot1=v1n.clone().applyQuaternion(Q1);//
var Q2=新的三个.Quaternion().setFromUnitVectors(v1nrot1,v2n);
var Q12=新的三个四元数().多个四元数(Q2,Q1);
//打印Q12
printq(“--Q12--”,Q12);
//现在看看Q12是否有效
打印(“--检查结果”);
var v1rot=v1.clone().applyQuaternion(Q12);
打印(“v1rot点v2”,v1rot.dot(v2.dd)(1,5));
var v1nrot2=v1n.clone().applyQuaternion(Q12);
打印(“v1nrot2点v2n”,v1nrot2点(v2n).dd(1,5));
};
Number.prototype.dd=函数(b4,af){//格式nn.nnn
//用法:string=n.dd(2,3)或(2).dd(2,3)
if(isNaN(parseFloat(this))| |!isFinite(this))返回这个;
var pfx=“”,pos,b4s,b4v,afs,afv;
var s=String(这个+0.5*Math.pow(10,-af));
如果(s.substring(0,1)=“-”{pfx=“-”;s=s.substring(1);b4-=1;}
如果(s)子串(0,1)=“0”)s=s子串(1);
如果((pos=s.indexOf(“.”)=-1)s+=”;
b4s=s.子串(0,位置);b4v=b4s.长度;
afs=s.子串(位置+1);afv=afs.长度;
如果(b4>b4v)pfx+=“0”。重复(b4-b4v);
如果(af>afv)afs+=“0”。重复(af afv);
如果(af我的答案#2:不依赖于两组的方向

让我们再次假设我们要将v1和v1n旋转到v2和v2n。我们可以使用.setFromUnitVectors(v1,v2)获得四元数Q1,将v1旋转到v2。v1n将旋转到v1nrot1,这是v2的法线,但不是v2n。我们可以使用.setFromUnitVectors(v1nrot1,v2n)再次获得四元数Q2,将v1nrot1旋转到v2n。第二次旋转不会影响v1rot(=v2),因为v1rot与v1nrot1和v2n垂直。如果它们不正常,则需要额外一步来获得法线。最后,v1rot点v2=1和v1nrot2点v2n=1显示Q2Q1旋转工作。代码被注释

<!doctype html>
<html><!-- https://stackoverflow.com/questions/61619752/ -->
  <head>
    <title> SO.html </title>
    <style type="text/css">
* { font-family:monospace; font-size:16px; }
    </style>
    <script src="http://threejs.org/build/three.js"></script>
    <script type="text/javascript">
  "use strict";
  const k57=180/Math.PI;
  var div1elt;
window.onload = function() {
  div1elt = document.getElementById("div1");
  // get v1 and v1n
  print("  --  v1 and v1n");
  var v1 = new THREE.Vector3(1,2,3).normalize();
  var vtmp = new THREE.Quaternion(1,0,0).normalize();
  var v1n = v1.clone().cross(vtmp).normalize(); 
  printv("v1", v1);
  printv("v1n", v1n);
  print("v1 dot v1n", v1.dot(v1n));
  // get v2 and v2n
  print("  --  v2 and v2n");
  var v2 = new THREE.Vector3(4,3,2).normalize();
  var vtmp = new THREE.Quaternion(0,0,1).normalize();
  var v2n = v2.clone().cross(vtmp).normalize(); 
  printv("v2", v2);
  printv("v2n", v2n);
  print("v2 dot v2n", v2.dot(v2n));
  // get Q1 that rotates v1 to v1rot (and v1n to v1nrot1)
  var Q1 = new THREE.Quaternion().setFromUnitVectors(v1, v2);
  // get Q2 that rotates v1nrot1 to v1nrot2
  // Q2 will not rotate v1rot because v1nrot1 and v2n are normal to v1rot
  var v1nrot1 = v1n.clone().applyQuaternion(Q1); // 
  var Q2 = new THREE.Quaternion().setFromUnitVectors(v1nrot1, v2n);
  var Q12 = new THREE.Quaternion().multiplyQuaternions(Q2,Q1);
  // print Q12
  printq("  --  Q12  --",Q12);
  // now see if Q12 works
  print("  --  check results");
  var v1rot = v1.clone().applyQuaternion(Q12);
  print("v1rot dot v2", v1rot.dot(v2).dd(1,5));
  var v1nrot2 = v1n.clone().applyQuaternion(Q12);
  print("v1nrot2 dot v2n", v1nrot2.dot(v2n).dd(1,5));  
};
Number.prototype.dd = function(b4, af) { // formats nn.nnn
  // usage: string = n.dd(2,3) or (2).dd(2,3)
  if (isNaN(parseFloat(this)) || !isFinite(this)) return this;
  var pfx = "", pos, b4s, b4v, afs, afv;
  var s = String(this+.5*Math.pow(10,-af));
  if (s.substring(0,1) == "-") { pfx = "-"; s = s.substring(1); b4-=1; }
  if (s.substring(0,1) == "0") s = s.substring(1);
  if ((pos = s.indexOf("."))==-1) s+=".";
  b4s = s.substring(0,pos); b4v = b4s.length;
  afs = s.substring(pos+1); afv = afs.length;
  if (b4>b4v) pfx+= "0".repeat(b4-b4v);
  if (af>afv) afs +="0".repeat(af-afv);
  if (af<afv) afs = afs.substring(0,af);
  return pfx+b4s+((af!=0)?".":"")+afs;
};
function printq(txt, q) { // print q
  var ang = Math.atan2(Math.sqrt(q.x*q.x+q.y*q.y+q.z*q.z), q.w);
  var len = Math.sqrt(q.w*q.w+q.x*q.x+q.y*q.y+q.z*q.z);
  print(txt, q.w.dd(2,5),q.x.dd(2,5),q.y.dd(2,5),q.z.dd(2,5),
        "[len="+len.dd(2,5)+", ang="+(ang*k57).dd(4,1)+"]");
}
function printv(txt, v) { // print v
  var len = Math.sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
  print(txt, v.x.dd(2,5),v.y.dd(2,5),v.z.dd(2,5),
        "[len="+len.dd(2,5)+"]");
}
function print(what) { // print
  var s="";
  for (var i1=0; i1<arguments.length; i1+=1) {
    if (s != "") s += ", ";
    s+= arguments[i1];
  }
  div1elt.innerHTML += s + "<br />";
}
    </script>
  </head>
  <body>
    <div id="div1"></div>
  </body>
</html>

SO.html
*{字体系列:单空格;字体大小:16px;}
“严格使用”;
常数k57=180/Math.PI;
var div1elt;
window.onload=函数(){
div1elt=document.getElementById(“div1”);
//获取v1和v1n
打印(“--v1和v1n”);
var v1=新的3.Vector3(1,2,3).normalize();
var vtmp=新的三个四元数(1,0,0).normalize();
var v1n=v1.clone().cross(vtmp.normalize();
printv(“v1”,v1);
printv(“v1n”,v1n);
打印(“v1点v1n”,v1.dot(v1n));
//获取v2和v2n
打印(“--v2和v2n”);
var v2=新的3.Vector3(4,3,2).normalize();
var vtmp=新的三个四元数(0,0,1).normalize();
var v2n=v2.clone().cross(vtmp.normalize();
printv(“v2”,v2);
printv(“v2n”,v2n);
打印(“v2点v2n”,v2点(v2n));
//获取将v1旋转到v1ro的Q1