【问题标题】:Replace plane in space with ThreeJS用 ThreeJS 替换空间中的平面
【发布时间】:2021-09-10 15:37:06
【问题描述】:

我想将 ThreeJS 中的平面替换为特定的 Z 值。

我创建了一个 shapeBufferGeometry,其形状包含 Vector3s,其中包含 x y 和 z 值。

这是我的代码和我得到的。我希望白色平面与水色线的位置相匹配。

下面的代码允许我用我的平面渲染场景中的不同点以及它周围的顶点。

我知道我可以使用 translate 来移动飞机,但我不知道如何正确使用它。我怎么知道根据我的向量值应该在哪个轴上平移我的几何图形。

<!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>My first three.js app</title>
            
            <style>
                body { margin: 0; }
            </style>
        </head>
        <body>
            <canvas id="c" width="800" height="500"></canvas>
            <script>
            </script>
            <script type="module">
                import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
                import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
                import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
                import { ConvexGeometry } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/geometries/ConvexGeometry.js'
                
                var scene = new THREE.Scene();
                var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
                camera.position.set(0, 20, 40);
                camera.lookAt(scene.position);
                var renderer = new THREE.WebGLRenderer({
                antialias: true
                });
                renderer.setSize(window.innerWidth, window.innerHeight);
                document.body.appendChild(renderer.domElement);
    
                var controls = new OrbitControls(camera, renderer.domElement);
                controls.target = new THREE.Vector3(10, 0, 10);
                controls.update();
    
                var grid = new THREE.GridHelper(50, 50, 0x808080, 0x202020); // xy-grid
                grid.geometry.rotateX(Math.PI * 0.5);
                scene.add(grid);
    
                var points = [ // all of them are on the xz-plane
                //  new THREE.Vector3(5, 0, 5),
                // new THREE.Vector3(25, 0, 5),
                // new THREE.Vector3(25, 0, 15),
                // new THREE.Vector3(15, 0, 15),
                // new THREE.Vector3(15, 0, 25),
                // new THREE.Vector3(5, 0, 25),
                // new THREE.Vector3(5, 0, 5)
    
                new THREE.Vector3(199.2353333,7.6714966,  32),
                new THREE.Vector3(199.0974316,276.6667291, 32),
                new THREE.Vector3(75.2343077,276.6715748, 32),
                new THREE.Vector3(75.2343077,232.6714966, 32),
                new THREE.Vector3(101.1792999,232.6714966, 32),
                new THREE.Vector3(101.1792999,194.6807462, 32),
                new THREE.Vector3(75.2343077,194.6714966, 32),
                new THREE.Vector3(75.2343077,7.6714966, 32),
                new THREE.Vector3(199.2353333,7.6714966, 32)
                ]
    
                var geom = new THREE.BufferGeometry().setFromPoints(points);
                var pointsObj = new THREE.Points(geom, new THREE.PointsMaterial({
                color: "red"
                }));
                scene.add(pointsObj);
    
                var line = new THREE.LineLoop(geom, new THREE.LineBasicMaterial({
                color: "aqua"
                }));
                scene.add(line);
    
                // normals 
                var normal = new THREE.Vector3(0, 0, 1); // I already know the normal of xz-plane ;)
                scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
    
                var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
                scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#FF001F' )); // aqua
    
                // 1 quaternions
                var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ);
                var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal);
    
                // 2 make it parallel to xy-plane
                points.forEach(p => {
                p.applyQuaternion(quaternion)
                });
    
                // 3 create shape and shapeGeometry
                var shape = new THREE.Shape(points);
                var shapeGeom = new THREE.ShapeBufferGeometry(shape);
                shapeGeom.computeFaceNormals();
                shapeGeom.computeVertexNormals();
    
                // 4 put our points back to their origins
                points.forEach(p => {
                p.applyQuaternion(quaternionBack)
                });
    
                // 5 assign points to .vertices
                shapeGeom.vertices = points;
    
                var shapeMesh = new THREE.Mesh(shapeGeom, new THREE.MeshBasicMaterial({
                color: '#FF001F ',
                side: THREE.DoubleSide
                }));
    
                
                scene.add(shapeMesh);
    
    
                // scene.add( new THREE.FaceNormalsHelper( shapeMesh ) );
    
    
    
                render();
    
                function render() {
                requestAnimationFrame(render);
                renderer.render(scene, camera);
                }
            </script>
        </body>
    </html> 

我得到的结果:

【问题讨论】:

    标签: javascript three.js plane buffer-geometry


    【解决方案1】:

    不需要添加最后一个点来闭合轮廓。

    您的步骤// 5 assign points to .vertices 需要通过ShapeUtils 检查points 的CCW。将 Vector3 数组分配给缓冲区几何图形的 .vertices 是没有用的,因为该类型的几何图形没有该属性,因此您正在使用缓冲区属性。调用shapeGeom.computeFaceNormals();也是没用的。

    body{
      overflow: hidden;
      margin: 0;
    }
    <script type="module">
    import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
    import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
    import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
    import { ConvexGeometry } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/geometries/ConvexGeometry.js'
    
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
    camera.position.set(0, 20, 40).setLength(500).add(new THREE.Vector3(150, 150, 0));
    camera.lookAt(150, 150, 0);
    var renderer = new THREE.WebGLRenderer({
    antialias: true
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    var controls = new OrbitControls(camera, renderer.domElement);
    controls.target = new THREE.Vector3(10, 0, 10);
    controls.update();
    
    var grid = new THREE.GridHelper(50, 50, 0x808080, 0x202020); // xy-grid
    grid.geometry.rotateX(Math.PI * 0.5);
    scene.add(grid);
    
    var points = [ // all of them are on the xz-plane
    //  new THREE.Vector3(5, 0, 5),
    // new THREE.Vector3(25, 0, 5),
    // new THREE.Vector3(25, 0, 15),
    // new THREE.Vector3(15, 0, 15),
    // new THREE.Vector3(15, 0, 25),
    // new THREE.Vector3(5, 0, 25),
    // new THREE.Vector3(5, 0, 5)
    
    new THREE.Vector3(199.2353333,7.6714966,  32),
    new THREE.Vector3(199.0974316,276.6667291, 32),
    new THREE.Vector3(75.2343077,276.6715748, 32),
    new THREE.Vector3(75.2343077,232.6714966, 32),
    new THREE.Vector3(101.1792999,232.6714966, 32),
    new THREE.Vector3(101.1792999,194.6807462, 32),
    new THREE.Vector3(75.2343077,194.6714966, 32),
    new THREE.Vector3(75.2343077,7.6714966, 32)/*,
    new THREE.Vector3(199.2353333,7.6714966, 32)*/
    ]
    
    var geom = new THREE.BufferGeometry().setFromPoints(points);
    var pointsObj = new THREE.Points(geom, new THREE.PointsMaterial({
    color: "red"
    }));
    scene.add(pointsObj);
    
    var line = new THREE.LineLoop(geom, new THREE.LineBasicMaterial({
    color: "aqua"
    }));
    scene.add(line);
    
    // normals 
    var normal = new THREE.Vector3(0, 0, 1); // I already know the normal of xz-plane ;)
    scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
    
    var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
    scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#FF001F' )); // aqua
    
    // 1 quaternions
    var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ);
    var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal);
    
    // 2 make it parallel to xy-plane
    points.forEach(p => {
    p.applyQuaternion(quaternion)
    });
    
    // 3 create shape and shapeGeometry
    var shape = new THREE.Shape(points);
    var shapeGeom = new THREE.ShapeBufferGeometry(shape);
    shapeGeom.computeFaceNormals();
    shapeGeom.computeVertexNormals();
    
    // 4 put our points back to their origins
    points.forEach(p => {
    p.applyQuaternion(quaternionBack)
    });
    
    // 5 assign points to .vertices
    if (!THREE.ShapeUtils.isClockWise(points)) points.reverse(); // CCW order
    points.forEach((p, idx) => {
      shapeGeom.attributes.position.setXYZ(idx, p.x, p.y, p.z);
    });
    
    console.log(points.length, shapeGeom.attributes.position.count);
    
    var shapeMesh = new THREE.Mesh(shapeGeom, new THREE.MeshBasicMaterial({
    color: "#FF001F",
    //side: THREE.DoubleSide
    }));
    
    
    
    
    scene.add(shapeMesh);
    
    
    // scene.add( new THREE.FaceNormalsHelper( shapeMesh ) );
    
    
    
    render();
    
    function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
    }
    </script>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-09
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      相关资源
      最近更新 更多