Как сделать изображение 360 x 235 градусов FOV с помощью ThreeJS? - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть камера, которая снимает круглые изображения, которые, как утверждают, представляют поле обзора 235 градусов, например: enter image description here

У меня есть некоторый опыт работы с Threejs и я использовалэто позволяет правильно отображать изображения 360x360, сохраненные в виде равноугольных проекций - для этого достаточно примеров в Интернете.

Но я хочу использовать Threejs для рендеринга моего круглого изображения, возможно, в качестве текстуры внутри сферы.Я рассмотрел некоторые примеры (например, https://threejs.org/examples/#webgl_panorama_dualfisheye и Отображение изображения на сферу в Three.js ), которые, кажется, указывают мне правильное направление, но я думаю, что просто неЯ не знаю достаточно о том, как работает ThreeJs, чтобы соединить части.

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

Поэтому я попытался использовать длинную версию конструктора SphereGeometry для создания частичной сферы (360 * 235), но изменение фи дало мне то, чтовыглядит как апельсин с отсутствующими ломтиками. Изменение тэты дало мне правильную форму, но текстура не наложилась на него правильно.

Так что мой общий вопрос - как сделать эту работу, но я думаю, что главное ошеломляетя:

  1. что контролирует, как текстура наносится на сетку? (чтобы я мог рисовать текстуру только один разу, и только на ту часть сферы, которая мне нужна)

  2. Я вижу, что настройка UV необходима (geometry.faceVertexUvs?), и я читаю https://en.wikipedia.org/wiki/UV_mapping, поэтому явроде как понимаю, что это значит, но я не знаю, с чего начать с определения правильных UV для моего изображения (и все же, как и номер 1, как не показывать его на «тыльной стороне» сферы)

1 Ответ

0 голосов
/ 13 апреля 2019

Ладно, я пошёл и ещё немного почитал про УФ и много экспериментировал.Вот рабочий код (только соответствующий бит), который я в основном понимаю:

var geometry = new THREE.SphereGeometry( 30, 256, 128, 0, Math.PI * 2, 0, Math.PI );
geometry.scale( - 1, 1, 1 );//inside out

var imgWidth = 0.8;//I thought this should be 235/360, but used trial and error for less fisheye distortion

var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
for ( i = 0; i < faceVertexUvs.length; i ++ ) {

    var uvs = faceVertexUvs[ i ];
    var face = geometry.faces[ i ];
    //y is top to bottom
    //z is in-out?
    //x is side-side? positive x is front, negative is back

    for ( var j = 0; j < 3; j ++ ) {
        var fvNj = face.vertexNormals[j];
        var yaw = Math.atan2(fvNj.z, fvNj.x)/(Math.PI); //around, -1 to 1
        var pitch = Math.asin(fvNj.y)/Math.PI; //height, -0.5 to 0.5
        pitch = pitch * -1 + 0.5;//flip and make zero to one
        pitch *= imgWidth;

        if(pitch < 0.5){
            //how to do fisheye correction??
            //var correction = (fvNj.x == 0 && fvNj.z == 0) ? 1 : (Math.acos(fvNj.y) / Math.sqrt(fvNj.x * fvNj.x + fvNj.z * fvNj.z)) * (2 / Math.PI);
            var x = Math.cos(yaw * Math.PI);// -1 to 1
            var y = Math.sin(yaw * Math.PI);// -1 to 1
            var u = 0.5 + x*pitch;
            var v = 0.5 + y*pitch;  

            uvs[ j ].x = u;
            uvs[ j ].y = v;
        }else{
            uvs[j].x = 0;
            uvs[j].y = 0;
        }
    }
}

mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
...