Подтвердить что ты не робот

Three.js - связывает две фигуры вместе как одну?

Я новичок в мире three.js... Мой вопрос: могу ли я связать две разные формы вместе как одну форму? Например, связывая сферу и цилиндр вместе как один?

4b9b3361

Ответ 1

Вид, да, есть несколько вариантов:

  • через иерархию. Вы можете просто добавить одну сетку в другую с помощью функции add()
  • через функцию GeometryUtil merge(), чтобы объединить вершины и сетки двух объектов Geometry в один
  • с использованием основного 3D-редактора, поддерживающего логические операции между сетками и экспортом.

Метод 1 довольно прямолинейный:

var sphere = new THREE.Mesh( new THREE.SphereGeometry(100,16,12),new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
                var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(100, 100, 200, 16, 4, false ),new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
                cylinder.position.y = -100;
                scene.add(sphere);
                scene.add(cylinder);

Обратите внимание, что 16 повторяется, поэтому уровень подразделений в одной ячейке совпадает с другим (для достойного внешнего вида)

Метод 2.1 - через GeometryUtils

//make a sphere
                var sg = new THREE.SphereGeometry(100,16,12);
                //make cylinder - ideally the segmentation would be similar to predictable results
                var cg = new THREE.CylinderGeometry(100, 100, 200, 16, 4, false );
                //move vertices down for cylinder, so it maches half the sphere - offset pivot
                for(var i = 0 ; i < cg.vertices.length; i++) cg.vertices[i].position.y -= 100;
                //merge meshes
                THREE.GeometryUtils.merge(sg,cg);
                var mesh = new THREE.Mesh( sg,new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
                scene.add(mesh);

Метод 2.2 слияния Токарная полусфера и цилиндр:

var pts = [];//points array
                var detail = .1;//half-circle detail - how many angle increments will be used to generate points
                var radius = 100;//radius for half_sphere
                var total = Math.PI * .51;
                for(var angle = 0.0; angle < total ; angle+= detail)//loop from 0.0 radians to PI (0 - 180 degrees)
                    pts.push(new THREE.Vector3(0,Math.cos(angle) * radius,Math.sin(angle) * radius));//angle/radius to x,z
                var lathe = new THREE.LatheGeometry( pts, 16 );//create the lathe with 12 radial repetitions of the profile
                //rotate vertices in lathe geometry by 90 degrees
                var rx90 = new THREE.Matrix4();
                rx90.setRotationFromEuler(new THREE.Vector3(-Math.PI * .5,0,0));
                lathe.applyMatrix(rx90);
                //make cylinder - ideally the segmentation would be similar for predictable results
                var cg = new THREE.CylinderGeometry(100, 100, 200, 16, 4, false );
                //move vertices down for cylinder, so it maches half the sphere
                for(var i = 0 ; i < cg.vertices.length; i++) cg.vertices[i].position.y -= 100;
                //merge meshes
                THREE.GeometryUtils.merge(lathe,cg);
                var mesh = new THREE.Mesh( lathe, new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ) );
                mesh.position.y = 150;
                scene.add(mesh);

Одна проблема, с которой я не могу справиться в данный момент, исходит от лиц, находящихся внутри сетки. В идеале у них были бы нормали, чтобы они не отображались, но не нашли быстрого решения для этого.

Третий довольно прямолинейный. Большинство 3D-пакетов позволяют выполнять булевую операцию на сетках (например, слияние двух сеток вместе с операцией ADD (meshA + meshB)). Попробуйте создать цилиндр и сферу в Blender (бесплатно, с открытым исходным кодом), который уже имеет three.js экспортер. Кроме того, вы можете экспортировать файл .obj из объединенных сеток из вашего 3D-редактора или выбора и использовать convert_obj_three script.

Обновление

Я нашел еще один метод, который может быть проще/интуитивно понятным. Помните булевские операции, о которых я говорил выше?

Оказывается, для этого есть потрясающая js-библиотека: Конструктивная сплошная геометрия:

CSG library preview from owner's github page

Chandler Prall написал несколько удобных функций для подключения CSG с тэгом 3.js. Итак, с библиотекой CSG и оболочкой three.js для нее, вы можете просто сделать это:

var cylinder = THREE.CSG.toCSG(new THREE.CylinderGeometry(100, 100, 200, 16, 4, false ),new THREE.Vector3(0,-100,0));
var sphere   = THREE.CSG.toCSG(new THREE.SphereGeometry(100,16,12));
var geometry = cylinder.union(sphere);
var mesh     = new THREE.Mesh(THREE.CSG.fromCSG( geometry ),new THREE.MeshNormalMaterial());

Что дает хороший результат (никаких проблем с дополнительными лицами/переворачиванием нормалей/и т.д.):

cylinder-sphere union with CSG and three.js