2013-11-06 4 views
1

Я видел много подобных вопросов на 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.). Вот скриншот, обратите внимание на днища многогранников.

screenshot

Так что мои вопросы: а) есть лучший/простой способ сделать это? б) как я могу исправить его для нижних лиц ?, в) есть ли способ, по крайней мере, упростить код, используя более существующие функции от THREE.js?

Спасибо!

+0

pssssh! Странно, что всегда установка оси на '(0,0,0)' только сломала ее на определенных лицах. Спасибо за помощь. Если вы дадите ответ, я могу принять его как таковой и дать вам очки или что-то еще. – Ian

ответ

1

Вы имеете в виду это?

axis = n.clone().cross(z); 

Кроме того, Увс, как правило, (0, 0) в нижнем левом углу.

В отношении вопросов (a) и (c): Учитывая то, что вы делаете, «Нет».

Относительно вопроса (б): Я ожидаю, что вы сможете отследить это самостоятельно. :-)

Смежные вопросы