Выдавливание нескольких полигонов с несколькими отверстиями и текстурирование комбинированной формы

Этот вопрос связан с этим вопросом. Ответ показывает очень хороший способ выдавливания полигонов, имеющих отверстия (см. Отличный пример в реальном времени). Основное изучение ответа состояло в том, что пути в three.js (r58) не могут иметь более одной команды moveTo, и она должна находиться в начале пути, что означает, что путь должен быть нарушен с помощью moveTos, так что moveTo запускается всегда новый путь.

Выдавливание в three.js означает, что 2D-пути преобразуются в 3D-формы с использованием возможного скоса. Он подходит для выдавливания текстов для создания трехмерных букв и слов, но может также использоваться для выдавливания пользовательских путей.

Теперь возникает два вопроса:

  • Как можно обрабатывать многоугольники, которые имеют многоугольники с отверстиями и многоугольники без дыр?
  • как можно добавить текстуру к сгенерированной фигуре в целом?

Я сделал пример этого как SVG в http://jsbin.com/oqomuj/1/edit:

Изображение создается по этому пути:

<путь d = "
 M57.11271.77 L57.11,218.33 L41.99,218.63 L105,49,165.77 L138.41,193.18 L138.41,172.2 L152.53,172.2 L152.53,204.93 L168.99,218.63 L153.21.218.63 L153.21.271.77ZZ
 M74.14644,13105,49,264,13105,49,232,8 L74,14,232,8Z
 M115,35,250,7 L135,96,250,7 L135,96,232,61 L115,35,232,61Z
 M56,11,14,77 L56,11,92,33 L40,99,92,63 L104,49,39,77 L137,41,67,18 L137,41,46,2 L151,53,46,2 L151,53,78,93 L152,53,79,76 L155,55,77,23 L159. 5,74,52 L168,65,69,81 L176,46,66,93 L188.04,64,16 L200,63,62,7 L213,65,62,7 L226,05,64,09 L234,83,66,06 L245,65,69,73 L252,87,73,27 L259. 12,77,34 L262,63,80,33 L265,6,83,47 L268,01,86,76 L269,83,90,17 L271,08,93,68 L271,76,99,08 L271,04,94,64 L269,75,108,2 L267,87,111,63 L265,42,114,91 L262,48,118 95,120.92 L255.02,123.63 L245.86,128.34 L238.06,131.22 L226.48,133.99 L213.88,135.44 L200.63,135.44 L188.04,133.99 L176.46,131.22 L168.65,128.34 L159.5,123.63 L155.55,120.92 L152.21,118.12 L152.21,145.77Z
 M73.14 138,13 L104,49 138,13 L104,49,106,8 L73,14 106,8Z
 M114,35,124,7 L134,96,124,7 L134,96,106,61 L114,35,106,61Z
 M207,26,117,33 L210,57,117.26 L216,87,116,53 L222,66,115,15 L227,8,113,18 L233,11,110 L236,34,106,99 L238,51,103,64 L239,42,100,48 L239,42,97,67 L238,51,94,51,1182,32 L2,33,32,32 L2,36,32,32 L2,36,32,31,32,31,32,31,32,31,32,31,32,31,32,31,32,31,32,31,32,31 L2,31 L2,32, 84,97 L222,66,83 L216,87,81,62 L210,57,80,89 L203,94,80,89 L197,65,81,62 L191,86,83 L186,71,84,97 L181,41,88,15 L178,18,91,16 L176,01, 94,51 L175,1,97,67 L175,1,100,48 L176,01,103,64 L178,18,106,99 L181,4110 L186,71,113,18 L191,86,115,15 L197,65,116,53 L203,94,117,26Z
">

и этот путь преобразуется в отдельные массивы вершин:

var lower_house_material = [{x: 57.11, y: 271.77}, {x: 57.11, y: 218.33}, {x: 41.99, y: 218.63}, {x: 105.49, y: 165.77}, {x: 138.42, y: 193,18}, {х: 138,42, у: 172.2}, {х: 152,53, у: 172.2}, {х: 152,53, у: 204,93}, {х: 168.99, у: 218,63}, {х: 153,21, у: 218,63}, {х: 153,21, у: 271,77}];
var lower_house_hole_1 = [{x:74,14, y: 264,13}, {X: 105,49, Y: 264,13}, {X: 105,49, Y: 232,8}, {X: 74,14, Y: 232,8}];
var lower_house_hole_2 = [{x:115.35,y:250.7},{x:135.96,y:250.7},{x:135.96,y:232.61},{x:115.35,y:232.61}];

var upper_house_material = [{x:56.11,y:145.77},{x:56.11,y:92.33},{x:40.99,y:92.63},{x:104.49,y:39.77},{x:137.42,y:67,18}, {х: 137,42, у: 46,2}, {х: 151,53, у: 46,2}, {х: 151,53, у: 78,93}, {х: 152,53, у: 79,76}, {х: 155,55, у: 77,23}, {х: 159,5, у: 74,52}, {х: 168,65, у: 69,81}, {х: 176,46, у: 66,93}, {х: 188,04, у: 64,16}, {х: 200,63, у: 62,7}, {х: 213,65, у: 62,7}, {х: 226,05, у: 64,1}, {х: 234,83, у: 66,06}, {х: 245,65, у: 69,73}, {х: 252,87, у: 73,27}, {х: 259,12, у: 77,35}, {х: 262,63, у: 80,33}, {х: 265,6, у: 83,47}, {х: 268,01, у: 86,76}, {х: 269,84, у: 90,17}, {х: 271,08, у: 93,68}, {х: 271,76, у: 99,08}, {х: 271,04, у: 104.64}, {х: 269,75, у: 108.2}, {х: 267,87, у: 111,63}, {х: 265,42, у: 114,91}, {х: 262,44, у: 118,01}, {х: 258,96, у: 120,92}, {х: 255,02, у: 123,63}, {х: 245,86, у: 128,34}, {х: 238,06, у: 131,22}, {х: 226,48, у: 133,99}, {х: 213,88, у: 135,45}, {х: 200,63, у: 135,45}, {х: 188,04, у: 133,99}, {х: 176,46, у: 131,22}, {х: 168,65, у: 128,34}, {х: 159,5, у: 123,63}, {х: 155,55, у: 120,92}, {х: 152,21, у: 118,12}, {х: 152,21, у: 145,77}];
var upper_house_hole_1 = [{x:73.14,y:138.13},{x:104.49,y:138.13},{x:104.49,y:106.8},{x:73.14,y:106.8}];
var upper_house_hole_2 = [{x:114.35,y:124.7},{x:134.96,y:124.7},{x:134.96,y:106.61},{x:114.35,y:106.61}];
var upper_house_hole_3 = [{x:207,26, y: 117,33}, {x: 210,57, y: 117,26}, {x: 216,87, y: 116,53}, {x: 222,66, y: 115,15}, {x: 227,8, y: 113,18}, {х: 233,11, у: 110}, {х: 236,34, у: 106.99}, {х: 238,51, у: 103.64}, {х: 239,42, у: 100.48}, {х: 239,42, у: 97,67}, {х: 238,51, у: 94,51}, {х: 236,34, у: 91,16}, {х: 233,11, у: 88,15}, {х: 227,8, у: 84,97}, {х: 222,66, у: 83}, {х: 216,87, у: 81,62}, {х: 210,57, у: 80,89}, {х: 203.94, у: 80,89}, {х: 197,65, у: 81,62}, {х: 191,86, у: 83}, {х: 186,71, у: 84,97}, {х: 181,41, у: 88,15}, {х: 178,18, у: 91,16}, {х: 176,01, у: 94,51}, {х: 175,1, у: 97,67}, {х: 175,1, у: 100.48}, {х: 176,01, у: 103.64}, {х: 178,18, у: 106.99}, {х: 181,41, у: 110}, {х: 186,71, у: 113,18}, {х: 191,86, у: 115,15}, {х: 197,65, у: 116,53}, {х: 203.94, у: 117,26}];

Вопрос в том, как эту подобную структуру можно преобразовать в трехмерный объект в Three.js, чтобы ее можно было вытянуть, используя THREE.ExtrudeGeometry( shape, extrusionSettings ) а после этого текстурируется в целом?

Я могу изучить данные пути, чтобы узнать, какое отверстие принадлежит тому или иному многоугольнику, и обработать все как отдельные фигуры, но, поскольку я хочу использовать одно изображение текстуры для всех фигур, я думаю, что предпочтительным способом является обработка всех полигонов материала как одной фигуры. и дырочные полигоны как другие формы и использовать что-то вроде:

var shape = [lower_house_material, upper_house_material];
shape.holes = [lower_house_hole_1, lower_house_hole_2, upper_house_hole_1, upper_house_hole_2, upper_house_hole_3];
var 3d_geometry = THREE.ExtrudeGeometry (shape, extrusionSettings);

Итак 3d_geometry должен быть в конце один меш, к которому я могу добавить текстуру таким образом:

var textureFront = new THREE.ImageUtils.loadTexture ('textureFront.png');
var textureSide = new THREE.ImageUtils.loadTexture ('textureSide.png');
var materialFront = new THREE.MeshBasicMaterial ({map: textureFront});
var materialSide = new THREE.MeshBasicMaterial ({map: textureSide});
var materialArray = [materialFront, materialSide];
var faceMaterial = new THREE.MeshFaceMaterial (materialArray);
var final_mesh = new THREE.Mesh (3d_geometry, faceMaterial);

И одна из текстур может быть примерно такой (256x256px):

И текстура применяется:

А поскольку сетка выдавливается, на приведенном выше рисунке также есть 3D-толщина, но у вас есть идея текстурирования.

Я знаю, что y-координаты нужно перевернуть, но это тривиальная задача, а не вопрос моего вопроса, но если в Three.js есть готовая функция для отсечения y, это будет полезно.

Я потратил часы, чтобы изучить исходный код three.js, примеры и документацию, но поскольку наиболее часто встречающееся слово "todo", оно мало чем может помочь. И я очень новичок в Three.js, я думаю, что это может быть тривиальной задачей для некоторых опытных пользователей Three.js.

ОБНОВЛЕНИЕ: И просто чтобы убедиться, что многоугольники отверстий всегда хорошо себя ведут, это означает, что многоугольники отверстий всегда полностью находятся внутри многоугольников материала, и нет повторяющихся вершин или самопересечений ни в многоугольниках материала, ни в многоугольниках отверстий, а во всех остальных. Материал-полигоны имеют порядок намотки CW и отверстия CCW.

ОБНОВЛЕНИЕ: Объединение геометрий не было решением для текстурирования всего вытянутого многоугольника, заданного одной текстурой: http://jsfiddle.net/C5dga. Текстура повторяется для всех отдельных форм, поэтому объединение геометрий в этом случае не имеет никакого реального смысла. Возможно, можно найти решение по слиянию форм до их выдавливания, но пока не найдено решения для этого.

1 ответ

Решение

Вы можете объединить геометрию как в следующем фрагменте, в результате чего получается всего одна сетка. Из ваших предыдущих вопросов вы уже знаете, как текстурировать одну геометрию.

var geometry1 = new THREE.ExtrudeGeometry( shape1, extrusionSettings );
var geometry2 = new THREE.ExtrudeGeometry( shape2, extrusionSettings );

geometry1.merge( geometry2 );

. . .

var mesh = new THREE.Mesh( geometry1, material );

scene.add( mesh );

Скрипка: http://jsfiddle.net/pHn2B/88/

Скрипка: http://jsfiddle.net/C5dga/13/ (с текстурой)

РЕДАКТИРОВАТЬ: в качестве альтернативы для создания отдельных геометрий и использования merge Утилита, вы можете создать одну геометрию, используя вместо этого следующий шаблон:

var geometry1 = new THREE.ExtrudeGeometry( [ shape1, shape2 ], extrusionSettings );

РЕДАКТИРОВАТЬ: обновлено до three.js r.70

Другие вопросы по тегам