opengl

Sample code from LearnOpenGL.com
Log | Files | Refs

glm.c (6816B)


      1 #include <assert.h>
      2 #include <math.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 
      6 #include "glm.h"
      7 #include "err.h"
      8 
      9 static int numVec = 0; // number of vecs which are allocated and not freed.
     10 static int numMat = 0; // number of mats which are allocated and not freed.
     11 
     12 char *
     13 vecStr(char *s, vec *v)
     14 {
     15 	int cur = 0;
     16 	cur += sprintf(s, "[");
     17 	for (int i = 0; i < v->size; i++) {
     18 		cur += sprintf(&s[cur], "%f%s", v->data[i],
     19 			i == v->size-1 ? "]" : ", ");
     20 	}
     21 	s[cur] = '\0';
     22 	return s;
     23 }
     24 
     25 vec *
     26 vecMake(float *data, int size)
     27 {
     28 	vec *v = (vec *)malloc(sizeof(vec));
     29 	v->data = (float *)malloc(sizeof(float)*size);
     30 	for (int i = 0; i < size; i++) {
     31 		v->data[i] = data[i];
     32 	}
     33 	v->size = size;
     34 	numVec++;
     35 	return v;
     36 }
     37 
     38 vec *
     39 vecCopy(const vec *v)
     40 {
     41 	return vecMake(v->data, v->size);
     42 }
     43 
     44 void
     45 vecFree(vec *v)
     46 {
     47 	free(v->data);
     48 	free(v);
     49 	numVec--;
     50 }
     51 
     52 int
     53 vecCount(void)
     54 {
     55 	return numVec;
     56 }
     57 
     58 int
     59 vecEq(vec *v, vec *w)
     60 {
     61 	if (v->size != w->size)
     62 		return 0;
     63 	for (int i = 0; i < v->size; i++)
     64 		if (v->data[i] != w->data[i])
     65 			return 0;
     66 	return 1;
     67 }
     68 
     69 vec *
     70 vecAdd(vec *v, const vec *w)
     71 {
     72 	if (v->size != w->size)
     73 		assert(!"vector sizes don't match");
     74 	for (int i = 0; i < v->size; i++)
     75 		v->data[i] += w->data[i];
     76 	return v;
     77 }
     78 
     79 vec *
     80 vecSub(vec *v, const vec *w)
     81 {
     82 	if (v->size != w->size)
     83 		assert(!"vector sizes don't match");
     84 	for (int i = 0; i < v->size; i++)
     85 		v->data[i] -= w->data[i];
     86 	return v;
     87 }
     88 
     89 vec *
     90 vecSubRev(vec *v, const vec *w)
     91 {
     92 	if (v->size != w->size)
     93 		assert(!"vector sizes don't match");
     94 	for (int i = 0; i < v->size; i++)
     95 		v->data[i] = w->data[i] - v->data[i];
     96 	return v;
     97 }
     98 
     99 float
    100 vecDot(const vec *v, const vec *w)
    101 {
    102 	if (v->size != w->size) {
    103 		assert(!"vector sizes don't match");
    104 	}
    105 	float ret = 0;
    106 	for (int i = 0; i < v->size; i++) {
    107 		ret += v->data[i] * w->data[i];
    108 	}
    109 	return ret;
    110 }
    111 
    112 vec *
    113 vecCross(vec *v, const vec *w)
    114 {
    115 	if (v->size != 3 || w->size != 3) {
    116 		assert(!"vector sizes must be 3");
    117 	}
    118 	float p[3];
    119 	p[0] = v->data[1]*w->data[2] - v->data[2]*w->data[1];
    120 	p[1] = v->data[2]*w->data[0] - v->data[0]*w->data[2];
    121 	p[2] = v->data[0]*w->data[1] - v->data[1]*w->data[0];
    122 	for (int i = 0; i < 3; i++)
    123 		v->data[i] = p[i];
    124 	return v;
    125 }
    126 
    127 
    128 // TODO: deal with zero division properly
    129 vec *
    130 vecNormalize(vec *v)
    131 {
    132 	float sqnorm = 0;
    133 	for (int i = 0; i < v->size; i++)
    134 		sqnorm += v->data[i] * v->data[i];
    135 	float norm = sqrtf(sqnorm);
    136 	for (int i = 0; i < v->size; i++)
    137 		v->data[i] /= norm;
    138 	return v;
    139 }
    140 
    141 char *
    142 matStr(char *s, mat *m)
    143 {
    144 	int cur = 0;
    145 	for (int i = 0; i < m->size; i++) {
    146 		for (int j = 0; j < m->size; j++) {
    147 			cur += sprintf(&s[cur], "%2.2f%s", m->data[i+m->size*j],
    148 				j == m->size-1 ? "" : " ");
    149 		}
    150 		if (i != m->size - 1) {
    151 			cur += sprintf(&s[cur], "\n");
    152 		}
    153 	}
    154 	sprintf(&s[cur], "\n%c", '\0');
    155 	return s;
    156 }
    157 
    158 mat *
    159 matMake(float *data, int size)
    160 {
    161 	mat *m = (mat *)malloc(sizeof(mat));
    162 	m->data = (float *)malloc(sizeof(float)*size*size);
    163 	for (int i = 0; i < size*size; i++) {
    164 		m->data[i] = data[i];
    165 	}
    166 	m->size = size;
    167 	numMat++;
    168 	return m;
    169 }
    170 
    171 mat *
    172 matMakeIdent(int size)
    173 {
    174 	mat *m = (mat *)malloc(sizeof(mat));
    175 	m->data = (float *)calloc(sizeof(float), size*size);
    176 	for (int i = 0; i < size; i++) {
    177 		m->data[i + size*i] = 1;
    178 	}
    179 	m->size = size;
    180 	numMat++;
    181 	return m;
    182 }
    183 
    184 mat *
    185 matMakePers(float fov, float aspect, float near, float far)
    186 {
    187 	mat *m = (mat *)malloc(sizeof(mat));
    188 	m->data = (float *)calloc(sizeof(float), 16);
    189 	m->data[0] = 1 / (aspect * tanf(fov/2));
    190 	m->data[5] = 1 / tanf(fov/2);
    191 	m->data[10] = -(far + near) / (far - near);
    192 	m->data[11] = -1;
    193 	m->data[14] = -(2 * far * near) / (far - near);
    194 	
    195 	m->size = 4;
    196 	numMat++;
    197 	return m;
    198 }
    199 
    200 mat *
    201 matMakeOrth(float minx, float maxx, float miny, float maxy, float near,
    202 	float far)
    203 {
    204 	mat *m = (mat *)malloc(sizeof(mat));
    205 	m->data = (float *)calloc(sizeof(float), 16);
    206 	
    207 	m->data[0] = 2 / (maxx - minx);
    208 	m->data[12] = -(maxx + minx) / (maxx - minx);
    209 	m->data[5] = 2 / (maxy - miny);
    210 	m->data[13] = -(maxy + miny) / (maxy - miny);
    211 	m->data[10] = -2 / (far - near);
    212 	m->data[14] = -(far + near) / (far - near);
    213 	m->data[15] = 1;
    214 	
    215 	m->size = 4;
    216 	numMat++;
    217 	return m;	
    218 }
    219 
    220 mat *
    221 matMakeLookAt(const vec *pos, const vec *target, const vec *up)
    222 {
    223 	vec *dir = vecCopy(pos);
    224 	vecNormalize(vecSub(dir, target));
    225 	vec *right = vecCopy(up);
    226 	vecNormalize(vecCross(right, dir));
    227 	vec *camUp = vecCopy(dir);
    228 	vecCross(camUp, right);
    229 	vec *minusPos = vecMake((float[]){
    230 		-pos->data[0], -pos->data[1], -pos->data[2]},3);
    231 	
    232 	float data[] = {
    233 		right->data[0], camUp->data[0], dir->data[0], 0,
    234 		right->data[1], camUp->data[1], dir->data[1], 0,
    235 		right->data[2], camUp->data[2], dir->data[2], 0,
    236 		0, 0, 0, 1,
    237 	};
    238 	mat *lookat = matMake(data, 4);
    239 	translate(lookat, minusPos);
    240 	
    241 	vecFree(dir);
    242 	vecFree(right);
    243 	vecFree(camUp);
    244 	vecFree(minusPos);
    245 	return lookat;
    246 }
    247 
    248 mat *
    249 matCopy(const mat *m)
    250 {
    251 	mat *n = matMake(m->data, m->size);
    252 	return n;
    253 }
    254 
    255 void
    256 matFree(mat *m)
    257 {
    258 	free(m->data);
    259 	free(m);
    260 	numMat--;
    261 }
    262 
    263 int
    264 matCount(void)
    265 {
    266 	return numMat;
    267 }
    268 
    269 float
    270 *matDataPtr(mat *m)
    271 {
    272 	return m->data;
    273 }
    274 
    275 mat *
    276 matDot(mat *m, const mat *n) // m_ij = m->data[i + m->size*j]
    277 {
    278 	if (m->size != n->size)
    279 		assert(!"mat sizes don't match");
    280 	float *data = (float *)malloc(sizeof(float)*m->size*m->size);
    281 	for (int i = 0; i < m->size; i++) {
    282 		for (int j = 0; j < m->size; j++) {
    283 			data[i+m->size*j] = 0;
    284 			for (int k = 0; k < m->size; k++) {
    285 				data[i+m->size*j] += m->data[i+m->size*k] *
    286 					n->data[k+m->size*j];
    287 			}
    288 		}
    289 	}
    290 	free(m->data);
    291 	m->data = data;	
    292 	return m;
    293 }
    294 
    295 
    296 mat *
    297 translate(mat *m, const vec *v)
    298 {
    299 	if (m->size != 4 || v->size != 3)
    300 		assert(!"mat size must be 4 and vec size must be 3");
    301 	mat *t = matMakeIdent(4);
    302 	t->data[12] = v->data[0];
    303 	t->data[13] = v->data[1];
    304 	t->data[14] = v->data[2];
    305 	matDot(m, t);
    306 	matFree(t);
    307 	return m;
    308 }
    309 
    310 mat *
    311 rotate(mat *m, float rad, vec *axis)
    312 {
    313 	if (axis->size != 3)
    314 		assert(!"axis size must be 3");
    315 	float x = axis->data[0];
    316 	float y = axis->data[1];
    317 	float z = axis->data[2];
    318 	float c = cosf(rad);
    319 	float s = sinf(rad);
    320 	mat *rot = matMake((float[]){ // column major...
    321 		c+x*x*(1-c),   y*x*(1-c)+z*s, z*x*(1-c)-y*s, 0, 
    322 		x*y*(1-c)-z*s, c+y*y*(1-c),   z*y*(1-c)+x*s, 0, 
    323 		x*z*(1-c)+y*s, y*z*(1-c)-x*s, c+z*z*(1-c),   0, 
    324 		0,             0,             0,             1, 
    325 		}, 4);
    326 	matDot(m, rot);
    327 	matFree(rot);
    328 	return m;
    329 }
    330 
    331 mat *
    332 scale(mat *m, float s)
    333 {
    334 	mat *scl = matMakeIdent(m->size);
    335 	for (int i = 0; i < m->size; i++) {
    336 		scl->data[i + m->size*i] = s;
    337 	}
    338 	matDot(m, scl);
    339 	matFree(scl);
    340 	return m;
    341 }
    342 
    343 vec *
    344 matVecDot(const mat *m, vec *v)
    345 {
    346 	if (m->size != v->size)
    347 		assert(!"matrix and vector sizes don't match");
    348 	float *result = (float *)calloc(v->size, sizeof(float));
    349 	for (int i = 0; i < v->size; i++)
    350 		for (int j = 0; j < v->size; j++)
    351 			result[i] += m->data[i + v->size*j] * v->data[j];
    352 	free(v->data);
    353 	v->data = result;
    354 	return v;
    355 }