【问题标题】:How to merge two geometries or meshes using three.js r71?如何使用 three.js r71 合并两个几何图形或网格?
【发布时间】:2015-07-26 13:55:57
【问题描述】:

在这里我遇到了问题,因为我需要将两个几何(或网格)合并为一个。使用three.js的早期版本有一个很好的功能:

THREE.GeometryUtils.merge(pendulum, ball);

但是,它不再出现在新版本上。

我尝试将pendulumball 与以下代码合并:

ball 是一个网格。

var ballGeo = new THREE.SphereGeometry(24,35,35);
var ballMat = new THREE.MeshPhongMaterial({color: 0xF7FE2E}); 
var ball = new THREE.Mesh(ballGeo, ballMat); 
ball.position.set(0,0,0);

var pendulum = new THREE.CylinderGeometry(1, 1, 20, 16);
ball.updateMatrix();
pendulum.merge(ball.geometry, ball.matrix);
scene.add(pendulum);

毕竟,我得到了以下错误:

THREE.Object3D.add: object not an instance of THREE.Object3D. THREE.CylinderGeometry {uuid: "688B0EB1-70F7-4C51-86DB-5B1B90A8A24C", name: "", type: "CylinderGeometry", vertices: Array[1332], colors: Array[0]…}THREE.error @ three_r71.js:35THREE.Object3D.add @ three_r71.js:7770(anonymous function) @ pendulum.js:20

【问题讨论】:

    标签: javascript merge three.js


    【解决方案1】:

    最后,我找到了一个可能的解决方案。我发帖是因为它可能对其他人有用,而我却浪费了很多时间。棘手的是操纵网格和几何的概念:

    var ballGeo = new THREE.SphereGeometry(10,35,35);
    var material = new THREE.MeshPhongMaterial({color: 0xF7FE2E}); 
    var ball = new THREE.Mesh(ballGeo, material);
    
    var pendulumGeo = new THREE.CylinderGeometry(1, 1, 50, 16);
    ball.updateMatrix();
    pendulumGeo.merge(ball.geometry, ball.matrix);
    
    var pendulum = new THREE.Mesh(pendulumGeo, material);
    scene.add(pendulum);
    

    【讨论】:

    • “Tyler Crompton 在生活中的事迹毫无必要” - Lady Galadriel 谢谢
    • 这是一个非常有用的解决方案,如果 mesh1.position.set(xx, 0, 0); 甚至允许mesh2围绕mesh1旋转如果它设置为 (0, 0, 0),它会在 mesh1 内部或周围居中,具体取决于尺寸。
    • 感谢分享!将其用于将新网格/几何图形合并到现有网格中的方法。 function AddToGeometry(mainObject, objectToAdd) { objectToAdd.updateMatrix(); mainObject.geometry.merge(objectToAdd.geometry, objectToAdd.matrix); return mainObject; }
    【解决方案2】:

    为了更清楚地解释 Darius 的答案(当我试图更新 Doob 先生的程序城市的一个版本以使用 Face3 框时):

    本质上,您是将所有网格合并到一个几何体中。因此,例如,如果您想要合并一个盒子和球体:

    var box = new THREE.BoxGeometry(1, 1, 1);
    var sphere = new THREE.SphereGeometry(.65, 32, 32);
    

    ...进入单个几何体:

    var singleGeometry = new THREE.Geometry();
    

    ...您将为每个几何体创建一个网格:

    var boxMesh = new THREE.Mesh(box);
    var sphereMesh = new THREE.Mesh(sphere);
    

    ...然后为每个调用单个几何的merge方法,将每个几何和矩阵传递给方法:

    boxMesh.updateMatrix(); // as needed
    singleGeometry.merge(boxMesh.geometry, boxMesh.matrix);
    
    sphereMesh.updateMatrix(); // as needed
    singleGeometry.merge(sphereMesh.geometry, sphereMesh.matrix);
    

    合并后,从单个几何体创建一个网格并添加到场景中:

    var material = new THREE.MeshPhongMaterial({color: 0xFF0000});
    var mesh = new THREE.Mesh(singleGeometry, material);
    scene.add(mesh);
    

    一个工作示例:

    <!DOCTYPE html>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"></script>
    <!-- OrbitControls.js is not versioned and may stop working with r77 -->
    <script src='http://threejs.org/examples/js/controls/OrbitControls.js'></script>
    
    <body style='margin: 0px; background-color: #bbbbbb; overflow: hidden;'>
      <script>
        // init renderer
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
    
        // init scene and camera
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 3000);
        camera.position.z = 5;
        var controls = new THREE.OrbitControls(camera)
       	
        // our code
        var box = new THREE.BoxGeometry(1, 1, 1);
        var sphere = new THREE.SphereGeometry(.65, 32, 32);
    
        var singleGeometry = new THREE.Geometry();
    
        var boxMesh = new THREE.Mesh(box);
        var sphereMesh = new THREE.Mesh(sphere);
    
        boxMesh.updateMatrix(); // as needed
        singleGeometry.merge(boxMesh.geometry, boxMesh.matrix);
    
        sphereMesh.updateMatrix(); // as needed
        singleGeometry.merge(sphereMesh.geometry, sphereMesh.matrix);
    
        var material = new THREE.MeshPhongMaterial({color: 0xFF0000});
        var mesh = new THREE.Mesh(singleGeometry, material);
        scene.add(mesh);
    
        // a light
        var light = new THREE.HemisphereLight(0xfffff0, 0x101020, 1.25);
        light.position.set(0.75, 1, 0.25);
        scene.add(light);
    	
        // render
        requestAnimationFrame(function animate(){
    	    requestAnimationFrame(animate);
    	    renderer.render(scene, camera);		
        })
      </script>
    </body>

    至少,我是这样解释事物的;如果我有问题,向任何人道歉,因为我离成为 three.js 专家(目前正在学习)还差得很远。我只是“运气不好”尝试自定义 Doob 先生的程序城市代码,当最新版本破坏了一些东西时(合并的东西就是其中之一,事实上 three.js 不再使用四边形作为立方体 -ahem - 另一个盒子几何体 - 这带来了各种乐趣,让阴影等再次正常工作)。

    【讨论】:

    • 感谢您。更新我刚刚从 500,000 条警告中移植的一些代码看起来非常令人生畏。我对处理这个问题的方式不太满意,找到答案对于我无法控制的事情来说太难了。
    【解决方案3】:

    错误信息是正确的。 CylinderGeometry 不是 Object3D。网格是。 Mesh 由 Geometry 和 Material 构成。 Mesh 可以添加到场景中,而 Geometry 不能。

    在three.js的最新版本中,Geometry有两种合并方法:mergemergeMes​​h

    • merge 接受一个强制参数 geometry,以及两个可选参数 matrixmaterialIndexOffset
    • geom.mergeMes​​h(mesh) 基本上是 geom.merge(mesh.geometry, mesh.matrix),如其他答案中使用的那样。 (“geom”和“mesh”分别是几何和网格的任意名称。)网格的材质被忽略。

    【讨论】:

    • mergeMes​​h 赢得胜利。这要简单得多。
    【解决方案4】:

    这是我使用 mergeMes​​h 的四(或五)行(只要材料在其他地方定义)的终极紧凑版本:

    var geom = new THREE.Geometry();
    geom.mergeMesh(new THREE.Mesh(new THREE.BoxGeometry(2,20,2)));
    geom.mergeMesh(new THREE.Mesh(new THREE.BoxGeometry(5,5,5)));
    geom.mergeVertices(); // optional
    scene.add(new THREE.Mesh(geom, material));
    

    编辑:添加了可选的额外行以删除重复的顶点,这应该有助于提高性能。

    编辑 2:我使用的是最新版本,94。

    【讨论】:

    • 请告诉我们您当前使用的版本号?
    • 看起来不错。它是否也适用于使用VertexColorBufferGeometry
    • .Geometry() 现在是 BufferGeometry 吗?版本 130
    • mergeMes​​h 和 mergeVertices 未找到,而 'merge'ing 没有错误它不起作用版本 131
    猜你喜欢
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2012-11-20
    • 2019-01-18
    • 2013-11-18
    • 2013-06-16
    • 2013-05-24
    • 2013-07-24
    相关资源
    最近更新 更多