尝试实现相机

Posted

技术标签:

【中文标题】尝试实现相机【英文标题】:Trying to implement Camera 【发布时间】:2014-12-27 23:54:13 【问题描述】:

我正在尝试实现一个Camera 类,这样我就可以按如下方式走路和观察世界:

#ifndef _CAMERA_H_
#define _CAMERA_H_

#include <glm\glm.hpp>

class Camera

public:
    Camera();
    ~Camera();

    void Update(const glm::vec2& newXY);
    //if by = 0.0 it means, it will use the const Class speed to scale it
    void MoveForward(const float by = 0.0f);
    void MoveBackword(const float by = 0.0f);
    void MoveLef(const float by = 0.0f);
    void MoveRight(const float by = 0.0f);
    void MoveUp(const float by = 0.0f);
    void MoveDown(const float by = 0.0f);
    void Speed(const float speed = 0.0f);

    glm::vec3& GetCurrentPosition();
    glm::vec3& GetCurrentDirection();
    glm::mat4 GetWorldToView() const;
private:
    glm::vec3 position, viewDirection, strafeDir;
    glm::vec2 oldYX;

    float speed;
    const glm::vec3 up;
;

#endif

#include "Camera.h"
#include <glm\gtx\transform.hpp>

Camera::Camera()
    :up(0.0f, 1.0f, 0.0), viewDirection(0.0f, 0.0f, -1.0f),
    speed(0.1f)




Camera::~Camera()




void Camera::Update(const glm::vec2& newXY)

    glm::vec2 delta = newXY - oldYX;
    auto length = glm::length(delta);
    if (glm::length(delta) < 50.f)
    
        strafeDir = glm::cross(viewDirection, up);
        glm::mat4 rotation = glm::rotate(-delta.x * speed, up) *
            glm::rotate(-delta.y * speed, strafeDir);

        viewDirection = glm::mat3(rotation) * viewDirection;
    

    oldYX = newXY;


void Camera::Speed(const float speed)

    this->speed = speed;


void Camera::MoveForward(const float by)

    float s = by == 0.0f ? speed : by;

    position += s * viewDirection;

void Camera::MoveBackword(const float by)

    float s = by == 0.0f ? speed : by;

    position += -s * viewDirection;

void Camera::MoveLef(const float by )

    float s = by == 0.0f ? speed : by;
    position += -s * strafeDir;

void Camera::MoveRight(const float by )

    float s = by == 0.0f ? speed : by;
    position += -s * strafeDir;

void Camera::MoveUp(const float by )

    float s = by == 0.0f ? speed : by;
    position += s * up;

void Camera::MoveDown(const float by )

    float s = by == 0.0f ? speed : by;
    position += -s * up;


glm::vec3& Camera::GetCurrentPosition()

    return position;

glm::vec3& Camera::GetCurrentDirection()

    return viewDirection;


glm::mat4 Camera::GetWorldToView() const

    return glm::lookAt(position, position + viewDirection, up);

我更新和渲染如下:

void Game::OnUpdate()

    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glUniformMatrix4fv(program->GetUniformLocation("modelToViewWorld"), 1, GL_FALSE, &cam.GetWorldToView()[0][0]);



void Game::OnRender()


    model->Draw();


顶点着色器的样子:

#version 410

layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec2 inTexture;
layout (location = 2) in vec3 inNormal;

uniform mat4 modelToViewWorld;


void main()

        gl_Position    = vec4(mat3(modelToViewWorld) * inVertex, 1);


但我正在移动/旋转模型本身,而不是它周围的相机。我在这里做错了什么?

【问题讨论】:

哇,opengl 游戏。第一次看到这个。 【参考方案1】:

我认为问题在于您没有反转视图矩阵。模型-视图矩阵只是模型->世界坐标矩阵变换和世界->视图坐标矩阵变换的乘积。第一个获取局部模型空间中的坐标并将它们转换为世界空间,因此不需要反转。但是,第二个获取世界空间中相机的坐标并将它们转换为相机的局部坐标系,由于它与第一个相反,因此需要反转。

【讨论】:

【参考方案2】:

您不是在旋转模型,而是在旋转视图方向。

viewDirection = glm::mat3(rotation) * viewDirection;

您要做的是围绕对象旋转相机的中心,然后将相机的方向设置为朝向对象。

例如:

position = vec3( radius * cos(t), radius * sin(t), 0);
direction = normalize(-position);

【讨论】:

以上是关于尝试实现相机的主要内容,如果未能解决你的问题,请参考以下文章

如何使用额外的选项(如全景)实现相机功能?

如何检索 QML 相机提要并发送到 C++ 后端

Cordova 应用程序在尝试访问相机时崩溃

如何测量相机与物体之间的距离

在 Forge 查看器中控制相机

用于相机预览的Android单元测试?