commit 3599601fe771c39a57c86a9b7cc94a828d192bf8
parent 9bb9a98cfb4d4c7dd589fefe255955fedeeeede8
Author: Matsuda Kenji <info@mtkn.jp>
Date: Thu, 29 Jun 2023 09:33:33 +0900
add lookat
Diffstat:
M | glm.c | | | 96 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
M | glm.h | | | 13 | +++++++++++-- |
M | main.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;