【问题标题】:How can I set a flat plane to have the same rotation as the camera?如何将平面设置为与相机具有相同的旋转?
【发布时间】:2015-01-04 12:05:13
【问题描述】:

我想要一棵树的广告牌,始终面向相机。

目前,我只是使用glRotatef() 并将树的偏航旋转到相机的偏航:

glRotatef(camera.yaw(), 0f, 1f, 0f);

但是,不幸的是,这不起作用。

这棵树似乎在向右转,而它应该向左转。

我已经尝试过反转旋转,但这不起作用。

 glRotatef(-camera.yaw(), 0f, 1f, 0f);
OR
 glRotatef(camera.yaw(), 0f, -1f, 0f);

我总是可以求助于做一个交叉的广告牌(就像我在草地上做的那样),但是放大它看起来很糟糕。我宁愿仅将其用作最后的手段。

我也可以使用 3D 模型作为替代方案,但是我发现这要困难得多,而且它在显卡上的消耗也大得多。

我已经尝试过寻找here 的答案,但这不仅令人困惑,而且它也适用于 Flash,而且似乎甚至没有接近告诉如何为其他语言做到这一点。

如果需要(无论出于何种原因),我的整个渲染代码是:

public void render(){
    Main.TerrainDemo.shader.start();
    glPushMatrix();
    glDisable(GL_LIGHTING);
    glTranslatef(location.x * TerrainDemo.scale, location.y, location.z * TerrainDemo.scale); //Scale is the size of the map: More players online = bigger map.
    TexturedModel texturedModel = TerrainDemo.textModel;
    RawModel model = texturedModel.getRawModel();
    glDisable(GL_CULL_FACE);
    GL30.glBindVertexArray(model.getVaoID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, TerrainDemo.textModel.getTexture().getID());
    glScalef(size.x, size.y, size.z);
    glColor4f(0, 0, 0, 0.5f); //0,0,0, because of the shaders.
    glRotatef(Main.TerrainDemo.camera.yaw(), 0f, 1f, 0f);
    glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);
    glEnable(GL_LIGHTING);
    glPopMatrix();
    Main.TerrainDemo.shader.stop();
}

camera.yaw():

 /** @return the yaw of the camera in degrees */
public float yaw() {
    return yaw;
}

偏航角在 360 到 -360 之间。

 /** Processes mouse input and converts it in to camera movement. */
public void processMouse() {
    float mouseDX = Mouse.getDX() * 0.16f;
    float mouseDY = Mouse.getDY() * 0.16f;

    if (yaw + mouseDX >= 360) {
        yaw = yaw + mouseDX - 360;
    } else if (yaw + mouseDX < 0) {
        yaw = 360 - yaw + mouseDX;
    } else {
        yaw += mouseDX/50;
    }
    //Removed code relevant to pitch, since it is not relevant to this question.
}

更新: 我已经尝试了很多组合,但是 camera.yaw() 似乎与树木在做什么并没有关系? 不管我时间或划分或似乎用它做什么,它似乎总是错的!

【问题讨论】:

  • 原始问题是针对哪个 API 提出的,数学原理始终相同。我承认一开始围绕矩阵数学思考可能会令人困惑。我认为您的心理“障碍”源于您使用glRotate 及其兄弟姐妹的事实;这些函数不仅对任何严重的事情几乎毫无用处,而且它们也已被弃用,并已从现代 OpenGL 中完全删除。一旦您知道如何使用矩阵,OTOH 就很容易。对于广告牌,您想要做的是摆脱相对于相机的任何旋转。
  • 通过设置模型视图矩阵的一部分,最容易摆脱旋转,这将旋转到身份(乘以比例因子)。现在,在您的特定情况下,您实际上想要一个轴对齐的广告牌;这些设置起来有点棘手。
  • 还有一条建议:Billboard 已经过了一个世纪。除了蒸汽轨迹、光束和光晕或覆盖在场景上的 HUD 信息之类的东西之外,现代图形中没有它们的位置。使用真实几何。
  • @datenwolf 他们是这么过去的世纪吗?可以同时吸引超过 100,000 人参与的多个游戏仍然使用这种技术。你对我应该改用什么有更好的建议吗?
  • 某事告诉我,您只需稍微修改角度即可使其工作:您希望广告牌垂直于 XZ 平面中的相机前向矢量,这意味着它应该是相同的角度 + 90°。你试过用这种方式抵消那个旋转角度吗?

标签: java opengl lwjgl


【解决方案1】:

您想要的是一个轴对齐的广告牌。首先取局部坐标中的中心轴,我们称之为a。其次,您需要从视点到沿该轴的 某个 点的轴(树的底部就可以了),我们称之为 v。给定这两个向量,您想形成一个“三脚架”,其中一条腿与中心轴和视点方向共面。

这可以通过使用Gram-Schmidt process 将向量 va 正交化来完成,从而产生 v'。三脚架的第三条腿是 av' 之间的 cross product,产生 r = a × v'。轴对齐广告牌的边缘平行于ar;但这只是另一种说法,广告牌旋转到 (a,r) 平面,这正是旋转矩阵所描述的。假设未转换的广告牌几何图形在 XY 平面上,a 平行于 Y,那么旋转矩阵将是

[r, a, (0,0,1)]

或者用稍微复杂一点的方式来写它

| r.x , a.x , 0 |
| r.y , a.y , 0 |
| r.z , a.z , 1 |

为了形成一个完整的 4×4 齐次变换矩阵,将其扩展为

| r.x , a.x , 0 , t.x |
| r.y , a.y , 0 , t.y |
| r.z , a.z , 1 , t.z |
|  0  ,  0  , 0 ,  1  |

其中 t 是翻译。


请注意,如果关于矩阵和向量运算的任何内容对您来说还没有意义,您必须立即停止使用 OpenGL 所做的任何事情,并首先学习这些基本的基本技能。您将需要它们。

【讨论】:

  • 我不学习矩阵,因为我永远找不到学习它们的好地方。我发现的只是无聊的讲座,或者认为我知道一切的书籍,除了这本书试图教给我的确切内容。我不学习矩阵,因为我拒绝在学习时感到无聊。您对此有什么建议吗?
  • 即使是向量也会让我感到困惑。例如,人们是否经常突然将某个位置称为“向量”?我不想回答那个具体的问题,但是虽然我知道很多向量数学,但其中很多仍然会让我感到困惑,因为突然之间人们一直在提到“向量”,我不使用它们或我不使用它们的地方甚至不知道它们在特定情况下是如何使用的。
  • @Joehot200:网上当然有关于向量数学的很好的教程,但是如果它们仍然让你感到困惑(这并不罕见),也许你需要更深入地描述它的东西,采用更渐进的方法,以便您更好地了解它的工作原理。我个人觉得 MIT 线性代数课程的视频非常棒。试一试,然后找一本关于该主题的好教科书进行练习。
  • 你不能只给出一些代码,对吗?多年来,我一直在努力解决这个该死的答案,但这太令人困惑了(例如,为什么我使用我已经得到的值来计算相同的值?什么是“本地坐标”?等等?)
  • @Joehot200:我不能给你代码,因为这需要知道你的程序的整体结构(或者更确切地说数据是如何组织的)。 OpenGL 中也没有“相机”之类的东西。您可以做的是通过在整个场景上应用逆变换来“模拟”相机的效果。但这并不能帮助您解决广告牌问题,因为这需要您跟踪整个转换链(您的代码可能会或可能不会这样做)。另外,如果我给你代码怎么办?你会把它加入你的程序中,它可能有效,也可能无效,而且你不会更聪明。
猜你喜欢
  • 2021-08-29
  • 2013-04-17
  • 1970-01-01
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多