К сожалению, нет простого способа сделать это в three.js.
Чтобы получить правильный контроль над текстурированием нетривиальных сеток, вам, вероятно, сначала понадобится сделать UV-unwrapping модели. Обычно это должно делать человек, предоставляющий сетки, потому что это проще сделать в таких инструментах, как blender, 3dstudio, cinema4d и т.п.
Однако, я предполагаю, что у вас нет этого человека по какой-либо причине и нужно сделать это в javascript. Это так забавно. Предположим далее, что мы просто хотим отобразить изображение на переднюю и заднюю стороны сумки, внутри и края не будут текстурированы.
В трехмерных и трехмерных приложениях точное отображение текстуры происходит путем предоставления координат текстуры (или UV-координат) для каждой вершины для каждой грани. Эти УФ-координаты (от 0 до 1) определяют положение текстуры, принадлежащей вершине. Точка (0, 0)
- это нижний левый угол изображения, а (1, 1)
- верхний правый угол, независимо от соотношения сторон изображения.
Таким образом, для простого четырехугольника, изготовленный из двух треугольников, это будет что-то вроде этого:
const geometry = new THREE.Geometry();
const vertices = [
// the four vertices ABCD
[0,0,0], [0,1,0], [1,0,0], [1,1,0]
].map(v => new THREE.Vector3(...v));
// setup two triangles ADB and ACD:
//
// B---D
// |/|
// A---C
const normal = new THREE.Vector3(0,0,1);
const faces = [
new THREE.Face3(0, 3, 1, normal),
new THREE.Face3(0, 2, 3, normal)
];
geometry.vertices = vertices;
geometry.faces = faces;
Таким образом, это просто сама геометрии, но это важно знать, как он был построен для следующего шага - УФ-координаты:
const uvs = geometry.faceVertexUvs[0];
const vertexUvs = [
[0,0], [0,1], [1,0], [1,1]
].map(p => new THREE.Vector2(...p));
// we need to set the UV-coordinates for both faces separately, using
// the same scheme as before:
uvs[0] = [vertexUvs[0], vertexUvs[3], vertexUvs[1]];
uvs[1] = [vertexUvs[0], vertexUvs[2], vertexUvs[3]];
И все в порядке. Это примерно то, что делает THREE.PlaneGeometry
.Еще некоторые моменты о том, что:
- Three.js способен обрабатывать два различных набора уф-координат, поэтому есть
geometry.faceVertexUvs[0]
.
- индексы внутри этого массива соответствуют индексам в массиве faces, поэтому
uvs[0]
- это первая грань и uvs[1]
вторая.
- каждый из них снова представляет собой массив длиной 3, соответствующий вершинам этой грани.
Теперь в случае ваших сумок должно быть возможно выяснить, какие две стороны - лицевая сторона и обратная сторона. Вам нужно будет найти их и отредактировать их UV-координаты, чтобы они соответствовали позициям изображения, которое вы хотите увидеть (я не знаю, как именно выглядят эти модели, поэтому я не могу больше помочь вам здесь). Все другие УФ-координаты могут быть установлены на какое-то безопасное значение, например (0, 0)
, тогда все, что не является фронтальным или задним, будет иметь цвет нижнего левого пикселя вашей текстуры.
Если вы хотите текстурировать их также, вы должны действительно рассмотреть возможность создания текстурной карты в правильном программном обеспечении для редактирования 3D.
РЕДАКТИРОВАТЬ (2017-01-15)
Глядя на изображение с угловым логотипом, верхний левый треугольник переворачивается. Это связано с тем, что three.js использует другой граничный или вершинный порядок, чем в моем примере.
Это помогает понять это, если вы просто играете с ним в браузере-консоли или отладчике (это то, что я только что сделал). В соответствии с этим, самолет-геометрии из three.js имеет следующую структуру:
// A---B
// |/|
// C---D
vertices = [A, B, C, D]
faces = [Face3(A, C, B), Face3(C, B, D)]
Примечательным здесь, по какой-либо причине, первое лицо против часовой стрелки, и второе лицо по часовой стрелке порядка (я считаю, что это плохая практика, и треугольники всегда должны быть против часовой стрелки). Посмотрите на faceVertexUVs для геометрии, чтобы увидеть, как это должно выглядеть для этого случая (просто введите new THREE.PlaneGeometry(1,1).faceVertexUvs[0]
в консоль браузера)
Теперь для другой точки, масштабируя текстуры. Одна вещь, которую вы можете попробовать, - использовать значения UV, превышающие 1 для вершин. Это приведет к уменьшению текстуры. Тем не менее, это будет работать только если
- обертка режим текстура зажим к краю (
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
)
- всех текстур имеют 1px границы ширины в нейтральном цвете
В противном случае (и именно так я бы рекомендовал), вы должны использовать холст в качестве текстуры и подготовить изображение до его фактического использования. Я сделал простой пример здесь: http://codepen.io/usefulthink/pen/GrjmrM?editors=0010
Нужная информация о том, какой путь вы загрузили obj (сетка) и сколько у вас контроля над файлом из текстур ... Вы можете сделать сетку с текстурой для каждой стороны а затем как угодно, или вам нужно будет создать свои собственные координаты uv. Попробуйте это, я работал над http://stackoverflow.com/questions/29877032/three-js-webgl-custom-shader-sharing-texture- with-new-offset/30243114 # 30243114 – joshua