commit a7be13b51009a4be98599820a03f1dc67144be8f
parent edcb70b6c188b1806153cccb1f1ef0ae8a52d144
Author: William Casarin <jb55@jb55.com>
Date: Sun, 30 Jun 2019 10:45:36 -0700
dynamic nodes
Diffstat:
24 files changed, 404 insertions(+), 152 deletions(-)
diff --git a/TODOs.org b/TODOs.org
@@ -17,6 +17,16 @@ To create a sense of movement
CLOSED: [2019-06-22 Sat 12:52]
** DONE Load poses in engine
CLOSED: [2019-06-22 Sat 12:52]
+
+** TODO factor node properties
+
+perhaps there's a more minimal subset of node that would be useful to
+both joints and entities?
+
+** TODO use nodes for joints
+
+It will just be easier for interpolation
+
** TODO Load bone weights
** TODO Run pose
** TODO Simple animation test
diff --git a/src/animation.c b/src/animation.c
@@ -2,6 +2,7 @@
#include <stdio.h>
#include "xml.h"
#include "util.h"
+#include "node.h"
#include "animation.h"
enum dae_state {
@@ -23,20 +24,35 @@ struct dae_data {
void init_joint(struct joint *joint)
{
- memset(joint->children, -1, sizeof(joint->children));
joint->id = -1;
- mat4_id(joint->mat);
+ joint->n_children_ids = 0;
+ for (int i = 0; i < MAX_JOINT_CHILDREN; i++) {
+ joint->children_ids[i] = -1;
+ }
+ init_id(&joint->node_id);
}
+void new_joint(struct joint *joint)
+{
+ init_joint(joint);
+ new_node(&joint->node_id);
+}
+
+
void init_pose(struct pose *pose)
{
pose->njoints = 0;
+ for (int i = 0; i < MAX_JOINTS; i++) {
+ init_joint(&pose->joints[i]);
+ }
}
static void parse_joint(const char *t, int id, struct joint *joint)
{
- float *m = joint->mat;
- init_joint(joint);
+ struct node *node = get_node(&joint->node_id);
+ assert(node);
+
+ float *m = node->mat;
joint->id = id;
/* printf(" parsing joint %d: %s\n", id, t); */
@@ -82,15 +98,27 @@ static void dae_tag_end(struct xmlparser *x, const char *t, size_t tl, int what)
static void dae_tagbody(struct xmlparser *x, const char *d, size_t dl)
{
+ static int count = 0;
struct dae_data *data = (struct dae_data*)x->user_data;
if (data->state == PARSING_JOINT_MATRIX) {
assert(*data->nposes);
+
struct pose *pose = &data->poses[*data->nposes - 1];
+ assert(pose);
+
struct joint *joint = &pose->joints[pose->njoints];
+ assert(joint);
+
+ struct node *node = new_node(&joint->node_id);
+ assert(node);
+ assert((int64_t)joint->node_id.uuid != -1);
+ assert(&joint->node_id == &pose->joints[pose->njoints].node_id);
+
parse_joint(d, pose->njoints, joint);
- strncpy(joint->name, data->current_name, sizeof(data->current_name));
- joint->children[0] = data->node_level;
+ print_id(&joint->node_id);
+ node_set_label(node, data->current_name);
+ joint->children_ids[0] = data->node_level;
pose->njoints++;
data->state = PARSING_POSE;
}
@@ -135,18 +163,18 @@ static void process_joint_children(struct joint *joints, int njoints)
joint = &joints[i];
// node level is stored in here on the first parser pass
- int level = joint->children[0];
+ int level = joint->children_ids[0];
for (int j = i+1; j < njoints; j++) {
j2 = &joints[j];
- if (j2->children[0] == level + 1) {
+ if (j2->children_ids[0] == level + 1) {
/* printf("%s(%d) assigning child %s(%d)\n", */
/* joint->name, level, j2->name, j2->children[0]); */
- assert(joint->nchildren+1 < MAX_JOINT_CHILDREN);
- joint->children[joint->nchildren++] = j;
+ assert(joint->n_children_ids+1 < MAX_JOINT_CHILDREN);
+ joint->children_ids[joint->n_children_ids++] = j;
}
- else if (j2->children[0] <= level)
+ else if (j2->children_ids[0] <= level)
break;
}
}
@@ -183,5 +211,6 @@ void load_poses(const char *filename, struct pose *poses, int *nposes)
process_joint_children(pose->joints, pose->njoints);
}
+
fclose(data.dae_file);
}
diff --git a/src/animation.h b/src/animation.h
@@ -3,6 +3,7 @@
#define POLYADVENT_ANIMATION_H
#include "common.h"
+#include "node.h"
#define MAX_JOINT_CHILDREN 4
#define MAX_JOINTS 16
@@ -10,15 +11,13 @@
struct joint
{
- int children[MAX_JOINT_CHILDREN];
- int nchildren;
int id;
- char name[JOINT_LABEL_SIZE];
- float mat[MAT4_ELEMS];
+ int children_ids[MAX_JOINT_CHILDREN];
+ int n_children_ids;
+ node_id node_id;
};
-
struct pose
{
struct joint joints[MAX_JOINTS];
@@ -29,6 +28,7 @@ struct pose
void load_poses(const char *filename, struct pose *poses, int *nposes);
void init_joint(struct joint *joint);
+void init_pose(struct pose *pose);
#endif /* POLYADVENT_ANIMATION_H */
diff --git a/src/camera.h b/src/camera.h
@@ -8,7 +8,7 @@
struct camera {
float frustum[16];
- struct node node;
+ node_id node_id;
};
void
diff --git a/src/entity.c b/src/entity.c
@@ -18,8 +18,16 @@ struct entity *get_all_entities(u32 *count, entity_id **ids) {
return get_all_resources(&esys, count, ids);
}
-struct entity *init_entity(struct entity *ent) {
- node_init(&ent->node);
+struct entity *init_entity(struct entity *ent, node_id *id) {
+ node_id new_id;
+ if (id == NULL) {
+ init_id(&new_id);
+ new_node(&new_id);
+ ent->node_id = new_id;
+ }
+ else {
+ ent->node_id = *id;
+ }
ent->casts_shadows = 1;
return ent;
}
@@ -33,7 +41,12 @@ static inline struct entity *new_uninitialized_entity(entity_id *id) {
}
struct entity *new_entity(entity_id *id) {
- return init_entity(new_uninitialized_entity(id));
+ return new_entity_with_node(id, NULL);
+}
+
+
+struct entity *new_entity_with_node(entity_id *id, node_id *node) {
+ return init_entity(new_uninitialized_entity(id), node);
}
struct entity *add_entity(struct entity *e, entity_id *id) {
@@ -53,7 +66,17 @@ void destroy_entities() {
void destroy_entity(entity_id *id) {
struct entity *ent = get_entity(id);
- node_detach_from_parent(&ent->node);
+ assert(ent);
+ if (ent == NULL)
+ return;
+
+ struct node *node = get_node(&ent->node_id);
+ assert(node);
+ if (node == NULL)
+ return;
+
+ node_detach_from_parent(node);
+ destroy_resource(&esys, &ent->node_id);
destroy_resource(&esys, id);
}
diff --git a/src/entity.h b/src/entity.h
@@ -15,7 +15,7 @@ enum entity_flags {
};
struct entity {
- struct node node;
+ node_id node_id;
struct model *model;
u32 flags;
float velocity[3];
@@ -25,14 +25,15 @@ struct entity {
typedef struct resource_id entity_id;
-struct entity *init_entity(struct entity *);
+struct entity *init_entity(struct entity *, node_id *id);
void destroy_entities();
struct resource_manager *_internal_get_entity_system();
void destroy_entity(entity_id *);
void init_entity_system();
struct entity *get_entity(entity_id *);
struct entity *get_all_entities(u32 *count, entity_id **ids);
-struct entity *new_entity(entity_id *id);
+struct entity *new_entity(entity_id *);
+struct entity *new_entity_with_node(entity_id *, node_id *);
void destroy_entity_system();
#endif /* ENTITY_H */
diff --git a/src/game.c b/src/game.c
@@ -104,17 +104,27 @@ void game_init(struct game *game, int width, int height) {
init_gl(&game->test_resources, width, height);
init_entity_system();
init_model_manager();
+ init_node_manager();
init_geometry_manager();
init_user_settings(&game->user_settings);
check_gl();
struct resources *res = &game->test_resources;
mat4 *mvp = res->test_mvp;
- struct node *root = &res->root;
- struct node *sun_camera = &res->sun_camera;
+
+ init_id(&res->root_id);
+ init_id(&res->sun_camera_id);
+ init_id(&res->free_camera_id);
+
+ struct node *root = new_node(&res->root_id);
+ struct node *sun_camera = new_node(&res->sun_camera_id);
struct terrain *terrain = &game->terrain;
struct entity *player;
+ assert(root->parent_id.generation == 0);
+ assert(root);
+ assert(sun_camera);
+
mat4 *light_dir = res->light_dir;
int ok = 0;
@@ -168,34 +178,39 @@ void game_init(struct game *game, int width, int height) {
node_init(root);
node_init(sun_camera);
- init_orbit(&res->orbit_camera);
-
- root->label = "root";
+ new_orbit(&res->orbit_camera);
+ node_set_label(root, "root");
// ENTITIES
// player entity
+ init_id(&res->player_id);
player = new_entity(&res->player_id);
+ struct node *pnode = get_node(&player->node_id);
+ assert(pnode);
assert(res->player_id.index == 1);
player->model = get_model(model_pirate_officer);
- player->node.label = "player";
- node_attach(&player->node, root);
- node_translate(&player->node, V3(terrain->size/2.,terrain->size/2.,0.0));
+ node_set_label(pnode, "player");
+ node_attach(&player->node_id, &res->root_id);
+
+ assert(ideq(&pnode->parent_id, &res->root_id));
+
+ node_translate(pnode, V3(terrain->size/2.,terrain->size/2.,0.0));
// orbit camera
- res->orbit_camera.coords.azimuth = -quat_yaw(player->node.orientation) - RAD(90.0);
+ res->orbit_camera.coords.azimuth = -quat_yaw(pnode->orientation) - RAD(90.0);
res->orbit_camera.coords.inclination = RAD(60);
res->orbit_camera.coords.radius = 5.0;
- res->camera_node = &res->orbit_camera.node;
+ res->camera_node_id = res->orbit_camera.node_id;
// free camera
- node_init(&res->free_camera);
- res->free_camera.label = "free_camera";
- node_attach(&res->free_camera, &player->node);
- quat_axis_angle(V3(1,0,0), -45, res->free_camera.orientation);
- node_rotate(&res->free_camera, V3(100, 0, 0));
- node_translate(&res->free_camera, V3(0,-40,20));
+ struct node *freecam = new_node(&res->free_camera_id);
+ node_set_label(freecam, "freecam");
+ node_attach(&res->free_camera_id, &player->node_id);
+ quat_axis_angle(V3(1,0,0), -45, freecam->orientation);
+ node_rotate(freecam, V3(100, 0, 0));
+ node_translate(freecam, V3(0,-40,20));
input_init(&game->input);
diff --git a/src/game.h b/src/game.h
@@ -58,13 +58,13 @@ struct resources {
gpu_addr vertex_attrs[n_vertex_attrs];
- struct node root;
+ node_id root_id;
entity_id player_id;
struct geometry qh_test;
struct orbit orbit_camera;
- struct node free_camera;
- const struct node *camera_node;
- struct node sun_camera;
+ node_id free_camera_id;
+ node_id camera_node_id;
+ node_id sun_camera_id;
u32 test_cubemap;
float time;
diff --git a/src/geometry.c b/src/geometry.c
@@ -167,8 +167,9 @@ make_buffer_geometry_(struct make_geometry *mkgeom, struct geometry *geom) {
}
void
-make_buffer_geometry(struct make_geometry *mkgeom, geometry_id *geom_id) {
-
+make_buffer_geometry(struct make_geometry *mkgeom, geometry_id *geom_id)
+{
+ init_id(geom_id);
struct geometry *geom = new_geometry(geom_id);
make_buffer_geometry_(mkgeom, geom);
diff --git a/src/main.c b/src/main.c
@@ -71,7 +71,7 @@ int main(void)
struct render_config fbo_render_config = {
.draw_ui = 0,
.is_depth_pass = 1,
- .camera = game.test_resources.sun_camera.mat,
+ .camera = game.test_resources.sun_camera_id,
.projection = game.test_resources.proj_ortho,
.depth_vp = depth_vp
};
@@ -79,7 +79,7 @@ int main(void)
struct render_config default_config = {
.draw_ui = 0,
.is_depth_pass = 0,
- .camera = game.test_resources.camera_node->mat,
+ .camera = game.test_resources.camera_node_id,
.projection = game.test_resources.proj_persp,
.depth_vp = depth_vp
};
@@ -93,10 +93,11 @@ int main(void)
game.input.resized_height);
handle_resize(&game, game.input.resized_width, game.input.resized_height);
}
- default_config.camera = game.test_resources.camera_node->mat;
+ //default_config.camera = game.test_resources.camera_node->mat;
double new_time = hires_time_in_seconds();
double frame_time = new_time - last;
game.dt = frame_time;
+
update(&game);
/* while (accumulator >= dt) { */
diff --git a/src/model.c b/src/model.c
@@ -17,16 +17,24 @@ static struct resource_manager dyn_modelman;
static int static_models_initialized = 0;
struct model *init_model(struct model *model) {
+ init_id(&model->geom_id);
model->shading = SHADING_VERT_COLOR;
model->texture = 0;
return model;
}
+struct model *new_model(struct model *model)
+{
+ init_model(model);
+ null_id(&model->geom_id);
+ return model;
+}
+
static void initialize_static_models() {
for (int i = 0; i < NUM_STATIC_MODELS; i++) {
struct model_def *sm = &static_models[i];
assert(sm->id == i);
- init_model(&sm->model);
+ new_model(&sm->model);
}
static_models_initialized = 1;
}
diff --git a/src/node.c b/src/node.c
@@ -5,6 +5,36 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
+#include <stdint.h>
+
+static struct resource_manager node_manager = {0};
+
+static inline struct node *new_uninitialized_node(node_id *id)
+{
+ return new_resource(&node_manager, id);
+}
+
+struct node *new_node(node_id *id)
+{
+ struct node *n = node_init(new_uninitialized_node(id));
+ assert((int64_t)id->uuid != -1);
+ return n;
+}
+
+struct node *get_node(node_id *id)
+{
+ return get_resource(&node_manager, id);
+}
+
+void destroy_node(node_id *id)
+{
+ destroy_resource(&node_manager, id);
+}
+
+void init_node_manager()
+{
+ init_resource_manager(&node_manager, sizeof(struct node), 128, 0xFFFF);
+}
struct node *node_init(struct node *node) {
mat4_id(node->mat);
@@ -14,9 +44,9 @@ struct node *node_init(struct node *node) {
quat_id(node->orientation);
node->n_children = 0;
for (int i = 0; i < MAX_NODE_CHILDREN; ++i)
- node->children[i] = NULL;
+ init_id(&node->children_ids[i]);
node->flags = 0;
- node->parent = NULL;
+ null_id(&node->parent_id);
node_set_label(node, "unknown");
node->needs_recalc = 0;
node->custom_update = 0;
@@ -28,6 +58,11 @@ struct node *node_init(struct node *node) {
int node_set_label(struct node *node, const char *label)
{
strncpy(node->label, label, sizeof(node->label));
+ // return 0 if the string is too big and that we've truncated it
+ int ok = node->label[sizeof(node->label)-1] == '\0';
+ // strncpy won't write this for large strings =/
+ node->label[sizeof(node->label)-1] = '\0';
+ return ok;
}
void node_scale(struct node *node, float val) {
@@ -61,7 +96,8 @@ void node_rotate(struct node *node, vec3 *axis_angles) {
int node_needs_recalc(struct node *node)
{
- return (node->parent && node->parent->needs_recalc) || node->needs_recalc;
+ struct node *parent = get_node(&node->parent_id);
+ return (parent && parent->needs_recalc) || node->needs_recalc;
}
vec3 *node_world(struct node *node) {
@@ -77,13 +113,18 @@ void node_mark_for_recalc(struct node *node) {
node->needs_recalc = 1;
- for (int i = 0; i < node->n_children; ++i)
- node_mark_for_recalc(node->children[i]);
+ for (int i = 0; i < node->n_children; ++i) {
+ struct node *child = get_node(&node->children_ids[i]);
+ if (child)
+ node_mark_for_recalc(child);
+ }
}
static void node_recalc_children(struct node *node) {
for (int i = 0; i < node->n_children; ++i) {
- node_recalc(node->children[i]);
+ struct node *child = get_node(&node->children_ids[i]);
+ if (child)
+ node_recalc(child);
}
}
@@ -91,8 +132,9 @@ int node_recalc(struct node *node) {
assert(node);
float rot[9] = {1.0};
- if (node->parent && node_needs_recalc(node->parent))
- node_recalc(node->parent);
+ struct node *parent = get_node(&node->parent_id);
+ if (parent && node_needs_recalc(parent))
+ node_recalc(parent);
if (!node_needs_recalc(node)) {
node_recalc_children(node);
@@ -105,9 +147,9 @@ int node_recalc(struct node *node) {
quat_to_mat3(node->orientation, rot);
mat4_create_transform(node->pos, node->scale, rot, node->mat);
- if (node->parent) {
- assert(!node->parent->needs_recalc);
- mat4_multiply(node->parent->mat, node->mat, node->mat);
+ if (parent) {
+ assert(!parent->needs_recalc);
+ mat4_multiply(parent->mat, node->mat, node->mat);
}
}
@@ -122,10 +164,13 @@ int node_recalc(struct node *node) {
int node_detach(struct node *node, struct node *from) {
for (int i = 0; i < from->n_children; i++) {
- if (from->children[i] == node) {
- memmove(from->children[i], from->children[i+1],
- from->n_children - i - 1);
- assert(!"fixme, this should be times the size of *children");
+ node_id *child_id = &from->children_ids[i];
+ struct node *child = get_node(&from->children_ids[i]);
+ if (child && child == node) {
+ destroy_node(child_id);
+ memmove(&from->children_ids[i], &from->children_ids[i+1],
+ sizeof(*from->children_ids) * from->n_children - 1);
+ // TODO: test node_detach
from->n_children--;
return 1;
}
@@ -133,25 +178,38 @@ int node_detach(struct node *node, struct node *from) {
return 0;
}
-void node_detach_from_parent(struct node *node) {
- if (node->parent)
- node_detach(node, node->parent);
+void node_detach_from_parent(struct node *node)
+{
+ struct node *parent = get_node(&node->parent_id);
+
+ if (parent)
+ node_detach(node, parent);
}
// count the total number of nodes
-int node_count(struct node *node) {
+int node_count(struct node *node)
+{
int c = 1;
for (int i = 0; i < node->n_children; i++) {
- c += node_count(node->children[i]);
+ struct node *child = get_node(&node->children_ids[i]);
+ assert(child);
+ if (child)
+ c += node_count(child);
}
return c;
}
-void node_attach(struct node *node, struct node *to) {
- assert(to->n_children <= MAX_NODE_CHILDREN);
+void node_attach(struct resource_id *node_id, struct resource_id *to_id)
+{
+ struct node *node = get_node(node_id);
+ struct node *to = get_node(to_id);
+
+ assert(node);
+ assert(to && to->n_children <= MAX_NODE_CHILDREN);
- node->parent = to;
- to->children[to->n_children++] = node;
+ node->parent_id = *to_id;
+ assert(node->parent_id.uuid == to_id->uuid);
+ to->children_ids[to->n_children++] = *node_id;
}
void node_forward(struct node *node, float *dir) {
diff --git a/src/node.h b/src/node.h
@@ -2,30 +2,35 @@
#ifndef POLYADVENT_NODE_H
#define POLYADVENT_NODE_H
+#include "resource.h"
+
#define MAX_NODE_CHILDREN 4
enum node_flags {
NODE_IGNORE_RECALC = 1 << 0
};
+typedef struct resource_id node_id;
+
struct node {
- float pos[3];
- float rot[3];
- float scale[3];
- float mat[16];
- float orientation[4];
- char label[8];
- int needs_recalc;
- int flags;
- int n_children;
- void (*custom_update)(struct node*);
- void *custom_update_data;
- struct node* parent;
- struct node* children[MAX_NODE_CHILDREN];
+ float pos[3];
+ float rot[3];
+ float scale[3];
+ float mat[16];
+ float orientation[4];
+ char label[8];
+ int needs_recalc;
+ int flags;
+ int n_children;
+ void (*custom_update)(struct node*);
+ void *custom_update_data;
+
+ node_id parent_id;
+ node_id children_ids[MAX_NODE_CHILDREN];
};
int node_recalc(struct node *root);
-void node_attach(struct node *node, struct node *to);
+void node_attach(node_id *node, node_id *to);
int node_detach(struct node *node, struct node *from);
void node_detach_from_parent(struct node *node);
void node_mark_for_recalc(struct node *node);
@@ -39,4 +44,9 @@ int node_count(struct node *node);
float *node_world(struct node *node);
int node_set_label(struct node *node, const char *label);
+struct node *get_node(node_id *);
+struct node *new_node(node_id *);
+void destroy_node(node_id *);
+void init_node_manager();
+
#endif /* POLYADVENT_NODE_H */
diff --git a/src/orbit.c b/src/orbit.c
@@ -49,10 +49,12 @@ vec3 *spherical_look_at(struct spherical *s, vec3 *target, mat4 *mat) {
static void orbit_node_update(struct node *node) {
- if (!node->parent)
+ struct node *parent = get_node(&node->parent_id);
+
+ if (!parent)
return;
- float *a = node->parent->mat;
+ float *a = parent->mat;
float *b = node->pos;
float *dst = node->mat;
@@ -71,9 +73,10 @@ static void orbit_node_update(struct node *node) {
}
-void init_orbit(struct orbit *orbit) {
- node_init(&orbit->node);
- orbit->node.label = "orbit_camera";
+void new_orbit(struct orbit *orbit) {
+ init_id(&orbit->node_id);
+ struct node *node = new_node(&orbit->node_id);
+ node_set_label(node, "orbcam");
/* orbit->node.custom_update = orbit_node_update; */
/* orbit->node.custom_update_data = orbit; */
}
diff --git a/src/orbit.h b/src/orbit.h
@@ -14,10 +14,10 @@ struct spherical {
struct orbit {
struct spherical coords;
- struct node node;
+ node_id node_id;
};
-void init_orbit(struct orbit *orbit);
+void new_orbit(struct orbit *orbit);
vec3 *spherical_dir(struct spherical s, vec3 *dir);
vec3 *spherical_pos(struct spherical *s, vec3 *from, vec3 *to);
diff --git a/src/render.c b/src/render.c
@@ -260,7 +260,10 @@ void render (struct game *game, struct render_config *config) {
mat4 *projection = config->projection;
mat4 *light = res->light_dir;
- const mat4 *camera = config->camera;
+ struct node *camera_node = get_node(&config->camera);
+ assert(camera_node);
+
+ const mat4 *camera = camera_node->mat;
u32 num_entities;
struct entity *entities =
@@ -331,8 +334,13 @@ void render (struct game *game, struct render_config *config) {
res->sun_color[2]);
check_gl();
- mat4_multiply(view_proj, entity->node.mat, mvp);
- mat4_copy(entity->node.mat, model_view);
+ struct node *node = get_node(&entity->node_id);
+ assert(node);
+ if (node == NULL)
+ return;
+
+ mat4_multiply(view_proj, node->mat, mvp);
+ mat4_copy(node->mat, model_view);
mat4_multiply(config->depth_vp, model_view, depth_mvp);
glUniformMatrix4fv(res->uniforms.depth_mvp, 1, 0, depth_mvp);
check_gl();
@@ -340,7 +348,7 @@ void render (struct game *game, struct render_config *config) {
glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp);
check_gl();
- glUniformMatrix4fv(res->uniforms.model, 1, 0, entity->node.mat);
+ glUniformMatrix4fv(res->uniforms.model, 1, 0, node->mat);
check_gl();
recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix);
diff --git a/src/render.h b/src/render.h
@@ -2,15 +2,16 @@
#define POLYADVENT_RENDER_H
#include "geometry.h"
+#include "node.h"
struct game;
struct render_config {
int draw_ui;
int is_depth_pass;
- const float *camera;
- float *projection;
- float *depth_vp;
+ node_id camera;
+ float* projection;
+ float* depth_vp;
};
void init_gl(struct resources *resources, int width, int height);
diff --git a/src/resource.c b/src/resource.c
@@ -11,6 +11,7 @@ static u64 resource_uuids = 0;
static inline void *index_resource(struct resource_manager *r, int i) {
unsigned char *p = r->resources;
+ assert(p);
return p + (i * r->elem_size);
}
@@ -24,12 +25,19 @@ void *get_all_resources(struct resource_manager *r, u32 *count, struct resource_
return r->resources;
}
-void init_resource_id(struct resource_id *id) {
+void init_id(struct resource_id *id) {
id->index = -1;
id->generation = -1;
id->uuid = -1;
}
+void null_id(struct resource_id *id)
+{
+ id->generation = 0;
+ id->uuid = -1;
+ id->index = -1;
+}
+
void init_resource_manager(struct resource_manager *r, u32 elem_size,
u32 initial_elements, u32 max_elements) {
r->generation = 1;
@@ -118,8 +126,16 @@ static void resize(struct resource_manager *r)
r->generation += 2;
}
+void print_id(struct resource_id *id)
+{
+ printf("res_id(uuid:%llu ind:%d gen:%d)\n", id->uuid, id->index, id->generation);
+}
+
void *new_resource(struct resource_manager *r, struct resource_id *id)
{
+ assert(id);
+ assert((int)id->index == -1 && "res_id already initialized or uninitialized");
+
struct resource_id *fresh_id;
if (r->resource_count + 1 > r->max_capacity)
@@ -139,13 +155,19 @@ void *new_resource(struct resource_manager *r, struct resource_id *id)
}
void *get_resource(struct resource_manager *r, struct resource_id *id) {
- if (id->generation == 0)
+ assert((int64_t)id->generation != -1 && "id intialized but not allocated (needs new_ call)");
+
+ if (id->generation == 0) {
+ //unusual("getting already deleted resource %llu\n", id->uuid);
return NULL;
+ }
enum refresh_status res = refresh_id(r, id, id);
- if (res == RESOURCE_DELETED)
+ if (res == RESOURCE_DELETED) {
+ unusual("getting deleted resource %llu\n", id->uuid);
return NULL;
+ }
return index_resource(r, id->index);
}
diff --git a/src/resource.h b/src/resource.h
@@ -29,12 +29,14 @@ struct resource_manager {
#define ideq(a, b) ((a)->uuid == (b)->uuid)
-void init_resource_id(struct resource_id *id);
+void init_id(struct resource_id *id);
void *get_resource(struct resource_manager *r, struct resource_id *id);
void *get_all_resources(struct resource_manager *, u32 *count, struct resource_id **ids);
void destroy_resource(struct resource_manager *, struct resource_id *id);
void destroy_resource_manager(struct resource_manager *);
void *new_resource(struct resource_manager *, struct resource_id *id);
+void print_id(struct resource_id *);
+void null_id(struct resource_id *id);
void init_resource_manager(struct resource_manager *r, u32 elem_size,
u32 initial_elements, u32 max_elements);
diff --git a/src/scene.c b/src/scene.c
@@ -26,14 +26,18 @@ void default_scene(struct game *game) {
player->flags &= ~ENT_INVISIBLE;
struct entity *tower = new_entity(NULL);
+ struct node *tnode = get_node(&tower->node_id);
+ struct node *pnode = get_node(&player->node_id);
+
+ assert(tnode);
tower->model = get_model(model_tower);
- tower->node.label = "tower";
- node_attach(&tower->node, &player->node);
- node_translate(&tower->node, V3(0.0, 50.0, 0.0));
- node_recalc(&tower->node);
- float z = terrain->fn(terrain, tower->node.mat[M_X], tower->node.mat[M_Y]);
- node_detach(&tower->node, &player->node);
- tower->node.mat[M_Z] = z;
+ node_set_label(tnode, "tower");
+ node_attach(&tower->node_id, &player->node_id);
+ node_translate(tnode, V3(0.0, 50.0, 0.0));
+ node_recalc(tnode);
+ float z = terrain->fn(terrain, tnode->mat[M_X], tnode->mat[M_Y]);
+ node_detach(tnode, pnode);
+ tnode->mat[M_Z] = z;
// END ENTITIES
diff --git a/src/terrain.c b/src/terrain.c
@@ -52,17 +52,20 @@ void reset_terrain(struct terrain *terrain, float size) {
}
void init_terrain(struct terrain *terrain, float size) {
- struct entity *ent;
+ init_id(&terrain->entity_id);
+ struct entity *ent = new_entity(&terrain->entity_id);
+ struct node *node = get_node(&ent->node_id);
- ent = new_entity(&terrain->entity_id);
+ assert(node);
assert(terrain->entity_id.index == 0);
+
terrain->model.shading = SHADING_TERRAIN;
ent->model = &terrain->model;
- ent->node.label = "terrain_node";
+ node_set_label(node, "terrain");
ent->casts_shadows = 0;
// this is scale for some reason!?
- ent->node.pos[2] = 20.0;
+ node->pos[2] = 20.0;
reset_terrain(terrain, size);
}
diff --git a/src/update.c b/src/update.c
@@ -10,8 +10,10 @@
#include "uniform.h"
#include "game.h"
#include "mat_util.h"
+#include "resource.h"
#include "shader.h"
#include "file.h"
+#include "debug.h"
#include <math.h>
static void movement(struct game *game, struct node *node, float speed_mult) {
@@ -93,9 +95,10 @@ void update_terrain(struct terrain *terrain) {
struct entity *ent = get_entity(&terrain->entity_id);
assert(ent);
struct perlin_settings *ts = &terrain->settings;
- struct node *tnode = &ent->node;
+ struct node *tnode = get_node(&ent->node_id);
+ assert(tnode);
- printf("updating terrain\n");
+ debug("updating terrain\n");
if (first) {
reset_terrain(terrain, terrain->size);
@@ -137,24 +140,25 @@ void update_terrain(struct terrain *terrain) {
static void player_terrain_collision(struct terrain *terrain, struct entity *player) {
// player movement
static vec3 last_pos[3] = {0};
+ struct node *node = get_node(&player->node_id);
- if (!vec3_eq(player->node.pos, last_pos, 0.0001)) {
- float player_z = player->node.pos[2];
+ if (!vec3_eq(node->pos, last_pos, 0.0001)) {
+ float player_z = node->pos[2];
float terrain_z =
- terrain->fn(terrain, player->node.pos[0], player->node.pos[1]);
+ terrain->fn(terrain, node->pos[0], node->pos[1]);
float inset =
min(0.0, player_z - terrain_z);
if (inset <= 0)
- node_translate(&player->node, V3(0.0, 0.0, -inset));
+ node_translate(node, V3(0.0, 0.0, -inset));
}
}
-static void player_movement(struct game *game, struct entity *player) {
- movement(game, &player->node, 2.0);
+static void player_movement(struct game *game, struct node *player_node) {
+ movement(game, player_node, 2.0);
}
@@ -224,6 +228,10 @@ static void day_night_cycle(float time, struct resources *res) {
float val = time * 0.0001;
float intensity = 1.0;//max(0.0, vec3_dot(res->light_dir, V3(0.0, 0.0, 1.0))); */
struct entity *player = get_player(res);
+ struct node *pnode = get_node(&player->node_id);
+ assert(pnode);
+ struct node *suncam = get_node(&res->sun_camera_id);
+ assert(suncam);
float light_pos[3];
@@ -258,30 +266,37 @@ static void day_night_cycle(float time, struct resources *res) {
/* printf("intensity %f(%f) n %f light_dir %f %f\n", roots, intensity, */
/* n, res->light_dir[1], res->light_dir[2]); */
- vec3_add(player->node.pos, res->light_dir, light_pos);
+ vec3_add(pnode->pos, res->light_dir, light_pos);
/* float target[3]; */
/* float hh = player->model.geom.max[2] / 2.0; */
/* vec3_copy(player->node.pos, target); */
/* target[2] += 2.0; */
- look_at(light_pos, player->node.pos, V3(0, 0, 1.0), res->sun_camera.mat);
+ look_at(light_pos, pnode->pos, V3(0, 0, 1.0), suncam->mat);
/* look_at(light_pos, player->node.pos, V3(0, 0, 1.0), res->sun_camera.mat); */
}
static void gravity(struct game *game) {
struct entity *player = get_player(&game->test_resources);
+ struct node *pnode = get_node(&player->node_id);
+ assert(pnode);
- node_translate(&player->node, V3(0.0, 0.0, -1.0));
+ node_translate(pnode, V3(0.0, 0.0, -1.0));
}
void orbit_update_from_mouse(struct orbit *camera, struct input *input,
float mouse_sens, struct entity *player,
- float dt) {
+ float dt)
+{
float target[3];
- struct node *target_node = &player->node;
+ struct node *target_node = get_node(&player->node_id);
+ struct node *cam_node = get_node(&camera->node_id);
struct geometry *player_geom = get_geometry(&player->model->geom_id);
+ assert(target_node);
+ assert(cam_node);
+
node_recalc(target_node);
vec3_copy(node_world(target_node), target);
vec3_add(target, V3(0.0, 0.0, player_geom->max[2] * 2.0), target);
@@ -315,7 +330,7 @@ void orbit_update_from_mouse(struct orbit *camera, struct input *input,
/* camera->coords.inclination, */
/* camera->coords.radius); */
- spherical_look_at(&camera->coords, target, camera->node.mat);
+ spherical_look_at(&camera->coords, target, cam_node->mat);
}
@@ -339,19 +354,23 @@ static void player_update(struct game *game, struct entity *player) {
struct resources *res = &game->test_resources;
struct orbit *camera = &res->orbit_camera;
+ struct node *node = get_node(&player->node_id);
+ struct node *cam_node = get_node(&res->camera_node_id);
+ assert(node);
+ assert(cam_node);
orbit_update_from_mouse(camera, &game->input, game->user_settings.mouse_sens,
player, game->dt);
- camera_keep_above_ground(&game->terrain, res->camera_node);
+ camera_keep_above_ground(&game->terrain, cam_node);
// move player camera toward camera orientation
if (input_is_dragging(&game->input, SDL_BUTTON_RIGHT)) {
float yaw = game->test_resources.orbit_camera.coords.azimuth;
- quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), player->node.orientation);
+ quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), node->orientation);
}
player_terrain_collision(&game->terrain, player);
- node_recalc(&player->node);
+ node_recalc(node);
}
@@ -359,10 +378,18 @@ static void player_update(struct game *game, struct entity *player) {
void update (struct game *game) {
static int toggle_fog = 0;
static int first = 1;
- struct resources *res = &game->test_resources;
- struct terrain *terrain = &game->terrain;
- struct node *root = &game->test_resources.root;
- struct entity *player = get_player(res);
+ struct resources *res = &game->test_resources;
+ struct terrain *terrain = &game->terrain;
+ struct node *root = get_node(&game->test_resources.root_id);
+ struct entity *player = get_player(res);
+ struct node *pnode = get_node(&player->node_id);
+ struct node *cam_node = get_node(&res->camera_node_id);
+ struct node *freecam_node = get_node(&res->free_camera_id);
+
+ assert(pnode);
+ assert(cam_node);
+ assert(freecam_node);
+
float *time = &res->time;
float *light = res->light_dir;
@@ -377,12 +404,15 @@ void update (struct game *game) {
/* vec3_scale(camera_dir, -1, camera_dir); */
if (game->input.modifiers & KMOD_LALT) {
- if (res->camera_node == &res->free_camera)
- movement(game, &res->free_camera, 1.0);
+ if (ideq(&res->camera_node_id, &res->free_camera_id))
+ movement(game, freecam_node, 1.0);
}
else {
- player_movement(game, player);
+ player_movement(game, pnode);
}
+
+ assert(root->parent_id.generation == 0);
+
player_update(game, player);
if (was_key_pressed_this_frame(game, SDL_SCANCODE_R))
@@ -395,10 +425,10 @@ void update (struct game *game) {
toggle_fog = 1;
if (was_key_pressed_this_frame(game, SDL_SCANCODE_EQUALS)) {
- if (res->camera_node != &res->free_camera)
- res->camera_node = &res->free_camera;
+ if (!ideq(&res->camera_node_id, &res->free_camera_id))
+ res->camera_node_id = res->free_camera_id;
else
- res->camera_node = &res->orbit_camera.node;
+ res->camera_node_id = res->orbit_camera.node_id;
}
if (toggle_fog) {
diff --git a/test/test_animation.c b/test/test_animation.c
@@ -9,9 +9,16 @@ int main(int argc, char *argv[])
{
struct pose *pose;
struct joint *joint;
+ struct node *node;
struct pose poses[4];
int nposes;
+ init_node_manager();
+
+ for (int i = 0; i < (int)ARRAY_SIZE(poses); i++) {
+ init_pose(&poses[i]);
+ }
+
load_poses("data/models/pirate-officer.dae", poses, &nposes);
assert(nposes == 1);
@@ -19,12 +26,16 @@ int main(int argc, char *argv[])
assert(pose->njoints == 11);
joint = &pose->joints[0];
- assert(approxeq(joint->mat[0], 0.999897));
+ node = get_node(&joint->node_id);
+ assert(node);
+ assert(approxeq(node->mat[0], 0.999897));
joint = &pose->joints[1];
- assert(approxeq(joint->mat[1], -0.01434187));
+ node = get_node(&joint->node_id);
+ assert(node);
+ assert(approxeq(node->mat[1], -0.01434187));
- assert(pose->joints[0].nchildren == 3);
+ assert(pose->joints[0].n_children_ids == 3);
return 0;
}
diff --git a/test/test_resource.c b/test/test_resource.c
@@ -2,6 +2,7 @@
#include "resource.h"
#include "entity.h"
#include "model.h"
+#include "util.h"
#include "debug.h"
#include <assert.h>
@@ -9,29 +10,34 @@ void test_compact()
{
printf("test_compact\n");
struct resource_manager r;
- struct resource_id id, first_id;
+ struct resource_id ids[3], first_id;
int *p;
init_resource_manager(&r, sizeof(int), 2, 4);
+ for (int i = 0; i < (int)ARRAY_SIZE(ids); i++)
+ init_id(&ids[i]);
+
+ init_id(&first_id);
+
p = new_resource(&r, &first_id);
assert(r.resource_count == 1);
*p = 11;
- p = new_resource(&r, &id);
+ p = new_resource(&r, &ids[0]);
*p = 22;
assert(r.resource_count == 2);
destroy_resource(&r, &first_id);
assert(r.resource_count == 1);
assert(get_resource(&r, &first_id) == NULL);
- assert(*(int*)get_resource(&r, &id) == 22);
+ assert(*(int*)get_resource(&r, &ids[0]) == 22);
- new_resource(&r, &id);
+ new_resource(&r, &ids[1]);
assert(r.resource_count == 2);
assert(r.current_capacity == 2);
- new_resource(&r, &id);
+ new_resource(&r, &ids[2]);
assert(r.resource_count == 3);
assert(r.current_capacity >= 3);
}
@@ -46,6 +52,9 @@ void test_int_resource_manager()
// 2 item case
init_resource_manager(&r, sizeof(int), 1, 2);
+ init_id(&id);
+ init_id(&first_id);
+
p = new_resource(&r, &first_id);
assert(p);
*p = 42;
@@ -73,8 +82,11 @@ void test_entity_system()
entity_id ent_id;
entity_id *ids;
+ init_node_manager();
init_entity_system();
+ init_id(&ent_id);
+
ents = get_all_entities(&count, &ids);
assert(count == 0);