+#ifndef NEXUS3D_CGMATH2_H_
+#define NEXUS3D_CGMATH2_H_
+
+#include <math.h>
+#include <string.h>
+
+#define CGM_PI 3.141592653589793
+
+typedef struct {
+ float x, y;
+} cgm_vec2;
+
+typedef struct {
+ float x, y, z;
+} cgm_vec3;
+
+typedef struct {
+ float x, y, z, w;
+} cgm_vec4, cgm_quat;
+
+typedef struct {
+ cgm_vec3 origin, dir;
+} cgm_ray;
+
+typedef enum cgm_euler_mode {
+ CGM_EULER_XYZ,
+ CGM_EULER_XZY,
+ CGM_EULER_YXZ,
+ CGM_EULER_YZX,
+ CGM_EULER_ZXY,
+ CGM_EULER_ZYX,
+ CGM_EULER_ZXZ,
+ CGM_EULER_ZYZ,
+ CGM_EULER_YXY,
+ CGM_EULER_YZY,
+ CGM_EULER_XYX,
+ CGM_EULER_XZX
+} cgm_euler_mode;
+
+#ifdef __cplusplus
+#define CGM_INLINE inline
+
+extern "C" {
+#else
+
+#if (__STDC_VERSION__ >= 199901) || defined(__GNUC__)
+#define CGM_INLINE inline
+#else
+#define CGM_INLINE __inline
+#endif
+
+#endif
+
+/* --- operations on cgm_vec3 --- */
+static CGM_INLINE cgm_vec3 cgm_vcons(float x, float y, float z);
+
+static CGM_INLINE cgm_vec3 cgm_vadd(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vsub(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vmul(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vscale(cgm_vec3 v, float s);
+
+static CGM_INLINE cgm_vec3 cgm_vmul_m4v3(const float *m, cgm_vec3 v); /* m4x4 * v */
+static CGM_INLINE cgm_vec3 cgm_vmul_v3m4(cgm_vec3 v, const float *m); /* v * m4x4 */
+static CGM_INLINE cgm_vec3 cgm_vmul_m3v3(const float *m, cgm_vec3 v); /* m3x3 * v (m still 16 floats) */
+static CGM_INLINE cgm_vec3 cgm_vmul_v3m3(cgm_vec3 v, const float *m); /* v * m3x3 (m still 16 floats) */
+
+static CGM_INLINE float cgm_vdot(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vcross(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE float cgm_vlength(cgm_vec3 v);
+static CGM_INLINE float cgm_vlength_sq(cgm_vec3 v);
+static CGM_INLINE float cgm_vdist(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE float cgm_vdist_sq(cgm_vec3 a, cgm_vec3 b);
+
+static CGM_INLINE cgm_vec3 cgm_normalize(cgm_vec3 v);
+
+static CGM_INLINE cgm_vec3 cgm_vreflect(cgm_vec3 v, cgm_vec3 n);
+static CGM_INLINE cgm_vec3 cgm_vrefract(cgm_vec3 v, cgm_vec3 n, float ior);
+
+static CGM_INLINE cgm_vec3 cgm_vrotate_quat(cgm_vec3 v, cgm_quat q);
+static CGM_INLINE cgm_vec3 cgm_vrotate_axis(cgm_vec3 v, int axis, float angle);
+static CGM_INLINE cgm_vec3 cgm_vrotate(cgm_vec3 v, float angle, float x, float y, float z);
+static CGM_INLINE cgm_vec3 cgm_vrotate_euler(cgm_vec3 v, float a, float b, float c, enum cgm_euler_mode mode);
+
+static CGM_INLINE cgm_vec3 cgm_vlerp(cgm_vec3 a, cgm_vec3 b, float t);
+static CGM_INLINE cgm_vec3 cgm_vblend(cgm_vec3 a, float fa, cgm_vec3 b, float fb);
+
+#define cgm_velem(v, idx) ((&(v).x)[idx])
+
+/* --- operations on matrices --- */
+static CGM_INLINE void cgm_mcopy(float *dest, const float *src);
+static CGM_INLINE void cgm_mzero(float *m);
+static CGM_INLINE void cgm_midentity(float *m);
+
+static CGM_INLINE void cgm_mmul(float *a, const float *b);
+static CGM_INLINE void cgm_mpremul(float *a, const float *b);
+
+static CGM_INLINE void cgm_msubmatrix(float *m, int row, int col);
+static CGM_INLINE void cgm_mupper3(float *m);
+static CGM_INLINE float cgm_msubdet(const float *m, int row, int col);
+static CGM_INLINE float cgm_mcofactor(const float *m, int row, int col);
+static CGM_INLINE float cgm_mdet(const float *m);
+static CGM_INLINE void cgm_mtranspose(float *m);
+static CGM_INLINE void cgm_mcofmatrix(float *m);
+static CGM_INLINE int cgm_minverse(float *m); /* returns 0 on success, -1 for singular */
+
+static CGM_INLINE void cgm_mtranslation(float *m, float x, float y, float z);
+static CGM_INLINE void cgm_mscaling(float *m, float sx, float sy, float sz);
+static CGM_INLINE void cgm_mrotation_x(float *m, float angle);
+static CGM_INLINE void cgm_mrotation_y(float *m, float angle);
+static CGM_INLINE void cgm_mrotation_z(float *m, float angle);
+static CGM_INLINE void cgm_mrotation_axis(float *m, int idx, float angle);
+static CGM_INLINE void cgm_mrotation(float *m, float angle, float x, float y, float z);
+static CGM_INLINE void cgm_mrotation_euler(float *m, float a, float b, float c, int mode);
+static CGM_INLINE void cgm_mrotation_quat(float *m, cgm_quat q);
+
+static CGM_INLINE void cgm_mtranslate(float *m, float x, float y, float z);
+static CGM_INLINE void cgm_mscale(float *m, float sx, float sy, float sz);
+static CGM_INLINE void cgm_mrotate_x(float *m, float angle);
+static CGM_INLINE void cgm_mrotate_y(float *m, float angle);
+static CGM_INLINE void cgm_mrotate_z(float *m, float angle);
+static CGM_INLINE void cgm_mrotate_axis(float *m, int idx, float angle);
+static CGM_INLINE void cgm_mrotate(float *m, float angle, float x, float y, float z);
+static CGM_INLINE void cgm_mrotate_euler(float *m, float a, float b, float c, int mode);
+static CGM_INLINE void cgm_mrotate_quat(float *m, cgm_quat q);
+
+static CGM_INLINE void cgm_mpretranslate(float *m, float x, float y, float z);
+static CGM_INLINE void cgm_mprescale(float *m, float sx, float sy, float sz);
+static CGM_INLINE void cgm_mprerotate_x(float *m, float angle);
+static CGM_INLINE void cgm_mprerotate_y(float *m, float angle);
+static CGM_INLINE void cgm_mprerotate_z(float *m, float angle);
+static CGM_INLINE void cgm_mprerotate_axis(float *m, int idx, float angle);
+static CGM_INLINE void cgm_mprerotate(float *m, float angle, float x, float y, float z);
+static CGM_INLINE void cgm_mprerotate_euler(float *m, float a, float b, float c, int mode);
+static CGM_INLINE void cgm_mprerotate_quat(float *m, cgm_quat q);
+
+static CGM_INLINE cgm_vec3 cgm_mget_translation(const float *m);
+static CGM_INLINE cgm_quat cgm_mget_rotation(const float *m);
+static CGM_INLINE cgm_vec3 cgm_mget_scaling(const float *m);
+static CGM_INLINE cgm_vec4 cgm_mget_frustum_plane(const float *m, int p);
+
+static CGM_INLINE cgm_vec4 cgm_normalize_plane(cgm_vec4 p);
+
+static CGM_INLINE void cgm_mlookat(float *m, cgm_vec3 pos, cgm_vec3 targ, cgm_vec3 up);
+static CGM_INLINE void cgm_minv_lookat(float *m, cgm_vec3 pos, cgm_vec3 targ, cgm_vec3 up);
+static CGM_INLINE void cgm_mortho(float *m, float left, float right, float bot, float top,
+ float znear, float zfar);
+static CGM_INLINE void cgm_mfrustum(float *m, float left, float right, float bot, float top,
+ float znear, float zfar);
+static CGM_INLINE void cgm_mperspective(float *m, float vfov, float aspect, float znear, float zfar);
+
+static CGM_INLINE void cgm_mmirror(float *m, float a, float b, float c, float d);
+
+/* --- miscellaneous utility functions --- */
+static CGM_INLINE float cgm_deg_to_rad(float deg);
+static CGM_INLINE float cgm_rad_to_deg(float rad);
+
+static CGM_INLINE float cgm_smoothstep(float a, float b, float x);
+static CGM_INLINE float cgm_lerp(float a, float b, float t);
+static CGM_INLINE float cgm_logerp(float a, float b, float t);
+static CGM_INLINE float cgm_bezier(float a, float b, float c, float d, float t);
+static CGM_INLINE float cgm_bspline(float a, float b, float c, float d, float t);
+static CGM_INLINE float cgm_spline(float a, float b, float c, float d, float t);
+
+static CGM_INLINE cgm_vec3 cgm_discrand(float rad);
+static CGM_INLINE cgm_vec3 cgm_sphrand(float rad);
+
+static CGM_INLINE cgm_vec3 cgm_unproject(cgm_vec3 norm_scrpos, const float *inv_viewproj);
+static CGM_INLINE void cgm_glu_unproject(float winx, float winy, float winz,
+ const float *view, const float *proj, const int *vp,
+ float *objx, float *objy, float *objz);
+
+static CGM_INLINE cgm_ray cgm_pick_ray(float nx, float ny, const float *viewmat,
+ const float *projmat);
+
+static CGM_INLINE cgm_vec3 cgm_raypos(cgm_ray ray, float t);
+
+/* calculate barycentric coordinates of point pt in triangle (a, b, c) */
+static CGM_INLINE cgm_vec3 cgm_bary(cgm_vec3 a, cgm_vec3 b, cgm_vec3 c, cgm_vec3 pt);
+
+/* convert between unit vectors and spherical coordinates */
+static CGM_INLINE cgm_vec3 cgm_uvec_to_sph(cgm_vec3 v);
+static CGM_INLINE cgm_vec3 cgm_sph_to_uvec(float theta, float phi);
+
+#include "cgmvec3.inl"
+/*#include "cgmvec4.inl"
+#include "cgmquat.inl"*/
+#include "cgmmat.inl"
+/*#include "cgmray.inl"*/
+#include "cgmmisc.inl"
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NEXUS3D_CGMATH2_H_ */