opengl

Sample code from LearnOpenGL.com
Log | Files | Refs

commit 3599601fe771c39a57c86a9b7cc94a828d192bf8
parent 9bb9a98cfb4d4c7dd589fefe255955fedeeeede8
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Thu, 29 Jun 2023 09:33:33 +0900

add lookat

Diffstat:
Mglm.c | 96++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mglm.h | 13+++++++++++--
Mmain.c | 37++++++++++++++++++++++++-------------
3 files changed, 116 insertions(+), 30 deletions(-)

diff --git a/glm.c b/glm.c @@ -35,6 +35,12 @@ vecMake(float *data, int size) return v; } +vec * +vecCopy(const vec *v) +{ + return vecMake(v->data, v->size); +} + void vecFree(vec *v) { @@ -63,24 +69,30 @@ vecEq(vec *v, vec *w) vec * vecAdd(vec *v, const vec *w) { - if (v->size != w->size) { + if (v->size != w->size) assert(!"vector sizes don't match"); - } - for (int i = 0; i < v->size; i++) { + for (int i = 0; i < v->size; i++) v->data[i] += w->data[i]; - } return v; } vec * vecSub(vec *v, const vec *w) { - if (v->size != w->size) { + if (v->size != w->size) assert(!"vector sizes don't match"); - } - for (int i = 0; i < v->size; i++) { + for (int i = 0; i < v->size; i++) v->data[i] -= w->data[i]; - } + return v; +} + +vec * +vecSubRev(vec *v, const vec *w) +{ + if (v->size != w->size) + assert(!"vector sizes don't match"); + for (int i = 0; i < v->size; i++) + v->data[i] = w->data[i] - v->data[i]; return v; } @@ -112,6 +124,20 @@ vecCross(vec *v, const vec *w) return v; } + +// TODO: deal with zero division properly +vec * +vecNormalize(vec *v) +{ + float sqnorm = 0; + for (int i = 0; i < v->size; i++) + sqnorm += v->data[i] * v->data[i]; + float norm = sqrtf(sqnorm); + for (int i = 0; i < v->size; i++) + v->data[i] /= norm; + return v; +} + char * matStr(char *s, mat *m) { @@ -191,7 +217,40 @@ matMakeOrth(float minx, float maxx, float miny, float maxy, float near, return m; } +mat * +matMakeLookAt(const vec *pos, const vec *target, const vec *up) +{ + vec *dir = vecCopy(pos); + vecNormalize(vecSub(dir, target)); + vec *right = vecCopy(up); + vecNormalize(vecCross(right, dir)); + vec *camUp = vecCopy(dir); + vecCross(camUp, right); + vec *minusPos = vecMake((float[]){ + -pos->data[0], -pos->data[1], -pos->data[2]},3); + + float data[] = { + right->data[0], camUp->data[0], dir->data[0], 0, + right->data[1], camUp->data[1], dir->data[1], 0, + right->data[2], camUp->data[2], dir->data[2], 0, + 0, 0, 0, 1, + }; + mat *lookat = matMake(data, 4); + translate(lookat, minusPos); + + vecFree(dir); + vecFree(right); + vecFree(camUp); + vecFree(minusPos); + return lookat; +} +mat * +matCopy(const mat *m) +{ + mat *n = matMake(m->data, m->size); + return n; +} void matFree(mat *m) @@ -207,13 +266,6 @@ matCount(void) return numMat; } -mat * -matCopy(const mat *m) -{ - mat *n = matMake(m->data, m->size); - return n; -} - float *matDataPtr(mat *m) { @@ -287,3 +339,17 @@ scale(mat *m, float s) matFree(scl); return m; } + +vec * +matVecDot(const mat *m, vec *v) +{ + if (m->size != v->size) + assert(!"matrix and vector sizes don't match"); + float *result = (float *)calloc(v->size, sizeof(float)); + for (int i = 0; i < v->size; i++) + for (int j = 0; j < v->size; j++) + result[i] += m->data[i + v->size*j] * v->data[j]; + free(v->data); + v->data = result; + return v; +} diff --git a/glm.h b/glm.h @@ -12,8 +12,11 @@ typedef struct mat { // VecStr() set s the string representation of v and returns the same char*. char *vecStr(char *s, vec *v); // VecMake() allocates a vec and copy the data to its data. -// Caller is responsible to free the vec by calling vecFree(). +// Caller is responsible for freeing the vec by calling vecFree(). vec *vecMake(float *data, int size); +// VecCopy() returns the copy of v. Caller is responsible for freeing +// the resulting vec. +vec *vecCopy(const vec *v); // VecFree() frees v. void vecFree(vec* v); // VecCount() returns the number of vecs allocated and not yes freed. @@ -24,8 +27,11 @@ int vecEq(vec *v, vec *w); // an error occurs. vec *vecAdd(vec *v, const vec *w); vec *vecSub(vec *v, const vec *w); +// VecSubRev calcurates w - v and stores the result to v and returns v. +vec *vecSubRev(vec *v, const vec *w); float vecDot(const vec *v, const vec *w); vec *vecCross(vec *v, const vec *w); +vec *vecNormalize(vec *v); char *matStr(char *s, mat *m); mat *matMake(float *data, int size); @@ -33,14 +39,16 @@ mat *matMakeIdent(int size); mat *matMakePers(float fov, float aspect, float near, float far); mat *matMakeOrth(float minx, float maxx, float miny, float maxy, float near, float far); +mat *matMakeLookAt(const vec *pos, const vec *target, const vec *up); +mat *matCopy(const mat *m); void matFree(mat *m); mat *matDot(mat *m, const mat *n); int matCount(void); -mat *matCopy(const mat *m); float *matDataPtr(mat *m); mat *translate(mat *m, const vec *v); // axis must be an unit vector mat *rotate(mat *m, float rad, vec *axis); mat *scale(mat *m, float s); +vec *matVecDot(const mat *m, vec *v); +\ No newline at end of file diff --git a/main.c b/main.c @@ -99,20 +99,22 @@ main(void) int numCube = 3; vec *cubePositions[numCube]; - cubePositions[0] = vecMake((float []){-2.0, 0.0, -10.0}, 3); - cubePositions[1] = vecMake((float []){0.0, 3.0, -12.0}, 3); - cubePositions[2] = vecMake((float []){1.0, 1.0, -11.0}, 3); + cubePositions[0] = vecMake((float []){-2.0, 0.0, -2.0}, 3); + cubePositions[1] = vecMake((float []){0.0, 0.0, 0.0}, 3); + cubePositions[2] = vecMake((float []){1.0, 1.0, -1.0}, 3); mat *modelMat[numCube]; for (int i = 0; i < numCube; i++) { modelMat[i] = scale(matMakeIdent(4), 0.1); translate(modelMat[i], cubePositions[i]); } - mat *viewMat = matMakeIdent(4); mat *projMat = matMakePers((float)M_PI/4, (float)width/(float)height, 0.1, 100.0); - + vec *cameraPos = vecMake((float[]){4.0, 1.0, 4.0}, 3); + vec *cameraTarget = vecMake((float[]){0.0, 0.0, 0.0}, 3); + vec *cameraUp = vecMake((float[]){0.0, 1.0, 0.0}, 3); + mat *viewMat = matMakeLookAt(cameraPos, cameraTarget, cameraUp); vec *axis0 = vecMake((float[]){1.41421356/2, 1.41421356/2, 0.0}, 3); - vec *axis1 = vecMake((float[]){0.0, 0.0, 1.0}, 3); + vec *axis1 = vecMake((float[]){0.0, 1.0, 0.0}, 3); // initialize glfw glfwInit(); @@ -195,6 +197,7 @@ main(void) float lastTime = (float) glfwGetTime(); float rotation = 0; + while (!glfwWindowShouldClose(window)) { processInput(window); @@ -206,25 +209,33 @@ main(void) glUniform1i(glGetUniformLocation(shader->ID, "texture1"), 1); unsigned int tloc = glGetUniformLocation(shader->ID, "transform"); float now = (float) glfwGetTime(); + if (rotating) { + rotation += now-lastTime; + } + mat *view = matCopy(viewMat); + rotate(view, rotation, axis1); for (int i = 0; i < numCube; i++) { mat *transform = matCopy(modelMat[i]); - if (rotating) { - rotation += now-lastTime; - } rotate(transform, rotation, axis0); - ShaderSetMat4(shader, "model", matDataPtr(transform)); - ShaderSetMat4(shader, "view", matDataPtr(viewMat)); + ShaderSetMat4(shader, "view", matDataPtr(view)); ShaderSetMat4(shader, "proj", matDataPtr(projMat)); glDrawArrays(GL_TRIANGLES, 0, 36); matFree(transform); } + matFree(view); + lastTime = now; glfwPollEvents(); glfwSwapBuffers(window); } - + + + vecFree(cameraPos); + vecFree(cameraTarget); + vecFree(cameraUp); + vecFree(axis0); vecFree(axis1); for (int i = 0; i < sizeof(cubePositions)/sizeof(cubePositions[0]); i++) { @@ -244,7 +255,7 @@ main(void) assert(0); } if (vecCount() != 0) { - fprintf(stderr, "%d mats not freed\n", vecCount()); + fprintf(stderr, "%d vecs not freed\n", vecCount()); assert(0); } return 0;