我有一个摄像头拍摄声称代表235度视野的圆形图像,如下所示:
我有三个经验,并用它来正确渲染360x360图像存储为equirectangular投影 - 网上有大量的样本来做到这一点。
但我想使用threejs渲染我的圆形图像,可能是一个球体内的纹理。我看了一些例子(例如https://threejs.org/examples/#webgl_panorama_dualfisheye和Mapping image onto a sphere in Three.js),这些例子似乎指向了我正确的方向,但我想我还不太了解trijs如何将各个部分放在一起。
第二个(眼球)似乎让我接近,但遵循眼球代码确切意味着我的图像显示两次(我想这是有道理的,因为我的图像是方形的,纹理必须覆盖整个球体。
所以我尝试使用长版SphereGeometry的构造函数来制作一个部分球体(360 * 235)但是改变phi给了我一个看起来像橙色缺失切片的东西。改变theta给了我正确的形状,但纹理没有正确地放置它。
所以我的整体问题是如何使这项工作,但我认为主要的事情是:
好的,所以我去了解更多有关紫外线的信息并进行了大量的实验。这是工作代码(只是相关位),我大多理解:
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 );