threejs系列: 几何变换(下)🏄‍♂️

这里是 threejs系列:几何变换(下):

往期回顾:

  1. # threejs系列:相机与投影 📷
  2. # threejs系列:光源与光照🪀
  3. # threejs系列:自定义几何体🎃
  4. # threejs系列:几何变换(上)🍺
  5. threejs系列: 几何变换(下)🏄‍♂️
  6. threejs系列: 矩阵推导
  7. .......

高强度持续更新,从0到1深入了解 threejs 的奥秘,喜欢的点个关注呀

几何变换

在上一篇文章中我们学习了 threejs 封装的API,确实很轻易就完成了物体的变换。但或多或少会有一点意犹未尽的感觉。

如果不使用 threejs 的API,我们能否尝试自己实现呢?

  1. 我们先创建一个工具类
js 复制代码
class Utils {
    static rotate() {
        
    }   

    static translate() {

    }

    static scale() {

    }
}
  1. 创建一个物体
js 复制代码
let mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshPhongMaterial({ color: 0xFFFFFF }))
scene.add(mesh);
  1. 实现逻辑

由于物体的变换都是通过修改几何体的顶点完成的,所以我们需要拿到物体的顶点。

位移是容易理解的,只需要每个顶点朝着相同的方向加上相同的值就完成了。

js 复制代码
    // 位移
translate(mesh, vector) {
    let points = mesh.geometry.attributes.position.array;
    points = points.map((v, index) => {
        let isX = index % 3 == 0;
        let isY = index % 3 == 1;
        return isX ? v + vector.x : isY ? v + vector.y : v + vector.z
    })
    mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
}

其次是缩放,也很好理解,只需要每个顶点每个方向乘以相同的值。

js 复制代码
    // 缩放
static scale(mesh, vector) {
    let points = mesh.geometry.attributes.position.array;
    points = points.map((v, index) => {
        let isX = index % 3 == 0;
        let isY = index % 3 == 1;
        return isX ? v * vector.x : isY ? v * vector.y : v * vector.z
    })
    mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
}

最后是旋转,旋转稍微需要思考一下。

在阅读前面的文章中我们知道 2D 旋转公式是:

js 复制代码
x1 = x * Math.cos(angle) - y * Math.sin(angle);
y1 = x * Math.sin(angle) + y * Math.cos(angle);

又因为当我们绕着X方向旋转时,每个顶点的X轴位置时不变的,Y、Z同理,所以我们可以带入2D平面公式求旋转后的顶点坐标:

js 复制代码
  // 旋转
static __r(mesh, direct, radian) {
    let points = mesh.geometry.attributes.position.array;
    points = points.map((v, index) => {
        let isX = index % 3 == 0;
        let isY = index % 3 == 1;
        let isZ = index % 3 == 2;
        if (direct == 'X') {
            if (isY) {
                v = v * Math.cos(radian) - points[index + 1] * Math.sin(radian);
            }
            if (isZ) {
                v = points[index - 1] * Math.sin(radian) + v * Math.cos(radian);
            }
        }
        if (direct == 'Y') {
            if (isX) {
                v = v * Math.cos(radian) - points[index + 2] * Math.sin(radian);
            }
            if (isZ) {
                v = points[index - 2] * Math.sin(radian) + v * Math.cos(radian);
            }
        }
        if (direct == 'Z') {
            if (isX) {
                v = v * Math.cos(radian) - points[index + 1] * Math.sin(radian);
            }
            if (isY) {
                v = points[index - 1] * Math.sin(radian) + v * Math.cos(radian);
            }
        }
        return v;
    })
    mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
}


rotate(mesh, vector) {
    vector.x && this.__r(mesh, "X", vector.x);
    vector.y && this.__r(mesh, "X", vector.y);
    vector.z && this.__r(mesh, "Z", vector.z);
}
  1. 使用写好的工具函数
javascript 复制代码
Utils.scale(mesh, new THREE.Vector3(1, 1, 2))

Utils.translate(mesh, new THREE.Vector3(1, 1, 1));
Utils.rotate(mesh, new THREE.Euler(Math.PI / 3, Math.PI / 3, Math.PI / 3));

使用前后对比:

现在我们完美的使用数学表达式完成了几何变换。

相关推荐
古夕9 分钟前
JS 模块化
前端·javascript
wandongle10 分钟前
HTML面试整理
前端·面试·html
liucan23310 分钟前
JS执行速度似乎并不比Swift或者C语言慢
前端·ios
一只小风华~13 分钟前
HTML前端开发:JavaScript 常用事件详解
前端·javascript·html
Revol_C15 分钟前
【调试日志】我只是用wangeditor上传图片而已,页面咋就崩溃了呢~
前端·vue.js·程序员
天天码行空18 分钟前
GruntJS-前端自动化任务运行器从入门到实战
前端
smallzip19 分钟前
node大文件拷贝优化(显示进度)
前端·性能优化·node.js
mouseliu20 分钟前
python之二:docker部署项目
前端·python
要加油哦~32 分钟前
css | class中 ‘.‘ 和 ‘:‘ 的使用 | 如,何时用 &.is-selected{ ... } 何时用 &:hover{...}?
前端·css
不浪brown1 小时前
开源!矢量建筑白模泛光特效以及全国77个大中城市的矢量shp数据获取!
前端·cesium