如何使用three.js r71合并两个几何或网格?

Dar*_*kas 27 javascript merge three.js

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

THREE.GeometryUtils.merge(pendulum, ball);
Run Code Online (Sandbox Code Playgroud)

但是,它不再是新版本了.

我尝试合并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);
Run Code Online (Sandbox Code Playgroud)

毕竟,我收到以下错误:

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
Run Code Online (Sandbox Code Playgroud)

小智 33

更清楚地解释Darius的答案(当我努力解决它时,在尝试更新Doob先生的程序城市版本以使用Face3框时):

基本上,您将所有网格合并为单个几何.所以,例如,如果你想要合并一个盒子和球体:

var box = new THREE.BoxGeometry(1, 1, 1);
var sphere = new THREE.SphereGeometry(.65, 32, 32);
Run Code Online (Sandbox Code Playgroud)

...成一个几何:

var singleGeometry = new THREE.Geometry();
Run Code Online (Sandbox Code Playgroud)

...你会为每个几何创建一个Mesh:

var boxMesh = new THREE.Mesh(box);
var sphereMesh = new THREE.Mesh(sphere);
Run Code Online (Sandbox Code Playgroud)

...然后为每个几何体调用合并方法,将每个几何体和矩阵传递给方法:

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

sphereMesh.updateMatrix(); // as needed
singleGeometry.merge(sphereMesh.geometry, sphereMesh.matrix);
Run Code Online (Sandbox Code Playgroud)

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

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

一个工作的例子:

<!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>
Run Code Online (Sandbox Code Playgroud)

至少,这就是我解释事物的方式; 如果我有什么不对的话,向任何人道歉,因为我不是一个接近成为three.js专家(目前正在学习)的地方.当最新版本破坏事物时(合并的东西就是其中之一,事实上,three.js不再使用四边形作为立方体的事情)我只是有"运气不好"试图定制Doob先生的程序城市代码. - 另一个盒子几何形状 - 这使得阴影得到各种乐趣,并且再次正常工作).


Dar*_*kas 19

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

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);
Run Code Online (Sandbox Code Playgroud)

  • _"没有人在生活中没有Tyler Crompton的事迹"_ - _Lady Galadriel_谢谢你 (7认同)

Eli*_*sle 5

错误消息是正确的.CylinderGeometry不是Object3D.网格是.网格由几何和材质构成.可以将Mesh添加到场景中,而Geometry则不能.

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

  • merge采用强制参数几何,以及两个可选参数matrixmaterialIndexOffset.
  • GEOM.mergeMes​​h(mesh)基本上是geom的简写.合并(网格.几何,网格.矩阵),用于其他答案.('geom'和'mesh'分别是Geometry和Mesh的任意名称.)Mesh的材质被忽略.


Rob*_*ski 5

这是我使用 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));
Run Code Online (Sandbox Code Playgroud)

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

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