jjzjj

c++ - 在 Open GL 2.0 和 glm 中创建第一人称相机

coder 2024-02-12 原文

我对 Open GL 和 c++ 还很陌生,遇到过创建第一人称相机的问题。我不懂矩阵数学,所以这对我来说更加困难。到目前为止,为了计算相机的旋转,我已经这样做了:

void CameraFP::calculate_view()  {
    m_view = glm::rotate(m_view, this->get_rotation_x(), glm::vec3(1, 0, 0));
    m_view = glm::rotate(m_view, this->get_rotation_y(), glm::vec3(0, 1, 0));
}

每次更新调用都会调用该函数。

为了通过鼠标处理相机的旋转,我做了以下操作:

void CameraFP::process_mouse(sf::Window *app)  {
    GLfloat mouse_x = app->GetInput().GetMouseX();
    GLfloat mouse_y = app->GetInput().GetMouseY();

    GLfloat mouse_x_delta = std::max(mouse_x, old_mouse_x) - std::min(mouse_x, old_mouse_x);
    GLfloat mouse_y_delta = std::max(mouse_y, old_mouse_y) - std::min(mouse_y, old_mouse_y);

    y_rot += mouse_x_delta / (float)app->GetWidth();
    x_rot += mouse_y_delta / (float)app->GetHeight();

    this->old_mouse_x = mouse_x;
    this->old_mouse_y = mouse_y;

    app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
}

为了处理运动,我做了以下事情:

void CameraFP::process_keyboard(sf::Window *app)  {
    const sf::Input *input = &app->GetInput();

    if (input->IsKeyDown(sf::Key::W))  {
        position.z += 1.0f / 100.0f;
    }
    if (input->IsKeyDown(sf::Key::S))  {
        position.z -= 1.0f / 100.0f;
    }
    if (input->IsKeyDown(sf::Key::A))  {
        position.x -= 1.0f / 100.0f;
    }
    if (input->IsKeyDown(sf::Key::D))  {
        position.x += 1.0f / 100.0f;
    }
}

我的问题在于我的相机没有朝你面对的方向移动,而且它永远不会停止旋转:/。另外,如果你能给我指点一个指南或一些关于矩阵数学的东西,那就太棒了:)

编辑 2:'

我刚刚启动了一个新的过程鼠标功能,它沿着屏幕的 x 轴移 Action 为相机的 y 旋转正确。但是,无论我向左还是向右移动鼠标都没有关系,这两个 Action 都会使我向右旋转。与 3d 空间中的 x 轴相同,但这是向下发生的。关于造成这种情况的原因有什么想法吗?

void CameraFP::process_mouse(sf::Window *app)  {
    GLfloat mouse_x = app->GetInput().GetMouseX();
    GLfloat mouse_y = app->GetInput().GetMouseY();

    GLfloat mouse_x_delta = old_mouse_x - mouse_x;
    GLfloat mouse_y_delta = old_mouse_y - mouse_y;

    if (mouse_x_delta > 0)  {
        y_rot += mouse_x_delta / (float)app->GetWidth() * 0.1f;
    } else if (mouse_x_delta < 0)  {
        y_rot -= mouse_x_delta / (float)app->GetWidth() * 0.1f;
    }
    if (mouse_y_delta > 0)  {
        x_rot += mouse_y_delta / (float)app->GetWidth() * 0.1f;
    } else if (mouse_y_delta < 0)  {
        x_rot -= mouse_y_delta / (float)app->GetWidth() * 0.1f;
    }


    if (mouse_x != old_mouse_x)  {
        m_view = glm::rotate(m_view, y_rot, glm::vec3(0, 1, 0));
    }
    if (mouse_y != old_mouse_y)  {
        m_view = glm::rotate(m_view, x_rot, glm::vec3(1, 0, 0));
    }

    this->old_mouse_x = mouse_x;
    this->old_mouse_y = mouse_y;

    app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
}

最佳答案

目前我没有时间查找我的相机代码,但我现在可以告诉你的是,你的运动计算完全错误。
你没有将相机旋转考虑在内帐户。 你必须做这样的事情:

if (input->IsKeyDown(sf::Key::W))  {
    position.z += sin(camera_rot_y);
}
else if (input->IsKeyDown(sf::Key::S))  {
    position.z -=  sin(camera_rot_y);
}

if (input->IsKeyDown(sf::Key::A))  {
    position.x -=  cos(camera_rot_y);
}
else if (input->IsKeyDown(sf::Key::D))  {
    position.x +=  cos(camera_rot_y);
}

你也可以使用“else if”,因为你不能同时前进和后退。^^

此外,为什么要在以下代码中使用 std::min() 和 max()?

GLfloat mouse_x_delta = std::max(mouse_x, old_mouse_x) - std::min(mouse_x, old_mouse_x);
GLfloat mouse_y_delta = std::max(mouse_y, old_mouse_y) - std::min(mouse_y, old_mouse_y);

如果您想朝相反的方向旋转,您需要获得一个负增量,这对您的代码来说是不可能的。去掉 min() 和 max() 函数。

顺便说一句:我的相机代码不是最有效的(使用旋转而不是直接计算),但它可以工作。

关于c++ - 在 Open GL 2.0 和 glm 中创建第一人称相机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12126882/

有关c++ - 在 Open GL 2.0 和 glm 中创建第一人称相机的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  3. ruby - 如何在 Ruby 中创建无类 DSL? - 2

    我正在尝试找出如何为我的Ruby项目创建一种“无类DSL”,类似于在Cucumber步骤定义文件中定义步骤定义或在Sinatra应用程序中定义路由。例如,我想要一个文件,其中调用了我的所有DSL函数:#sample.rbwhen_string_matches/hello(.+)/do|name|call_another_method(name)end我认为用我的项目特有的一堆方法污染全局(内核)命名空间是一种不好的做法。因此方法when_string_matches和call_another_method将在我的库中定义,并且sample.rb文件将以某种方式在我的DSL方法的上下文中

  4. ruby-on-rails - 如何在 Rails 3 中创建自定义脚手架生成器? - 2

    有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我

  5. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

  8. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

    假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. ruby-on-rails - CarrierWave - PDF - 只选择第一页 - 2

    我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful

随机推荐