第一个公式:基本空间坐标变换
电脑屏幕是二维的,怎么体现出三维的感觉了。那就只能用改变物体在屏幕上的大小来给人,物体远近的感觉了。这个公式很简单,基于人的视觉感受,东西离自己越远就会越小,表示方法如下:
公式: X1=(d/Z)*X
d 是人眼到屏幕的距离,z 是到人眼的距离,X是某一点在平面的相对位置,X1是该点在屏幕投影的相对位置。图中黑色框框就是电脑屏幕。设一个平面距离屏幕为0时,在屏幕上展现的就是它最大的样子。
看看这个公式:d是固定的,X也有个最大值,那么只要平面离屏幕越远,x就会越小。符合人的视觉感受。
第二个公式:贴图坐标变换
因为一张图,投影到屏幕只会比原来小,所以根据屏幕上的位置去原图找相应的点
如图,假设原图的X,Y,0投影到屏幕的 U,V,0
那么U,V,0空间坐标系中任意一的点W对应到X,Y,0坐标系中了?
根据第一个公式可以找到W 在X,Y,0对应的向量P:
P=(Pz/d)W
我们要的是P的坐标(x,y),变形后有:
A=V X O
B=0 X U
C=U X V
x=A.W/C.W
y=B.W/C.W
注意:“X”是交集,而“.”是点乘
下面是代码实现
public class Method1 extends ScanRenderer { //屏幕上的一条扫描线
public void render(int offset, int left, int right) { //放入象素的起点,扫描的起点,终点
for (int x=left; x<=right; x++) { //每行从左往右扫
int tx = (int)(a.getDotProduct(viewPos) / //getDotProduct是点乘//viewPos是屏幕上的一点,我们对它经过变换去图中找相应的象素
c.getDotProduct(viewPos));
int ty = (int)(b.getDotProduct(viewPos) /
c.getDotProduct(viewPos));
doubleBufferData[offset++] = //从图像中找到相应位置的象素,放入数组
currentTexture.getColor(tx, ty);
viewPos.x++; //下一个屏幕上的点
}
}
}
下面这个是优化过的代码:
基于这样的公式变形:
u=A.V=Ax.Vx+Ay.Vy
V的同一行中的下一点V'横坐标是 Vx+1
此时u'=A.V'=Ax.Vx+Ay.Vy+Ax
=u+Ax
//////////////////////////////////////////////////////////////////
public class Method2 extends ScanRenderer {
public void render(int offset, int left, int right) {
float u = a.getDotProduct(viewPos);
float v = b.getDotProduct(viewPos);
float z = c.getDotProduct(viewPos);
float du = a.x;
float dv = b.x;
float dz = c.x;
for (int x=left; x<=right; x++) {
doubleBufferData[offset++] =
currentTexture.getColor(
(int)(u/z), (int)(v/z));
u+=du;
v+=dv;
z+=dz;
}
}
}