commit 7ceffcce1cee3906f774dab6ba64d82a68822b55
parent d4a6203a98bf458167b3b37454f0cd0dc7b6db29
Author: William Casarin <jb55@jb55.com>
Date: Tue, 1 May 2018 11:55:48 -0700
quats working. finally fixed camera node issues
Diffstat:
12 files changed, 129 insertions(+), 98 deletions(-)
diff --git a/src/camera.c b/src/camera.c
@@ -10,9 +10,9 @@ struct camera *camera_init(struct camera *cam) {
void
camera_follow(vec3 *cam_pos, vec3 *target, mat4 *cam) {
- cam_pos[0] = target[0] - 10;
- cam_pos[1] = target[1] - 20;
- cam_pos[2] = target[2] + 15;
+ /* cam_pos[0] = target[0] - 10; */
+ /* cam_pos[1] = target[1] - 20; */
+ /* cam_pos[2] = target[2] + 15; */
/* printf("cam %f %f %f looking at player %f %f %f\n", */
/* cam_pos[0], cam_pos[1], cam_pos[2], */
/* target[0], target[1], target[2]); */
diff --git a/src/game.c b/src/game.c
@@ -9,12 +9,19 @@ mat4 *cam_init = (float[16]){
-71.766136, -47.881512, -44.216671, 1.000000
};
+static void camera_update(struct node *node) {
+ mat4 *persp = (float*)node->custom_update_data;
+ mat4 *mat = (float*)node->mat;
+
+ mat4_inverse(mat, mat);
+ mat4_multiply(persp, mat, mat);
+}
+
void game_init(struct game *game) {
mat4 *mvp = game->test_resources.test_mvp;
struct node *root = &game->test_resources.root;
struct node *camera = &game->test_resources.camera;
struct node *player = &game->test_resources.player;
- struct node *player_camera = &game->test_resources.player_camera;
struct node *terrain_node = &game->test_resources.terrain_node;
mat4 *light_dir = game->test_resources.light_dir;
@@ -27,30 +34,30 @@ void game_init(struct game *game) {
node_init(root);
node_init(player);
node_init(camera);
- node_init(player_camera);
node_init(terrain_node);
root->label = "root";
player->label = "player";
camera->label = "camera";
- player_camera->label = "player_camera";
terrain_node->label = "terrain_node";
node_attach(player, root);
- node_attach(player_camera, player);
- node_attach(camera, root);
+ node_attach(camera, player);
+
+ quat_axis_angle(V3(1,0,0), -45, camera->orientation);
+
+ /* camera->custom_update = camera_update; */
+ /* camera->custom_update_data = (void*)game->test_resources.camera_persp; */
/* vec3_all(camera->scale, -1); */
- camera->mirrored = 1;
+ /* camera->mirrored = 1; */
- node_translate(player, V3(10,10,0));
- node_translate(camera, V3(0,0,20));
- node_translate(player_camera, V3(10,10,20));
+ node_translate(player, V3(20,20,0));
+ node_translate(camera, V3(0,-30,20));
/* node_recalc(camera); */
/* player_camera->mirrored = 1; */
/* camera->parent = player_camera; */
- quat_axis_angle(V3(1,0,0), 45, camera->orientation);
// move the camera a bit
/* mat4_translate(camera, 1.0f, 1.0f, 20.0f, camera); */
diff --git a/src/game.h b/src/game.h
@@ -32,7 +32,6 @@ struct resources {
struct node root;
struct node player;
- struct node player_camera;
struct node camera;
struct node terrain_node;
diff --git a/src/main.c b/src/main.c
@@ -45,7 +45,7 @@ int main(void)
game_init(&game);
game.terrain = &terrain;
- const double size = 2000;
+ const double size = 1000;
const double pdist = 1.7;
const double scale = 0.01;
/* printf("samples seed %d\n", seed); */
diff --git a/src/mat_util.c b/src/mat_util.c
@@ -27,3 +27,4 @@ mat4 *mat4_create_transform(float *pos, float *scale, quat *orientation, mat4 *d
return dest;
}
+
diff --git a/src/mat_util.h b/src/mat_util.h
@@ -8,5 +8,6 @@
void look_at(vec3 *eye, vec3 *target, vec3 *up, mat4 *dest);
mat4 *mat4_create_transform(float *pos, float *scale, quat *orientation, mat4 *dest);
+vec3 *vec3_forward(vec3 *p, quat orientation, vec3 *dest);
#endif /* POLYADVENT_MAT_UTIL_H */
diff --git a/src/node.c b/src/node.c
@@ -10,13 +10,14 @@ struct node *node_init(struct node *node) {
vec3_all(node->pos, 0);
vec3_all(node->rot, 0);
vec3_all(node->scale, 1.0);
+ quat_id(node->orientation);
node->n_children = 0;
for (int i = 0; i < MAX_NODE_CHILDREN; ++i)
node->children[i] = NULL;
node->parent = NULL;
- node->mirrored = 0;
node->label = "unknown";
node->needs_recalc = 0;
+ node->custom_update = 0;
node_mark_for_recalc(node);
return node;
@@ -31,12 +32,19 @@ void node_translate(struct node *node, vec3 *p) {
node_mark_for_recalc(node);
}
-void node_rotate(struct node *node, vec3 *p) {
- if (vec3_isall(p, 0))
+void node_rotate(struct node *node, vec3 *axis_angles) {
+ if (vec3_isall(axis_angles, 0))
return;
+ for (int i = 0; i < 3; ++i) {
+ float axis[3] = {0};
+ float quat[4];
+ axis[i] = 1;
+ quat_axis_angle(axis, axis_angles[i], quat);
+ quat_multiply(node->orientation, quat, node->orientation);
+ }
+
/* printf("translating %f %f %f\n", p[0], p[1], p[2]); */
- vec3_add(node->rot, p, node->rot);
node_mark_for_recalc(node);
}
@@ -44,6 +52,11 @@ int node_needs_recalc(struct node *node) {
return (node->parent && node->parent->needs_recalc) || node->needs_recalc;
}
+vec3 *node_world(struct node *node) {
+ assert(!node_needs_recalc(node));
+ return &node->mat[M_X];
+}
+
void node_mark_for_recalc(struct node *node) {
static int j = 0;
@@ -52,10 +65,8 @@ void node_mark_for_recalc(struct node *node) {
node->needs_recalc = 1;
- for (int i = 0; i < node->n_children; ++i) {
- printf("%d %s marking child %s for recalc\n", j++, node->label, node->children[i]->label);
+ for (int i = 0; i < node->n_children; ++i)
node_mark_for_recalc(node->children[i]);
- }
}
static void node_recalc_children(struct node *node) {
@@ -65,60 +76,28 @@ static void node_recalc_children(struct node *node) {
}
int node_recalc(struct node *node) {
- float rotate_axis[3];
- float tmp[16];
-
assert(node);
+ if (node->parent && node_needs_recalc(node->parent))
+ node_recalc(node->parent);
+
if (!node_needs_recalc(node)) {
- // XXX: do I need this?
- goto recalc_children;
+ node_recalc_children(node);
+ return 0;
}
- printf("recalculating %s\n", node->label);
-
node->needs_recalc = 0;
- if (node->mirrored) {
- mat4_create_transform(V3(-node->pos[0], -node->pos[1], -node->pos[2]),
- node->scale, node->orientation, node->mat);
- }
- else
- mat4_create_transform(node->pos, node->scale, node->orientation, node->mat);
-
- /* float m = node->mirrored ? -1 : 1; */
-
- /* // FIXME: this seems bad? */
- /* for (int i = 0; i < 3; ++i) { */
- /* if (node->rot[i] != 0) { */
- /* rotate_axis[0] = 0; */
- /* rotate_axis[1] = 0; */
- /* rotate_axis[2] = 0; */
- /* rotate_axis[i] = 1; */
- /* float x = node->pos[0]; */
- /* float y = node->pos[1]; */
- /* float z = node->pos[2]; */
- /* if (!node->mirrored) */
- /* mat4_translate(node->mat, V3(x, y, z), node->mat); */
- /* mat4_rotate(node->mat, node->rot[i]*m, rotate_axis, node->mat); */
- /* if (!node->mirrored) */
- /* mat4_translate(node->mat, V3(-x, -y, -z), node->mat); */
- /* } */
- /* } */
-
- /* if (node->pos[0] || node->pos[1] || node->pos[2]) */
- /* mat4_translate(node->mat, V3(node->pos[0]*m,node->pos[1]*m,node->pos[2]*m), */
- /* node->mat); */
-
- /* if (node->pos[0] || node->pos[1] || node->pos[2]) */
- /* mat4_translate(node->mat, node->pos, node->mat); */
+ mat4_create_transform(node->pos, node->scale, node->orientation, node->mat);
if (node->parent) {
assert(!node->parent->needs_recalc);
- mat4_multiply(node->mat, node->parent->mat, node->mat);
+ mat4_multiply(node->parent->mat, node->mat, node->mat);
}
-recalc_children:
+ if (node->custom_update)
+ node->custom_update(node);
+
node_recalc_children(node);
return 1;
@@ -131,3 +110,17 @@ void node_attach(struct node *node, struct node *to) {
node->parent = to;
to->children[to->n_children++] = node;
}
+
+void node_forward(struct node *node, float *dir) {
+ float movement[3] = {0};
+ float q[4] = {0};
+ quat_inverse(node->orientation, q);
+ quat_multiply_vec3(q, dir, movement);
+ vec3_add(node->pos, movement, node->pos);
+ printf("dir %f %f %f\nmovement %f %f %f\nquat %f %f %f %f\n",
+ dir[0], dir[1], dir[2],
+ movement[0], movement[1], movement[2],
+ node->orientation[0], node->orientation[1],
+ node->orientation[2], node->orientation[3]);
+ node_mark_for_recalc(node);
+}
diff --git a/src/node.h b/src/node.h
@@ -9,15 +9,14 @@ struct node {
float rot[3];
float scale[3];
float mat[16];
- float local[16];
float orientation[4];
char *label;
int needs_recalc;
int n_children;
- int mirrored; // TODO: make camera type
+ void (*custom_update)(struct node*);
+ void *custom_update_data;
struct node* parent;
struct node* children[MAX_NODE_CHILDREN];
- // TODO quaternion rot/orientation
};
int node_recalc(struct node *root);
@@ -25,6 +24,8 @@ void node_attach(struct node *node, struct node *to);
void node_mark_for_recalc(struct node *node);
struct node *node_init(struct node *node);
void node_translate(struct node *node, float *p);
+void node_forward(struct node *node, float *p);
void node_rotate(struct node *node, float *p);
+float *node_world(struct node *node);
#endif /* POLYADVENT_NODE_H */
diff --git a/src/quat.c b/src/quat.c
@@ -56,15 +56,45 @@ void quat_to_mat3(quat *quat, float *dest) {
float wy = w*y2;
float wz = w*z2;
- dest[0] = 1 - (yy + zz);
+ dest[0] = 1.0 - (yy + zz);
dest[1] = xy - wz;
dest[2] = xz + wy;
dest[3] = xy + wz;
- dest[4] = 1 - (xx + zz);
+ dest[4] = 1.0 - (xx + zz);
dest[5] = yz - wx;
dest[6] = xz - wy;
dest[7] = yz + wx;
- dest[8] = 1 - (xx + yy);
+ dest[8] = 1.0 - (xx + yy);
+}
+
+void quat_multiply_vec3(quat *quat, float *vec, float *dest) {
+ float x = vec[0], y = vec[1], z = vec[2];
+ float qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3];
+
+ // calculate quat * vec
+ float ix = qw*x + qy*z - qz*y;
+ float iy = qw*y + qz*x - qx*z;
+ float iz = qw*z + qx*y - qy*x;
+ float iw = -qx*x - qy*y - qz*z;
+
+ // calculate result * inverse quat
+ dest[0] = ix*qw + iw*-qx + iy*-qz - iz*-qy;
+ dest[1] = iy*qw + iw*-qy + iz*-qx - ix*-qz;
+ dest[2] = iz*qw + iw*-qz + ix*-qy - iy*-qx;
+}
+
+quat *quat_inverse(quat *q, quat *dest) {
+ if(!dest || q == dest) {
+ q[0] *= 1;
+ q[1] *= 1;
+ q[2] *= 1;
+ return q;
+ }
+ dest[0] = -q[0];
+ dest[1] = -q[1];
+ dest[2] = -q[2];
+ dest[3] = q[3];
+ return dest;
}
diff --git a/src/quat.h b/src/quat.h
@@ -4,10 +4,13 @@
#define POLYADVENT_QUAT4_
typedef float quat;
+#define QUAT(x,y,z,w) ((quat[4]){x,y,z,w})
void quat_id(quat *dest);
void quat_multiply(quat *a, quat *b, quat *dest);
void quat_axis_angle(float *axis, float angle, quat *dest);
void quat_to_mat3(quat *quat, float *dest);
+void quat_multiply_vec3(quat *quat, float *vec, float *dest);
+quat *quat_inverse(quat *q, quat *dest);
#endif /* POLYADVENT_QUAT4_ */
diff --git a/src/render.c b/src/render.c
@@ -211,7 +211,6 @@ void render (struct game *game, struct geometry *geom) {
struct node *player = &res->player;
struct node *camera = &res->camera;
- struct node *player_camera = &res->player_camera;
float fade_factor = res->fade_factor;
@@ -223,7 +222,9 @@ void render (struct game *game, struct geometry *geom) {
/* printf("camera_pos %f %f %f", camera_pos[0], camera_pos[1], camera_pos[2]); */
/* mat4_print(camera->mat); */
/* node_recalc(&res->camera); */
- mat4_multiply(persp, camera->mat, mvp);
+ /* mat4_multiply(persp, camera->mat, mvp); */
+ mat4_inverse(camera->mat, tmp_matrix);
+ mat4_multiply(persp, tmp_matrix, mvp);
/* mat4_multiply(mvp, tmp_matrix, tmp_matrix); */
glUniform3f(res->uniforms.light_dir, light[0], light[1], light[2]);
@@ -237,13 +238,6 @@ void render (struct game *game, struct geometry *geom) {
/* mat4_print(player->mat); */
render_cube(res);
- //player camera
-
- mat4_multiply(mvp, player_camera->mat, tmp_matrix);
- glUniformMatrix4fv(res->uniforms.mvp, 1, 0, tmp_matrix);
- /* mat4_multiply(persp, tmp_matrix, mvp); */
- render_cube(res);
-
// terrain
glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp);
render_geom(res, geom, GL_TRIANGLES);
diff --git a/src/update.c b/src/update.c
@@ -16,35 +16,35 @@ static void movement(struct game *game, struct node *node) {
amt *= 6;
if (game->input.keystates[SDL_SCANCODE_A])
- node_translate(node, V3(-amt,0,0));
+ node_forward(node, V3(-amt,0,0));
if (game->input.keystates[SDL_SCANCODE_E])
- node_translate(node, V3(0,0,amt));
+ node_forward(node, V3(0,0,amt));
if (game->input.keystates[SDL_SCANCODE_Q])
- node_translate(node, V3(0,0,-amt));
+ node_forward(node, V3(0,0,-amt));
if (game->input.keystates[SDL_SCANCODE_D])
- node_translate(node, V3(amt,0,0));
+ node_forward(node, V3(amt,0,0));
if (game->input.keystates[SDL_SCANCODE_W])
- node_translate(node, V3(0,amt,0));
+ node_forward(node, V3(0,amt,0));
if (game->input.keystates[SDL_SCANCODE_S])
- node_translate(node, V3(0,-amt,0));
+ node_forward(node, V3(0,-amt,0));
// TODO: mark as update
- if (game->input.keystates[SDL_SCANCODE_UP])
- node_rotate(node, V3(amt * 0.01,0,0));
+ /* if (game->input.keystates[SDL_SCANCODE_UP]) */
+ /* node_rotate(node, V3(amt * 0.01,0,0)); */
if (game->input.keystates[SDL_SCANCODE_RIGHT])
- node_rotate(node, V3(0, 0, -amt * 0.01));
+ node_rotate(node, V3(0, 0, amt * 0.01));
if (game->input.keystates[SDL_SCANCODE_LEFT])
- node_rotate(node, V3(0, 0, amt * 0.01));
+ node_rotate(node, V3(0, 0, -amt * 0.01));
- if (game->input.keystates[SDL_SCANCODE_DOWN])
- node_rotate(node, V3(-amt * 0.01, 0, 0));
+ /* if (game->input.keystates[SDL_SCANCODE_DOWN]) */
+ /* node_rotate(node, V3(-amt * 0.01, 0, 0)); */
if (game->input.keystates[SDL_SCANCODE_P])
mat4_print(node->mat);
@@ -92,16 +92,18 @@ void update (struct game *game, u32 dt) {
game->terrain->fn(game->terrain, res->player.pos[0], res->player.pos[1]) +
PLAYER_HEIGHT;
+ node_recalc(&res->camera);
+
vec3_copy(res->player.pos, last_pos);
+ }
- /* node_recalc(&res->root); */
- node_recalc(&res->root);
- camera_follow(res->camera.pos, &res->player_camera.mat[M_X], res->camera.mat);
- node_mark_for_recalc(&res->camera);
- /* node_recalc(&res->camera); */
+ node_recalc(&res->camera);
+ vec3 *camera_world = node_world(&res->camera);
+ float cam_terrain_z =
+ game->terrain->fn(game->terrain, camera_world[0], camera_world[1]);
- /* movement(game, res->camera); */
- }
+ if (camera_world[2] < cam_terrain_z)
+ camera_world[2] = cam_terrain_z + 10.0;
}
if (game->input.keystates[SDL_SCANCODE_C]) {