学习[threejs] threejs 实现随机曲线

283 阅读1分钟
  1. 安装噪声函数 simplex-noise

    
    import { createNoise3D } from "simplex-noise";
    // 创建噪声
    const noise = createNoise3D(Math.random);
    
  2. 使用噪声函数创建噪声位置

    // 噪音
    computeCurl(x: number, y: number, z: number) {
        var eps = 0.0001;
    
        var curl = new THREE.Vector3();
    
        //Find rate of change in YZ plane
        var n1 = noise(x, y + eps, z);
        var n2 = noise(x, y - eps, z);
        //Average to find approximate derivative
        var a = (n1 - n2) / (2 * eps);
        var n1 = noise(x, y, z + eps);
        var n2 = noise(x, y, z - eps);
        //Average to find approximate derivative
        var b = (n1 - n2) / (2 * eps);
        curl.x = a - b;
    
        //Find rate of change in XZ plane
        n1 = noise(x, y, z + eps);
        n2 = noise(x, y, z - eps);
        a = (n1 - n2) / (2 * eps);
        n1 = noise(x + eps, y, z);
        n2 = noise(x - eps, y, z);
        b = (n1 - n2) / (2 * eps);
        curl.y = a - b;
    
        //Find rate of change in XY plane
        n1 = noise(x + eps, y, z);
        n2 = noise(x - eps, y, z);
        a = (n1 - n2) / (2 * eps);
        n1 = noise(x, y + eps, z);
        n2 = noise(x, y - eps, z);
        b = (n1 - n2) / (2 * eps);
        curl.z = a - b;
    
        return curl;
    }
    
  3. 创建管道曲线所需要的1000个随机点坐标

    // 创建曲线路径
    getCurve(start: THREE.Vector3) {
        const scale = 3;
        const points = [];
        points.push(start);
        const currentPoint = start.clone();
        for (let i = 0; i < 1000; i++) {
            const v = this.computeCurl(
                currentPoint.x / scale,
                currentPoint.y / scale,
                currentPoint.z / scale
            );
            // 添加缩放向量
            currentPoint.addScaledVector(v, 0.001);
            points.push(currentPoint.clone());
        }
        return points;
    }
    
  4. 创建管道图形

    getBox(point: THREE.Vector3) {
        const path = new THREE.CatmullRomCurve3(
            this.getCurve(point)
        );
        const geometry2 = new THREE.TubeGeometry(
            path,
            1000,
            0.005
        );
        const material = new THREE.ShaderMaterial({
            fragmentShader: fs,
            vertexShader: vs,
        });
        const mesh = new THREE.Mesh(geometry2, material);
        return mesh;
    }
    
  5. 创建多组管道

    getBoxList() {
        for (let i = 0; i < 100; i++) {
            // this.getBox();
            this.experience.scene.add(
                this.getBox(
                    new THREE.Vector3(
                        Math.random() - 0.5,
                        Math.random() - 0.5,
                        Math.random() - 0.5
                    )
                )
            );
        }
    }
    

image.png