Я видел много подобных вопросов на StackOverflow и в других местах, но никто не обращался напрямую к моей проблеме. Я создаю n-сторонние многогранники с использованием выпуклого генератора корпуса в THREE.js. Я хочу нанести квадратную текстуру на каждую грань каждого многогранника так, чтобы она не искажалась и правильно рисовалась с перспективой (т. Е. Не противодействовала перспективе или что-то в этом роде).Улучшение генерации UV-координат для повернутых треугольников/граней в THREE.js
Моя первая попытка, и большинство из того, что я видел в другом месте, выглядел следующим образом:
function faceUv(v1, v2, v3) {
return [
new THREE.Vector2(0,0),
new THREE.Vector2(1,0),
new THREE.Vector2(1,1)
];
}
Это изменяет соотношение сторон текстуры на лицах, которые не XY выровненных правильные треугольники. То есть, все они;)
Итак, я подумал, что попробую повернуть лицо, которое должно быть выровнено с плоскостью XY, а затем вычислить UVs, как если бы на них наносили квадрат 1x1. Таким образом, треугольник, как это - после выравнивания XY - получите следующие уф COORDS:
0,0 1,0
* v1(uv=1.0,0.0)
v3(uv=0.1,0.5)
*
* v2(uv=0.5,0.8)
0,1 1,1
Это было бы достаточно хорошо для моих целей.
Вот мое текущее решение:
function faceUv(v1, v2, v3) {
var z = new THREE.Vector3(0, 0, 1),
n = new THREE.Triangle(v1, v2, v3).normal(),
// from http://stackoverflow.com/questions/13199126/find-opengl-rotation-matrix-for-a-plane-given-the-normal-vector-after-the-rotat
// RotationAxis = cross(N, N')
// RotationAngle = arccos(dot(N, N')/(|N| * |N'|))
axis = new n.clone().cross(z),
angle = Math.acos(n.clone().dot(z)/(n.length() * z.length()));
var mtx = new THREE.Matrix4().makeRotationAxis(axis, angle);
var inv = new THREE.Matrix4().getInverse(mtx);
var v1r = v1.clone().applyMatrix4(inv),
v2r = v2.clone().applyMatrix4(inv),
v3r = v3.clone().applyMatrix4(inv),
ul = v1r.clone().min(v2r).min(v3r),
lr = v1r.clone().max(v2r).max(v3r),
scale = new THREE.Vector2(1.0/(lr.x - ul.x), 1.0/(lr.y - ul.y));
v1r.sub(ul);
v2r.sub(ul);
v3r.sub(ul);
return [
new THREE.Vector2(v1r.x * scale.x, v1r.y * scale.y),
new THREE.Vector2(v2r.x * scale.x, v2r.y * scale.y),
new THREE.Vector2(v3r.x * scale.x, v3r.y * scale.y)
];
}
Это, кажется, работает очень хорошо, за исключением лиц, которые совмещены с YZ плоскости (т.е. с нормальным числом 0, -1,0.). Вот скриншот, обратите внимание на днища многогранников.
Так что мои вопросы: а) есть лучший/простой способ сделать это? б) как я могу исправить его для нижних лиц ?, в) есть ли способ, по крайней мере, упростить код, используя более существующие функции от THREE.js?
Спасибо!
pssssh! Странно, что всегда установка оси на '(0,0,0)' только сломала ее на определенных лицах. Спасибо за помощь. Если вы дадите ответ, я могу принять его как таковой и дать вам очки или что-то еще. – Ian