Skip to content

Instantly share code, notes, and snippets.

@progschj
Created February 26, 2015 16:32
Show Gist options
  • Save progschj/0aabdf3e02bbfc913b86 to your computer and use it in GitHub Desktop.
Save progschj/0aabdf3e02bbfc913b86 to your computer and use it in GitHub Desktop.
#ifndef MATH_UTIL_H
#define MATH_UTIL_H
#include <math.h>
#include <float.h>
static const float PI = 3.14159265358979323846f;
static inline float dot3(const float *a, const float *b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
static inline float dist3(const float *a, const float *b) {
float dx = a[0] - b[0];
float dy = a[1] - b[1];
float dz = a[2] - b[2];
return sqrtf(dx*dx + dy*dy + dz*dz);
}
static inline float dot4(const float *a, const float *b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
}
static inline float* cross(float *dst, const float *a, const float *b) {
dst[0] = a[1]*b[2] - a[2]*b[1];
dst[1] = a[2]*b[0] - a[0]*b[2];
dst[2] = a[0]*b[1] - a[1]*b[0];
return dst;
}
static inline float triple_product(const float *a, const float *b, const float *c) {
return (a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1])
- (a[0]*b[2]*c[1] + a[1]*b[0]*c[2] + a[2]*b[1]*c[0]);
}
// annoyingly fminf/fmaxf handle NaNs differently than sse and this
// ternary versions compile to single instructions
static inline float fast_minf(float a, float b) {
return a<b?a:b;
}
static inline float fast_maxf(float a, float b) {
return a>b?a:b;
}
static inline float clamp(float x, float low, float high) {
return fast_minf(high, fast_maxf(low, x));
}
float smoothstep(float x) {
x = clamp(x, 0.0f, 1.0f);
return (x*x)*(3.0f - 2.0f*x);
}
static inline void cpyTransform(float *A, const float *B) {
for(int i = 0;i<16;++i) {
A[i] = B[i];
}
}
static inline void transpose(float *A, const float *B) {
for(int i = 0;i<4;++i) {
for(int j = 0;j<4;++j) {
A[i+4*j] = B[j+4*i];
}
}
}
static inline void normalize(float *x, float *y, float *z) {
float il = 1.0/sqrt(*x * *x + *y * *y + *z * *z);
*x *= il; *y *= il; *z *= il;
}
static inline void mul3(float *A, float *B, float *C) {
for(int i = 0;i<4;++i) {
for(int j = 0;j<4;++j) {
float dot = 0;
for(int k = 0;k<4;++k) {
dot += B[i+4*k]*C[k+4*j];
}
A[i+4*j] = dot;
}
}
}
static inline void mul2(float *A, float *C) {
float tmp[16];
cpyTransform(tmp, A);
mul3(A,tmp,C);
}
static inline void transpose_mul3(float *A, float *B, float *C) {
for(int i = 0;i<4;++i) {
for(int j = 0;j<4;++j) {
float dot = 0;
for(int k = 0;k<4;++k) {
dot += B[i+4*k]*C[j+4*k];
}
A[i+4*j] = dot;
}
}
}
static inline void transpose_mul2(float *A, float *C) {
float tmp[16];
cpyTransform(tmp, A);
transpose_mul3(A,tmp,C);
}
static inline void setIdentity(float *A) {
A[ 0] = 1; A[ 4] = 0; A[ 8] = 0; A[12] = 0;
A[ 1] = 0; A[ 5] = 1; A[ 9] = 0; A[13] = 0;
A[ 2] = 0; A[ 6] = 0; A[10] = 1; A[14] = 0;
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 1;
}
static inline void setTranslate(float *A, float x, float y, float z) {
A[ 0] = 1; A[ 4] = 0; A[ 8] = 0; A[12] = x;
A[ 1] = 0; A[ 5] = 1; A[ 9] = 0; A[13] = y;
A[ 2] = 0; A[ 6] = 0; A[10] = 1; A[14] = z;
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 1;
}
static inline void mulTranslate(float *A, float x, float y, float z) {
float tmp[16];
setTranslate(tmp, x, y, z);
mul2(A, tmp);
}
static inline void setScale(float *A, float x, float y, float z) {
A[ 0] = x; A[ 4] = 0; A[ 8] = 0; A[12] = 0;
A[ 1] = 0; A[ 5] = y; A[ 9] = 0; A[13] = 0;
A[ 2] = 0; A[ 6] = 0; A[10] = z; A[14] = 0;
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 1;
}
static inline void mulScale(float *A, float x, float y, float z) {
float tmp[16];
setScale(tmp, x, y, z);
mul2(A, tmp);
}
static inline void setRotateFromVectors(float *A, const float *u, const float *v) {
float lu2 = u[0]*u[0] + u[1]*u[1] + u[2]*u[2];
float lv2 = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
if(lu2*lv2<1.e-10) {
setIdentity(A);
return;
}
float scaler = 1.0f/sqrtf(lu2*lv2);
float c = (u[0]*v[0] + u[1]*v[1] + u[2]*v[2])*scaler;
float x = (v[1]*u[2] - v[2]*u[1])*scaler;
float y = (v[2]*u[0] - v[0]*u[2])*scaler;
float z = (v[0]*u[1] - v[1]*u[0])*scaler;
float s2 = x*x + y*y + z*z;
if(s2<1.e-10) {
setIdentity(A);
return;
}
float cs2 = (1.0f-c)/s2;
A[ 0] = c+x*x*cs2; A[ 4] = x*y*cs2+z; A[ 8] = x*z*cs2-y; A[12] = 0;
A[ 1] = x*y*cs2-z; A[ 5] = c+y*y*cs2; A[ 9] = y*z*cs2+x; A[13] = 0;
A[ 2] = x*z*cs2+y; A[ 6] = y*z*cs2-x; A[10] = c+z*z*cs2; A[14] = 0;
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 1;
}
static inline void mulRotateFromVectors(float *A, const float *u, const float *v) {
float tmp[16];
setRotateFromVectors(tmp, u, v);
mul2(A, tmp);
}
static inline void setRotate(float *A, float x, float y, float z, float angle) {
float l = 1.0f/sqrtf(x*x + y*y + z*z);
x *= l; y *= l; z *= l;
float c = cosf(angle);
float s = sinf(angle);
A[ 0] = x*x*(1.0f-c)+c; A[ 4] = x*y*(1.0f-c)+z*s; A[ 8] = x*z*(1.0f-c)-y*s; A[12] = 0;
A[ 1] = x*y*(1.0f-c)-z*s; A[ 5] = y*y*(1.0f-c)+c; A[ 9] = y*z*(1.0f-c)+x*s; A[13] = 0;
A[ 2] = x*z*(1.0f-c)+y*s; A[ 6] = y*z*(1.0f-c)-x*s; A[10] = z*z*(1.0f-c)+c; A[14] = 0;
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 1;
}
static inline void mulRotate(float *A, float x, float y, float z, float angle) {
float tmp[16];
setRotate(tmp, x, y, z, angle);
mul2(A, tmp);
}
static inline void setFrustum(float *A, float left, float right, float top, float bottom, float near, float far) {
A[ 0] = 2.0f*near/(right-left); A[ 4] = 0; A[ 8] = (right+left)/(right-left); A[12] = 0;
A[ 1] = 0; A[ 5] = 2.0f*near/(top-bottom); A[ 9] = (top+bottom)/(top-bottom); A[13] = 0;
A[ 2] = 0; A[ 6] = 0; A[10] = (far+near)/(near-far); A[14] = 2*far*near/(near-far);
A[ 3] = 0; A[ 7] = 0; A[11] = -1; A[15] = 0;
}
static inline void setInverseFrustum(float *A, float left, float right, float top, float bottom, float near, float far) {
A[ 0] = (right-left)/(2.0f*near); A[ 4] = 0; A[8] = 0; A[12] = (right+left)/(2*near);
A[ 1] = 0; A[ 5] = (top-bottom)/(2.0f*near); A[9] = 0; A[13] = (top+bottom)/(2*near);
A[ 2] = 0; A[ 6] = 0; A[10] = 0; A[14] = -1;
A[ 3] = 0; A[ 7] = 0; A[11] = (near-far)/(2*near*far); A[15] = (near+far)/(2*near*far);
}
static inline void mulInverseFrustum(float *A, float left, float right, float top, float bottom, float near, float far) {
float tmp[16];
setInverseFrustum(tmp, left, right, top, bottom, near, far);
mul2(A, tmp);
}
static inline void setOrtho(float *A, float left, float right, float top, float bottom, float near, float far) {
A[ 0] = 2.0f/(right-left); A[ 4] = 0; A[ 8] = 0; A[12] = (left+right)/(left-right);
A[ 1] = 0; A[ 5] = 2.0f/(top-bottom); A[ 9] = 0; A[13] = (bottom+top)/(bottom-top);
A[ 2] = 0; A[ 6] = 0; A[10] = 2.0f/(near-far); A[14] = (near+far)/(near-far);
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 1;
}
static inline void transformVector(float *y, const float *A, const float *x) {
float tmp[4];
for(int i = 0;i<4;++i) {
tmp[i] = A[0+i]*x[0] + A[4+i]*x[1] + A[8+i]*x[2] + A[12+i]*x[3];
}
for(int i = 0;i<4;++i) {
y[i] = tmp[i];
}
}
static inline void transformVector3(float *y, const float *A, const float *x) {
float tmp[4];
for(int i = 0;i<4;++i) {
tmp[i] = A[0+i]*x[0] + A[4+i]*x[1] + A[8+i]*x[2] + A[12+i];
}
float w = 1.0f/tmp[3];
for(int i = 0;i<3;++i) {
y[i] = tmp[i]*w;
}
}
static inline void affineTransformVector3(float *y, const float *A, const float *x) {
float tmp[3];
for(int i = 0;i<3;++i) {
tmp[i] = A[0+i]*x[0] + A[4+i]*x[1] + A[8+i]*x[2] + A[12+i];
}
for(int i = 0;i<3;++i) {
y[i] = tmp[i];
}
}
static inline void transposeTransformVector3(float *y, const float *A, const float *x) {
float tmp[4];
for(int i = 0;i<4;++i) {
tmp[i] = A[4*i+0]*x[0] + A[4*i+1]*x[1] + A[4*i+2]*x[2] + A[4*i+3];
}
float w = 1.0f/tmp[3];
for(int i = 0;i<3;++i) {
y[i] = tmp[i]*w;
}
}
static inline void setRotateDerivative(float *A, float x, float y, float z, float angle) {
float l = 1.0f/sqrtf(x*x + y*y + z*z);
x *= l; y *= l; z *= l;
float c = -sinf(angle);
float s = cosf(angle);
A[ 0] = c+x*x*(-c); A[ 4] = x*y*(-c)+z*s; A[ 8] = x*z*(-c)-y*s; A[12] = 0;
A[ 1] = x*y*(-c)-z*s; A[ 5] = c+y*y*(-c); A[ 9] = y*z*(-c)+x*s; A[13] = 0;
A[ 2] = x*z*(-c)+y*s; A[ 6] = y*z*(-c)-x*s; A[10] = c+z*z*(-c); A[14] = 0;
A[ 3] = 0; A[ 7] = 0; A[11] = 0; A[15] = 0;
}
static inline void mulRotateDerivative(float *A, float x, float y, float z, float angle) {
float tmp[16];
setRotateDerivative(tmp, x, y, z, angle);
mul2(A, tmp);
}
#endif
#ifndef SHADER_BUILD_H
#define SHADER_BUILD_H
#include <gl_core_3_3.h>
#include <stdlib.h>
#include <stdio.h>
static int check_shader_compile_status(GLuint obj) {
GLint status;
glGetShaderiv(obj, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE) {
GLint length;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
char *log = (char*)malloc(length);
glGetShaderInfoLog(obj, length, &length, &log[0]);
fprintf(stderr, "%s", log);
free(log);
return 0;
}
return 1;
}
static int check_program_link_status(GLuint obj) {
GLint status;
glGetProgramiv(obj, GL_LINK_STATUS, &status);
if(status == GL_FALSE) {
GLint length;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
char *log = (char*)malloc(length);
glGetProgramInfoLog(obj, length, &length, &log[0]);
fprintf(stderr, "%s", log);
free(log);
return 0;
}
return 1;
}
typedef struct shader_source_t {
GLenum type;
const char *source;
} shader_source;
static GLuint shader_build(const shader_source *sources) {
GLuint shader_program = glCreateProgram();
for(;sources->source != NULL;++sources) {
GLuint shader = glCreateShader(sources->type);
glShaderSource(shader, 1, &sources->source, 0);
glCompileShader(shader);
if(!check_shader_compile_status(shader)) {
return 0;
}
glAttachShader(shader_program, shader);
glDeleteShader(shader);
}
glLinkProgram(shader_program);
if(!check_program_link_status(shader_program)) {
return 0;
}
return shader_program;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment