|
|
|
|
@ -7,6 +7,12 @@
|
|
|
|
|
|
|
|
|
|
#include "camera.h" |
|
|
|
|
|
|
|
|
|
using glm::ivec2; |
|
|
|
|
using glm::vec2; |
|
|
|
|
using glm::vec3; |
|
|
|
|
using glm::mat4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: add these props to scene json
|
|
|
|
|
#define MOVE_SPEED 5.f |
|
|
|
|
#define ROTATE_SPEED 0.005f |
|
|
|
|
@ -22,9 +28,9 @@
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
cameraInitPerspective(Camera* cam, |
|
|
|
|
glm::vec3 position, |
|
|
|
|
glm::vec3 target, |
|
|
|
|
glm::vec3 world_up, |
|
|
|
|
vec3 position, |
|
|
|
|
vec3 target, |
|
|
|
|
vec3 world_up, |
|
|
|
|
float aspect_ratio) |
|
|
|
|
{ |
|
|
|
|
assert(aspect_ratio > 0); |
|
|
|
|
@ -48,7 +54,7 @@ cameraInitPerspective(Camera* cam,
|
|
|
|
|
|
|
|
|
|
cam->view = |
|
|
|
|
glm::lookAt(cam->position, cam->position + cam->forward, cam->up); |
|
|
|
|
cam->model = glm::mat4(1.0f); |
|
|
|
|
cam->model = mat4(1.0f); |
|
|
|
|
cam->MVP = cam->projection * cam->view * cam->model; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -60,49 +66,49 @@ cameraInitOrthographic(/*camera& cam, */)
|
|
|
|
|
// left, right, bottom, top, zNear, zFar
|
|
|
|
|
cam.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); |
|
|
|
|
cam.view = glm::lookAt( |
|
|
|
|
glm::vec3(0.0f, 0.0f, 1.0f), // camera position
|
|
|
|
|
glm::vec3(0.0f, 0.0f, 0.0f), // look at position
|
|
|
|
|
glm::vec3(0,1,0) // "up" vector
|
|
|
|
|
vec3(0.0f, 0.0f, 1.0f), // camera position
|
|
|
|
|
vec3(0.0f, 0.0f, 0.0f), // look at position
|
|
|
|
|
vec3(0,1,0) // "up" vector
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
cam.model = glm::mat4(1.0f); |
|
|
|
|
cam.model = mat4(1.0f); |
|
|
|
|
cam.MVP = cam.projection * cam.view * cam.model; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
glm::vec2 |
|
|
|
|
vec2 |
|
|
|
|
cameraUnproject(Camera& cam, int x, int y, int vp_width, int vp_height) |
|
|
|
|
{ |
|
|
|
|
// NOTE: using depth buffer may not be as accurate as doing ray-cast
|
|
|
|
|
GLfloat depth; |
|
|
|
|
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); |
|
|
|
|
glm::vec4 viewport = glm::vec4(0, 0, vp_width, vp_height); |
|
|
|
|
glm::vec3 wincoord = glm::vec3(x, y, depth); |
|
|
|
|
glm::vec3 vU = glm::unProject(wincoord, cam.view, cam.projection, viewport); |
|
|
|
|
vec4 viewport = vec4(0, 0, vp_width, vp_height); |
|
|
|
|
vec3 wincoord = vec3(x, y, depth); |
|
|
|
|
vec3 vU = glm::unProject(wincoord, cam.view, cam.projection, viewport); |
|
|
|
|
|
|
|
|
|
return glm::vec2(vU.x, vU.y); |
|
|
|
|
return vec2(vU.x, vU.y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
glm::vec3 |
|
|
|
|
cameraCreateRay(Camera& cam, glm::ivec2 vp_coords, glm::ivec2 vp_dims) |
|
|
|
|
vec3 |
|
|
|
|
cameraCreateRay(Camera& cam, ivec2 vp_coords, ivec2 vp_dims) |
|
|
|
|
{ |
|
|
|
|
// NOTE: http://antongerdelan.net/opengl/raycasting.html
|
|
|
|
|
float x = 2.f * vp_coords.x / vp_dims.x - 1.f; |
|
|
|
|
float y = 2.f * vp_coords.y / vp_dims.y - 1.f; |
|
|
|
|
glm::vec4 ray_clip = glm::vec4(x, y, -1.f, 1.f); |
|
|
|
|
glm::vec4 ray_eye = glm::inverse(cam.projection) * ray_clip; |
|
|
|
|
ray_eye = glm::vec4(ray_eye.x, ray_eye.y, -1.f, 0); // NOTE: reset as ray
|
|
|
|
|
glm::vec4 ray_world = glm::normalize(glm::inverse(cam.view) * ray_eye); |
|
|
|
|
vec4 ray_clip = vec4(x, y, -1.f, 1.f); |
|
|
|
|
vec4 ray_eye = glm::inverse(cam.projection) * ray_clip; |
|
|
|
|
ray_eye = vec4(ray_eye.x, ray_eye.y, -1.f, 0); // NOTE: reset as ray
|
|
|
|
|
vec4 ray_world = glm::normalize(glm::inverse(cam.view) * ray_eye); |
|
|
|
|
|
|
|
|
|
return glm::vec3(ray_world.x, ray_world.y, ray_world.z); |
|
|
|
|
return vec3(ray_world.x, ray_world.y, ray_world.z); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
cameraIntersectPlane(Camera& cam, |
|
|
|
|
glm::vec3 ray, |
|
|
|
|
glm::vec3 plane_origin, |
|
|
|
|
glm::vec3 plane_normal, |
|
|
|
|
glm::vec3& intersection) |
|
|
|
|
vec3 ray, |
|
|
|
|
vec3 plane_origin, |
|
|
|
|
vec3 plane_normal, |
|
|
|
|
vec3& intersection) |
|
|
|
|
{ |
|
|
|
|
// NOTE: https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection
|
|
|
|
|
float divisor = glm::dot(ray, plane_normal); |
|
|
|
|
@ -112,8 +118,8 @@ cameraIntersectPlane(Camera& cam,
|
|
|
|
|
|
|
|
|
|
float distance = |
|
|
|
|
glm::dot((plane_origin - cam.position), plane_normal) / divisor; |
|
|
|
|
glm::vec3 xsect = cam.position + (ray * distance); |
|
|
|
|
intersection = glm::vec3(xsect.x, xsect.y, xsect.z); |
|
|
|
|
vec3 xsect = cam.position + (ray * distance); |
|
|
|
|
intersection = vec3(xsect.x, xsect.y, xsect.z); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
@ -130,11 +136,11 @@ cameraMove(Camera& cam,
|
|
|
|
|
if (!up && !left && !down && !right && !forward && !backward) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
glm::vec3 f = cam.forward; |
|
|
|
|
glm::vec3 u = cam.up; |
|
|
|
|
glm::vec3 old = cam.position; |
|
|
|
|
glm::vec3 &p = cam.position; |
|
|
|
|
glm::vec3 v(0.f); // normalized direction
|
|
|
|
|
vec3 f = cam.forward; |
|
|
|
|
vec3 u = cam.up; |
|
|
|
|
vec3 old = cam.position; |
|
|
|
|
vec3 &p = cam.position; |
|
|
|
|
vec3 v(0.f); // normalized direction
|
|
|
|
|
|
|
|
|
|
// TODO: still seems like we're adding magnitude when moving in 2 directions
|
|
|
|
|
#if 0 |
|
|
|
|
@ -154,7 +160,7 @@ cameraMove(Camera& cam,
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
p += (v * MOVE_SPEED); |
|
|
|
|
glm::vec3 diff = old - p; |
|
|
|
|
vec3 diff = old - p; |
|
|
|
|
cam.view = glm::translate(cam.view, diff); |
|
|
|
|
cam.MVP = cam.projection * cam.view * cam.model; |
|
|
|
|
} |
|
|
|
|
@ -172,7 +178,7 @@ cameraRotate(Camera& cam, i32 xrel, i32 yrel)
|
|
|
|
|
if (v < (-1 * a)) v = (-1 * a); |
|
|
|
|
if (v > a) v = a; |
|
|
|
|
|
|
|
|
|
cam.forward = glm::vec3( |
|
|
|
|
cam.forward = vec3( |
|
|
|
|
glm::cos(v) * glm::sin(h), |
|
|
|
|
glm::cos(v) * glm::cos(h), |
|
|
|
|
glm::sin(v) |
|
|
|
|
@ -195,10 +201,10 @@ cameraRoll(Camera& cam, bool CW, bool CCW)
|
|
|
|
|
float a = 0.005f; |
|
|
|
|
if (CW) a *= 1; |
|
|
|
|
if (CCW) a *= -1; |
|
|
|
|
glm::mat4 m = glm::rotate(glm::mat4(1.f), a, cam.forward); |
|
|
|
|
glm::vec4 v(cam.up.x, cam.up.y, cam.up.z, 0); |
|
|
|
|
mat4 m = glm::rotate(mat4(1.f), a, cam.forward); |
|
|
|
|
vec4 v(cam.up.x, cam.up.y, cam.up.z, 0); |
|
|
|
|
v = v * m; |
|
|
|
|
cam.up = glm::vec3(v.x, v.y, v.z); |
|
|
|
|
cam.up = vec3(v.x, v.y, v.z); |
|
|
|
|
cam.view *= m; |
|
|
|
|
cam.MVP = cam.projection * cam.view * cam.model; |
|
|
|
|
} |
|
|
|
|
|