119 lines
3.2 KiB
C
119 lines
3.2 KiB
C
|
/*
|
||
|
* Copyright (c), Recep Aslantas.
|
||
|
*
|
||
|
* MIT License (MIT), http://opensource.org/licenses/MIT
|
||
|
* Full license can be found in the LICENSE file
|
||
|
*/
|
||
|
|
||
|
#ifndef cglm_project_h
|
||
|
#define cglm_project_h
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "vec3.h"
|
||
|
#include "vec4.h"
|
||
|
#include "mat4.h"
|
||
|
|
||
|
/*!
|
||
|
* @brief maps the specified viewport coordinates into specified space [1]
|
||
|
* the matrix should contain projection matrix.
|
||
|
*
|
||
|
* if you don't have ( and don't want to have ) an inverse matrix then use
|
||
|
* glm_unproject version. You may use existing inverse of matrix in somewhere
|
||
|
* else, this is why glm_unprojecti exists to save save inversion cost
|
||
|
*
|
||
|
* [1] space:
|
||
|
* 1- if m = invProj: View Space
|
||
|
* 2- if m = invViewProj: World Space
|
||
|
* 3- if m = invMVP: Object Space
|
||
|
*
|
||
|
* You probably want to map the coordinates into object space
|
||
|
* so use invMVP as m
|
||
|
*
|
||
|
* Computing viewProj:
|
||
|
* glm_mat4_mul(proj, view, viewProj);
|
||
|
* glm_mat4_mul(viewProj, model, MVP);
|
||
|
* glm_mat4_inv(viewProj, invMVP);
|
||
|
*
|
||
|
* @param[in] pos point/position in viewport coordinates
|
||
|
* @param[in] invMat matrix (see brief)
|
||
|
* @param[in] vp viewport as [x, y, width, height]
|
||
|
* @param[out] dest unprojected coordinates
|
||
|
*/
|
||
|
CGLM_INLINE
|
||
|
void
|
||
|
glm_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) {
|
||
|
vec4 v;
|
||
|
|
||
|
v[0] = 2.0f * (pos[0] - vp[0]) / vp[2] - 1.0f;
|
||
|
v[1] = 2.0f * (pos[1] - vp[1]) / vp[3] - 1.0f;
|
||
|
v[2] = 2.0f * pos[2] - 1.0f;
|
||
|
v[3] = 1.0f;
|
||
|
|
||
|
glm_mat4_mulv(invMat, v, v);
|
||
|
glm_vec4_scale(v, 1.0f / v[3], v);
|
||
|
glm_vec3(v, dest);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief maps the specified viewport coordinates into specified space [1]
|
||
|
* the matrix should contain projection matrix.
|
||
|
*
|
||
|
* this is same as glm_unprojecti except this function get inverse matrix for
|
||
|
* you.
|
||
|
*
|
||
|
* [1] space:
|
||
|
* 1- if m = proj: View Space
|
||
|
* 2- if m = viewProj: World Space
|
||
|
* 3- if m = MVP: Object Space
|
||
|
*
|
||
|
* You probably want to map the coordinates into object space
|
||
|
* so use MVP as m
|
||
|
*
|
||
|
* Computing viewProj and MVP:
|
||
|
* glm_mat4_mul(proj, view, viewProj);
|
||
|
* glm_mat4_mul(viewProj, model, MVP);
|
||
|
*
|
||
|
* @param[in] pos point/position in viewport coordinates
|
||
|
* @param[in] m matrix (see brief)
|
||
|
* @param[in] vp viewport as [x, y, width, height]
|
||
|
* @param[out] dest unprojected coordinates
|
||
|
*/
|
||
|
CGLM_INLINE
|
||
|
void
|
||
|
glm_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
|
||
|
mat4 inv;
|
||
|
glm_mat4_inv(m, inv);
|
||
|
glm_unprojecti(pos, inv, vp, dest);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief map object coordinates to window coordinates
|
||
|
*
|
||
|
* Computing MVP:
|
||
|
* glm_mat4_mul(proj, view, viewProj);
|
||
|
* glm_mat4_mul(viewProj, model, MVP);
|
||
|
*
|
||
|
* @param[in] pos object coordinates
|
||
|
* @param[in] m MVP matrix
|
||
|
* @param[in] vp viewport as [x, y, width, height]
|
||
|
* @param[out] dest projected coordinates
|
||
|
*/
|
||
|
CGLM_INLINE
|
||
|
void
|
||
|
glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
|
||
|
CGLM_ALIGN(16) vec4 pos4, vone = GLM_VEC4_ONE_INIT;
|
||
|
|
||
|
glm_vec4(pos, 1.0f, pos4);
|
||
|
|
||
|
glm_mat4_mulv(m, pos4, pos4);
|
||
|
glm_vec4_scale(pos4, 1.0f / pos4[3], pos4); /* pos = pos / pos.w */
|
||
|
glm_vec4_add(pos4, vone, pos4);
|
||
|
glm_vec4_scale(pos4, 0.5f, pos4);
|
||
|
|
||
|
dest[0] = pos4[0] * vp[2] + vp[0];
|
||
|
dest[1] = pos4[1] * vp[3] + vp[1];
|
||
|
dest[2] = pos4[2];
|
||
|
}
|
||
|
|
||
|
#endif /* cglm_project_h */
|