Mam taki kod:
struct Camera
{
void setPerspective(float fov, float aspect, float nearClip, float farClip)
{
projection = glm::perspective(glm::radians(fov), aspect, farClip, nearClip);
inverseProjection = glm::inverse(projection);
}
void setWorldOffset(const glm::vec3& offset)
{
updatedMatrices = false;
position() = glm::vec4(offset, 1.0f);
}
void AddWorldOffset(const glm::vec3& offset)
{
updatedMatrices = false;
position() += glm::vec4(offset, 1.0f);
}
void AddRelativeOffset(const glm::vec3& offset)
{
UpdateBasis();
updatedMatrices = false;
position() += glm::vec4(
offset.x * getRight() +
offset.y * getUp() +
offset.z * getForward(),
1.0f
);
}
void setWorldAngles(const glm::vec3& angles)
{
updatedBasis = false;
updatedMatrices = false;
rotation = glm::angleAxis(angles.z, glm::vec3(0.0f, 0.0f, 1.0f));
rotation *= glm::angleAxis(angles.x, glm::vec3(1.0f, 0.0f, 0.0f));
rotation *= glm::angleAxis(angles.y, glm::vec3(0.0f, 1.0f, 0.0f));
rotation = normalize(rotation);
}
void AddWorldAngles(const glm::vec3& angles)
{
updatedBasis = false;
updatedMatrices = false;
rotation *= glm::angleAxis(angles.z, glm::vec3(0.0f, 0.0f, 1.0f));
rotation *= glm::angleAxis(angles.x, glm::vec3(1.0f, 0.0f, 0.0f));
rotation *= glm::angleAxis(angles.y, glm::vec3(0.0f, 1.0f, 0.0f));
rotation = normalize(rotation);
}
void setRelativeAngles(const glm::vec3& angles)
{
updatedBasis = false;
updatedMatrices = false;
rotation = glm::angleAxis(angles.z, getForward());
rotation *= glm::angleAxis(angles.x, getRight());
rotation *= glm::angleAxis(angles.y, getUp());
rotation = normalize(rotation);
}
void AddRelativeAngles(const glm::vec3& angles)
{
updatedBasis = false;
updatedMatrices = false;
rotation *= glm::angleAxis(angles.z, getForward());
rotation *= glm::angleAxis(angles.x, getRight());
rotation *= glm::angleAxis(angles.y, getUp());
rotation = glm::normalize(rotation);
}
void UpdateBasis()
{
if (updatedBasis) return;
updatedBasis = true;
const auto mat = glm::mat3_cast(rotation);
inverseView[0] = glm::vec4(mat[0], 0.0f);
inverseView[1] = glm::vec4(mat[1], 0.0f);
inverseView[2] = glm::vec4(mat[2], 0.0f);
inverseView[3] = glm::vec4(getPosition(), 1.0f);
}
void RecalculateView()
{
if (updatedMatrices) return;
updatedMatrices = true;
UpdateBasis();
view = glm::inverse(inverseView);
viewProjection = projection * view;
//inverseViewProjection = glm::inverse(viewProjection);
inverseViewProjection = inverseView * inverseProjection
frustumCorners[0] = glm::vec3(inverseViewProjection * glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f));
frustumCorners[1] = glm::vec3(inverseViewProjection * glm::vec4(1.0f, -1.0f, -1.0f, 1.0f));
frustumCorners[2] = glm::vec3(inverseViewProjection * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f));
frustumCorners[3] = glm::vec3(inverseViewProjection * glm::vec4(1.0f, 1.0f, -1.0f, 1.0f));
}
glm::vec4& position() { return inverseView[3]; }
const glm::vec3 getRight() const { return glm::vec3(inverseView[0]); }
const glm::vec3 getUp() const { return glm::vec3(inverseView[1]); }
const glm::vec3 getForward() const { return glm::vec3(inverseView[2]); }
const glm::vec3 getPosition() const { return glm::vec3(inverseView[3]); }
[[nodiscard]] inline const std::array<glm::vec3, 4>& getFrustumCorners() const noexcept { return frustumCorners; }
private:
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
glm::mat4 viewProjection = glm::mat4(1.0f);
glm::mat4 inverseView = glm::mat4(1.0f);
glm::mat4 inverseProjection = glm::mat4(1.0f);
glm::mat4 inverseViewProjection = glm::mat4(1.0f);
std::array<glm::vec3, 4> frustumCorners{};
glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
bool updatedBasis = true;
bool updatedMatrices = true;
};
na moje wygląda dobrze, renderowana scena też wygląda dobrze:
napisałem też kod, który kontroluje tę kamerę:
const glm::vec2 mousePos = Input::get().getMousePosition();
const glm::vec2 delta = (mousePos - lastMousePosition);
lastMousePosition = mousePos;
if (Input::get().isKeyPressed(Key_Shift)) {
speed = baseSpeed * shiftMultiplier;
} else {
speed = baseSpeed;
}
if (Input::get().isKeyPressed(Key_W)) {
camera.AddRelativeOffset(glm::vec3(0.0f, 0.0f, -speed * dt));
} else if (Input::get().isKeyPressed(Key_S)) {
camera.AddRelativeOffset(glm::vec3(0.0f, 0.0f, speed * dt));
}
if (Input::get().isKeyPressed(Key_A)) {
camera.AddRelativeOffset(glm::vec3(-speed * dt, 0.0f, 0.0f));
} else if (Input::get().isKeyPressed(Key_D)) {
camera.AddRelativeOffset(glm::vec3(speed * dt, 0.0f, 0.0f));
}
if (Input::get().isKeyPressed(Key_Space)) {
camera.AddRelativeOffset(glm::vec3(0.0f, speed * dt, 0.0f));
} else if (Input::get().isKeyPressed(Key_Control)) {
camera.AddRelativeOffset(glm::vec3(0.0f, -speed * dt, 0.0f));
}
if (Input::get().isKeyPressed(Key_Q)) {
camera.AddRelativeAngles(glm::vec3(0.0f, 0.0f, -speed * dt));
} else if (Input::get().isKeyPressed(Key_E)) {
camera.AddRelativeAngles(glm::vec3(0.0f, 0.0f, speed * dt));
}
if (Input::get().isMouseButtonPressed(Mouse_Left)) {
const float offsetLengthPercent = glm::length(delta) / (0.5f * 800.0f);
const float scaledRotationSpeed = rotationSpeed * offsetLengthPercent;
glm::vec3 angles = 0.0f;
angles.x = glm::radians(-delta.y * scaledRotationSpeed * dt);
angles.y = glm::radians(-delta.x * scaledRotationSpeed * dt);
angles.z = 0.0f;
camera.AddRelativeAngles(angles);
}
camera.RecalculateView();
no i ruch prawo, lewo, góra, dół, przód, tył działa, obrót na Q i E też działa, ale jak nakładam kilka typów obrotu, np. trochę roll na Q i potem ruszę myszką to ten obrót nie jest poprawny:
zatacza ona takie koło jak na filmiku:
jak to naprawić? Nie jestem pewien co tutaj jest nie tak.