Я успешно применил текстуру изображения к кубу с помощью UV-преобразования (для создания программы просмотра фото-сфер). Хотя текстура идеально совмещена с гранями куба, линии, на которых соединяются грани, видны как тонкие прямые.
Та же проблема не возникает, если плитки текстуры разделяются с помощью Canvas и применяются к кубу с помощью MultiMaterial.
На следующем изображении сравниваются результаты двух методов наложения текстуры (щелкните, чтобы увеличить изображение):
Живой пример можно найти на CodePen.io
Изображение, используемое для текстуры, можно найти здесь
Вот код, который выполняет отображение UV (это довольно просто):
function mapCubeUV(geometry, cubeH) {
// converting all vertices into polar coordinates
geometry.faceVertexUvs[0] = []; // This clears out any UV mapping that may have already existed on the object
// walking through all the faces defined by the object
// ... we need to define a UV map for each of them
geometry.faces.forEach(function(face) {
var uvs = [];
var ids = [ 'a', 'b', 'c'],
faceSign = face.normal.x+'.'+face.normal.y+'.'+face.normal.z;
for( var i = 0; i < ids.length; i++ ) {
// using the point to access the vertice
var vertexIndex = face[ ids[ i ] ],
vertex = geometry.vertices[ vertexIndex ],
tileIx,
uvY, uvX;
// face order in the image: West, East, Up, Down, South, North
switch(faceSign) {
case '1.0.0': // West
uvY = vertex.y;
uvX = -vertex.z;
tileIx = 0;
break;
case '-1.0.0': // East
uvY = vertex.y;
uvX = vertex.z;
tileIx = 1;
break;
case '0.1.0': // Up
uvY = -vertex.z;
uvX = vertex.x;
tileIx = 2;
break;
case '0.-1.0': // Down
uvY = vertex.z;
uvX = vertex.x;
tileIx = 3;
break;
case '0.0.1': // South
uvY = vertex.y;
uvX = vertex.x;
tileIx = 4;
break;
case '0.0.-1': // North
uvY = vertex.y;
uvX = -vertex.x;
tileIx = 5;
break;
}
// coordinate values range from [-cubeH/2, +cubeH/2]
// here we're fixing moving the range to [0, +cubeH]
uvY = uvY+cubeH/2;
uvX = uvX+cubeH/2;
// each UV coordinate represents decimal range [0, +1]
uvY = uvY/cubeH;
uvX = uvX/cubeH;
// since the image contains multiple texture tiles (8 of them = 6 with
// images + 2 dummy, which were added so that the width is a multiple of 2),
// [uvX] must be adjusted to point to the part of the image
// containing current tile
uvX = (uvX+tileIx)/8;
uvs.push( new THREE.Vector2( uvX, uvY ) );
}
geometry.faceVertexUvs[ 0 ].push( uvs );
});
geometry.uvsNeedUpdate = true;
return(geometry);
}
Я дважды проверил значения, полученные с помощью вышеуказанной функции, и все выглядит хорошо - значения UV при умножении на ширину и высоту изображения дают правильные значения в пикселях. Вот дамп:
Face VerticeA VerticeB VerticeC
0: ( 0,1), ( 0,0), (0.125,1)
1: ( 0,0), (0.125,0), (0.125,1)
2: (0.125,1), (0.125,0), ( 0.25,1)
3: (0.125,0), ( 0.25,0), ( 0.25,1)
4: ( 0.25,1), ( 0.25,0), (0.375,1)
5: ( 0.25,0), (0.375,0), (0.375,1)
6: (0.375,1), (0.375,0), ( 0.5,1)
7: (0.375,0), ( 0.5,0), ( 0.5,1)
8: ( 0.5,1), ( 0.5,0), (0.625,1)
9: ( 0.5,0), (0.625,0), (0.625,1)
10: (0.625,1), (0.625,0), ( 0.75,1)
11: (0.625,0), ( 0.75,0), ( 0.75,1)
Я что-то делаю не так или есть какие-то проблемы с Three.js?
P.S. тест был основан на примере, найденном на веб-сайте Three.js
P.P.S
очень похожий вопрос можно найти ЗДЕСЬ (хотя это не касается ручного расчета UV-карты)