yabba/transform.cpp
#include "transform.hpp"
const GLfloat LookAt::id[] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
LookAt::LookAt(const Window* w, GLuint m, GLuint v, GLuint p): window(w), uniModel(m), uniView(v), uniProj(p) {
viewport = glm::vec4(0.0f, 0.0f, window->w, window->h);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, id);
glUniformMatrix4fv(uniView, 1, GL_FALSE, id);
glUniformMatrix4fv(uniProj, 1, GL_FALSE, id);
}
int LookAt::project(int cam_angle, GLfloat view_x, GLfloat view_y) {
cam_angle = MAX(20, MIN(90, cam_angle));
// camera distance is that we see everything at the given fov
static const GLfloat fov = 45.0f;
static const GLfloat g = glm::radians(180.0f - 90.0f - (fov/2.0f));
static const GLfloat x = 1.0f / glm::cos(g);
static const GLfloat cam_dist = glm::sqrt(x*x - 1);
view = glm::lookAt(
glm::vec3( // camera position
view_x,
-cam_dist*glm::cos(glm::radians((float)cam_angle)),
cam_dist*glm::cos(glm::radians(90.0f-(float)cam_angle))
),
glm::vec3(view_x, view_y, 0.0f), // camera target
glm::vec3(0.0f, 1.0f, 0.0f) // up vector in positive y direction
);
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
// TODO: pre-compute model*view*proj and bind result only
proj = glm::perspective(glm::radians(fov), 1.0f, 1.0f, 10.0f); // we take care of the ratio for ourselves, so no (float)window->w/(float)window->h needed here
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
return cam_angle;
}
void LookAt::unproject(double x, double y, float z, GLfloat& xx, GLfloat& yy) const {
glm::vec3 pos = glm::vec3(x, y, z);
glm::vec3 un = glm::unProject(pos, view, proj, viewport);
xx = un.x;
yy = un.y;
}