1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#include "scene_memory.h"
#include <gfx/sizes.h>
#include "animation_impl.h"
#include "camera_impl.h"
#include "light_impl.h"
#include "material_impl.h"
#include "mesh_impl.h"
#include "model_impl.h"
#include "node_impl.h"
#include "object_impl.h"
#include "scene_impl.h"
#include <mempool.h>
DEF_MEMPOOL(anima_pool, Anima, GFX_MAX_NUM_ANIMAS)
DEF_MEMPOOL(animation_pool, Animation, GFX_MAX_NUM_ANIMATIONS)
DEF_MEMPOOL(camera_pool, SceneCamera, GFX_MAX_NUM_CAMERAS)
DEF_MEMPOOL(light_pool, Light, GFX_MAX_NUM_LIGHTS)
DEF_MEMPOOL(material_pool, Material, GFX_MAX_NUM_MATERIALS)
DEF_MEMPOOL(mesh_pool, Mesh, GFX_MAX_NUM_MESHES)
DEF_MEMPOOL(mesh_link_pool, MeshLink, GFX_MAX_NUM_MESH_LINKS)
DEF_MEMPOOL(model_pool, Model, GFX_MAX_NUM_MODELS)
DEF_MEMPOOL(node_pool, SceneNode, GFX_MAX_NUM_NODES)
DEF_MEMPOOL(object_pool, SceneObject, GFX_MAX_NUM_OBJECTS)
DEF_MEMPOOL(scene_pool, Scene, GFX_MAX_NUM_SCENES)
DEF_MEMPOOL(skeleton_pool, Skeleton, GFX_MAX_NUM_SKELETONS)
/// Scene memory.
///
/// Holds memory pools for every type of scene object.
typedef struct SceneMemory {
anima_pool animas;
animation_pool animations;
camera_pool cameras;
light_pool lights;
material_pool materials;
mesh_pool meshs; // Purposeful typo to make the PLURAL() macro work.
mesh_link_pool mesh_links;
model_pool models;
node_pool nodes;
object_pool objects;
scene_pool scenes;
skeleton_pool skeletons;
} SceneMemory;
static SceneMemory mem;
#define ALLOC_DUMMY(POOL) \
{ \
const void* object = mempool_alloc(POOL); \
assert(mempool_get_block_index(POOL, object) == 0); \
}
#define PLURAL(name) name##s
#define MEM_FIELD(name) mem.PLURAL(name)
void scene_mem_init() {
mempool_make(&mem.animas);
mempool_make(&mem.animations);
mempool_make(&mem.cameras);
mempool_make(&mem.lights);
mempool_make(&mem.materials);
mempool_make(&mem.meshs);
mempool_make(&mem.mesh_links);
mempool_make(&mem.models);
mempool_make(&mem.nodes);
mempool_make(&mem.objects);
mempool_make(&mem.scenes);
mempool_make(&mem.skeletons);
// Allocate dummy objects at index 0 to guarantee that no objects allocated by
// the caller map to index 0.
ALLOC_DUMMY(&mem.animas);
ALLOC_DUMMY(&mem.animations);
ALLOC_DUMMY(&mem.cameras);
ALLOC_DUMMY(&mem.lights);
ALLOC_DUMMY(&mem.materials);
ALLOC_DUMMY(&mem.meshs);
ALLOC_DUMMY(&mem.mesh_links);
ALLOC_DUMMY(&mem.models);
ALLOC_DUMMY(&mem.nodes);
ALLOC_DUMMY(&mem.objects);
ALLOC_DUMMY(&mem.scenes);
ALLOC_DUMMY(&mem.skeletons);
}
void scene_mem_destroy() {
// NOTE: the dummy objects are not constructed, so the destruction code below
// always skips index 0. (I don't really like the conditional inside the loop,
// but this gets the job done without having to specialize the loop macro.)
#define DESTROY(name) \
mempool_foreach(&MEM_FIELD(name), obj, { \
if (i > 0) { \
gfx_destroy_##name(&obj); \
} \
})
// Models contain scene elements. Destruction is handled by the remainder of
// scene destructionb elow.
//
// First destroy the scenes. This will recursively destroy the scene's nodes
// and their objects and avoid a double-free when we then destroy any stray
// scene elements.
DESTROY(scene);
// Then delete stray nodes. This will delete their children nodes and
// resource.
DESTROY(node);
// Destroy remaining scene elements.
DESTROY(anima);
// Animations are owned by animas and do not have a destructor.
DESTROY(camera);
DESTROY(light);
DESTROY(material);
DESTROY(mesh);
// Mesh links don't have a destructor.
DESTROY(object);
// Skeletons are owned by animas and do not have a destructor.
}
#define DEF_MEMORY(name, type) \
/* xyz* mem_alloc_xyz(); */ \
type* mem_alloc_##name() { return mempool_alloc(&MEM_FIELD(name)); } \
/* void mem_free_xyz(xyz**); */ \
void mem_free_##name(type** obj) { mempool_free(&MEM_FIELD(name), obj); } \
/* xyz* mem_get_xyz(xyz_idx); */ \
type* mem_get_##name(NAMED_INDEX(name) index) { \
assert(index.val != 0); /* 0 is the dummy allocation. */ \
return mempool_get_block(&MEM_FIELD(name), index.val); \
} \
/* xyz_idx mem_get_xyz_index(const xyz*); */ \
NAMED_INDEX(name) mem_get_##name##_index(const type* obj) { \
return (NAMED_INDEX(name)){ \
.val = mempool_get_block_index(&MEM_FIELD(name), obj)}; \
}
DEF_MEMORY(anima, Anima)
DEF_MEMORY(animation, Animation)
DEF_MEMORY(camera, SceneCamera)
DEF_MEMORY(light, Light)
DEF_MEMORY(material, Material)
DEF_MEMORY(mesh, Mesh)
DEF_MEMORY(mesh_link, MeshLink)
DEF_MEMORY(model, Model)
DEF_MEMORY(node, SceneNode)
DEF_MEMORY(object, SceneObject)
DEF_MEMORY(scene, Scene)
DEF_MEMORY(skeleton, Skeleton)
|