UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_mesh_anim.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "r_local.h"
27 #include "r_mesh.h"
28 #include "r_mesh_anim.h"
29 
30 #define LOOPNEXT(x) ((x + 1 < MAX_ANIMLIST) ? x + 1 : 0)
31 
35 static inline void R_AnimAdd (animState_t* as, const model_t* mod, const mAliasAnim_t* anim)
36 {
37  assert(as->ladd < sizeof(as->list));
38 
39  as->list[as->ladd] = anim - mod->alias.animdata;
40 
41  /* advance in list (no overflow protection!) */
42  as->ladd = LOOPNEXT(as->ladd);
43 }
47 #define R_AnimGetAliasAnim(mod, as) ((mod)->alias.animdata + (as)->list[(as)->lcur])
48 
59 static const mAliasAnim_t* R_AnimGet (const model_t* mod, const char* name)
60 {
61  mAliasAnim_t* anim;
62  int i;
63 
64  if (!mod || !mod->alias.num_anims)
65  return nullptr;
66 
67  for (i = 0, anim = mod->alias.animdata; i < mod->alias.num_anims; i++, anim++)
68  if (Q_streq(name, anim->name))
69  return anim;
70 
71  return nullptr;
72 }
73 
84 void R_AnimAppend (animState_t* as, const model_t* mod, const char* name)
85 {
86  const mAliasAnim_t* anim;
87 
88  if (!mod) {
89  Com_Printf("R_AnimAppend: No model given (%s)\n", name);
90  return;
91  }
92 
93  if (!mod->alias.num_anims) {
94  Com_Printf("R_AnimAppend: Model with no animations (%s) (model: %s)\n", name, mod->name);
95  return;
96  }
97 
98  /* get animation */
99  anim = R_AnimGet(mod, name);
100  if (!anim) {
101  Com_Printf("R_AnimAppend: No such animation: %s (model: %s)\n", name, mod->name);
102  return;
103  }
104 
105  if (as->lcur == as->ladd) {
106  /* first animation */
107  as->oldframe = anim->from;
108  if (anim->to > anim->from)
109  as->frame = anim->from + 1;
110  else
111  as->frame = anim->from;
112 
113  as->backlerp = 0.0;
114  as->time = anim->time;
115  as->dt = 0;
116 
117  as->change = true;
118  }
119 
120  R_AnimAdd(as, mod, anim);
121 }
122 
123 
134 void R_AnimChange (animState_t* as, const model_t* mod, const char* name)
135 {
136  const mAliasAnim_t* anim;
137 
138  if (!mod) {
139  Com_Printf("R_AnimChange: No model given (%s)\n", name);
140  return;
141  }
142 
143  if (!mod->alias.num_anims) {
144  Com_Printf("R_AnimChange: Model with no animations (%s) (model: %s)\n", name, mod->name);
145  return;
146  }
147 
148  /* get animation */
149  anim = R_AnimGet(mod, name);
150  if (!anim) {
151  Com_Printf("R_AnimChange: No such animation: %s (model: %s)\n", name, mod->name);
152  return;
153  }
154 
155  if (as->lcur == as->ladd) {
156  /* first animation */
157  as->oldframe = anim->from;
158  if (anim->to > anim->from)
159  as->frame = anim->from + 1;
160  else
161  as->frame = anim->from;
162 
163  as->backlerp = 1.0;
164  as->time = anim->time;
165  as->dt = 0;
166 
167  as->change = true;
168  } else {
169  /* next animation */
170  as->ladd = LOOPNEXT(as->lcur);
171  if (anim->time < as->time)
172  as->time = anim->time;
173  /* don't change to the same animation */
174  if (anim != R_AnimGetAliasAnim(mod, as))
175  as->change = true;
176  }
177 
178  R_AnimAdd(as, mod, anim);
179 }
180 
181 
192 void R_AnimRun (animState_t* as, const model_t* mod, int msec)
193 {
194  assert(as->lcur < MAX_ANIMLIST);
195 
196  if (!mod || !mod->alias.num_anims)
197  return;
198 
199  if (as->lcur == as->ladd)
200  return;
201 
202  as->dt += msec;
203 
204  while (as->dt > as->time) {
205  const mAliasAnim_t* anim = R_AnimGetAliasAnim(mod, as);
206  as->dt -= as->time;
207 
208  if (as->change || as->frame >= anim->to) {
209  /* go to next animation if it isn't the last one */
210  if (LOOPNEXT(as->lcur) != as->ladd)
211  as->lcur = LOOPNEXT(as->lcur);
212 
213  anim = R_AnimGetAliasAnim(mod, as);
214 
215  /* prepare next frame */
216  as->dt = 0;
217  as->time = anim->time;
218  as->oldframe = as->frame;
219  as->frame = anim->from;
220  as->change = false;
221  } else {
222  /* next frame of the same animation */
223  as->time = anim->time;
224  as->oldframe = as->frame;
225  as->frame++;
226  }
227  }
228 
229  as->backlerp = 1.0 - (float) as->dt / as->time;
230 }
231 
242 const char* R_AnimGetName (const animState_t* as, const model_t* mod)
243 {
244  const mAliasAnim_t* anim;
245 
246  assert(as->lcur < MAX_ANIMLIST);
247 
248  if (!mod || !mod->alias.num_anims)
249  return nullptr;
250 
251  if (as->lcur == as->ladd)
252  return nullptr;
253 
254  anim = R_AnimGetAliasAnim(mod, as);
255  return anim->name;
256 }
int oldframe
Definition: r_entity.h:56
mAliasModel_t alias
Definition: r_model.h:63
static const mAliasAnim_t * R_AnimGet(const model_t *mod, const char *name)
Searches a given animation id in the given model data.
Definition: r_mesh_anim.cpp:59
int time
Definition: r_entity.h:58
#define R_AnimGetAliasAnim(mod, as)
Get the mAliasAnim_t for the given animation state.
Definition: r_mesh_anim.cpp:47
#define LOOPNEXT(x)
Definition: r_mesh_anim.cpp:30
local graphics definitions
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
#define MAX_ANIMLIST
Definition: r_entity.h:27
static void R_AnimAdd(animState_t *as, const model_t *mod, const mAliasAnim_t *anim)
Adds the given animation to the animation state.
Definition: r_mesh_anim.cpp:35
void R_AnimChange(animState_t *as, const model_t *mod, const char *name)
Changes the animation for md2 models.
int frame
Definition: r_entity.h:55
byte list[MAX_ANIMLIST]
Definition: r_entity.h:62
byte lcur
Definition: r_entity.h:63
char name[MAX_QPATH]
Definition: r_model.h:44
void R_AnimRun(animState_t *as, const model_t *mod, int msec)
Run the animation of the given model.
byte change
Definition: r_entity.h:65
QGL_EXTERN GLint i
Definition: r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
const char * R_AnimGetName(const animState_t *as, const model_t *mod)
Get the current running animation for a model.
char name[MAX_ANIMNAME]
byte ladd
Definition: r_entity.h:64
#define Q_streq(a, b)
Definition: shared.h:136
void R_AnimAppend(animState_t *as, const model_t *mod, const char *name)
Appends a new animation to the current running one.
Definition: r_mesh_anim.cpp:84
mAliasAnim_t * animdata
float backlerp
Definition: r_entity.h:57