commit fe404d05973bd84e45bc4f24e871cd777ae16d5c
parent ab66e332265639a252e3d3c9b679b64b04836ac1
Author: William Casarin <jb55@jb55.com>
Date: Mon, 30 Apr 2018 14:28:01 -0700
scene graph improvements
Diffstat:
12 files changed, 183 insertions(+), 30 deletions(-)
diff --git a/src/camera.c b/src/camera.c
@@ -11,15 +11,15 @@ struct camera *camera_init(struct camera *cam) {
void
-camera_follow(vec3 *cam_pos, vec3 *target_prev, vec3 *target, mat4 *cam) {
- cam_pos[0] = target[0];
+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] + 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]); */
- /* look_at(cam_pos, target, V3(0,1,0), cam); */
+ look_at(cam_pos, target, V3(0,1,0), cam);
/* cam_pos[0] = -target[0]; */
/* cam_pos[1] = -target[1]; */
/* cam_pos[2] = target[2]; */
diff --git a/src/camera.h b/src/camera.h
@@ -12,6 +12,6 @@ struct camera {
};
void
-camera_follow(vec3 *cam_pos, vec3 *target_prev, vec3 *target, mat4 *cam);
+camera_follow(vec3 *cam_pos, vec3 *target, mat4 *cam);
#endif /* POLYADVENT_CAMERA_H */
diff --git a/src/game.c b/src/game.c
@@ -12,8 +12,10 @@ mat4 *cam_init = (float[16]){
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;
@@ -23,17 +25,33 @@ void game_init(struct game *game) {
light_dir[1] = 1;
light_dir[2] = 0.8;
+ 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);
+
/* vec3_all(camera->scale, -1); */
camera->mirrored = 1;
node_translate(player, V3(10,10,0));
- node_translate(camera, V3(50,0,20));
+ node_translate(camera, V3(0,0,20));
+ node_translate(player_camera, V3(10,10,20));
+ /* node_recalc(camera); */
- camera->rot[0] = -45;
+ /* player_camera->mirrored = 1; */
+ /* camera->parent = player_camera; */
+ camera->rot[0] = 45;
// 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
@@ -30,11 +30,12 @@ struct resources {
gpu_addr normal;
} attributes;
+ struct node root;
struct node player;
+ struct node player_camera;
struct node camera;
struct node terrain_node;
- float normal_matrix[MAT4_ELEMS];
float test_mvp[MAT4_ELEMS];
float light_dir[3];
float camera_persp[MAT4_ELEMS];
diff --git a/src/mat4.c b/src/mat4.c
@@ -327,3 +327,40 @@ void mat4_print(const mat4 *m) {
}
printf("\n");
}
+
+/* mat4 *mat4_create_transform(float *pos, float *scale, float *rot, mat4 *dest) { */
+/* if (!dest) { dest = mat4.create(); } */
+
+/* float halfAngle = 0.5*angle; */
+/* float sin_ = sin(halfAngle); */
+
+/* dest[0] = sin_*axis[0]; */
+/* dest[1] = sin_*axis[1]; */
+/* dest[2] = sin_*axis[2]; */
+/* dest[3] = cos(halfAngle); */
+
+/* var rot = quat4.toMat3(orientation); */
+
+/* dest[0] = scale[0] * rot[0]; */
+/* dest[1] = scale[0] * rot[1]; */
+/* dest[2] = scale[0] * rot[2]; */
+/* dest[3] = 0; */
+
+/* dest[4] = scale[1] * rot[3]; */
+/* dest[5] = scale[1] * rot[4]; */
+/* dest[6] = scale[1] * rot[5]; */
+/* dest[7] = 0; */
+
+/* dest[8] = scale[2] * rot[6]; */
+/* dest[9] = scale[2] * rot[7]; */
+/* dest[10] = scale[2] * rot[8]; */
+/* dest[11] = 0; */
+
+/* dest[12] = position[0]; */
+/* dest[13] = position[1]; */
+/* dest[14] = position[2]; */
+/* dest[15] = 1; */
+
+/* return dest; */
+/* } */
+/* } */
diff --git a/src/mat4.h b/src/mat4.h
@@ -5,6 +5,8 @@ typedef float mat4;
#define M_Y 13
#define M_Z 14
+
+/* mat4 *mat4_create_transform(mat4 *a, float *pos, float *scale, float *rot); */
mat4 *mat4_scale(mat4 *a, float v[3], mat4 *out);
mat4 *mat4_frustum (float left, float right, float bottom,
float top, float near, float far, mat4 *dest);
diff --git a/src/node.c b/src/node.c
@@ -4,15 +4,22 @@
#include "mat4.h"
#include "vec3.h"
#include <stdio.h>
+#include <assert.h>
struct node *node_init(struct node *node) {
mat4_id(node->mat);
vec3_all(node->pos, 0);
vec3_all(node->rot, 0);
vec3_all(node->scale, 1.0);
- node->children = 0;
+ 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_mark_for_recalc(node);
+
return node;
}
@@ -22,17 +29,47 @@ void node_translate(struct node *node, vec3 *p) {
/* printf("translating %f %f %f\n", p[0], p[1], p[2]); */
vec3_add(node->pos, p, node->pos);
+ node_mark_for_recalc(node);
+}
+
+int node_needs_recalc(struct node *node) {
+ return (node->parent && node->parent->needs_recalc) || node->needs_recalc;
+}
+
+void node_mark_for_recalc(struct node *node) {
+ static int j = 0;
+
+ if (node->needs_recalc)
+ return;
+
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);
+ node_mark_for_recalc(node->children[i]);
+ }
+}
+
+static void node_recalc_children(struct node *node) {
+ for (int i = 0; i < node->n_children; ++i) {
+ node_recalc(node->children[i]);
+ }
}
int node_recalc(struct node *node) {
float rotate_axis[3];
+ float tmp[16];
- if (!node->needs_recalc)
- return 0;
+ assert(node);
- mat4_id(node->mat);
+ if (!node_needs_recalc(node)) {
+ // XXX: do I need this?
+ goto recalc_children;
+ }
+ printf("recalculating %s\n", node->label);
+
+ mat4_id(node->mat);
node->needs_recalc = 0;
@@ -54,7 +91,7 @@ int node_recalc(struct node *node) {
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], rotate_axis, 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);
}
@@ -64,10 +101,24 @@ int node_recalc(struct node *node) {
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); */
+ if (node->parent) {
+ assert(!node->parent->needs_recalc);
+ mat4_multiply(node->mat, node->parent->mat, node->mat);
+ }
+
+recalc_children:
+ node_recalc_children(node);
+
return 1;
}
+
+void node_attach(struct node *node, struct node *to) {
+ assert(to->n_children <= MAX_NODE_CHILDREN);
+
+ node->parent = to;
+ to->children[to->n_children++] = node;
+}
diff --git a/src/node.h b/src/node.h
@@ -2,18 +2,26 @@
#ifndef POLYADVENT_NODE_H
#define POLYADVENT_NODE_H
+#define MAX_NODE_CHILDREN 4
+
struct node {
float pos[3];
float rot[3];
float scale[3];
float mat[16];
+ float orientation[4];
+ char *label;
int needs_recalc;
+ int n_children;
int mirrored; // TODO: make camera type
- struct node* children;
- // TODO quaternion rotation
+ struct node* parent;
+ struct node* children[MAX_NODE_CHILDREN];
+ // TODO quaternion rot/orientation
};
-int node_recalc(struct node *node);
+int node_recalc(struct node *root);
+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);
diff --git a/src/render.c b/src/render.c
@@ -206,11 +206,12 @@ void render (struct game *game, struct geometry *geom) {
struct resources *res = &game->test_resources;
mat4 *mvp = res->test_mvp;
- mat4 *normal = res->normal_matrix;
mat4 *persp = res->camera_persp;
mat4 *light = res->light_dir;
+
struct node *player = &res->player;
struct node *camera = &res->camera;
+ struct node *player_camera = &res->player_camera;
float fade_factor = res->fade_factor;
@@ -220,8 +221,8 @@ void render (struct game *game, struct geometry *geom) {
/* v3[1] = fade_factor * 1.4f; */
/* mat4_rotate(mvp, 0.004f, v3, mvp); */
/* printf("camera_pos %f %f %f", camera_pos[0], camera_pos[1], camera_pos[2]); */
- node_recalc(camera);
/* mat4_print(camera->mat); */
+ /* node_recalc(&res->camera); */
mat4_multiply(persp, camera->mat, mvp);
/* mat4_multiply(mvp, tmp_matrix, tmp_matrix); */
@@ -230,10 +231,17 @@ void render (struct game *game, struct geometry *geom) {
glUniform1f(res->uniforms.tscale, res->uniforms.tscale);
//player
- node_recalc(player);
mat4_multiply(mvp, player->mat, tmp_matrix);
glUniformMatrix4fv(res->uniforms.mvp, 1, 0, tmp_matrix);
/* mat4_multiply(persp, tmp_matrix, mvp); */
+ /* 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
diff --git a/src/update.c b/src/update.c
@@ -9,7 +9,7 @@
#include "poisson.h"
#include "uniform.h"
-void movement(struct game *game, struct node *node) {
+static void movement(struct game *game, struct node *node) {
float amt = 0.25;
if (game->input.modifiers & KMOD_SHIFT)
@@ -33,6 +33,7 @@ void movement(struct game *game, struct node *node) {
if (game->input.keystates[SDL_SCANCODE_S])
node_translate(node, V3(0,-amt,0));
+ // TODO: mark as update
if (game->input.keystates[SDL_SCANCODE_UP])
node->rot[0] += amt * 0.01;
@@ -61,6 +62,7 @@ void update (struct game *game, u32 dt) {
struct perlin_settings *ts = &game->terrain->settings;
float player_prev[MAT4_ELEMS];
struct node *tnode = &game->test_resources.terrain_node;
+ struct node *root = &game->test_resources.root;
float *light = res->light_dir;
if (first) {
@@ -73,23 +75,33 @@ void update (struct game *game, u32 dt) {
movement(game, &res->camera);
/* mat4_multiply(res->player, res->ca era, res->player); */
}
- if (game->input.modifiers & KMOD_LCTRL) {
+ else if (game->input.modifiers & KMOD_LCTRL) {
movement(game, &res->terrain_node);
/* mat4_multiply(res->player, res->ca era, res->player); */
}
else {
- movement(game, &res->player);
/* mat4_copy(res->player, player_prev); */
+ static vec3 last_pos[3] = {0};
+
+ movement(game, &res->player);
+
+ if (!vec3_eq(res->player.pos, last_pos, 0.0001)) {
+ printf("else\n");
- res->player.pos[2] =
- game->terrain->fn(game->terrain, res->player.pos[0], res->player.pos[1]) +
+ res->player.pos[2] =
+ game->terrain->fn(game->terrain, res->player.pos[0], res->player.pos[1]) +
PLAYER_HEIGHT;
- res->player.needs_recalc = 1;
- node_recalc(&res->camera);
- camera_follow(res->camera.pos, res->player.pos, res->player.pos, res->camera.mat);
- res->camera.needs_recalc = 1;
- /* movement(game, 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); */
+
+ /* movement(game, res->camera); */
+ }
}
if (game->input.keystates[SDL_SCANCODE_C]) {
@@ -176,4 +188,5 @@ void update (struct game *game, u32 dt) {
}
+ node_recalc(root);
}
diff --git a/src/vec3.c b/src/vec3.c
@@ -223,3 +223,16 @@ int vec3_isall(vec3 *vec, float n) {
return 1;
}
+
+int vec3_eq(vec3 *a, vec3 *b, float precision) {
+ return fabs(a[0] - b[0]) <= precision &&
+ fabs(a[1] - b[1]) <= precision &&
+ fabs(a[2] - b[2]) <= precision;
+}
+
+
+void vec3_copy(vec3 *a, vec3 *dest) {
+ dest[0] = a[0];
+ dest[1] = a[1];
+ dest[2] = a[2];
+}
diff --git a/src/vec3.h b/src/vec3.h
@@ -20,3 +20,5 @@ float vec3_dot(vec3 *vec, vec3 *vec2);
int vec3_isall(vec3 *vec, float n);
vec3 *vec3_all(vec3 *vec, float n);
vec3 *vec3_add(vec3 *vec, vec3 *vec2, vec3 *dest);
+int vec3_eq(vec3 *a, vec3 *b, float precision);
+void vec3_copy(vec3 *a, vec3 *dest);