Math 在Three.js中基于局部向量定位子网格

Math 在Three.js中基于局部向量定位子网格,math,matrix,3d,three.js,rotation,Math,Matrix,3d,Three.js,Rotation,我需要帮助定位网格的具体点,是根据当地坐标。我创建了高度为0.1的粉红色圆柱体,以演示我希望彼此接触的立方体的局部点 我还想让cube2成为cube1的孩子,但这暂时不是交易的破坏者 预期结果:立方体以其特定的角接触,并以适当的旋转-粉红色圆柱体应该是像素完美的相互覆盖 我试图用以下方法解决这个问题: cube2.position.copy(cube_position.clone().add(cube2_position)) cube2.rotation.setFromVector3(cube_

我需要帮助定位网格的具体点,是根据当地坐标。我创建了高度为0.1的粉红色圆柱体,以演示我希望彼此接触的立方体的局部点

我还想让cube2成为cube1的孩子,但这暂时不是交易的破坏者

预期结果:立方体以其特定的角接触,并以适当的旋转-粉红色圆柱体应该是像素完美的相互覆盖

我试图用以下方法解决这个问题:

cube2.position.copy(cube_position.clone().add(cube2_position))
cube2.rotation.setFromVector3(cube_rotation.clone().add(cube2_rotation))
但这并不像预期的那样有效。我应该使用某种矩阵变换吗

const scene=new THREE.scene();
const-camera=新的3.PerspectiveCamera(45,window.innerWidth/window.innerHeight,11000);
摄像机。位置。设置(25,25,12);
//设置多维数据集
var geometry=新的三立方测量法(6,6,6);
var material=新的3.0网格LambertMaterial({
颜色:0x00fff0
});
var cube=新的三个网格(几何体、材质);
场景.添加(立方体);
立方体位置集(0.3,1,-2);
cube.rotation.set(Math.PI/3,Math.PI/2,1)
var geometry2=新的三立方测量法(4,4,4);
var material2=新的3.0网格LambertMaterial({
颜色:0x0fff00
});
var cube2=新的三网格(geometry2,material2);
cube.add(cube2);
立方体位置=新的三个向量3(3,3,3)
立方体旋转=新的3.Vector3(Math.PI/3,Math.PI/4,0)
立方2_位置=新的三个向量3(2,-2,2)
立方体2_旋转=新的3.Vector3(Math.PI/2,Math.PI/2,0)
//可视化点
vmat=新的三点网格LambertMaterial({
颜色:0xFF00FF,
不透明度:0.5,
透明:正确
});
v1=新的三网格(新的三圆柱几何体(1,1,0.1,10),vmat);
cube.add(v1)
v1.位置.复制(立方体位置)
v1.rotation.setFromVector3(立方体旋转)
v2=新的三网格(新的三圆柱几何体(1,1,0.1,10),vmat);
立方2.add(v2)
v2.位置。复制(立方位置)
v2.旋转。从矢量3设置(立方旋转)
//错误:将立方体与指定点上的立方体2连接
cube2.position.copy(cube_position.clone().add(cube2_position))
cube2.rotation.setFromVector3(cube\u rotation.clone().add(cube2\u rotation))
//安装支架
var pointLight=新的三点光源(0xFFFFFF);
点光源位置x=10;
点光源位置y=50;
点光源位置z=130;
场景.添加(点光源)
const renderer=new THREE.WebGLRenderer({
反别名:对
});
renderer.setSize(window.innerWidth、window.innerHeight);
渲染器.setClearColor(0x20252f);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.doElement);
const controls=新的三个.orbitControl(摄影机、渲染器.doElement);
制作动画();
函数animate(){
请求动画帧(动画);
render();
}
函数render(){
渲染器。渲染(场景、摄影机);
}

所以,矩阵在解决旋转问题方面非常强大。我通过两个步骤来正确设置
cube2
旋转和位置

  • 轮换

    cube1
    cube2
    v1
    v2
    之间的关系是: 我们想要的是
    v2
    世界旋转等于
    v1
    相反的世界旋转。当两个对象具有相同的旋转时,它们具有相同的旋转矩阵(世界矩阵)。我们有以下公式:

    V1opposite.w = V2.w
    V1opposite.l * C1.w = V2.l * C2.l * C1.l
    V1opposite.l = V2.l * C2.l
    C2.l = V1opposite.l * V2.l(-1)
    
    其中v1.w表示
    v1
    相反世界矩阵,V2.w表示
    V2
    世界矩阵,C表示
    cube
    ,V2.l(-1)表示
    V2
    局部矩阵的逆矩阵。现在,我们可以计算
    cube2
    旋转矩阵

  • 位置

    我们需要的是使
    v1
    v2
    的世界位置相同。以下是显示坐标空间的图表: 因为
    v2
    cube2
    的子级,我们需要移动
    cube2
    。在世界空间中,我们应该将
    cube2
    v2
    转换到
    v1
    ,现在我们得到
    cube2
    世界位置,
    cube2
    cube1
    的子体,只需应用
    cube1
    的逆矩阵即可得到
    cube2
    局部位置

这是一个jsfiddle

希望有帮助

更新

我写了一个函数,你可以不用
v1
v2
来使用它

//connect obj1 and obj2 on obj1's point1 and obj2's point2.
function connect(obj1,obj2,point1,point2)
{
    var point1World = new THREE.Vector3().copy(point1).applyMatrix4(obj1.matrixWorld);
    var point2World = new THREE.Vector3().copy(point2).applyMatrix4(obj2.matrixWorld);
    var translation = new THREE.Vector3().subVectors(point1World,point2World);
    var obj2World = new THREE.Vector3().copy(obj2.getWorldPosition());
    obj2World.add(translation);
    if(obj2.parent !== null)
    {
        var inverseMatrix = new THREE.Matrix4().getInverse(obj2.parent.matrixWorld);
        obj2World.applyMatrix4(inverseMatrix);
    }
    obj2.position.copy(obj2World);
}
我还添加了一个祖父多维数据集来包含
cube1
cube2

好吧,这有点帮助,v1和v2的创建只是为了演示,所以不应该用它们来解决这个问题。此外,我不能在计算之间使用渲染。我正试图解决这个问题,所以我可以在我的应用程序中使用你的解决方案,但似乎不可能,因为我需要更新v2和cube2的位置,我认为这很方便,如果你不想这样做,你可以让它们的位置应用变换矩阵。除了使用,你想用哪种方法解决它?有什么限制吗?我可以继续帮助你。我在我的实际应用程序中实现了你的解决方案,当它是孙子(第一个立方体的孩子的孩子)时,所有东西都有奇怪的偏移量。它让我发疯,我不知道如何正确地实现它。@Patryk我的解决方案建立在v1,v2上。我想知道我是否可以用立方体的康纳顶点来实现它。我想知道你的最终目标,就在康纳河上碰一下?它们之间有固定的轮换吗?这更复杂,而且我不能共享源代码。基本上,我正在构建一个3d编辑器的引导版本。v1和v2演示了两个网格之间的连接。在该编辑器中,您将每个元素定位为其他一些元素的子元素。你可以有无限多代的孩子。此外,当我应用您的解决方案时,除了只在一代子代上定位外,每次运行代码时,它都会使网格在瞬间移动到全局0,0,0。