我正在尝试让相机绕 JOGL 太阳系模型中的一颗行星运行,但该行星不想停留在视野中心。相机基本上应该围绕地球绕一个完美的圆,实际上是在一个固定的半径上绕地球运行。行星应该始终出现在屏幕中央,但它并没有停留在那里。我试图弄清楚行星的计算位置和行星的实际位置之间是否存在距离,或者我是否需要使用一些三角操作,但我得到的只是一个更混乱的相机和行星。
==========编辑==================
我还尝试使用 gluLookAt 来设置相机:
但相机似乎只是停留在原点,没有旋转或平移。
这是我的显示功能
public void display(GLAutoDrawable drawable) {
//initialise the display matrix
gl = initMatrix(drawable, GL2.GL_MODELVIEW);
//get earth position
float earthX = artbook.get(3).getX(),
earthZ = artbook.get(3).getZ(),
earthRotation = artbook.get(3).getRotation();
//Draw each planet
Planet art;
for(int i = 0; i < artbook.size(); i++) {
returnToOrigin();
//apply camera transformations first
gl.glRotatef(-(earthRotation), 0, 1, 0);
gl.glTranslatef(-earthX, 0, -earthZ-0.1f);
//then draw the planets
art = artbook.get(i);
drawPlanet(art);
}
frameCount += 1;
}
此轨道函数可找到行星与太阳当前的轨道角
/**
* Finds the orbital angle of the planet on it's orbit and translate the planet there
* @param art
* @return the actual offset of the planet
*/
private void orbitPlanet(Planet art) {
float sunRadius = 109.3f,
radius = art.getRadius(),
offset = art.getOffset(),
orbit;
//if the planet isn't the sun, skew the offset
float skew = sunRadius + radius;
if(radius != sunRadius) offset += skew;
//Get the new orbital position of the planet
orbit = art.orbit(frameCount) % 360;
//set the position of the planet
float x = (float) (offset * Math.cos(Math.toRadians(orbit)));
float z = (float) (offset * Math.sin(Math.toRadians(orbit)));
gl.glTranslatef(x, 0, z);
art.setX(x);
art.setZ(z);
}
这是 Planet 类函数,用于确定给定帧期间的轨道角。
/**
* Finds the new orbital angle at the current frame
* @param frameCount The current Frame
* @return The new angle the planet makes with the sun
*/
public float orbit(float frameCount) {
//find the new orbit angle theta and the delta between the current and new orbit
float theta = frameCount * 1/(this.orbitRate);
this.orbit = theta;
return this.orbit;
}
绕其轴 {0,1,0} 旋转的行星旋转,而该行星本身又绕太阳旋转(原点 {0,0,0})。
一般算法是
P' = ProjectionMatrix * ViewMatrix * ModelMatrix * P
然后(在详细介绍之前)步骤如下:
投影矩阵:
GL_PROJECTION
查看矩阵:
GL_MODELVIEW
模型矩阵:
P:
查看矩阵
由于相机绕行星运行,我们需要计算行星的位置。 为此,我们假设轨道平面是 xz 平面,y 是向上向量。
哪里
angle:以弧度表示的轨道角
半径:从原点到行星中心的距离
planet_x = cos(angle) * radius;
planet_y = 0;
planet_z = sin(angle) * radius;
现在我们有了行星位置,它是 lookAt 函数的目标参数,剩下的就是计算眼睛位置。 这里我们再次假设,轨道平面与上面相同(xz 平面)。
从您的描述中,我们知道相机以与绕其自身轴旋转相同的速度绕行星运行, 因此,我们只需重用上述操作中计算出的 sin/cos 值 (cx, sz),并将其乘以到地球中心的距离。
eye_x = cx * distance;
eye_y = 0;
eye_z = sz * distance;
但是,那是在原点附近,我们仍然需要将其转换为实际的行星位置
eye_x += planet_x;
eye_z += planet_z;
模型矩阵
由于我们手动计算了行星位置(请参阅 ViewMatrix 部分),因此我们可以省略旋转部分并将其简单地转换为计算的位置。
我们算法的实际组成如下:
/* ProjectionMatrix */
glMatrixMode(GL_PROJECTION);
gluPerspective(fovy, aspect, zNear, zFar);
/* ViewMatrix */
glMatrixMode(GL_MODELVIEW);
gluLookAt(
eye_x, eye_y, eye_z, //eye
planet_x, planet_y, planet_z, //target
0, 1, 0 //up vector: y-axis
);
/* ModelMatrix */
glTranslatef(planet_x, planet_y, planet_z);
glRotatef(
angle, //rotation angle in radians of the planet around its own axis
0, 1, 0 //rotation vector, since the rotation takes place in the xz-plane -> y-axis
);
/* planet */
gluSphere(...);