math - 在 Three.js 中根据局部向量定位子网格

标签 math matrix 3d three.js rotation

我需要帮助将网格定位到根据本地坐标给出的特定点。我创建了高度为 0.1 的粉红色圆柱体来展示我想让彼此接触的立方体的局部点。

此外,我希望cube2 成为cube1 的 child ,但这暂时不是交易破坏者。

预期结果:立方体与其特定的角接触并正确旋转 - 粉红色圆柱体应该像素完美地相互覆盖。

我试图解决它:

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 = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(25, 25, 12);
// setup cubes

var geometry = new THREE.CubeGeometry(6, 6, 6);
var material = new THREE.MeshLambertMaterial({
  color: 0x00fff0
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

cube.position.set(0.3, 1, -2);
cube.rotation.set(Math.PI / 3, Math.PI / 2, 1)

var geometry2 = new THREE.CubeGeometry(4, 4, 4);
var material2 = new THREE.MeshLambertMaterial({
  color: 0x0fff00
});
var cube2 = new THREE.Mesh(geometry2, material2);
cube.add(cube2);

cube_position = new THREE.Vector3(3, 3, 3)
cube_rotation = new THREE.Vector3(Math.PI / 3, Math.PI / 4, 0)
cube2_position = new THREE.Vector3(2, -2, 2)
cube2_rotation = new THREE.Vector3(Math.PI / 2, Math.PI / 2, 0)

// visualize points
vmat = new THREE.MeshLambertMaterial({
  color: 0xFF00FF,
  opacity: 0.5,
  transparent: true
});
v1 = new THREE.Mesh(new THREE.CylinderGeometry(1, 1, 0.1, 10), vmat);
cube.add(v1)
v1.position.copy(cube_position)
v1.rotation.setFromVector3(cube_rotation)

v2 = new THREE.Mesh(new THREE.CylinderGeometry(1, 1, 0.1, 10), vmat);
cube2.add(v2)
v2.position.copy(cube2_position)
v2.rotation.setFromVector3(cube2_rotation)

// BUG: connect cube with cube2 on specified points

cube2.position.copy(cube_position.clone().add(cube2_position))
cube2.rotation.setFromVector3(cube_rotation.clone().add(cube2_rotation))

// setup rest
var pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight)

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x20252f);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);

const controls = new THREE.OrbitControls(camera, renderer.domElement);

animate();

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  renderer.render(scene, camera);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r82/three.js"></script>
<script src="https://yume.human-interactive.org/examples/buffer-geometry/OrbitControls.js"></script>

最佳答案

因此,Matrix 在解决旋转问题方面非常强大。我分两步设置cube2正确旋转和定位。

  • 回转
    cube1之间的关系, cube2 , v1 , v2是:
    enter image description here
    我们要的是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)
    

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

    我们需要的是制作v1v2世界地位相同。这是显示坐标空间的图形:enter image description here
    因为 v2cube2 的 child ,我们需要搬家 cube2 .在世界空间中,我们应该翻译cube2距离 v2v1 ,现在我们得到了 cube2世界排名,cube2cube1 的 child ,只需应用 cube1 的逆矩阵获取 cube2本地位置。

  • 这是一个 jsfiddle example .

    希望它有所帮助。

    更新

    我写了一个函数,不用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);
    }
    

    我还添加了一个祖父立方体来包含 cube1cube2 .
    jsfiddle

    关于math - 在 Three.js 中根据局部向量定位子网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44950463/

    相关文章:

    arrays - 如何获得整个矩阵,数组或数据框的均值,中位数和其他统计信息?

    java - Java中动态数组的二维静态数组

    opengl-es - 如何在 OpenGL ES 中将深度缓冲区 "push"后退一点?

    c# - XNA Flash 或 Silverlight 集成

    java - 如何将字符串转换为数学方程式?

    java - π近似误差导致第29位发散

    c++ - 类模板 cpp、hpp、cpp

    algorithm - 如何阅读 dale-chall 数学符号?

    解决代数问题的算法?

    ios - Scenekit - SCNNode 的多次旋转和轴的方向