Skip to content
Snippets Groups Projects
Commit d02f2309 authored by Adam Štěpánek's avatar Adam Štěpánek
Browse files

Finish implementing positional camera

parent bda71f63
No related branches found
No related tags found
No related merge requests found
......@@ -13,7 +13,7 @@ private:
GLuint _id;
public:
GLuint id() {
GLuint id() const {
return _id;
}
};
......@@ -8,9 +8,8 @@
///
/// Use left mouse button to change the point of view.
/// Use right mouse button to zoom in and zoom out.
class RotateCamera
{
private:
class RotateCamera {
private:
/// Constants that defines the behaviour of the camera
/// - Minimum elevation in radians
static const float minElevation;
......@@ -28,29 +27,33 @@ class RotateCamera
/// - 90 degrees .. I look in -x direction
/// - 180 degrees .. I look in +z direction
/// - 270 degrees .. I look in +x direction
float angleDirection;
float _angleDirection = 0.0f;
/// angle_direction is an angle in which determines from which "height" I look.
/// - positive elevation .. I look from above the xz plane
/// - negative elevation .. I look from below the xz plane
float angleElevation;
float _angleElevation = 0.5f;
/// Distance from (0,0,0), the point at which I look
float distance;
float _distance = 50.0f;
/// Final position of the eye in world space coordinates, for LookAt or shaders
glm::vec3 eyePosition;
glm::vec3 _eyePosition;
/// Last X and Y coordinates of the mouse cursor
int lastX, lastY;
int _lastX = 0;
int _lastY = 0;
/// True or false if moused buttons are pressed and the user rotates/zooms the camera
bool isRotating, isZooming;
bool _isRotating = false;
bool _isZooming = false;
glm::vec3 _center = glm::vec3(0.0f, 0.0f, 0.0f);
/// Recomputes 'eye_position' from 'angle_direction', 'angle_elevation', and 'distance'
void updateEyePos();
public:
public:
RotateCamera();
/// Call when the user presses or releases a mouse button (see glfwSetMouseButtonCallback)
......@@ -60,7 +63,25 @@ class RotateCamera
void onMouseMove(double x, double y);
/// Returns the position of the eye in world space coordinates
glm::vec3 getEyePosition() const {
return eyePosition;
glm::vec3 eyePosition() const {
return _eyePosition;
}
glm::vec3 center() const {
return _center;
}
void center(const glm::vec3 value) {
_center = value;
updateEyePos();
}
float angleDirection() const {
return _angleDirection;
}
void angleDirection(float value) {
_angleDirection = value;
updateEyePos();
}
};
......@@ -8,63 +8,57 @@ const float RotateCamera::minDistance = 1.0f;
const float RotateCamera::angleSensitivity = 0.008f;
const float RotateCamera::zoomSensitivity = 0.003f;
RotateCamera::RotateCamera()
: angleDirection(0.0f), angleElevation(0.785398163f), distance(15.0f), lastX(0), lastY(0), isRotating(false),
isZooming(false)
{
RotateCamera::RotateCamera() {
updateEyePos();
}
void RotateCamera::updateEyePos()
{
eyePosition.x = distance * cosf(angleElevation) * -sinf(angleDirection);
eyePosition.y = distance * sinf(angleElevation);
eyePosition.z = distance * cosf(angleElevation) * cosf(angleDirection);
void RotateCamera::updateEyePos() {
_eyePosition.x = _center.x + _distance * cosf(_angleElevation) * -sinf(_angleDirection);
_eyePosition.y = _center.y + _distance * sinf(_angleElevation);
_eyePosition.z = _center.z + _distance * cosf(_angleElevation) * cosf(_angleDirection);
}
void RotateCamera::onMouseButton(int button, int action, int mods)
{
void RotateCamera::onMouseButton(int button, int action, int mods) {
// Left mouse button affects the angles
if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (action == GLFW_PRESS) {
isRotating = true;
_isRotating = true;
} else {
isRotating = false;
_isRotating = false;
}
}
// Right mouse button affects the zoom
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
if (action == GLFW_PRESS) {
isZooming = true;
_isZooming = true;
} else {
isZooming = false;
_isZooming = false;
}
}
}
void RotateCamera::onMouseMove(double x, double y)
{
float dx = float(x - lastX);
float dy = float(y - lastY);
lastX = static_cast<int>(x);
lastY = static_cast<int>(y);
void RotateCamera::onMouseMove(double x, double y) {
float dx = float(x - _lastX);
float dy = float(y - _lastY);
_lastX = static_cast<int>(x);
_lastY = static_cast<int>(y);
if (isRotating) {
angleDirection += dx * angleSensitivity;
angleElevation += dy * angleSensitivity;
if (_isRotating) {
_angleDirection += dx * angleSensitivity;
_angleElevation += dy * angleSensitivity;
// Clamp the results
if (angleElevation > maxElevation)
angleElevation = maxElevation;
if (angleElevation < minElevation)
angleElevation = minElevation;
if (_angleElevation > maxElevation)
_angleElevation = maxElevation;
if (_angleElevation < minElevation)
_angleElevation = minElevation;
}
if (isZooming) {
distance *= (1.0f + dy * zoomSensitivity);
if (_isZooming) {
_distance *= (1.0f + dy * zoomSensitivity);
// Clamp the results
if (distance < minDistance)
distance = minDistance;
if (_distance < minDistance)
_distance = minDistance;
}
updateEyePos();
}
......@@ -4,9 +4,9 @@ Application::Application(size_t initialWidth, size_t initialHeight) {
this->width = initialWidth;
this->height = initialHeight;
cameraUbo.position = glm::vec4(camera.getEyePosition(), 1.0f);
cameraUbo.position = glm::vec4(camera.eyePosition(), 1.0f);
cameraUbo.projection = glm::perspective(glm::radians(45.0f), float(width) / float(height), 0.01f, 1000.0f);
cameraUbo.view = glm::lookAt(camera.getEyePosition(), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
cameraUbo.view = glm::lookAt(camera.eyePosition(), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
LightUBO directionalLight;
directionalLight.position = glm::vec4(1.0f, 1.0f, 1.0f, 0.0f);
......@@ -25,24 +25,12 @@ Application::Application(size_t initialWidth, size_t initialHeight) {
beltMaterial.diffuseColor(glm::vec4(1.0f));
beltMaterial.specularColor(glm::vec4(1.0f, 1.0f, 1.0f, 2048.0f));
pioneerModelMatrix = glm::mat4(1.0f);
pioneerModelMatrix = glm::translate(pioneerModelMatrix, glm::vec3(0.0f, 4.0f, 15.0f));
pioneerModelMatrix = glm::scale(pioneerModelMatrix, glm::vec3(0.2f));
pioneerModelMatrix = glm::rotate(pioneerModelMatrix, -3.14159f / 8.0f, glm::vec3(1.0, 0.0, 0.0));
pioneer.modelMatrix() = glm::scale(pioneer.modelMatrix(), glm::vec3(0.2f));
pioneer.modelMatrix() = glm::rotate(pioneer.modelMatrix(), -3.14159f / 8.0f, glm::vec3(1.0, 0.0, 0.0));
voyagerModelMatrix = glm::mat4(1.0f);
voyagerModelMatrix = glm::translate(voyagerModelMatrix, glm::vec3(20.0f, 2.0f, 0.0f));
voyagerModelMatrix = glm::scale(voyagerModelMatrix, glm::vec3(0.1f));
voyagerModelMatrix = glm::rotate(voyagerModelMatrix, 3.14159f / 2.0f, glm::vec3(1.0, 0.0, 0.0));
voyagerModelMatrix = glm::rotate(voyagerModelMatrix, 3.14159f / 2.0f, glm::vec3(0.0, 0.0, 1.0));
ulyssesModelMatrix = glm::mat4(1.0f);
galileoModelMatrix = glm::mat4(1.0f);
cassiniModelMatrix = glm::mat4(1.0f);
junoModelMatrix = glm::mat4(1.0f);
voyager.modelMatrix() = glm::scale(voyager.modelMatrix(), glm::vec3(0.1f));
voyager.modelMatrix() = glm::rotate(voyager.modelMatrix(), 3.14159f / 2.0f, glm::vec3(1.0, 0.0, 0.0));
voyager.modelMatrix() = glm::rotate(voyager.modelMatrix(), 3.14159f / 2.0f, glm::vec3(0.0, 0.0, 1.0));
glCreateBuffers(1, &cameraBuffer);
glNamedBufferStorage(cameraBuffer, sizeof(CameraUBO), &cameraUbo, GL_DYNAMIC_STORAGE_BIT);
......@@ -79,25 +67,20 @@ void Application::drawProbe(Scene &scene, const glm::mat4 &modelMatrix) {
}
void Application::render() {
time = glfwGetTime();
// --------------------------------------------------------------------------
// Update data
// --------------------------------------------------------------------------
time = glfwGetTime();
if (lastTime > 0.0) {
rotateProbeMatrix(pioneerModelMatrix, 0.2f);
rotateProbeMatrix(voyagerModelMatrix, -0.1f);
}
pioneer.update();
voyager.update();
// Camera
glm::vec3 cameraPosition;
if (followedProbe) {
cameraPosition = glm::vec3(*followedProbe * glm::vec4(camera.getEyePosition(), 1.0f));
} else {
cameraPosition = camera.getEyePosition();
camera.center(followedProbe->position());
camera.angleDirection(camera.angleDirection() - followedProbe->deltaAngle());
}
cameraUbo.position = glm::vec4(cameraPosition, 1.0f);
cameraUbo.view = glm::lookAt(cameraPosition, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
cameraUbo.position = glm::vec4(camera.eyePosition(), 1.0f);
cameraUbo.view = glm::lookAt(camera.eyePosition(), camera.center(), glm::vec3(0.0f, 1.0f, 0.0f));
glNamedBufferSubData(cameraBuffer, 0, sizeof(CameraUBO), &cameraUbo);
// Belt
......@@ -147,8 +130,8 @@ void Application::render() {
glBindVertexArray(teapot.vao());
glDrawElementsInstanced(teapot.mode(), teapot.indicesCount(), GL_UNSIGNED_INT, nullptr, 2048);
drawProbe(pioneer, pioneerModelMatrix);
drawProbe(voyager, voyagerModelMatrix);
pioneer.draw();
voyager.draw();
//drawScene(ulysses, ulyssesModelMatrix);
//drawScene(galileo, galileoModelMatrix);
//drawScene(cassini, cassiniModelMatrix);
......@@ -206,12 +189,13 @@ void Application::onKeyPressed(GLFWwindow *window, int key, int scancode, int ac
switch (key) {
case GLFW_KEY_0:
followedProbe = nullptr;
camera.center(glm::vec3(0.0f));
break;
case GLFW_KEY_1:
followedProbe = &pioneerModelMatrix;
followedProbe = &pioneer;
break;
case GLFW_KEY_2:
followedProbe = &voyagerModelMatrix;
followedProbe = &voyager;
break;
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
#include "mesh.hpp"
#include "playback.hpp"
#include "probe.hpp"
#include "program.hpp"
#include "rotate_camera.hpp"
#include "scene.hpp"
......@@ -63,18 +64,12 @@ private:
Mesh teapot = Mesh::teapot();
Mesh polarTeapot = Mesh::polarTeapot();
Scene pioneer = Scene("objects/pioneer/pioneer.obj");
glm::mat4 pioneerModelMatrix;
Scene voyager = Scene("objects/voyager/voyager.obj");
glm::mat4 voyagerModelMatrix;
//Scene ulysses = Scene("objects/ulysses/ulysses.obj");
glm::mat4 ulyssesModelMatrix;
//Scene galileo = Scene("objects/galileo/galileo.obj");
glm::mat4 galileoModelMatrix;
//Scene cassini = Scene("objects/cassini/cassini.obj");
glm::mat4 cassiniModelMatrix;
//Scene juno = Scene("objects/juno/Juno.obj");
glm::mat4 junoModelMatrix;
Probe pioneer = Probe("objects/pioneer/pioneer.obj", { 0.0f, 4.0f, 15.0f }, 0.2f, texturedObjectProgram, normalMappedObjectProgram);
Probe voyager = Probe("objects/voyager/voyager.obj", { 20.0f, 2.0f, 0.0f }, -0.1f, texturedObjectProgram, normalMappedObjectProgram);
//Probe ulysses = Probe("objects/ulysses/ulysses.obj", { 20.0f, 2.0f, 0.0f }, texturedObjectProgram, normalMappedObjectProgram);
//Probe galileo = Probe("objects/galileo/galileo.obj", { 20.0f, 2.0f, 0.0f }, texturedObjectProgram, normalMappedObjectProgram);
//Probe cassini = Probe("objects/cassini/cassini.obj", { 20.0f, 2.0f, 0.0f }, texturedObjectProgram, normalMappedObjectProgram);
//Probe juno = Probe("objects/juno/Juno.obj", { 20.0f, 2.0f, 0.0f }, texturedObjectProgram, normalMappedObjectProgram);
Material jupiterMaterial;
glm::mat4 jupiterModelMatrix;
......@@ -103,7 +98,7 @@ private:
double lastTime = 0.0f;
double music[Playback::magicCount] = { 0 };
const double musicStepDown = -0.03;
glm::mat4 *followedProbe = nullptr;
Probe *followedProbe = nullptr;
void rotateProbeMatrix(glm::mat4 &modelMatrix, float velocity);
void drawProbe(Scene &scene, const glm::mat4 &modelMatrix);
......
#pragma once
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <memory>
#include <program.hpp>
#include <scene.hpp>
class Probe {
public:
Probe(const std::string& objPath,
const glm::vec3& startPosition,
float speed,
const Program& texturedObjectProgram,
const Program& normalMappedObjectProgram)
: _startPosition(startPosition)
, _speed(speed)
, _modelMatrix(glm::translate(glm::mat4(1.0f), startPosition))
, _texturedObjectProgram(texturedObjectProgram)
, _normalMappedObjectProgram(normalMappedObjectProgram) {
_scene = std::make_unique<Scene>(objPath);
}
public:
void update() {
_time = glfwGetTime();
if (_lastTime > 0.0) {
_deltaAngle = (_time - _lastTime) * _speed;
_modelMatrix = glm::rotate(glm::mat4(1.0f), float(_deltaAngle) , glm::vec3(0.0f, 1.0f, 0.0f)) * _modelMatrix;
_position = _modelMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
_lastTime = _time;
}
void draw() {
for (auto& mesh : _scene->meshes()) {
GLuint program = mesh->material() && mesh->material()->normalTexture()
? _normalMappedObjectProgram.id()
: _texturedObjectProgram.id();
glUseProgram(program);
glProgramUniformMatrix4fv(program, 0, 1, GL_FALSE, glm::value_ptr(_modelMatrix));
mesh->draw();
}
}
glm::mat4& modelMatrix() {
return _modelMatrix;
}
float speed() const {
return _speed;
}
double deltaAngle() const {
return _deltaAngle;
}
const glm::vec3& position() const {
return _position;
}
private:
std::unique_ptr<Scene> _scene;
float _speed = 0.0f;
glm::mat4 _modelMatrix;
glm::vec3 _startPosition;
const Program& _texturedObjectProgram;
const Program& _normalMappedObjectProgram;
double _time = 0.0;
double _lastTime = 0.0;
double _deltaAngle = 0.0;
glm::vec3 _position = glm::vec3(0.0f);
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment