用户:
ParseYPasy查看:0 回复:4 评论:0 创建时间:2022-03-10T11:59:32
问题:
给定一个点(x,y,z),以及:
关于原点旋转的角度
x轴方向旋转:rx
y轴方向旋转:ry
z轴方向旋转:rz
x轴方向平移:Δx
y轴方向平移:Δy
z轴方向平移:Δz
求其在变换后在平面上的投影坐标。
过程
首先画出坐标系。

我们一般将x轴,y轴与屏幕上的x,y轴对应,而z轴与屏幕垂直,即“距离坐标”。
首先,我们可以很容易地将一个三维点投影为2维:
A(x,y,z) ——> A'(x,y)
但我们不仅需要将这个点投影到屏幕上,还需要施加缩放,即“近大远小”的空间透视。
假如我们令c=1为正常视距,那么对于c<1的情况,就需进行缩小,对于c>1的情况,需要放大。
即:
A'(xz,yz)
这样的图虽然是可以体现透视,但如果我们设定一个坐标点(1,1,1):
它的投影就是(1,1),在屏幕上会特别靠近原点。
因此,我们需要加上缩放因子。
设定因子为scale,那么:
A1(xz*scale,yz*scale)
缩放因子通常定为100,此时点的投影就能适中显示。
之后,我们开始讨论旋转,平移。
旋转与平移会有顺序上的问题,如下:

我们规定,先进行旋转,后进行平移。
那么,我们来看看旋转。
1.z轴方向上的旋转
对于我们而言,z轴旋转就是在屏幕上顺时针或逆时针旋转:z轴垂直屏幕,我们绕着它旋转就是平行于屏幕旋转。
那么,我们只需要求出A'(即A在屏幕上投影)的旋转后坐标即可。
我们首先需要求得A'关于屏幕原点的绝对角度,如下:

如下图,推导:


那么我们便能推导出z轴旋转后的角度:

再反过来,推出旋转后的坐标:
代码效果:
#include <iostream>
#include <cmath>
int main(){
double x,y;
double theta = asin(y/sqrt(x*x+y*y)) + rz;
theta-=(int(theta)/360)*360;
double x2 = cos(theta)*sqrt(x*x+y*y),
y2 = sin(theta)*sqrt(x*x+y*y);
}
对于三维坐标点,就是如下的变换:

其余的x,y轴都基本一致,我们放出所有变换综合的效果:

最终写法:

由此,我们完成了旋转部分,接下来的平移就是小儿科了。
令x,y,z轴的偏移量为Δx,Δy,Δz,则最终版本如下:
我们完成了对一个三维坐标点的转换,接下来,投影点坐标如下:

投影点计算完毕,最终,我们只需要输入数据,并利用画笔将各个投影点连接起来,就可以完成立体图形的渲染。
3D面渲染的论文将在下周左右发布。
P.S.该技术将被应用于个人的Render2,Render3作品,基于Kitten4,开源且有丰富的渲染组件
简要介绍下,Render2与Render3并不是普通的迭代版本关系,而是并行开发的两个渲染工具,Render2注重平面图形的高效且精致渲染,Render3则主要负责立体图形渲染。