diff --git a/include/cglm/call.h b/include/cglm/call.h
index 3f7bf14..ce08b78 100644
--- a/include/cglm/call.h
+++ b/include/cglm/call.h
@@ -24,6 +24,7 @@ extern "C" {
#include "call/frustum.h"
#include "call/box.h"
#include "call/io.h"
+#include "call/project.h"
#ifdef __cplusplus
}
diff --git a/include/cglm/call/project.h b/include/cglm/call/project.h
new file mode 100644
index 0000000..1120b21
--- /dev/null
+++ b/include/cglm/call/project.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_project_h
+#define cglmc_project_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_unprojecti(mat4 invMat, vec4 vp, vec3 coord, vec3 dest);
+
+CGLM_EXPORT
+void
+glmc_unproject(mat4 m, vec2 vp, vec3 coord, vec3 dest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_project_h */
+
+
diff --git a/include/cglm/cglm.h b/include/cglm/cglm.h
index e99bb09..52c7e97 100644
--- a/include/cglm/cglm.h
+++ b/include/cglm/cglm.h
@@ -23,5 +23,6 @@
#include "color.h"
#include "util.h"
#include "io.h"
+#include "project.h"
#endif /* cglm_h */
diff --git a/include/cglm/project.h b/include/cglm/project.h
new file mode 100644
index 0000000..27cb42a
--- /dev/null
+++ b/include/cglm/project.h
@@ -0,0 +1,84 @@
+/*
+ * 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 "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] invMat matrix (see brief)
+ * @param[in] vp viewport as [x, y, width, height]
+ * @param[in] coord viewport coordinates
+ * @param[out] dest unprojected coordinates
+ */
+CGLM_INLINE
+void
+glm_unprojecti(mat4 invMat, vec4 vp, vec3 coord, vec4 dest) {
+ vec4 v;
+
+ v[0] = 2.0f * (coord[0] - vp[0]) / vp[2] - 1.0f;
+ v[1] = 2.0f * (coord[1] - vp[1]) / vp[3] - 1.0f;
+ v[2] = 2.0f * coord[2] - 1.0f;
+ v[3] = 1.0f;
+
+ glm_mat4_mulv(invMat, 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:
+ * glm_mat4_mul(proj, view, viewProj);
+ * glm_mat4_mul(viewProj, model, MVP);
+ *
+ * @param[in] m matrix (see brief)
+ * @param[in] vp viewport as [x, y, width, height]
+ * @param[in] coord viewport coordinates
+ * @param[out] dest unprojected coordinates
+ */
+CGLM_INLINE
+void
+glm_unproject(mat4 m, vec2 vp, vec3 coord, vec3 dest) {
+ mat4 inv;
+ glm_mat4_inv(m, inv);
+ glm_unprojecti(inv, vp, coord, dest);
+}
+
+#endif /* cglm_project_h */
diff --git a/src/project.c b/src/project.c
new file mode 100644
index 0000000..80e0b44
--- /dev/null
+++ b/src/project.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#include "../include/cglm/cglm.h"
+#include "../include/cglm/call.h"
+
+CGLM_EXPORT
+void
+glmc_unprojecti(mat4 invMat, vec4 vp, vec3 coord, vec3 dest) {
+ glm_unprojecti(invMat, vp, coord, dest);
+}
+
+CGLM_EXPORT
+void
+glmc_unproject(mat4 m, vec2 vp, vec3 coord, vec3 dest) {
+ glm_unproject(m, vp, coord, dest);
+}
diff --git a/win/cglm.vcxproj b/win/cglm.vcxproj
index 4a0463d..415a87d 100644
--- a/win/cglm.vcxproj
+++ b/win/cglm.vcxproj
@@ -29,6 +29,7 @@
+
@@ -47,6 +48,7 @@
+
@@ -60,6 +62,7 @@
+
diff --git a/win/cglm.vcxproj.filters b/win/cglm.vcxproj.filters
index 506f3d8..3090d72 100644
--- a/win/cglm.vcxproj.filters
+++ b/win/cglm.vcxproj.filters
@@ -75,6 +75,9 @@
src
+
+ src
+
@@ -206,5 +209,11 @@
include\cglm
+
+ include\cglm
+
+
+ include\cglm\call
+
\ No newline at end of file