]> git.localhorst.tv Git - blobs.git/blob - src/graphics/viewport.cpp
51e8cddd046fe3fd55be684427023ede5fa93ea7
[blobs.git] / src / graphics / viewport.cpp
1 #include "Camera.hpp"
2 #include "Viewport.hpp"
3
4 #include "../creature/Creature.hpp"
5 #include "../math/const.hpp"
6 #include "../world/Body.hpp"
7 #include "../world/Planet.hpp"
8
9 #include <cmath>
10 #include <GL/glew.h>
11 #include <glm/gtx/euler_angles.hpp>
12 #include <glm/gtx/rotate_vector.hpp>
13 #include <glm/gtx/transform.hpp>
14
15
16 namespace blobs {
17 namespace graphics {
18
19 Camera::Camera(const world::Body &r) noexcept
20 : fov(PI * 0.25)
21 , aspect(1.0f)
22 , near(0.1f)
23 , far(12560.0f)
24 , projection(glm::perspective(fov, aspect, near, far))
25 , view(1.0f)
26 , ref(&r)
27 , track_orient(false) {
28
29 }
30
31 Camera::~Camera() noexcept {
32 }
33
34 Camera &Camera::FOV(float f) noexcept {
35         fov = f;
36         UpdateProjection();
37         return *this;
38 }
39
40 Camera &Camera::Aspect(float r) noexcept {
41         aspect = r;
42         UpdateProjection();
43         return *this;
44 }
45
46 Camera &Camera::Aspect(float w, float h) noexcept {
47         Aspect(w / h);
48         return *this;
49 }
50
51 Camera &Camera::Clip(float n, float f) noexcept {
52         near = n;
53         far = f;
54         UpdateProjection();
55         return *this;
56 }
57
58 Camera &Camera::Reference(const world::Body &r) noexcept {
59         ref = &r;
60         return *this;
61 }
62
63 Camera &Camera::Orbital(const glm::vec3 &pos) noexcept {
64         track_orient = false;
65         view = glm::lookAt(pos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
66         return *this;
67 }
68
69 Camera &Camera::Radial(const creature::Creature &c, double distance, const glm::dvec3 &angle) {
70         const creature::Situation &s = c.GetSituation();
71         glm::dvec3 pos(s.Position());
72         glm::dvec3 up(0.0);
73         glm::dvec3 dir(0.0, 0.0, -distance);
74         if (s.OnSurface()) {
75                 Reference(s.GetPlanet());
76                 track_orient = true;
77                 up = s.GetPlanet().NormalAt(s.Position());
78                 glm::dvec3 ref(glm::normalize(glm::cross(up, glm::dvec3(up.z, up.x, up.y))));
79                 dir =
80                         glm::dmat3(ref, up, glm::cross(ref, up))
81                         * glm::dmat3(glm::eulerAngleYX(-angle.y, -angle.x))
82                         * dir;
83         } else {
84                 up.y = 1.0;
85                 dir = glm::dmat3(glm::eulerAngleYX(-angle.y, -angle.x)) * dir;
86         }
87         pos += up * (c.Size() * 0.5);
88         up = glm::rotate(up, angle.z, glm::normalize(-dir));
89         view = glm::lookAt(pos - dir, pos, up);
90         return *this;
91 }
92
93 glm::mat4 Camera::Model(const world::Body &b) const noexcept {
94         if (&b == ref) {
95                 return track_orient ? glm::mat4(1.0f) : glm::mat4(ref->LocalTransform());
96         } else if (b.HasParent() && &b.Parent() == ref) {
97                 return glm::mat4(track_orient
98                         ? ref->InverseTransform() * b.FromParent() * b.LocalTransform()
99                         : b.FromParent() * b.LocalTransform());
100         } else if (ref->HasParent() && &ref->Parent() == &b) {
101                 return glm::mat4(track_orient
102                         ? ref->InverseTransform() * ref->ToParent() * b.LocalTransform()
103                         : ref->ToParent() * b.LocalTransform());
104         } else {
105                 return glm::mat4(track_orient
106                         ? ref->InverseTransform() * ref->ToUniverse() * b.FromUniverse() * b.LocalTransform()
107                         : ref->ToUniverse() * b.FromUniverse() * b.LocalTransform());
108         }
109 }
110
111 void Camera::UpdateProjection() noexcept {
112         projection = glm::perspective(fov, aspect, near, far);
113 }
114
115
116 Viewport::Viewport(int w, int h)
117 : width(w)
118 , height(h) {
119         Resize(w, h);
120         glClearColor(0.0, 0.0, 0.0, 1.0);
121 }
122
123 Viewport::~Viewport() {
124 }
125
126
127 void Viewport::Resize(int w, int h) {
128         width = w;
129         height = h;
130         glViewport(0, 0, w, h);
131 }
132
133 void Viewport::Clear() {
134         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
135 }
136
137 void Viewport::ClearDepth() {
138         glClear(GL_DEPTH_BUFFER_BIT);
139 }
140
141 }
142 }