欢迎光临散文网 会员登陆 & 注册

坐标转换的一个比较成熟的想法 ///

2022-12-16 11:13 作者:ICE27182  | 我要投稿

我大概说一下怎么坐标转换 因为是用在我的3D渲染器里的 所以会结合一点

把一个三维点的坐标转化为另一个空间直角坐标系里的坐标 

已知一个空间直角坐标系中一点A 我们想把它转化为一个经过任意旋转的空间直角坐标系中的坐标(p2 中由两两垂直的绿色和橙色向量为坐标轴的坐标系) 

这里中目标坐标系的z轴正方向是确定的 即视线方向 

这里坐标系y轴都表示高 x和z是平面     (你问我为什么? 8年mc你说为什么)

p1: 绿色是新坐标系的z轴正方向 也是摄像机的视线方向;    cyan是新坐标系中的轴正方向;    橙色是新坐标系中的x轴正方向

明确一下已知量然后开始: 

  1. A点在原坐标系中的坐标

  2. 新坐标系的z轴正方向在原坐标系中的向量坐标, 记该向量为n

  3. 新坐标系的另一根坐标轴与z轴的关系(当然 你知道它坐标也行 目的是确定新坐标系)


首先,我们先确定新坐标系。

    在这个例子中,平面法向量就是目标坐标系的z轴正方向(p2中的绿色向量),坐标轴两两垂直,且因为最终看到的2D画面的的高就是高(自己根据结论理解下 不知道怎么说),所以目标坐标系中新x轴的必然在原坐标系的xz平面上,新坐标系的x轴正方向在原坐标系中y=0。那么根据它与z轴正方向

    确立了新坐标系的两条坐标轴,第三条坐标轴的位置就确定了,方向的话怎么发现怎么来就好了。

    在3D渲染器里我是用2个角度表示视线向量的,α和β,分别表示视线向量n和原坐标系的xy面与xz面的夹角。 定义域的话 α∈[-180°, 180°], β∈[-90°, 90°]

p2: cyan色的是n    红色角度为α    蓝色角度为β  点的名字不用管 见p3

为了计算方便,我们让n为单位向量,即 |n| = 1

设 vec(n) = (x,y,z)        vec()表示是向量

p3

那么我们就可以得到 |ON| = 1

=> |MN| = y = sinβ · |ON| = sinβ

     |OM| = cosβ · |ON| = cosβ

=> |OC| = x = cosα · |OM| = cosα cosβ

     |MC| = z = sinα · |OM| = sinα cosβ

=> vec(n) = (cosα cosβ, sinβ, sinα cosβ), |n| = 1

del x,y,z


记p1橙色向量和cyan向量分别为nh(horizontal)和nv(vertical)

设 vec(nh) = (x,0,z) 

由nh⊥n 易得 x = cos(α-90°)cosβ, y = sin(α-90°)cosβ    => vec(nh) =  (cos(α-90°) cosβ, 0, sin(α-90°) cosβ) = (sinα cosβ, 0, -cosα cosβ)

del x,z

同理, vec(nv) = (cosα cos(β-90°), sin(β-90°), sinα cos(β-90°)) = (cosα sinβ, -cosβ, sinα sinβ)

但是这里有个小问题 |n|和|nv|都为1 但是|nh|因为y轴坐标被固定了 所以长度不总是1 那么我们需要变换一下 方法也很简单:

    vec(nh0) = (sinα cosβ, 0, -cosα cosβ)

    nh_len = sin²α·cos²β+cos²α·cos²β

    vec(nh) = vec(nh0)/nh_len

    表达式如下:

    vec(nh) = (sinα cosβ / (sin²α·cos²β+cos²α·cos²β), 0 ,-cosα cosβ / (sin²α·cos²β+cos²α·cos²β))

值得注意的是它的定义域是不包含β=±90°的 所以可以在程序里加一个分类讨论 如果为|β|=90°时直接把原坐标系里的y和z换一下就是新坐标系了 记得考虑一下正负



综上我们就得到了得到新坐标轴的单位向量在原坐标系中的坐标:

    vec(n) = (cosα cosβ, sinβ, sinα cosβ)

    vec(nh) = (sinα cosβ / (sin²α·cos²β+cos²α·cos²β), 0 ,-cosα cosβ / (sin²α·cos²β+cos²α·cos²β)), |β| ≠ ±90°

    vec(nv) = (cosα sinβ, -cosβ, sinα sinβ)


那么接下来的事情就很简单了 记得向量投影吗

A' = (vec(OA)·vec(nh), vec(OA)·vec(nv), vec(OA)·vec(n))


因为是单位向量,所以直接点乘就好了,不用再除模了,毕竟是1

坐标转换的一个比较成熟的想法 ///的评论 (共 条)

分享到微博请遵守国家法律