使用 Three.js 进行矩阵变换(Matrix Transformations)

person 少陵野老    watch_later 2024-10-11 22:57:33
visibility 38    class Matrix Transformations    bookmark 专栏

在 3D 图形中,矩阵变换是对对象进行位置、旋转和缩放等操作的基础。Three.js 提供了丰富的 API 来实现这些变换,本文将详细介绍矩阵变换的基本概念、常用方法,以及如何在 Three.js 中应用这些变换。

1. 矩阵变换的基本概念

矩阵变换是通过 4x4 矩阵对 3D 对象进行变换的方式。常见的变换类型包括:

  • 平移(Translation):移动对象的位置。
  • 旋转(Rotation):围绕某个轴旋转对象。
  • 缩放(Scaling):改变对象的大小。

这些变换可以组合使用,以实现更复杂的效果。

2. 准备工作

确保在 HTML 文件中引入 Three.js:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 矩阵变换示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>

3. 创建基本的 Three.js 场景

3.1 初始化场景、摄像机和渲染器

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

3.2 添加简单的 3D 对象

我们将在场景中添加一个立方体和一个球体,以便演示矩阵变换:

const geometryCube = new THREE.BoxGeometry(1, 1, 1);
const materialCube = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometryCube, materialCube);
scene.add(cube);

const geometrySphere = new THREE.SphereGeometry(0.5, 32, 32);
const materialSphere = new THREE.MeshBasicMaterial({ color: 0x0000ff });
const sphere = new THREE.Mesh(geometrySphere, materialSphere);
sphere.position.x = 3; // 初始位置
scene.add(sphere);

3.3 设置摄像机位置

设置摄像机的位置,以便能够看到场景中的对象:

camera.position.z = 5;

4. 矩阵变换操作

4.1 平移变换(Translation)

平移可以通过 position 属性直接设置:

cube.position.set(1, 1, 1); // 将立方体移动到 (1, 1, 1)

还可以通过 translateXtranslateYtranslateZ 方法进行相对平移:

cube.translateX(2); // 向右平移 2 个单位

4.2 旋转变换(Rotation)

旋转可以通过 rotation 属性设置,单位为弧度:

cube.rotation.x = Math.PI / 4; // 绕 X 轴旋转 45 度
cube.rotation.y = Math.PI / 4; // 绕 Y 轴旋转 45 度

也可以使用 rotateXrotateYrotateZ 方法进行相对旋转:

cube.rotateY(Math.PI / 2); // 绕 Y 轴顺时针旋转 90 度

4.3 缩放变换(Scaling)

缩放可以通过 scale 属性设置:

cube.scale.set(1.5, 1.5, 1.5); // 将立方体缩放到 1.5 倍

也可以使用 scale 方法进行相对缩放(不过不常用):

cube.scale.x *= 2; // 将立方体的 X 轴缩放加倍

5. 矩阵变换示例

5.1 组合变换

将平移、旋转和缩放结合起来,创建一个简单的动画:

function animate() {
    requestAnimationFrame(animate);

    // 旋转
    cube.rotation.y += 0.01;

    // 平移
    cube.position.x += 0.01;
    if (cube.position.x > 3) {
        cube.position.x = -3; // 重置位置
    }

    // 渲染场景
    renderer.render(scene, camera);
}

animate();

6. 使用矩阵手动进行变换

有时,我们可能需要直接操作矩阵。Three.js 提供了 Matrix4 类来处理这种情况。

6.1 创建和应用矩阵

创建一个变换矩阵:

const matrix = new THREE.Matrix4();
matrix.makeTranslation(1, 2, 0); // 创建平移矩阵
cube.applyMatrix4(matrix); // 应用矩阵

6.2 组合矩阵

可以组合多个矩阵以实现复合变换:

const translationMatrix = new THREE.Matrix4().makeTranslation(1, 0, 0);
const rotationMatrix = new THREE.Matrix4().makeRotationY(Math.PI / 2);
const scalingMatrix = new THREE.Matrix4().makeScale(1.5, 1.5, 1.5);

// 组合变换
const combinedMatrix = new THREE.Matrix4()
    .multiplyMatrices(translationMatrix, rotationMatrix)
    .multiply(scalingMatrix);
  
cube.applyMatrix4(combinedMatrix); // 应用复合变换

7. 完整示例代码

以下是一个完整的示例,展示了如何在 Three.js 中使用矩阵变换:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 矩阵变换示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        const geometryCube = new THREE.BoxGeometry(1, 1, 1);
        const materialCube = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const cube = new THREE.Mesh(geometryCube, materialCube);
        scene.add(cube);

        const geometrySphere = new THREE.SphereGeometry(0.5, 32, 32);
        const materialSphere = new THREE.MeshBasicMaterial({ color: 0x0000ff });
        const sphere = new THREE.Mesh(geometrySphere, materialSphere);
        sphere.position.x = 3;
        scene.add(sphere);

        camera.position.z = 5;

        function animate() {
            requestAnimationFrame(animate);
            cube.rotation.y += 0.01; // 旋转
            cube.position.x += 0.01; // 平移
            if (cube.position.x > 3) {
                cube.position.x = -3; // 重置位置
            }
            renderer.render(scene, camera);
        }

        // 使用矩阵进行平移
        const matrix = new THREE.Matrix4();
        matrix.makeTranslation(1, 2, 0);
        cube.applyMatrix4(matrix);

        animate();
    </script>
</body>
</html>

8. 处理窗口调整

确保在窗口调整大小时更新渲染器和摄像机:

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

9. 结论

在本文中,我们详细探讨了如何在 Three.js 中使用矩阵变换,包括平移、旋转和缩放的实现,以及如何通过矩阵直接操作对象的变换。掌握这些基本概念和技巧,对于创建复杂的 3D 应用至关重要。希望这篇博客能够帮助你更好地理解和应用 Three.js 的矩阵变换!如有任何问题或建议,欢迎在评论区留言讨论!

评论区
评论列表
menu