在这里我遇到了问题,因为我需要将两个几何(或网格)合并到一个。使用trex.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
更清楚地解释了达里乌斯的答案(当我对此苦苦挣扎时,试图更新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);
...然后调用每个几何的单一几何方法的合并方法,将每种几何和矩阵传递到该方法中:
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>
至少,这就是我解释事物的方式;如果我有问题,请向任何人致歉,因为我没有一个即将成为三名JS专家(目前正在学习)的地方。我只是有"厄运"来尝试自定义杜布先生的过程城市代码,当时最新版本破坏了东西(合并的东西就是其中之一,这是三分之一的事实,即三个js不再使用Quads进行Cube -Ahem - 盒几何形状 - 另一个导致了各种乐趣,使阴影变得正确工作)。
最后,我找到了一个可能的解决方案。我发帖,因为当我浪费很多小时时,这对别人可能很有用。棘手的事情是关于操纵网格和几何形状的概念:
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);
错误消息正确。圆柱体测定不是对象3D。网格是。网格是用几何形状和材料构造的。可以将网格添加到场景中,而几何不能。
在最新版本的三个.js中,几何形状具有两个合并方法: Merge 和 Mergemesh 。。
- Merge 采用强制性参数几何,两个可选的参数 matrix 和 MiteralIndexOffset 。。
- GEOM。 Mergemesh (网格)基本上是Geom的速记。 Merge (网格。几何,mesh。/em>),如其他答案所用。('geom'和'网格'分别是几何和网格的任意名称。)网格的材料被忽略。
这是我使用Mergemesh的四(或五个)行(或在其他地方定义的材料)中的最终紧凑版本(只要材料定义):
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。
我在此处发布的答案和代码不起作用,因为合并方法的第二个参数是整数,而不是矩阵。据我所知,合并方法并没有真正以有用的方式运行。因此,我使用以下方法制作了带鼻锥的简单火箭。
import * as BufferGeometryUtils from '../three.js/examples/jsm/utils/BufferGeometryUtils.js'
lengthSegments = 2
radius = 5
radialSegments = 32
const bodyLength = dParamWithUnits['launchVehicleBodyLength'].value
const noseConeLength = dParamWithUnits['launchVehicleNoseConeLength'].value
// Create the vehicle's body
const launchVehicleBodyGeometry = new THREE.CylinderGeometry(radius, radius, bodyLength, radialSegments, lengthSegments, false)
launchVehicleBodyGeometry.name = "body"
// Create the nose cone
const launchVehicleNoseConeGeometry = new THREE.CylinderGeometry(0, radius, noseConeLength, radialSegments, lengthSegments, false)
launchVehicleNoseConeGeometry.name = "noseCone"
launchVehicleNoseConeGeometry.translate(0, (bodyLength+noseConeLength)/2, 0)
// Merge the nosecone into the body
const launchVehicleGeometry = BufferGeometryUtils.mergeBufferGeometries([launchVehicleBodyGeometry, launchVehicleNoseConeGeometry])
// Rotate the vehicle to horizontal
launchVehicleGeometry.rotateX(-Math.PI/2)
const launchVehicleMaterial = new THREE.MeshPhongMaterial( {color: 0x7f3f00})
const launchVehicleMesh = new THREE.Mesh(launchVehicleGeometry, launchVehicleMaterial)