我目前正在编写JAVA中的菜单系统,需要将世界坐标转换为屏幕坐标。我已经阅读了很多关于如何做的帖子,并建立了以下内容:
float[] v = new float[]{0,0,0,1}; //four vector location of object in object space
//multiply by model matrix
v[0] = model[0]*v[0] + model[4]*v[1] + model[8]*v[2] + model[12]*v[3];
v[1] = model[1]*v[0] + model[5]*v[1] + model[9]*v[2] + model[13]*v[3];
v[2] = model[2]*v[0] + model[6]*v[1] + model[10]*v[2] + model[14]*v[3];
v[3] = model[3]*v[0] + model[7]*v[1] + model[11]*v[2] + model[15]*v[3];
//multiply by projection matrix
v[0] = projection[0]*v[0] + projection[4]*v[1] + projection[8]*v[2] + projection[12]*v[3];
v[1] = projection[1]*v[0] + projection[5]*v[1] + projection[9]*v[2] + projection[13]*v[3];
v[2] = projection[2]*v[0] + projection[6]*v[1] + projection[10]*v[2] + projection[14]*v[3];
v[3] = projection[3]*v[0] + projection[7]*v[1] + projection[11]*v[2] + projection[15]*v[3];
//account for distortions
v[0] = v[0]/v[3];
v[1] = v[1]/v[3];
v[2] = v[2]/v[3];
v[3] = v[3]/v[3];
//transform to screen coords.
onScreenX = (int)((viewport[2] * (v[0] + 1.0f)) / 2.0f) + viewport[0];
onScreenY = (int)((viewport[3] * (v[1] + 1.0f)) / 2.0f) + viewport[1];
System.out.println(onScreenX + ", " + onScreenY);
现在我遇到的一个大问题是,在我进行透视分割之后,我的值应该在-1和1之间。但是,即使对象明显在屏幕上,我也会得到一些超出此范围的值。我不确定我在这里可以找到什么。
我已经知道函数gluProject()
但是这个计算远离我的glu
对象所在的位置,因此该函数没有用。必须用矩阵数学来完成。
答案 0 :(得分:1)
这些计算用新的值覆盖v
向量中的值,然后在仍应使用旧值的地方使用它们。
只看前两个作业:
v[0] = model[0]*v[0] + model[4]*v[1] + model[8]*v[2] + model[12]*v[3];
v[1] = model[1]*v[0] + model[5]*v[1] + model[9]*v[2] + model[13]*v[3];
第一个语句为v[0]
分配一个新值,然后在第二个语句的右侧使用它。因此,对于v[1]
的计算,v[0]
的新值与v[1]
,v[2]
和v[3]
的旧值一起使用。
在整个计算过程中,同样的模式仍在继续。
避免这种情况的最简单方法是为计算的每个步骤使用新的向量。例如:
float[] vModel = new float[4];
vModel[0] = model[0]*v[0] + model[4]*v[1] + model[8]*v[2] + model[12]*v[3];
vModel[1] = model[1]*v[0] + model[5]*v[1] + model[9]*v[2] + model[13]*v[3];
...
float[] vProj = new float[4];
vProj[0] = projection[0]*vModel[0] + ...
...
这可以避免在旧值仍在使用时用新值覆盖值。