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 }