我希望确定3D空间(x,y,z)中点的2D屏幕坐标(x,y)。
我希望投射的点是由GPS坐标和海拔高度表示的真实世界点。
例如: Point(Lat:49.291882,Long:-123.131676,Height:14m)
摄像机位置和高度也可以确定为x,y,z点。我还有相机的标题(罗盘度),倾斜度(地平线上方/下方)和滚动(绕z轴)。
我没有3D编程的经验,因此,我已经阅读了透视投影的主题,并了解到它需要了解矩阵,变换等等 - 所有这些都使我目前感到困惑。
我被告知OpenGL可能用于构建真实世界点的3D模型,设置相机方向并检索3D点的2D坐标。
但是,我不确定使用OpenGL是否是解决此问题的最佳解决方案,即使它是我不知道如何创建模型,设置相机等
有人可以提出解决问题的最佳方法吗?如果OpenGL是一个可行的解决方案,我必须使用OpenGL ES,如果这有任何区别。哦,无论我选择哪种解决方案,都必须快速执行。
感谢您的帮助
答案 0 :(得分:13)
这是一个非常一般的答案。假设相机处于(Xc,Yc,Zc)并且您要投影的点是P =(X,Y,Z)。从摄像机到投影到的2D平面的距离为F(因此平面的方程为Z-Zc = F)。投影到平面上的P的2D坐标是(X',Y')。
然后,非常简单:
X'=((X-Xc)*(F / Z))+ Xc
Y'=((Y-Yc)*(F / Z))+ Yc
如果你的相机是原点,那么这简化为:
X'= X *(F / Z)
Y'= Y *(F / Z)
答案 1 :(得分:4)
确实需要perspective projection和matrix operations大大简化这样做。我假设您已经知道,为了进行这些计算,您的spherical coordinates必须转换为Cartesian coordinates。
使用OpenGL可能会比滚动自己的software rasterizer节省大量工作。所以,我先建议trying it。您可以在PC上对系统进行原型设计,因为只要您保持简单,OpenGL ES就不会有太大差异。
答案 2 :(得分:2)
如果只需要计算某些点的坐标,你应该只需要一些代数技能,而不需要用openGL进行3D编程。
此外 openGL不处理地理坐标
首先获得一些关于WGS84和测地坐标的文档,首先要将GPS数据转换为笛卡尔坐标系(例如,以地球为中心的笛卡尔坐标系定义为WGS84椭圆体)。
然后可以进行矩阵计算。 变换链大致是:
首次转化时,请参阅this 最后一个涉及投影矩阵 其他只是坐标旋转和平移。 “一些本地框架”是本地笛卡尔框架,其原点是您的相机位置 与椭圆体相切。
答案 3 :(得分:2)
我推荐Eric Lengyel的“3D游戏编程和计算机图形学数学”。它涵盖了矩阵,变换,视锥体,透视投影等。
“OpenGL编程指南”(红皮书)中有关于查看转换和设置相机的一章(包括如何使用gluLookAt)。
如果您对显示3D场景不感兴趣并且仅限于使用OpenGL ES,那么最好编写自己的代码来执行从3D到2D窗口坐标的映射。作为起点,您可以下载Mesa 3D,OpenGL的开源实现,以了解它们如何实现gluPerspective(设置投影矩阵),gluLookAt(设置相机转换)和gluProject(投影3D点)到2D窗口坐标)。
答案 4 :(得分:0)
return [((fol/v[2])*v[0]+x),((fol/v[2])*v[1]+y)];
指向[0,0,1]的点将为x = 0和y = 0,除非您添加中心屏幕xy-而不是相机xy。 fol是从fov角度和屏幕宽度得出的焦距-三角形(切线)的高度。此方法将不匹配three.js透视矩阵,这就是为什么我要寻找它。
我不应该寻找它。我在openGL上匹配了xy,就像超级胶水一样!但是我无法使其在Java中正常工作。完美的搭配紧随其后。
var pmat = [0,0,0,0,0,0,0,0,0,0,
(farclip + nearclip) / (nearclip - farclip),-1,0,0,
2*farclip*nearclip / (nearclip - farclip),0 ];
void setpmat() {
double fl; // = tan(dtor(90-fovx/aspect/2)); /// UNIT focal length
fl = 1/tan(dtor(fov/Aspect/2)); /// same number
pmat[0] = fl/Aspect;
pmat[5] = fl;
}
void fovmat(double v[],double p[]) {
int cx = (int)(_Width/2),cy = (int)(_Height/2);
double pnt2[4], pnt[4] = { 0,0,0,1 } ;
COPYVECTOR(pnt,p);NORMALIZE(pnt);
popmatrix4(pnt2,pmat,pnt);
COPYVECTOR(v,pnt2);
v[0] *= -cx; v[1] *= -cy;
v[0] += cx; v[1] += cy;
} // world to screen matrix
void w2sm(int xy[],double p[]) {
double v[3]; fovmat(v,p);
xy[0] = (int)v[0];
xy[1] = (int)v[1];
}
我还有另一种匹配Three.js xy的方法,直到我得到矩阵起作用,只是一种情况。必须以2的纵横比运行
function w2s(fol,v,x,y) {
var a = width / height;
var b = height/width ;
/// b = .5 // a = 2
var f = 1/Math.tan(dtor(_fov/a)) * x * b;
return [intr((f/v[2])*v[0]+x),intr((f/v[2])*v[1]+y)];
}
将其与倒置的相机矩阵一起使用,则需要invert_matrix()。
v = orbital(i);
v = subv(v,campos);
v3 = popmatrix(wmatrix,v); //inverted mat
if (v3[2] > 0) {
xy = w2s(flen,v3,cx,cy);
最后,这是(每个人现在都应该知道的)无矩阵匹配,任何方面。
function angle2fol(deg,centerx) {
var b = width / height;
var a = dtor(90 - (clamp(deg,0.0001,174.0) / 2));
return asa_sin(PI_5,centerx,a) / b;
}
function asa_sin(a,s,b) {
return Math.sin(b) * (s / Math.sin(PI-(a+b)));
} // ASA solve opposing side of angle2 (b)
function w2s(fol,v,x,y) {
return [intr((fol/v[2])*v[0]+x),intr((fol/v[2])*v[1]+y)];
}
更新了用于打样的图像。输入_fov可让您“大约”获得1.5。要正确查看FOV读数,请使用新的焦距重做三角形。
function afov(deg,centerx) {
var f = angle2fol(deg,centerx);
return rtod(2 * sss_cos(f,centerx,sas_cos(f,PI_5,centerx)));
}
function sas_cos(s,a,ss) {
return Math.sqrt((Math.pow(s,2)+Math.pow(ss,2))-(2*s*ss*Math.cos(a)));
} // Side Angle Side - solve length of missing side
function sss_cos(a,b,c) {
with (Math) {
return acos((pow(a,2)+pow(c,2)-pow(b,2))/(2*a*c));
}
} // SSS solve angle opposite side2 (b)
星空库确认了视角,然后可以测量VIEW! http://innerbeing.epizy.com/cwebgl/perspective.jpg
我可以用一个词进动来解释对月球北极的90度校正。那么当前的上升向量是多少。 PNT?拉德克?
function ininorths() {
if (0) {
var c = ctime;
var v = LunarPos(jdm(c));
c += secday();
var vv = LunarPos(jdm(c));
vv = crossprod(v,vv);
v = eyeradec(vv);
echo(v,vv);
v = [266.86-90,65.64]; //old
}
var v = [282.6425,65.8873]; /// new.
// ...
}
我还没有解释两套矢量:Three.milkyway.matrix和3D到2D绘图。他们是:
function drawmilkyway() {
var v2 = radec2pos(dtor(192.8595), dtor(27.1283),75000000);
// gcenter 266.4168 -29.0078
var v3 = radec2pos(dtor(266.4168), dtor(-29.0078),75000000);
// ...
}
function initmwmat() {
var r,u,e;
e = radec2pos(dtor(156.35), dtor(12.7),1);
u = radec2pos(dtor(60.1533), dtor(25.5935),1);
r = normaliz(crossprod(u,e));
u = normaliz(crossprod(e,r));
e = normaliz(crossprod(r,u));
var m = MilkyWayMatrix;
m[0]=r[0];m[1]=r[1];m[2]=r[2];m[3]=0.0;
m[4]=u[0];m[5]=u[1];m[6]=u[2];m[7]=0.0;
m[8]=e[0];m[9]=e[1];m[10]=e[2];m[11]=0.0;
m[12]=0.0;m[13]=0.0;m[14]=0.0;m[15]=1.0;
}
/// draw vectors and matrix were the same in C !
void initmwmat(double m[16]) {
double r[3], u[3], e[3];
radec2pos(e,dtor(192.8595), dtor(27.1283),1); //up
radec2pos(u,dtor(266.4051), dtor(-28.9362),-1); //eye
}