我有一些树,这些树大大落后于游戏,所以我想检查一下树是否在镜头前。
我从Mathematics forum得到了一些帮助,并且还看了This link来帮助我将俯仰/偏航转换为所需的方向向量。
但是出于某种原因,每当我将相机向左移动时,树木都会变得可见,每当我向右移动它们时,它们都变得不可见(所以如果相机指向Z轴上的+1,似乎要渲染树,但在Z轴上为-1,它似乎不渲染它们。 (参见http://i.gyazo.com/cdd05dc3f5dbdc07577c6e41fab3a549获得较少跳跃的.mp4)
我使用以下代码检查对象是否在相机前面:
Ship you = shipsID.get(UID);
int dis = 300;
Vector3f X = new Vector3f(camera.x(), camera.y(), camera.z());
float x = (float) (Math.cos(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float y = (float) (Math.sin(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float z = (float) Math.sin(Math.toRadians(camera.pitch()));
Vector3f V = new Vector3f(x, y, z);
for (Tree tree : trees){
Vector3f Y = new Vector3f(tree.location.x, tree.location.y, tree.location.z);
Vector3f YMinusX = Y.negate(X);//new Vector3f(Y.x - X.x, Y.y - X.y, Y.z - X.z);
float dot = Vector3f.dot(YMinusX, V);
if (dot > 0){
tree.render();
}
}
有人能告诉我这里做错了什么吗?如果是数学,我就无法解决..或者代码......或者是什么?
相机翻译代码:
public void applyTranslations() {
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_MODELVIEW);
glRotatef(pitch, 1, 0, 0);
glRotatef(yaw, 0, 1, 0);
lastYaw = yaw;
glRotatef(roll, 0, 0, 1);
glTranslatef(-x, -y, -z);
glPopAttrib();
}
更新:
它似乎是相机正在寻找的地方。例如,如果我查看-Z,则没有任何反应,但如果我查看+ Z,它们都会渲染。
if (dot > 0) code
似乎在某种程度上是+ Z而不是+ TheCameraRotation。
答案 0 :(得分:5)
你的相机旋转偏转Y,暗示Y是你向上的向量。但是,float z = (float) Math.sin(Math.toRadians(camera.pitch()));
为您的向上向量提供了Z
。存在不一致。我首先在此处交换y
和z
,然后在每个帧中打印出所有内容,以便您可以看到旋转相机时会发生什么。同时渲染一棵树并打印dot
。例如。你可能会很快注意到,只有当你看到树的左侧90度时,数字才会接近1.0,从而缩小了问题的范围。正如@DWilches指出的那样,交换cos / sin会改变旋转的相位,这会产生这样的效果。
您可以考虑将点积限制在相机的视野范围内。树木不仅仅是点,还存在问题。正如@glampert建议的那样,更好的方法是在相机平截头体上测试树边界框。
尽管如此,树几何看起来并不复杂。优化明智,我开始尝试更快地绘制它们。你在使用VBO吗?也许看看减少绘制调用的方法,比如实例化。甚至可能会为LOD或广告牌使用一些模型。更进一步,广告牌上有多棵树。遮挡剔除方法可用于忽略山脉背后的树木。
[修改]
由于你的树木大致都在飞机上,你可以将问题限制在相机的偏航中:
float angleToTree = Math.atan2(tree.location.z - camera.z(), tree.location.x - camera.x());
float angleDiff = angleToTree - camera.yaw();
if (angleDiff > Math.PI)
angleDiff -= 2.0f * Math.PI;
if (angleDiff < -Math.PI)
angleDiff += 2.0f * Math.PI;
if (abs(angleDiff) < cameraFOV + 0.1f) //bias as trees are not points
tree.render();
答案 1 :(得分:4)
你能这样写吗
Ship you = shipsID.get(UID);
int dis = 300;
Vector3f X = new Vector3f(camera.x(), camera.y(), camera.z());
float x = (float) (Math.cos(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float y = (float) (Math.sin(Math.toRadians(camera.yaw()))*Math.cos(Math.toRadians(camera.pitch())));
float z = (float) Math.sin(Math.toRadians(camera.pitch()));
Vector3f V = new Vector3f(x, y, z);
for (Tree tree : trees){
Vector3f Y = new Vector3f(tree.location.x, tree.location.y, tree.location.z);
Vector3f YMinusX = Y.negate(X);//new Vector3f(Y.x - X.x, Y.y - X.y, Y.z - X.z);
float dot = Vector3f.dot(YMinusX, V);
if (dot > 0){
tree.render();
}
}
正如您所看到的,对每棵树执行的计算要少得多。
答案 2 :(得分:2)
对于我所看到的here,正确的公式是:
x = Math.sin(pitch) * Math.cos(yaw);
y = Math.sin(pitch) * Math.sin(yaw);
z = Math.cos(pitch);
你可以尝试一下吗?