-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathscene.c
187 lines (159 loc) · 5.11 KB
/
scene.c
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include "mio.h"
static int find_bone(struct skel *skel, const char *name)
{
int i;
for (i = 0; i < skel->count; i++)
if (!strcmp(skel->name[i], name))
return i;
return -1;
}
void pose_lerp(struct pose *p, const struct pose *a, const struct pose *b, float t)
{
vec_lerp(p->position, a->position, b->position, t);
quat_lerp_neighbor_normalize(p->rotation, a->rotation, b->rotation, t);
vec_lerp(p->scale, a->scale, b->scale, t);
}
void init_transform(struct transform *trafo)
{
vec_init(trafo->position, 0, 0, 0);
quat_init(trafo->rotation, 0, 0, 0, 1);
vec_init(trafo->scale, 1, 1, 1);
mat_identity(trafo->matrix);
}
void init_skelpose(struct skelpose *skelpose, struct skel *skel)
{
int i;
skelpose->skel = skel;
for (i = 0; i < skel->count; i++)
skelpose->pose[i] = skel->pose[i];
}
void init_lamp(struct lamp *lamp)
{
lamp->type = LAMP_POINT;
vec_init(lamp->color, 1, 1, 1);
lamp->energy = 1;
lamp->distance = 25;
lamp->spot_angle = 45;
}
void update_transform(struct transform *transform)
{
mat_from_pose(transform->matrix, transform->position, transform->rotation, transform->scale);
}
void update_transform_parent(struct transform *transform, struct transform *parent)
{
mat4 local_matrix;
mat_from_pose(local_matrix, transform->position, transform->rotation, transform->scale);
mat_mul44(transform->matrix, parent->matrix, local_matrix);
}
void calc_pose(mat4 out, struct skel *skel, struct pose *pose, int bone)
{
int parent = skel->parent[bone];
if (parent == -1) {
mat_from_pose(out, pose[bone].position, pose[bone].rotation, pose[bone].scale);
} else {
mat4 par, loc;
calc_pose(par, skel, pose, parent);
mat_from_pose(loc, pose[bone].position, pose[bone].rotation, pose[bone].scale);
mat_mul44(out, par, loc);
}
}
void update_transform_parent_skel(struct transform *transform,
struct transform *parent, struct skelpose *skelpose, const char *bone)
{
mat4 local_matrix, pose_matrix, m;
int i = find_bone(skelpose->skel, bone);
mat_from_pose(local_matrix, transform->position, transform->rotation, transform->scale);
calc_pose(pose_matrix, skelpose->skel, skelpose->pose, i);
mat_mul44(m, pose_matrix, local_matrix);
mat_mul44(transform->matrix, parent->matrix, m);
}
static mat4 proj;
static mat4 view;
void render_camera(mat4 iproj, mat4 iview)
{
mat_copy(proj, iproj);
mat_copy(view, iview);
}
void render_skelpose(struct transform *transform, struct skelpose *skelpose)
{
struct skel *skel = skelpose->skel;
struct pose *pose = skelpose->pose;
mat4 local_pose[MAXBONE];
mat4 model_pose[MAXBONE];
mat4 model_view;
calc_matrix_from_pose(local_pose, pose, skel->count);
calc_abs_matrix(model_pose, local_pose, skel->parent, skel->count);
mat_mul(model_view, view, transform->matrix);
draw_begin(proj, model_view);
draw_set_color(1, 1, 1, 1);
draw_skel(model_pose, skel->parent, skel->count);
draw_end();
}
void animate_skelpose(struct skelpose *skelpose, struct anim *anim, float frame, float blend)
{
struct skel *skel = skelpose->skel;
struct pose *pose = skelpose->pose;
struct skel *askel = anim->skel;
struct pose apose[MAXBONE];
int si, ai;
extract_frame(apose, anim, frame);
if (anim->loop) {
vec3 dpos;
vec4 drot, identity, tmp;
float t;
t = frame / (anim->frames - 1);
vec_scale(dpos, anim->motion.position, t);
vec_sub(apose[0].position, apose[0].position, dpos);
quat_init(identity, 0, 0, 0, 1);
quat_conjugate(drot, anim->motion.rotation);
quat_lerp_neighbor_normalize(drot, identity, drot, t);
quat_copy(tmp, apose[0].rotation);
quat_mul(apose[0].rotation, drot, tmp);
}
for (si = 0; si < skel->count; si++) {
// TODO: bone map
ai = find_bone(askel, skel->name[si]);
if (blend == 1)
pose[si] = ai >= 0 ? apose[ai] : skel->pose[si];
else
pose_lerp(pose+si, pose+si, ai >= 0 ? apose+ai : skel->pose+si, blend);
}
}
void render_mesh_skel(struct transform *transform, struct mesh *mesh, struct skelpose *skelpose)
{
struct skel *skel = skelpose->skel;
struct pose *pose = skelpose->pose;
struct skel *ms = mesh->skel;
mat4 local_pose[MAXBONE];
mat4 model_pose[MAXBONE];
mat4 model_view;
mat4 model_from_bind_pose[MAXBONE];
int mi, si;
calc_matrix_from_pose(local_pose, pose, skel->count);
calc_abs_matrix(model_pose, local_pose, skel->parent, skel->count);
mat_mul(model_view, view, transform->matrix);
for (mi = 0; mi < ms->count; mi++) {
// TODO: bone map
si = find_bone(skel, ms->name[mi]);
if (si < 0) {
fprintf(stderr, "cannot find bone: %s\n", skel->name[mi]);
return; /* error! */
}
mat_mul(model_from_bind_pose[mi], model_pose[si], mesh->inv_bind_matrix[mi]);
}
render_skinned_mesh(mesh, proj, model_view, model_from_bind_pose);
}
void render_mesh(struct transform *transform, struct mesh *mesh)
{
mat4 model_view;
mat_mul(model_view, view, transform->matrix);
render_static_mesh(mesh, proj, model_view);
}
void render_lamp(struct transform *transform, struct lamp *lamp)
{
switch (lamp->type) {
case LAMP_POINT: render_point_lamp(lamp, proj, view, transform->matrix); break;
case LAMP_SPOT: render_spot_lamp(lamp, proj, view, transform->matrix); break;
case LAMP_SUN: render_sun_lamp(lamp, proj, view, transform->matrix); break;
}
}