【问题标题】:Cannot render a mesh with THREE js无法使用三个 js 渲染网格
【发布时间】:2018-11-01 07:03:31
【问题描述】:

这段代码应该在三个 js 中生成一个圆环网格。我很确定数学是正确的。但是,如果我更改某些参数,它只会渲染一块圆环或奇怪的东西。我的 THREE.Mesh 练习有什么不好的地方吗?

// the vertices of the mesh and the vertex normals ----------------
        var nx = 64;
        var ny = 32;
        var R = 10; var r = 3;
        var Vertices = new Array(nx);
        var Normals = new Array(nx);
        for (var i = 0; i < nx; i++) {
            Vertices[i] = new Array(ny);
            Normals[i] = new Array(ny);
            var u = i / nx * 2 * Math.PI;
            var cos_u = Math.cos(u);
            var sin_u = Math.sin(u);
            var cx = R * cos_u;
            var cy = R * sin_u;
            for (var j = 0; j < ny; j++) {
                var v = j / ny * 2 * Math.PI;
                var rcos_v = r * Math.cos(v);
                var rsin_v = r * Math.sin(v);
                Vertices[i][j] = new THREE.Vector3(
                    cx + rcos_v * cos_u,
                    cy + rcos_v * sin_u,
                    rsin_v
                );
                Normals[i][j] = new THREE.Vector3(
                    rcos_v * cos_u,
                    rcos_v * sin_u,
                    rsin_v
                );
            }
        }

// vertices as a dot cloud ----------------------------------------
        var dotGeometry = new THREE.Geometry();
        for (var i = 0; i < nx; i++) {
            for (var j = 0; j < ny; j++) {
                dotGeometry.vertices.push(Vertices[i][j]);
            }
        }
        var dotMaterial =
            new THREE.PointsMaterial({ size: 1, sizeAttenuation: false });
        var cloud = new THREE.Points(dotGeometry, dotMaterial);

// mesh -----------------------------------------------------------
        var geom = new THREE.Geometry();
        for (var i = 0; i < nx; i++) {
            var ip1 = (i == nx - 1 ? 0 : i + 1);
            for (var j = 0; j < ny; j++) {
                var jp1 = (j == ny - 1 ? 0 : j + 1);
                geom.vertices.push(Vertices[i][j]);
                geom.vertices.push(Vertices[i][jp1]);
                geom.vertices.push(Vertices[ip1][j]);
                var vnormals1 = 
                    [Normals[i][j], Normals[i][jp1], Normals[ip1][j]];
                geom.faces.push(new THREE.Face3(
                    i * ny + j,
                    i * ny + jp1,
                    ip1 * ny + j,
                    vnormals1
                ));
                geom.vertices.push(Vertices[i][jp1]);
                geom.vertices.push(Vertices[ip1][jp1]);
                geom.vertices.push(Vertices[ip1][j]);
                var vnormals2 = 
                    [Normals[i][jp1], Normals[ip1][jp1], Normals[ip1][j]];
                geom.faces.push(new THREE.Face3(
                    i * ny + jp1,
                    ip1 * ny + jp1,
                    ip1 * ny + j,
                    vnormals2
                ));
            }
        }

        var torusMesh = new THREE.Mesh(
            geom, 
            new THREE.MeshNormalMaterial({ wireframe: false }));

// three js scene -------------------------------------------------
        var scene = new THREE.Scene();

        var aspect = window.innerWidth / window.innerHeight;
        var camera = new THREE.PerspectiveCamera(50, aspect, 1, 10000);
        camera.position.z = 30;
        scene.add(camera);

        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        var object = new THREE.Object3D();
        object.add(torusMesh);
        object.add(cloud);
        scene.add(object);
        renderer.render(scene, camera);

// animation ---------------------------------------------------------
        var isDragging = false;
        var previousMousePosition = {
            x: 0,
            y: 0
        };
        $(renderer.domElement).on('mousedown', function (e) {
            isDragging = true;
        }).on('mousemove', function (e) {
            var deltaMove = {
                x: e.offsetX - previousMousePosition.x,
                y: e.offsetY - previousMousePosition.y
            };
            if (isDragging) {
                var deltaRotationQuaternion = new THREE.Quaternion()
                    .setFromEuler(new THREE.Euler(
                        Math.PI / 180 * (deltaMove.y * 1),
                        Math.PI / 180 * (deltaMove.x * 1),
                        0,
                        'XYZ'
                    ));
                object.quaternion.multiplyQuaternions(deltaRotationQuaternion,
                    object.quaternion);
            }
            previousMousePosition = {
                x: e.offsetX,
                y: e.offsetY
            };
        });

        $(document).on('mouseup', function (e) {
            isDragging = false;
        });

        window.requestAnimFrame = (function () {
            return window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                function (callback) {
                    window.setTimeout(callback, 1000 / 60);
                };
        })();

        function render() {
            renderer.render(scene, camera);
            requestAnimFrame(render);
        }

        render();
canvas {
            width: 100%;
            height: 100%
        }
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"&gt;&lt;/script&gt;

【问题讨论】:

    标签: javascript html three.js


    【解决方案1】:

    我认为你的代码有两个问题:

    • 使用Geometry 时,只需将Face3 类型的对象添加到faces 数组即可定义面。几何的顶点只定义一次。在你的情况下,你可以这样做:

      geom.vertices = dotGeometry.vertices;
      
    • 此外,您的面部缠绕顺序不正确。您必须切换第一个和第三个索引。

    // the vertices of the mesh and the vertex normals ----------------
            var nx = 64;
            var ny = 32;
            var R = 10; var r = 3;
            var Vertices = new Array(nx);
            var Normals = new Array(nx);
            for (var i = 0; i < nx; i++) {
                Vertices[i] = new Array(ny);
                Normals[i] = new Array(ny);
                var u = i / nx * 2 * Math.PI;
                var cos_u = Math.cos(u);
                var sin_u = Math.sin(u);
                var cx = R * cos_u;
                var cy = R * sin_u;
                for (var j = 0; j < ny; j++) {
                    var v = j / ny * 2 * Math.PI;
                    var rcos_v = r * Math.cos(v);
                    var rsin_v = r * Math.sin(v);
                    Vertices[i][j] = new THREE.Vector3(
                        cx + rcos_v * cos_u,
                        cy + rcos_v * sin_u,
                        rsin_v
                    );
                    Normals[i][j] = new THREE.Vector3(
                        rcos_v * cos_u,
                        rcos_v * sin_u,
                        rsin_v
                    );
                }
            }
    
    // vertices as a dot cloud ----------------------------------------
            var dotGeometry = new THREE.Geometry();
            for (var i = 0; i < nx; i++) {
                for (var j = 0; j < ny; j++) {
                    dotGeometry.vertices.push(Vertices[i][j]);
                }
            }
            var dotMaterial =
                new THREE.PointsMaterial({ size: 1, sizeAttenuation: false });
            var cloud = new THREE.Points(dotGeometry, dotMaterial);
    
    // mesh -----------------------------------------------------------
            var geom = new THREE.Geometry();
            geom.vertices = dotGeometry.vertices;
            for (var i = 0; i < nx; i++) {
                var ip1 = (i == nx - 1 ? 0 : i + 1);
                for (var j = 0; j < ny; j++) {
                    var jp1 = (j == ny - 1 ? 0 : j + 1);
    
                    var vnormals1 = 
                        [Normals[i][j], Normals[i][jp1], Normals[ip1][j]];
                    geom.faces.push(new THREE.Face3(
                        ip1 * ny + j,
                        i * ny + jp1,
                        i * ny + j,
                        vnormals1
                    ));
     
                    var vnormals2 = 
                        [Normals[i][jp1], Normals[ip1][jp1], Normals[ip1][j]];
                    geom.faces.push(new THREE.Face3(
                        ip1 * ny + j,
                        ip1 * ny + jp1,
                        i * ny + jp1,
                        vnormals2
                    ));
                }
            }
    
            var torusMesh = new THREE.Mesh(
                geom, 
                new THREE.MeshNormalMaterial({ wireframe: false }));
    
    // three js scene -------------------------------------------------
            var scene = new THREE.Scene();
    
            var aspect = window.innerWidth / window.innerHeight;
            var camera = new THREE.PerspectiveCamera(50, aspect, 1, 10000);
            camera.position.z = 30;
            scene.add(camera);
    
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            var object = new THREE.Object3D();
            object.add(torusMesh);
            object.add(cloud);
            scene.add(object);
            renderer.render(scene, camera);
    
    // animation ---------------------------------------------------------
            var isDragging = false;
            var previousMousePosition = {
                x: 0,
                y: 0
            };
            $(renderer.domElement).on('mousedown', function (e) {
                isDragging = true;
            }).on('mousemove', function (e) {
                var deltaMove = {
                    x: e.offsetX - previousMousePosition.x,
                    y: e.offsetY - previousMousePosition.y
                };
                if (isDragging) {
                    var deltaRotationQuaternion = new THREE.Quaternion()
                        .setFromEuler(new THREE.Euler(
                            Math.PI / 180 * (deltaMove.y * 1),
                            Math.PI / 180 * (deltaMove.x * 1),
                            0,
                            'XYZ'
                        ));
                    object.quaternion.multiplyQuaternions(deltaRotationQuaternion,
                        object.quaternion);
                }
                previousMousePosition = {
                    x: e.offsetX,
                    y: e.offsetY
                };
            });
    
            $(document).on('mouseup', function (e) {
                isDragging = false;
            });
    
            window.requestAnimFrame = (function () {
                return window.requestAnimationFrame ||
                    window.webkitRequestAnimationFrame ||
                    window.mozRequestAnimationFrame ||
                    function (callback) {
                        window.setTimeout(callback, 1000 / 60);
                    };
            })();
    
            function render() {
                renderer.render(scene, camera);
                requestAnimFrame(render);
            }
    
            render();
    canvas {
                width: 100%;
                height: 100%
            }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
    <script
      src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
      integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E="
      crossorigin="anonymous"></script>

    另外,考虑使用TorusBufferGeometry的方法。此外,使用BufferGeometry 生成几何图形比使用Geometry 更快。

    【讨论】:

    • 谢谢!我知道圆环在三个 js 中可用。这只是一个练习,也是更复杂的事情的初步步骤。
    • 这仍然对我不起作用 :( 顺便说一句,我仍然收到此警告:[.WebGL-0x55bf7783fad0]GL ERROR :GL_INVALID_ENUM : glGetIntegerv: pname was GL_MAX_SAMPLES_ANGLE
    • 圆环在您的片段中显得完整。看看这个:fiddle。对我来说,只出现了环面的一部分。代码是正确的,我把三角形倒过来了。
    • 你在 Linux 上吗?如果是这样,您可以忽略上述警告。它与您的特定环面实现无关。
    猜你喜欢
    • 2019-01-28
    • 2018-11-02
    • 2020-11-27
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2013-10-17
    • 1970-01-01
    • 2018-05-19
    相关资源
    最近更新 更多