如何使用 three.js r71 合并两个几何体或网格?
How to merge two geometries or meshes using three.js r71?
这里我遇到了问题,因为我需要将两个几何体(或网格)合并为一个。使用 three.js 的早期版本有一个很好的功能:
THREE.GeometryUtils.merge(pendulum, ball);
但是,新版本上已经没有了。
我尝试使用以下代码合并 pendulum
和 ball
:
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
最后,我找到了一个可能的解决方案。我发帖是因为它可能对其他人有用,而我却浪费了很多时间。棘手的事情是关于操纵网格和几何的概念:
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);
为了更清楚地解释 Darius 的回答(因为我在尝试更新 Mr 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 专家(目前正在学习)还差得很远。我刚刚用 "bad luck" 尝试自定义 Doob 先生的程序城市代码,当最新版本出现问题时(合并内容就是其中之一,事实上 three.js 不再使用四边形cube -ahem- box geometry the other - 这导致了各种乐趣,让阴影等再次正常工作)。
错误信息是对的。 CylinderGeometry 不是 Object3D。网格是。 Mesh 由 Geometry 和 Material 构成。 Mesh 可以添加到场景中,而 Geometry 不能。
在最新版本的three.js中,Geometry有两种合并方法:merge和mergeMesh.
- merge 需要一个强制参数 geometry,以及两个可选参数 matrix 和 materialIndexOffset.
- geom.mergeMesh(mesh) 基本上是一个 shorthand for geom.merge(mesh.geometry, mesh.matrix),如其他答案中所用。 ('geom' 和 'mesh' 分别是几何体和网格的任意名称。)忽略网格的 Material。
这是我使用 mergeMesh:
的四(或五)行(只要 material 在其他地方定义)的最终紧凑版本
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。
这里我遇到了问题,因为我需要将两个几何体(或网格)合并为一个。使用 three.js 的早期版本有一个很好的功能:
THREE.GeometryUtils.merge(pendulum, ball);
但是,新版本上已经没有了。
我尝试使用以下代码合并 pendulum
和 ball
:
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
最后,我找到了一个可能的解决方案。我发帖是因为它可能对其他人有用,而我却浪费了很多时间。棘手的事情是关于操纵网格和几何的概念:
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);
为了更清楚地解释 Darius 的回答(因为我在尝试更新 Mr 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 专家(目前正在学习)还差得很远。我刚刚用 "bad luck" 尝试自定义 Doob 先生的程序城市代码,当最新版本出现问题时(合并内容就是其中之一,事实上 three.js 不再使用四边形cube -ahem- box geometry the other - 这导致了各种乐趣,让阴影等再次正常工作)。
错误信息是对的。 CylinderGeometry 不是 Object3D。网格是。 Mesh 由 Geometry 和 Material 构成。 Mesh 可以添加到场景中,而 Geometry 不能。
在最新版本的three.js中,Geometry有两种合并方法:merge和mergeMesh.
- merge 需要一个强制参数 geometry,以及两个可选参数 matrix 和 materialIndexOffset.
- geom.mergeMesh(mesh) 基本上是一个 shorthand for geom.merge(mesh.geometry, mesh.matrix),如其他答案中所用。 ('geom' 和 'mesh' 分别是几何体和网格的任意名称。)忽略网格的 Material。
这是我使用 mergeMesh:
的四(或五)行(只要 material 在其他地方定义)的最终紧凑版本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。