Vraag Hoe twee geometrieën of mazen samen te voegen met behulp van three.js r71?


Hier ben ik tegen het probleem aangelopen, omdat ik twee geometrieën (of mazen) moet samenvoegen tot één geometrie. Met de eerdere versies van three.js was er een leuke functie:

THREE.GeometryUtils.merge(pendulum, ball);

Het is echter niet meer op de nieuwe versie.

Ik probeerde te fuseren pendulum en ball met de volgende code:

ball is een mesh.

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);

Ik heb tenslotte de volgende foutmelding gekregen:

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

21
2018-05-14 19:44


oorsprong


antwoorden:


Het antwoord van Darius duidelijker uitleggen (terwijl ik ermee worstelde, terwijl ik probeerde een versie van de procedurele stad van de heer Doob te updaten om met de Face3-boxen te werken):

In wezen voeg je al je mazen samen tot een enkele geometrie. Dus als u bijvoorbeeld een doos en een bol wilt samenvoegen:

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

... in een enkele geometrie:

var singleGeometry = new THREE.Geometry();

... u zou een netwerk creëren voor elke geometrie:

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

... noem dan de samenvoegingsmethode van de enkele geometrie voor elk, waarbij de geometrie en de matrix van elk in de methode worden doorgevoerd:

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

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

Eenmaal samengevoegd, maakt u een net van de enkele geometrie en voegt u toe aan de scène:

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

Een werkend voorbeeld:

<!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>

Dat is tenminste hoe ik dingen interpreteer; excuses aan iedereen als ik iets fout heb, want ik ben er niet op uit om een ​​expert van three.js te zijn (momenteel aan het leren). Ik had gewoon de "pech" om de hand te houden aan het aanpassen van de procedurele stadscode van Mr. Doob, wanneer de nieuwste versie dingen verbreekt (het samenvoegspul is daar een van, het feit dat three.js geen gebruik meer maakt van quads voor cube -ahem - vakgeometrie de andere - wat heeft geleid tot allerlei soorten lol om de zonwering en dergelijke weer goed te laten werken).


27
2017-10-28 16:12



Eindelijk vond ik een mogelijke oplossing. Ik post het omdat het nuttig kan zijn voor iemand anders, terwijl ik veel uren verspilde. Het lastige is om het concept van mazen en geometrieën te manipuleren:

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);

16
2018-05-14 19:54



Het foutbericht is goed. CylinderGeometry is geen Object3D. Mesh is. Een gaas is opgebouwd uit een geometrie en een materiaal. Een mesh kan aan de scène worden toegevoegd, terwijl een geometrie dat niet kan.

In de nieuwste versies van three.js heeft Geometry twee samenvoegmethoden: samensmelten en mergeMesh.

  • samensmelten neemt een verplicht argument geometrieen twee optionele argumenten Matrix en materialIndexOffset.
  • geom.mergeMesh(mesh) is eigenlijk een afkorting voor geom.samensmelten(Mesh.geometrie, mesh.Matrix), zoals gebruikt in andere antwoorden. ('geom' en 'mesh' zijn willekeurige namen voor respectievelijk een geometrie en een mesh.) Het materiaal van de mesh wordt genegeerd.

5
2018-05-25 19:12



Dit is mijn ultieme compacte versie in vier (of vijf) regels (zolang materiaal ergens anders wordt gedefinieerd) met gebruik van 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));

Bewerken: extra optionele regel toegevoegd om dubbele hoekpunten te verwijderen, wat de prestaties zou helpen verbeteren.

Bewerken 2: ik gebruik de nieuwste versie, 94.


0
2017-07-29 20:35