web-dev-qa-db-ja.com

three.js r71を使用して2つのジオメトリまたはメッシュをマージする方法

ここでは、2つのジオメトリ(またはメッシュ)を1つにマージする必要があるため、問題にぶつかりました。 three.jsの以前のバージョンを使用すると、Nice関数がありました。

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
26

最後に、可能な解決策を見つけました。私は多くの時間を浪費している間、それが他の誰かに役立つかもしれないので、私は投稿しています。難しいのは、メッシュとジオメトリの概念を操作することです。

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

ダリウスの答えをより明確に説明するために(Food3ボックスで動作するようにDoob氏の手続き都市のバージョンを更新しようとしていたので、私はそれに苦労した):

基本的に、すべてのメッシュを単一のジオメトリにマージしています。したがって、たとえば、ボックスと球体をマージする場合:

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のエキスパート(現在は学んでいる)に近いとは言えないので、何かおかしいことがあれば誰にでも謝罪します。最新バージョンで問題が発生したときに、Mr。Doobの手続き型都市コードのカスタマイズを試してみました。 -他のボックスジオメトリ-シェーディングを取得するなど、あらゆる種類の楽しみが適切に機能するようになりました。

33
Andrew Ayers

エラーメッセージは正しいです。 CylinderGeometryはObject3Dではありません。メッシュです。メッシュは、ジオメトリとマテリアルから構築されます。メッシュはシーンに追加できますが、ジオメトリは追加できません。

Three.jsの最新バージョンでは、Geometryには2つのマージメソッドがあります:mergeおよびmergeMes​​h

  • mergeは必須の引数geometryと2つのオプションの引数matrixおよびmaterialIndexOffset
  • geom。mergeMes​​h(mesh)は基本的にgeom。mergeの省略形です(mesh。geometry、mesh。matrix)、その他で使用答えます。 (「geom」と「mesh」は、それぞれジオメトリとメッシュの任意の名前です。)メッシュのマテリアルは無視されます。
5
Elias Hasle

これは、mergeMes​​hを使用した4行(または5行)の(素材がどこかで定義されている限り)私の究極のコンパクトバージョンです。

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を使用しています。

1
Rob Kwasowski