Three.js进行模型剖切,剖切面颜色可控。

用three.js自带的.clippingPlanes可以对模型进行剖切,通过GUI可以控制剖切面的移动。为了看到剖切面,一般使用THREE.Plane制作一个可视化平面。这里由于我们需要对剖切面进行贴纹理之类的操作,于是放弃了使用Plane,选择自己画一个BufferGeometry,使其跟随剖切面移动,并且将顶点颜色通过剖切面所在高度来确定,最后通过插值获得渐变的颜色。为了方便,中间被剖切的模型只画了一个平面。

代码可能有些乱,没整理也没注释,凑合看,准备放到项目中再优化。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>cloudchart</title>
    <script src="../build/three.js"></script>
    <script src="../examples/js/controls/OrbitControls.js"></script>
    <script src="../examples/js/libs/dat.gui.min.js"></script>
</head>

<body>
    <script type="module">
        // import * as THREE from "/build/Three"
        // import { OrbitControls } from "/examples/js/controls/Orbitcontrols"

        let scene = new THREE.Scene();

        let camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.set(100, 100, 100);
        camera.lookAt(scene.position);

        let pointLight = new THREE.PointLight(0xffffff);
        pointLight.position.set(100, 100, 100);
        scene.add(pointLight);
        let ambientLight = new THREE.AmbientLight(0x444444);
        scene.add(ambientLight);


        let geometry0 = new THREE.BufferGeometry();
        let geometry1 = new THREE.BufferGeometry();

        let vertices0 = new Float32Array([
             25,  25, 0,
             25, -25, 0,
            -25, -25, 0,

             25,  25, 0,
            -25, -25, 0,
            -25,  25, 0,
        ]);
        let vertices1 = new Float32Array([
             50, 0,  50,
            -50, 0,  50,
            -50, 0, -50,

             50, 0,  50,
            -50, 0, -50,
             50, 0, -50,
        ]);


        geometry0.setAttribute("position", new THREE.BufferAttribute(vertices0, 3));
        geometry1.setAttribute("position", new THREE.BufferAttribute(vertices1, 3));

        let colors0 = new Float32Array([
            0.3, 0.3, 0.3,
            Math.random(), Math.random(), Math.random(),
            0.7, 0.7, 0.7,

            0.3, 0.3, 0.3,
            0.7, 0.7, 0.7,
            Math.random(), Math.random(), Math.random(),
        ]);
        const colors1 = (parms) => {
            return (new Float32Array([
                0.3, 0.3, 0.3,
                Math.random() * parms / 50, Math.random() * parms / 50, Math.random() * parms / 50,
                0.7, 0.7, 0.7,

                0.3, 0.3, 0.3,
                0.7, 0.7, 0.7,
                Math.random() * parms / 50, Math.random() * parms / 50, Math.random() * parms / 50,
            ]))
        }

        geometry0.attributes.color = new THREE.BufferAttribute(colors0, 3);
        geometry1.attributes.color = new THREE.BufferAttribute(colors1(0), 3);

        let params = {
            planeY: {
                constant: 0
            }
        };
        let planes = [new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)];
        console.log(params);

        let material0 = new THREE.MeshBasicMaterial({
            vertexColors: THREE.VertexColors,
            side: THREE.DoubleSide,
            clippingPlanes: planes,
            clipIntersection: true
        });
        let material1 = new THREE.MeshBasicMaterial({
            vertexColors: THREE.VertexColors,
            side: THREE.DoubleSide,
        })

        let mesh0 = new THREE.Mesh(geometry0, material0);
        let mesh1 = new THREE.Mesh(geometry1, material1);

        // console.log('diatance', planes[0].constant);
        // mesh1.position.y = data1;
        // console.log('data1', data1);
        // console.log('y', mesh1.position.y);

        scene.add(mesh0);
        scene.add(mesh1);

        let axesHelper = new THREE.AxesHelper(100);
        scene.add(axesHelper);

        let renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x000000);
        document.body.appendChild(renderer.domElement);

        let gui = new dat.GUI();
        gui.add(params.planeY, 'constant').min(-50).max(50).onChange(
            (parms) => {
                planes[0].constant = -parms;
                mesh1.position.y = parms;
                geometry1.attributes.color = new THREE.BufferAttribute(colors1(parms), 3);
            }
        );
        // let helper = new THREE.PlaneHelper(planes[0], 100, 0x323fff);
        // scene.add(helper);

        // renderer.clippingPlanes = planes;
        renderer.localClippingEnabled = true;

        function animate() {
            renderer.render(scene, camera);
            requestAnimationFrame(animate);
        }
        animate();
        function createControls() {
            
        }
        let controls = new THREE.OrbitControls(camera, renderer.domElement);
        // controls.addEventListener("change", render);

    </script>
</body>

</html>

 

posted @ 2021-02-25 15:37  Chill_寒  阅读(4040)  评论(1编辑  收藏  举报