Inexor
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
animmodel.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 struct animmodel : model
4 {
5  struct animspec
6  {
7  int frame, range;
8  float speed;
9  int priority;
10  };
11 
12  struct animpos
13  {
14  int anim, fr1, fr2;
15  float t;
16 
17  void setframes(const animinfo &info)
18  {
19  anim = info.anim;
20  if(info.range<=1)
21  {
22  fr1 = 0;
23  t = 0;
24  }
25  else
26  {
27  int time = info.anim&ANIM_SETTIME ? info.basetime : lastmillis-info.basetime;
28  fr1 = (int)(time/info.speed); // round to full frames
29  t = (time-fr1*info.speed)/info.speed; // progress of the frame, value from 0.0f to 1.0f
30  }
31  if(info.anim&ANIM_LOOP)
32  {
33  fr1 = fr1%info.range+info.frame;
34  fr2 = fr1+1;
35  if(fr2>=info.frame+info.range) fr2 = info.frame;
36  }
37  else
38  {
39  fr1 = min(fr1, info.range-1)+info.frame;
40  fr2 = min(fr1+1, info.frame+info.range-1);
41  }
42  if(info.anim&ANIM_REVERSE)
43  {
44  fr1 = (info.frame+info.range-1)-(fr1-info.frame);
45  fr2 = (info.frame+info.range-1)-(fr2-info.frame);
46  }
47  }
48 
49  bool operator==(const animpos &a) const { return fr1==a.fr1 && fr2==a.fr2 && (fr1==fr2 || t==a.t); }
50  bool operator!=(const animpos &a) const { return fr1!=a.fr1 || fr2!=a.fr2 || (fr1!=fr2 && t!=a.t); }
51  };
52 
53  struct part;
54 
55  struct animstate
56  {
59  float interp;
60 
61  bool operator==(const animstate &a) const { return cur==a.cur && (interp<1 ? interp==a.interp && prev==a.prev : a.interp>=1); }
62  bool operator!=(const animstate &a) const { return cur!=a.cur || (interp<1 ? interp!=a.interp || prev!=a.prev : a.interp<1); }
63  };
64 
65  struct linkedpart;
66  struct mesh;
67 
68  struct shaderparams
69  {
71 
72  shaderparams() : spec(1.0f), ambient(0.3f), glow(3.0f), glowdelta(0), glowpulse(0), specglare(1), glowglare(1), fullbright(0), envmapmin(0), envmapmax(0), scrollu(0), scrollv(0), alphatest(0.9f) {}
73  };
74 
76  {
79 
80  int version;
81 
83 
84  bool checkversion()
85  {
86  if(version >= firstversion) return true;
88  if(++lastversion <= 0)
89  {
90  enumerate(keys, shaderparamskey, key, key.version = -1);
91  firstversion = 0;
92  lastversion = 1;
93  version = 0;
94  }
95  return false;
96  }
97 
98  static inline void invalidate()
99  {
101  }
102  };
103 
105  {
111 
112  skin() : owner(nullptr), tex(notexture), masks(notexture), envmap(nullptr), normalmap(nullptr), shader(nullptr), alphablend(true), cullface(true), key(nullptr) {}
113 
114  bool masked() const { return masks != notexture; }
115  bool envmapped() { return envmapmax>0 && envmapmodels; }
116  bool bumpmapped() { return normalmap && bumpmodels; }
117  bool tangents() { return bumpmapped(); }
118  bool alphatested() const { return alphatest > 0 && tex->type&Texture::ALPHA; }
119 
120  void setkey()
121  {
122  key = &shaderparamskey::keys[*this];
123  }
124 
125  void setshaderparams(mesh *m, const animstate *as)
126  {
127  float mincolor = as->cur.anim&ANIM_FULLBRIGHT ? fullbrightmodels/100.0f : 0.0f;
128  if(fullbright)
129  {
130  gle::colorf(fullbright/2, fullbright/2, fullbright/2, transparent);
131  }
132  else
133  {
134  gle::color(vec(lightcolor).max(mincolor), transparent);
135  }
136 
137  if(key->checkversion() && Shader::lastshader->owner == key) return;
139 
141 
142  if(fullbright)
143  {
144  LOCALPARAMF(lightscale, 0, 0, 2);
145  }
146  else
147  {
148  float bias = max(mincolor-1.0f, 0.2f), scale = 0.5f*max(0.8f-bias, 0.0f),
149  minshade = scale*max(ambient, mincolor);
150  LOCALPARAMF(lightscale, scale - minshade, scale, minshade + bias);
151  }
152  float curglow = glow;
153  if(glowpulse > 0)
154  {
155  float curpulse = lastmillis*glowpulse;
156  curpulse -= floor(curpulse);
157  curglow += glowdelta*2*fabs(curpulse - 0.5f);
158  }
159  LOCALPARAMF(maskscale, 0.5f*spec, 0.5f*curglow, 16*specglare, 4*glowglare);
161  if(envmapped()) LOCALPARAMF(envmapscale, envmapmin-envmapmax, envmapmax);
162  }
163 
165  {
166  #define DOMODELSHADER(name, body) \
167  do { \
168  static Shader *name##shader = NULL; \
169  if(!name##shader) name##shader = useshaderbyname(#name); \
170  body; \
171  } while(0)
172  #define LOADMODELSHADER(name) DOMODELSHADER(name, return name##shader)
173  #define SETMODELSHADER(m, name) DOMODELSHADER(name, (m)->setshader(name##shader))
174  if(shader) return shader;
175 
176  string opts;
177  int optslen = 0;
178  if(alphatested()) opts[optslen++] = 'a';
179  if(owner->tangents()) opts[optslen++] = 'q';
180  if(bumpmapped()) opts[optslen++] = 'n';
181  if(envmapped()) opts[optslen++] = 'e';
182  if(masked()) opts[optslen++] = 'm';
183  if(!fullbright && (masked() || spec>=0.01f)) opts[optslen++] = 's';
184  opts[optslen++] = '\0';
185 
186  defformatstring(name, "model%s", opts);
187  shader = generateshader(name, "modelshader \"%s\"", opts);
188  return shader;
189  }
190 
191  void cleanup()
192  {
193  if(shader && shader->standard) shader = nullptr;
194  }
195 
196  void preloadBIH()
197  {
199  }
200 
201  void preloadshader(bool force)
202  {
203  if(force) cleanup();
204  loadshader();
205  }
206 
207  void setshader(mesh *m, const animstate *as)
208  {
209  m->setshader(loadshader());
210  }
211 
212  void bind(mesh *b, const animstate *as)
213  {
214  if(!cullface && enablecullface) { glDisable(GL_CULL_FACE); enablecullface = false; }
215  else if(cullface && !enablecullface) { glEnable(GL_CULL_FACE); enablecullface = true; }
216 
217  if(as->cur.anim&ANIM_NOSKIN)
218  {
219  if(enablealphablend) { glDisable(GL_BLEND); enablealphablend = false; }
220  if(shadowmapping) SETMODELSHADER(b, shadowmapcaster);
221  else /*if(as->cur.anim&ANIM_SHADOW)*/ SETMODELSHADER(b, notexturemodel);
222  return;
223  }
224  setshader(b, as);
225  setshaderparams(b, as);
226  int activetmu = 0;
227  if(tex!=lasttex)
228  {
229  glBindTexture(GL_TEXTURE_2D, tex->id);
230  lasttex = tex;
231  }
233  {
234  glActiveTexture_(GL_TEXTURE3);
235  activetmu = 3;
236  glBindTexture(GL_TEXTURE_2D, normalmap->id);
238  }
239  if(tex->type&Texture::ALPHA)
240  {
241  if(alphablend)
242  {
244  {
245  glEnable(GL_BLEND);
246  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
247  enablealphablend = true;
248  }
249  }
250  else if(enablealphablend) { glDisable(GL_BLEND); enablealphablend = false; }
251  }
252  else if(enablealphablend && transparent>=1) { glDisable(GL_BLEND); enablealphablend = false; }
253  if(masked() && masks!=lastmasks)
254  {
255  glActiveTexture_(GL_TEXTURE1);
256  activetmu = 1;
257  glBindTexture(GL_TEXTURE_2D, masks->id);
258  lastmasks = masks;
259  }
260  if(envmapped())
261  {
262  GLuint emtex = envmap ? envmap->id : closestenvmaptex;
263  if(lastenvmaptex!=emtex)
264  {
265  glActiveTexture_(GL_TEXTURE2);
266  activetmu = 2;
267  glBindTexture(GL_TEXTURE_CUBE_MAP, emtex);
268  lastenvmaptex = emtex;
269  }
270  }
271  if(activetmu != 0) glActiveTexture_(GL_TEXTURE0);
272  }
273  };
274 
275  struct meshgroup;
276 
277  struct mesh
278  {
280  char *name;
281  bool noclip;
282 
283  mesh() : group(nullptr), name(nullptr), noclip(false)
284  {
285  }
286 
287  virtual ~mesh()
288  {
289  DELETEA(name);
290  }
291 
292  virtual void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) {}
293 
294  virtual void genBIH(BIH::mesh &m) {}
296  {
297  BIH::mesh &m = bih.add();
298  m.xform = t;
299  m.tex = s.tex;
301  if(noclip) m.flags |= BIH::MESH_NOCLIP;
302  if(s.cullface) m.flags |= BIH::MESH_CULLFACE;
303  genBIH(m);
304  }
305 
306  virtual void setshader(Shader *s)
307  {
308  if(glaring) s->setvariant(0, 1);
309  else s->set();
310  }
311 
312  template<class V, class T> void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight)
313  {
314  hashtable<vec, int> share;
315  int *next = new int[numverts];
316  memset(next, -1, numverts*sizeof(int));
317  loopi(numverts)
318  {
319  V &v = verts[i];
320  v.norm = vec(0, 0, 0);
321  int idx = share.access(v.pos, i);
322  if(idx != i) { next[i] = next[idx]; next[idx] = i; }
323  }
324  loopi(numtris)
325  {
326  T &t = tris[i];
327  V &v1 = verts[t.vert[0]], &v2 = verts[t.vert[1]], &v3 = verts[t.vert[2]];
328  vec norm;
329  norm.cross(vec(v2.pos).sub(v1.pos), vec(v3.pos).sub(v1.pos));
330  if(!areaweight) norm.normalize();
331  v1.norm.add(norm);
332  v2.norm.add(norm);
333  v3.norm.add(norm);
334  }
335  vec *norms = new vec[numverts];
336  memset(norms, 0, numverts*sizeof(vec));
337  loopi(numverts)
338  {
339  V &v = verts[i];
340  norms[i].add(v.norm);
341  if(next[i] >= 0)
342  {
343  float vlimit = limit*v.norm.magnitude();
344  for(int j = next[i]; j >= 0; j = next[j])
345  {
346  V &o = verts[j];
347  if(v.norm.dot(o.norm) >= vlimit*o.norm.magnitude())
348  {
349  norms[i].add(o.norm);
350  norms[j].add(v.norm);
351  }
352  }
353  }
354  }
355  loopi(numverts) verts[i].norm = norms[i].normalize();
356  delete[] next;
357  delete[] norms;
358  }
359 
360  template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight)
361  {
362  loopi(numverts) verts[i].norm = vec(0, 0, 0);
363  loopi(numtris)
364  {
365  T &t = tris[i];
366  V &v1 = verts[t.vert[0]], &v2 = verts[t.vert[1]], &v3 = verts[t.vert[2]];
367  vec norm;
368  norm.cross(vec(v2.pos).sub(v1.pos), vec(v3.pos).sub(v1.pos));
369  if(!areaweight) norm.normalize();
370  v1.norm.add(norm);
371  v2.norm.add(norm);
372  v3.norm.add(norm);
373  }
374  loopi(numverts) verts[i].norm.normalize();
375  }
376 
377  template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes)
378  {
379  if(!numverts) return;
380  loopi(numframes) buildnorms(&verts[i*numverts], numverts, tris, numtris, areaweight);
381  }
382 
383  static inline void fixqtangent(quat &q, float bt)
384  {
385  static const float bias = -1.5f/65535, biasscale = sqrtf(1 - bias*bias);
386  if(bt < 0)
387  {
388  if(q.w >= 0) q.neg();
389  if(q.w > bias) { q.mul3(biasscale); q.w = bias; }
390  }
391  else if(q.w < 0) q.neg();
392  }
393 
394  template<class V> static inline void calctangent(V &v, const vec &n, const vec &t, float bt)
395  {
396  matrix3 m;
397  m.c = n;
398  m.a = t;
399  m.b.cross(m.c, m.a);
400  quat q(m);
401  fixqtangent(q, bt);
402  v.tangent = q;
403  }
404 
405  template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight)
406  {
407  vec *tangent = new vec[2*numverts], *bitangent = tangent+numverts;
408  memset(tangent, 0, 2*numverts*sizeof(vec));
409  loopi(numtris)
410  {
411  const T &t = tris[i];
412  const vec &e0 = verts[t.vert[0]].pos;
413  vec e1 = vec(verts[t.vert[1]].pos).sub(e0), e2 = vec(verts[t.vert[2]].pos).sub(e0);
414 
415  const vec2 &tc0 = tcverts[t.vert[0]].tc,
416  &tc1 = tcverts[t.vert[1]].tc,
417  &tc2 = tcverts[t.vert[2]].tc;
418  float u1 = tc1.x - tc0.x, v1 = tc1.y - tc0.y,
419  u2 = tc2.x - tc0.x, v2 = tc2.y - tc0.y;
420  vec u(e2), v(e2);
421  u.mul(v1).sub(vec(e1).mul(v2));
422  v.mul(u1).sub(vec(e1).mul(u2));
423 
424  if(vec().cross(e2, e1).dot(vec().cross(v, u)) >= 0)
425  {
426  u.neg();
427  v.neg();
428  }
429 
430  if(!areaweight)
431  {
432  u.normalize();
433  v.normalize();
434  }
435 
436  loopj(3)
437  {
438  tangent[t.vert[j]].sub(u);
439  bitangent[t.vert[j]].add(v);
440  }
441  }
442  loopi(numverts)
443  {
444  const vec &n = verts[i].norm,
445  &t = tangent[i],
446  &bt = bitangent[i];
447  B &bv = bumpverts[i];
448  matrix3 m;
449  m.c = n;
450  (m.a = t).project(m.c).normalize();
451  m.b.cross(m.c, m.a);
452  quat q(m);
453  fixqtangent(q, m.b.dot(bt));
454  bv.tangent = q;
455  }
456  delete[] tangent;
457  }
458 
459  template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight, int numframes)
460  {
461  loopi(numframes) calctangents(&bumpverts[i*numverts], &verts[i*numverts], tcverts, numverts, tris, numtris, areaweight);
462  }
463  };
464 
465  struct meshgroup
466  {
468  int shared;
469  char *name;
471 
472  meshgroup() : next(nullptr), shared(0), name(nullptr)
473  {
474  }
475 
476  virtual ~meshgroup()
477  {
478  DELETEA(name);
479  meshes.deletecontents();
480  DELETEP(next);
481  }
482 
483  virtual int findtag(const char *name) { return -1; }
484  virtual void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) {}
485 
486  void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m)
487  {
488  loopv(meshes) meshes[i]->calcbb(bbmin, bbmax, m);
489  }
490 
492  {
493  loopv(meshes) meshes[i]->genBIH(skins[i], bih, t);
494  }
495 
496  virtual void *animkey() { return this; }
497  virtual int totalframes() const { return 1; }
498  bool hasframe(int i) const { return i>=0 && i<totalframes(); }
499  bool hasframes(int i, int n) const { return i>=0 && i+n<=totalframes(); }
500  int clipframes(int i, int n) const { return min(n, totalframes() - i); }
501 
502  virtual void cleanup() {}
503  virtual void preload(part *p) {}
504  virtual void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) {}
505 
506  void bindpos(GLuint ebuf, GLuint vbuf, void *v, int stride)
507  {
508  if(lastebuf!=ebuf)
509  {
510  gle::bindebo(ebuf);
511  lastebuf = ebuf;
512  }
513  if(lastvbuf!=vbuf)
514  {
515  gle::bindvbo(vbuf);
516  if(!lastvbuf) gle::enablevertex();
517  gle::vertexpointer(stride, v);
518  lastvbuf = vbuf;
519  }
520  }
521 
522  void bindtc(void *v, int stride)
523  {
524  if(!enabletc)
525  {
526  gle::enabletexcoord0();
527  enabletc = true;
528  }
529  if(lasttcbuf!=lastvbuf)
530  {
531  gle::texcoord0pointer(stride, v);
533  }
534  }
535 
536  void bindnormals(void *v, int stride)
537  {
538  if(!enablenormals)
539  {
540  gle::enablenormal();
541  enablenormals = true;
542  }
543  if(lastnbuf!=lastvbuf)
544  {
545  gle::normalpointer(stride, v);
546  lastnbuf = lastvbuf;
547  }
548  }
549 
550  void bindtangents(void *v, int stride)
551  {
552  if(!enabletangents)
553  {
554  gle::enabletangent();
555  enabletangents = true;
556  }
557  if(lastxbuf!=lastvbuf)
558  {
559  gle::tangentpointer(stride, v, GL_SHORT);
560  lastxbuf = lastvbuf;
561  }
562  }
563 
564  void bindbones(void *wv, void *bv, int stride)
565  {
566  if(!enablebones)
567  {
568  gle::enableboneweight();
569  gle::enableboneindex();
570  enablebones = true;
571  }
572  if(lastbbuf!=lastvbuf)
573  {
574  gle::boneweightpointer(stride, wv);
575  gle::boneindexpointer(stride, bv);
576  lastbbuf = lastvbuf;
577  }
578  }
579  };
580 
581  virtual meshgroup *loadmeshes(const char *name, va_list args) { return nullptr; }
582 
583  meshgroup *sharemeshes(const char *name, ...)
584  {
585  static hashnameset<meshgroup *> meshgroups;
586  if(!meshgroups.access(name))
587  {
588  va_list args;
589  va_start(args, name);
590  meshgroup *group = loadmeshes(name, args);
591  va_end(args);
592  if(!group) return nullptr;
593  meshgroups.add(group);
594  }
595  return meshgroups[name];
596  }
597 
598  struct linkedpart
599  {
600  part *p;
605 
606  linkedpart() : p(nullptr), tag(-1), anim(-1), basetime(0), translate(0, 0, 0), pos(nullptr) {}
607  };
608 
609  struct part
610  {
612  int index;
620 
621  part(animmodel *model, int index = 0) : model(model), index(index), meshes(nullptr), numanimparts(1), pitchscale(1), pitchoffset(0), pitchmin(0), pitchmax(0), translate(0, 0, 0)
622  {
623  loopk(MAXANIMPARTS) anims[k] = nullptr;
624  }
625  virtual ~part()
626  {
628  }
629 
630  virtual void cleanup()
631  {
632  if(meshes) meshes->cleanup();
633  loopv(skins) skins[i].cleanup();
634  }
635 
636  void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m)
637  {
638  matrix4x3 t = m;
639  t.translate(translate);
640  t.scale(model->scale);
641  meshes->calcbb(bbmin, bbmax, t);
642  loopv(links)
643  {
644  matrix4x3 n;
645  meshes->concattagtransform(this, links[i].tag, m, n);
647  links[i].p->calcbb(bbmin, bbmax, n);
648  }
649  }
650 
652  {
653  matrix4x3 t = m;
654  t.translate(translate);
655  t.scale(model->scale);
656  meshes->genBIH(skins, bih, t);
657  loopv(links)
658  {
659  matrix4x3 n;
660  meshes->concattagtransform(this, links[i].tag, m, n);
662  links[i].p->genBIH(bih, n);
663  }
664  }
665 
666  bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = nullptr)
667  {
668  int i = meshes ? meshes->findtag(tag) : -1;
669  if(i<0)
670  {
671  loopv(links) if(links[i].p && links[i].p->link(p, tag, translate, anim, basetime, pos)) return true;
672  return false;
673  }
674  linkedpart &l = links.add();
675  l.p = p;
676  l.tag = i;
677  l.anim = anim;
678  l.basetime = basetime;
679  l.translate = translate;
680  l.pos = pos;
681  return true;
682  }
683 
684  bool unlink(part *p)
685  {
686  loopvrev(links) if(links[i].p==p) { links.remove(i, 1); return true; }
687  loopv(links) if(links[i].p && links[i].p->unlink(p)) return true;
688  return false;
689  }
690 
691  void initskins(Texture *tex = notexture, Texture *masks = notexture, int limit = 0)
692  {
693  if(!limit)
694  {
695  if(!meshes) return;
696  limit = meshes->meshes.length();
697  }
698  while(skins.length() < limit)
699  {
700  skin &s = skins.add();
701  s.owner = this;
702  s.tex = tex;
703  s.masks = masks;
704  }
705  }
706 
707  bool envmapped()
708  {
709  loopv(skins) if(skins[i].envmapped()) return true;
710  return false;
711  }
712 
713  bool tangents()
714  {
715  loopv(skins) if(skins[i].tangents()) return true;
716  return false;
717  }
718 
719  void preloadBIH()
720  {
721  loopv(skins) skins[i].preloadBIH();
722  }
723 
724  void preloadshaders(bool force)
725  {
726  loopv(skins) skins[i].preloadshader(force);
727  }
728 
730  {
731  if(meshes) meshes->preload(this);
732  }
733 
734  virtual void getdefaultanim(animinfo &info, int anim, uint varseed, dynent *d)
735  {
736  info.frame = 0;
737  info.range = 1;
738  }
739 
740  bool calcanim(int animpart, int anim, int basetime, int basetime2, dynent *d, int interp, animinfo &info, int &aitime)
741  {
742  uint varseed = uint((size_t)d);
743  info.anim = anim;
744  info.basetime = basetime;
745  info.varseed = varseed;
746  info.speed = anim&ANIM_SETSPEED ? basetime2 : 100.0f;
747  if((anim&ANIM_INDEX)==ANIM_ALL)
748  {
749  info.frame = 0;
750  info.range = meshes->totalframes();
751  }
752  else
753  {
754  animspec *spec = nullptr;
755  if(anims[animpart])
756  {
757  int primaryidx = anim&ANIM_INDEX;
758  if(primaryidx < NUMANIMS)
759  {
760  vector<animspec> &primary = anims[animpart][primaryidx];
761  if(primary.length()) spec = &primary[uint(varseed + basetime)%primary.length()];
762  }
763  if((anim>>ANIM_SECONDARY)&(ANIM_INDEX|ANIM_DIR))
764  {
765  int secondaryidx = (anim>>ANIM_SECONDARY)&ANIM_INDEX;
766  if(secondaryidx < NUMANIMS)
767  {
768  vector<animspec> &secondary = anims[animpart][secondaryidx];
769  if(secondary.length())
770  {
771  animspec &spec2 = secondary[uint(varseed + basetime2)%secondary.length()];
772  if(!spec || spec2.priority > spec->priority)
773  {
774  spec = &spec2;
775  info.anim >>= ANIM_SECONDARY;
776  info.basetime = basetime2;
777  }
778  }
779  }
780  }
781  }
782  if(spec)
783  {
784  info.frame = spec->frame;
785  info.range = spec->range;
786  if(spec->speed>0) info.speed = 1000.0f/spec->speed;
787  }
788  else getdefaultanim(info, anim, uint(varseed + info.basetime), d);
789  }
790 
791  info.anim &= (1<<ANIM_SECONDARY)-1;
792  info.anim |= anim&ANIM_FLAGS;
793  if((info.anim&ANIM_CLAMP) != ANIM_CLAMP)
794  {
795  if(info.anim&(ANIM_LOOP|ANIM_START|ANIM_END))
796  {
797  info.anim &= ~ANIM_SETTIME;
798  if(!info.basetime) info.basetime = -((int)(size_t)d&0xFFF);
799  }
800  if(info.anim&(ANIM_START|ANIM_END))
801  {
802  if(info.anim&ANIM_END) info.frame += info.range-1;
803  info.range = 1;
804  }
805  }
806 
807  if(!meshes->hasframes(info.frame, info.range))
808  {
809  if(!meshes->hasframe(info.frame)) return false;
810  info.range = meshes->clipframes(info.frame, info.range);
811  }
812 
813  if(d && interp>=0)
814  {
815  animinterpinfo &ai = d->animinterp[interp];
816  if((info.anim&ANIM_CLAMP)==ANIM_CLAMP) aitime = min(aitime, int(info.range*info.speed*0.5e-3f));
817  void *ak = meshes->animkey();
818  if(d->ragdoll && !(anim&ANIM_RAGDOLL))
819  {
820  ai.prev.range = ai.cur.range = 0;
821  ai.lastswitch = -1;
822  }
823  else if(ai.lastmodel!=ak || ai.lastswitch<0 || lastmillis-d->lastrendered>aitime)
824  {
825  ai.prev = ai.cur = info;
826  ai.lastswitch = lastmillis-aitime*2;
827  }
828  else if(ai.cur!=info)
829  {
830  if(lastmillis-ai.lastswitch>aitime/2) ai.prev = ai.cur;
831  ai.cur = info;
832  ai.lastswitch = lastmillis;
833  }
834  else if(info.anim&ANIM_SETTIME) ai.cur.basetime = info.basetime;
835  ai.lastmodel = ak;
836  }
837  return true;
838  }
839 
840  void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d)
841  {
843  render(anim, basetime, basetime2, pitch, axis, forward, d, as);
844  }
845 
846  void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, animstate *as)
847  {
848  if(!(anim&ANIM_REUSE)) loopi(numanimparts)
849  {
850  animinfo info;
851  int interp = d && index+numanimparts<=MAXANIMPARTS ? index+i : -1, aitime = animationinterpolationtime;
852  if(!calcanim(i, anim, basetime, basetime2, d, interp, info, aitime)) return;
853  animstate &p = as[i];
854  p.owner = this;
855  p.cur.setframes(info);
856  p.interp = 1;
857  if(interp>=0 && d->animinterp[interp].prev.range>0)
858  {
859  int diff = lastmillis-d->animinterp[interp].lastswitch;
860  if(diff<aitime)
861  {
862  p.prev.setframes(d->animinterp[interp].prev);
863  p.interp = diff/float(aitime);
864  }
865  }
866  }
867 
868  vec oaxis, oforward;
870  float pitchamount = pitchscale*pitch + pitchoffset;
871  if(pitchmin || pitchmax) pitchamount = clamp(pitchamount, pitchmin, pitchmax);
872  if(as->cur.anim&ANIM_NOPITCH || (as->interp < 1 && as->prev.anim&ANIM_NOPITCH))
873  pitchamount *= (as->cur.anim&ANIM_NOPITCH ? 0 : as->interp) + (as->interp < 1 && as->prev.anim&ANIM_NOPITCH ? 0 : 1-as->interp);
874  if(pitchamount)
875  {
876  ++matrixpos;
878  matrixstack[matrixpos].rotate(pitchamount*RAD, oaxis);
879  }
880  matrixstack[matrixpos].transposedtransformnormal(forward, oforward);
881 
882  if(!(anim&ANIM_NORENDER))
883  {
884  matrix4 modelmatrix;
886  if(model->scale!=1) modelmatrix.scale(model->scale);
887  if(!translate.iszero()) modelmatrix.translate(translate);
888  GLOBALPARAM(modelmatrix, modelmatrix);
889 
890  if(!(anim&ANIM_NOSKIN))
891  {
892  if(envmapped()) GLOBALPARAM(modelworld, matrix3(matrixstack[matrixpos]));
893 
894  vec odir, ocampos;
896  GLOBALPARAM(lightdir, odir);
898  ocampos.div(model->scale).sub(translate);
899  GLOBALPARAM(modelcamera, ocampos);
900  }
901  }
902 
903  meshes->render(as, pitch, oaxis, oforward, d, this);
904 
905  if(!(anim&ANIM_REUSE))
906  {
907  loopv(links)
908  {
909  linkedpart &link = links[i];
911 
912  matrixpos++;
914 
915  if(link.pos) *link.pos = matrixstack[matrixpos].gettranslation();
916 
917  if(!link.p)
918  {
919  matrixpos--;
920  continue;
921  }
922 
923  int nanim = anim, nbasetime = basetime, nbasetime2 = basetime2;
924  if(link.anim>=0)
925  {
926  nanim = link.anim | (anim&ANIM_FLAGS);
927  nbasetime = link.basetime;
928  nbasetime2 = 0;
929  }
930  link.p->render(nanim, nbasetime, nbasetime2, pitch, axis, forward, d);
931 
932  matrixpos--;
933  }
934  }
935 
936  if(pitchamount) matrixpos--;
937  }
938 
939  void setanim(int animpart, int num, int frame, int range, float speed, int priority = 0)
940  {
941  if(animpart<0 || animpart>=MAXANIMPARTS) return;
942  if(frame<0 || range<=0 || !meshes || !meshes->hasframes(frame, range))
943  {
944  Log.std->info("invalid frame {}, range {} in model {}", frame, range, model->name);
945  return;
946  }
947  if(!anims[animpart]) anims[animpart] = new vector<animspec>[NUMANIMS];
948  animspec &spec = anims[animpart][num].add();
949  spec.frame = frame;
950  spec.range = range;
951  spec.speed = speed;
952  spec.priority = priority;
953  }
954 
955  virtual void loaded()
956  {
957  meshes->shared++;
958  loopv(skins) skins[i].setkey();
959  }
960  };
961 
962  enum
963  {
964  LINK_TAG = 0,
967  };
968 
969  virtual int linktype(animmodel *m) const { return LINK_TAG; }
970 
971  void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, modelattach *a)
972  {
973  int numtags = 0;
974  if(a)
975  {
976  int index = parts.last()->index + parts.last()->numanimparts;
977  for(int i = 0; a[i].tag; i++)
978  {
979  numtags++;
980 
981  animmodel *m = (animmodel *)a[i].m;
982  if(!m)
983  {
984  if(a[i].pos) link(nullptr, a[i].tag, vec(0, 0, 0), 0, 0, a[i].pos);
985  continue;
986  }
987  part *p = m->parts[0];
988  switch(linktype(m))
989  {
990  case LINK_TAG:
991  p->index = link(p, a[i].tag, vec(0, 0, 0), a[i].anim, a[i].basetime, a[i].pos) ? index : -1;
992  break;
993 
994  case LINK_COOP:
995  p->index = index;
996  break;
997 
998  default:
999  continue;
1000  }
1001  index += p->numanimparts;
1002  }
1003  }
1004 
1005  animstate as[MAXANIMPARTS];
1006  parts[0]->render(anim, basetime, basetime2, pitch, axis, forward, d, as);
1007 
1008  if(a) for(int i = numtags-1; i >= 0; i--)
1009  {
1010  animmodel *m = (animmodel *)a[i].m;
1011  if(!m)
1012  {
1013  if(a[i].pos) unlink(nullptr);
1014  continue;
1015  }
1016  part *p = m->parts[0];
1017  switch(linktype(m))
1018  {
1019  case LINK_TAG:
1020  if(p->index >= 0) unlink(p);
1021  p->index = 0;
1022  break;
1023 
1024  case LINK_COOP:
1025  p->render(anim, basetime, basetime2, pitch, axis, forward, d);
1026  p->index = 0;
1027  break;
1028 
1029  case LINK_REUSE:
1030  p->render(anim | ANIM_REUSE, basetime, basetime2, pitch, axis, forward, d, as);
1031  break;
1032  }
1033  }
1034  }
1035 
1036  void render(int anim, int basetime, int basetime2, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, const vec &color, const vec &dir, float trans) override
1037  {
1038  yaw += spinyaw*lastmillis/1000.0f;
1039  pitch += offsetpitch + spinpitch*lastmillis/1000.0f;
1040 
1041  vec axis(0, -1, 0), forward(1, 0, 0);
1042 
1043  matrixpos = 0;
1044  matrixstack[0].identity();
1045  if(!d || !d->ragdoll || anim&ANIM_RAGDOLL)
1046  {
1049  matrixstack[0].transformnormal(vec(axis), axis);
1050  matrixstack[0].transformnormal(vec(forward), forward);
1052  }
1053  else pitch = 0;
1054 
1055  if(anim&ANIM_NORENDER)
1056  {
1057  render(anim, basetime, basetime2, pitch, axis, forward, d, a);
1058  if(d) d->lastrendered = lastmillis;
1059  return;
1060  }
1061 
1062  if(!(anim&ANIM_NOSKIN))
1063  {
1064  transparent = trans;
1065  lightdir = dir;
1066  lightcolor = color;
1067 
1068  if(envmapped())
1069  {
1070  setupenvmap:
1072  GLOBALPARAM(lightdirworld, dir);
1073  }
1074  else if(a) for(int i = 0; a[i].tag; i++) if(a[i].m && a[i].m->envmapped()) goto setupenvmap;
1075  }
1076 
1078  {
1079  enablepolygonoffset(GL_POLYGON_OFFSET_FILL);
1080  enabledepthoffset = true;
1081  }
1082 
1083  if(transparent<1)
1084  {
1085  if(anim&ANIM_GHOST)
1086  {
1087  glDepthFunc(GL_GREATER);
1088  glDepthMask(GL_FALSE);
1089  }
1090  else if(alphadepth)
1091  {
1092  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1093  render(anim|ANIM_NOSKIN, basetime, basetime2, pitch, axis, forward, d, a);
1094  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, fading ? GL_FALSE : GL_TRUE);
1095 
1096  glDepthFunc(GL_LEQUAL);
1097  }
1098 
1099  if(!enablealphablend)
1100  {
1101  glEnable(GL_BLEND);
1102  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1103  enablealphablend = true;
1104  }
1105  }
1106 
1107  render(anim, basetime, basetime2, pitch, axis, forward, d, a);
1108 
1109  if(transparent<1 && (alphadepth || anim&ANIM_GHOST))
1110  {
1111  glDepthFunc(GL_LESS);
1112  if(anim&ANIM_GHOST) glDepthMask(GL_TRUE);
1113  }
1114 
1115  if(d) d->lastrendered = lastmillis;
1116  }
1117 
1119 
1120  animmodel(const char *name) : model(name)
1121  {
1122  }
1123 
1124  ~animmodel() override
1125  {
1126  parts.deletecontents();
1127  }
1128 
1129  void cleanup() override
1130  {
1131  loopv(parts) parts[i]->cleanup();
1132  }
1133 
1135  {
1136  part *p = new part(this, parts.length());
1137  parts.add(p);
1138  return *p;
1139  }
1140 
1142  {
1143  m.identity();
1146  }
1147 
1149  {
1150  if(parts.empty()) return;
1151  matrix4x3 m;
1152  initmatrix(m);
1153  parts[0]->genBIH(bih, m);
1154  }
1155 
1156  void preloadBIH() override
1157  {
1159  if(bih) loopv(parts) parts[i]->preloadBIH();
1160  }
1161 
1162  BIH *setBIH() override
1163  {
1164  if(bih) return bih;
1165  vector<BIH::mesh> meshes;
1166  genBIH(meshes);
1167  bih = new BIH(meshes);
1168  return bih;
1169  }
1170 
1171  bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = nullptr)
1172  {
1173  if(parts.empty()) return false;
1174  return parts[0]->link(p, tag, translate, anim, basetime, pos);
1175  }
1176 
1177  bool unlink(part *p)
1178  {
1179  if(parts.empty()) return false;
1180  return parts[0]->unlink(p);
1181  }
1182 
1183  bool envmapped() override
1184  {
1185  loopv(parts) if(parts[i]->envmapped()) return true;
1186  return false;
1187  }
1188 
1189  virtual bool loaddefaultparts()
1190  {
1191  return true;
1192  }
1193 
1194  void preloadshaders(bool force) override
1195  {
1196  loopv(parts) parts[i]->preloadshaders(force);
1197  }
1198 
1199  void preloadmeshes() override
1200  {
1201  loopv(parts) parts[i]->preloadmeshes();
1202  }
1203 
1204  void setshader(Shader *shader) override
1205  {
1206  if(parts.empty()) loaddefaultparts();
1207  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].shader = shader;
1208  }
1209 
1210  void setenvmap(float envmapmin, float envmapmax, Texture *envmap) override
1211  {
1212  if(parts.empty()) loaddefaultparts();
1213  loopv(parts) loopvj(parts[i]->skins)
1214  {
1215  skin &s = parts[i]->skins[j];
1216  if(envmapmax)
1217  {
1218  s.envmapmin = envmapmin;
1219  s.envmapmax = envmapmax;
1220  }
1221  if(envmap) s.envmap = envmap;
1222  }
1223  }
1224 
1225  void setspec(float spec) override
1226  {
1227  if(parts.empty()) loaddefaultparts();
1228  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].spec = spec;
1229  }
1230 
1231  void setambient(float ambient) override
1232  {
1233  if(parts.empty()) loaddefaultparts();
1234  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].ambient = ambient;
1235  }
1236 
1237  void setglow(float glow, float delta, float pulse) override
1238  {
1239  if(parts.empty()) loaddefaultparts();
1240  loopv(parts) loopvj(parts[i]->skins)
1241  {
1242  skin &s = parts[i]->skins[j];
1243  s.glow = glow;
1244  s.glowdelta = delta;
1245  s.glowpulse = pulse;
1246  }
1247  }
1248 
1249  void setglare(float specglare, float glowglare) override
1250  {
1251  if(parts.empty()) loaddefaultparts();
1252  loopv(parts) loopvj(parts[i]->skins)
1253  {
1254  skin &s = parts[i]->skins[j];
1255  s.specglare = specglare;
1256  s.glowglare = glowglare;
1257  }
1258  }
1259 
1260  void setalphatest(float alphatest) override
1261  {
1262  if(parts.empty()) loaddefaultparts();
1263  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].alphatest = alphatest;
1264  }
1265 
1266  void setalphablend(bool alphablend) override
1267  {
1268  if(parts.empty()) loaddefaultparts();
1269  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].alphablend = alphablend;
1270  }
1271 
1272  void setfullbright(float fullbright) override
1273  {
1274  if(parts.empty()) loaddefaultparts();
1275  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].fullbright = fullbright;
1276  }
1277 
1278  void setcullface(bool cullface) override
1279  {
1280  if(parts.empty()) loaddefaultparts();
1281  loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].cullface = cullface;
1282  }
1283 
1284  void calcbb(vec &center, vec &radius) override
1285  {
1286  if(parts.empty()) return;
1287  vec bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f);
1288  matrix4x3 m;
1289  initmatrix(m);
1290  parts[0]->calcbb(bbmin, bbmax, m);
1291  radius = bbmax;
1292  radius.sub(bbmin);
1293  radius.mul(0.5f);
1294  center = bbmin;
1295  center.add(radius);
1296  }
1297 
1298  virtual void loaded()
1299  {
1300  scale /= 4;
1301  if(parts.length()) parts[0]->translate = translate;
1302  loopv(parts) parts[i]->loaded();
1303  }
1304 
1310  static int matrixpos;
1311  static matrix4 matrixstack[64];
1312 
1313  void startrender() override
1314  {
1316  enablecullface = true;
1317  lastalphatest = -1;
1319  lasttex = lastmasks = lastnormalmap = nullptr;
1320  transparent = 1;
1322  }
1323 
1324  static void disablebones()
1325  {
1326  gle::disableboneweight();
1327  gle::disableboneindex();
1328  enablebones = false;
1329  }
1330 
1331  static void disabletangents()
1332  {
1333  gle::disabletangent();
1334  enabletangents = false;
1335  }
1336 
1337  static void disabletc()
1338  {
1339  gle::disabletexcoord0();
1340  enabletc = false;
1341  }
1342 
1343  static void disablenormals()
1344  {
1345  gle::disablenormal();
1346  enablenormals = false;
1347  }
1348 
1349  static void disablevbo()
1350  {
1351  gle::clearvbo();
1352  gle::clearebo();
1353  gle::disablevertex();
1354  if(enabletc) disabletc();
1357  if(enablebones) disablebones();
1359  }
1360 
1361  void endrender() override
1362  {
1363  if(lastvbuf || lastebuf) disablevbo();
1364  if(enablealphablend) glDisable(GL_BLEND);
1365  if(!enablecullface) glEnable(GL_CULL_FACE);
1366  if(enabledepthoffset) disablepolygonoffset(GL_POLYGON_OFFSET_FILL);
1367  }
1368 };
1369 
1370 bool animmodel::enabletc = false, animmodel::enablealphablend = false,
1373 vec animmodel::lightdir(0, 0, 1), animmodel::lightcolor(1, 1, 1);
1377 Texture *animmodel::lasttex = nullptr, *animmodel::lastmasks = nullptr, *animmodel::lastnormalmap = nullptr;
1378 int animmodel::matrixpos = 0;
1380 
1381 static inline uint hthash(const animmodel::shaderparams &k)
1382 {
1383  return memhash(&k, sizeof(k));
1384 }
1385 
1386 static inline bool htcmp(const animmodel::shaderparams &x, const animmodel::shaderparams &y)
1387 {
1388  return !memcmp(&x, &y, sizeof(animmodel::shaderparams));
1389 }
1390 
1393 
1394 template<class MDL> struct modelloader
1395 {
1396  static MDL *loading;
1397  static string dir;
1398 
1399  static bool animated() { return true; }
1400  static bool multiparted() { return true; }
1401  static bool multimeshed() { return true; }
1402 };
1403 
1404 template<class MDL> MDL *modelloader<MDL>::loading = nullptr;
1405 template<class MDL> string modelloader<MDL>::dir = {'\0'}; // crashes clang if "" is used here
1406 
1407 template<class MDL, class MESH> struct modelcommands
1408 {
1409  typedef struct MDL::part part;
1410  typedef struct MDL::skin skin;
1411 
1412  static void setdir(char *name)
1413  {
1414  if(!MDL::loading) { Log.std->error("not loading an {}", MDL::formatname()); return; }
1415  formatstring(MDL::dir, "%s/%s", *modeldir, name);
1416  }
1417 
1418  #define loopmeshes(meshname, m, body) \
1419  if(!MDL::loading || MDL::loading->parts.empty()) { Log.std->error("not loading an {}", MDL::formatname()); return; } \
1420  part &mdl = *MDL::loading->parts.last(); \
1421  if(!mdl.meshes) return; \
1422  loopv(mdl.meshes->meshes) \
1423  { \
1424  MESH &m = *(MESH *)mdl.meshes->meshes[i]; \
1425  if(!strcmp(meshname, "*") || (m.name && !strcmp(m.name, meshname))) \
1426  { \
1427  body; \
1428  } \
1429  }
1430 
1431  #define loopskins(meshname, s, body) loopmeshes(meshname, m, { skin &s = mdl.skins[i]; body; })
1432 
1433  static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin)
1434  {
1435  loopskins(meshname, s,
1436  s.tex = textureload(makerelpath(MDL::dir, tex), 0, true, false);
1437  if(*masks)
1438  {
1439  s.masks = textureload(makerelpath(MDL::dir, masks), 0, true, false);
1440  s.envmapmax = *envmapmax;
1441  s.envmapmin = *envmapmin;
1442  }
1443  );
1444  }
1445 
1446  static void setspec(char *meshname, int *percent)
1447  {
1448  float spec = 1.0f;
1449  if(*percent>0) spec = *percent/100.0f;
1450  else if(*percent<0) spec = 0.0f;
1451  loopskins(meshname, s, s.spec = spec);
1452  }
1453 
1454  static void setambient(char *meshname, int *percent)
1455  {
1456  float ambient = 0.3f;
1457  if(*percent>0) ambient = *percent/100.0f;
1458  else if(*percent<0) ambient = 0.0f;
1459  loopskins(meshname, s, s.ambient = ambient);
1460  }
1461 
1462  static void setglow(char *meshname, int *percent, int *delta, float *pulse)
1463  {
1464  float glow = 3.0f, glowdelta = *delta/100.0f, glowpulse = *pulse > 0 ? *pulse/1000.0f : 0;
1465  if(*percent>0) glow = *percent/100.0f;
1466  else if(*percent<0) glow = 0.0f;
1467  glowdelta -= glow;
1468  loopskins(meshname, s, { s.glow = glow; s.glowdelta = glowdelta; s.glowpulse = glowpulse; });
1469  }
1470 
1471  static void setglare(char *meshname, float *specglare, float *glowglare)
1472  {
1473  loopskins(meshname, s, { s.specglare = *specglare; s.glowglare = *glowglare; });
1474  }
1475 
1476  static void setalphatest(char *meshname, float *cutoff)
1477  {
1478  loopskins(meshname, s, s.alphatest = max(0.0f, min(1.0f, *cutoff)));
1479  }
1480 
1481  static void setalphablend(char *meshname, int *blend)
1482  {
1483  loopskins(meshname, s, s.alphablend = *blend!=0);
1484  }
1485 
1486  static void setcullface(char *meshname, int *cullface)
1487  {
1488  loopskins(meshname, s, s.cullface = *cullface!=0);
1489  }
1490 
1491  static void setenvmap(char *meshname, char *envmap)
1492  {
1493  Texture *tex = cubemapload(envmap);
1494  loopskins(meshname, s, s.envmap = tex);
1495  }
1496 
1497  static void setbumpmap(char *meshname, char *normalmapfile)
1498  {
1499  Texture *normalmaptex = textureload(makerelpath(MDL::dir, normalmapfile), 0, true, false);
1500  loopskins(meshname, s, s.normalmap = normalmaptex);
1501  }
1502 
1503  static void setfullbright(char *meshname, float *fullbright)
1504  {
1505  loopskins(meshname, s, s.fullbright = *fullbright);
1506  }
1507 
1508  static void setshader(char *meshname, char *shader)
1509  {
1510  loopskins(meshname, s, s.shader = lookupshaderbyname(shader));
1511  }
1512 
1513  static void setscroll(char *meshname, float *scrollu, float *scrollv)
1514  {
1515  loopskins(meshname, s, { s.scrollu = *scrollu; s.scrollv = *scrollv; });
1516  }
1517 
1518  static void setnoclip(char *meshname, int *noclip)
1519  {
1520  loopmeshes(meshname, m, m.noclip = *noclip!=0);
1521  }
1522 
1523  static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z)
1524  {
1525  if(!MDL::loading) { Log.std->error("not loading an {}", MDL::formatname()); return; }
1526  if(!MDL::loading->parts.inrange(*parent) || !MDL::loading->parts.inrange(*child)) { Log.std->error("no models loaded to link"); return; }
1527  if(!MDL::loading->parts[*parent]->link(MDL::loading->parts[*child], tagname, vec(*x, *y, *z))) Log.std->error("could not link model {}", MDL::loading->name);
1528  }
1529 
1530  template<class F> void modelcommand(F *fun, const char *suffix, const char *args)
1531  {
1532  defformatstring(name, "%s%s", MDL::formatname(), suffix);
1533  addcommand(newstring(name), (void (*)())fun, args);
1534  }
1535 
1537  {
1538  modelcommand(setdir, "dir", "s");
1539  if(MDL::multimeshed())
1540  {
1541  modelcommand(setskin, "skin", "sssff");
1542  modelcommand(setspec, "spec", "si");
1543  modelcommand(setambient, "ambient", "si");
1544  modelcommand(setglow, "glow", "siif");
1545  modelcommand(setglare, "glare", "sff");
1546  modelcommand(setalphatest, "alphatest", "sf");
1547  modelcommand(setalphablend, "alphablend", "si");
1548  modelcommand(setcullface, "cullface", "si");
1549  modelcommand(setenvmap, "envmap", "ss");
1550  modelcommand(setbumpmap, "bumpmap", "ss");
1551  modelcommand(setfullbright, "fullbright", "sf");
1552  modelcommand(setshader, "shader", "ss");
1553  modelcommand(setscroll, "scroll", "sff");
1554  modelcommand(setnoclip, "noclip", "si");
1555  }
1556  if(MDL::multiparted()) modelcommand(setlink, "link", "iisfff");
1557  }
1558 };
1559 
part & addpart()
Definition: animmodel.hpp:1134
bool unlink(part *p)
Definition: animmodel.hpp:684
vec translate
Definition: model.hpp:46
Definition: geom.hpp:902
void setglare(float specglare, float glowglare) override
Definition: animmodel.hpp:1249
static void setbumpmap(char *meshname, char *normalmapfile)
Definition: animmodel.hpp:1497
#define RAD
Definition: cube_types.hpp:32
Vector template.
Definition: cube_vector.hpp:22
Shader * generateshader(const char *name, const char *fmt,...)
Definition: shader.cpp:79
Definition: texture.hpp:38
virtual void cleanup()
Definition: animmodel.hpp:502
void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d)
Definition: animmodel.hpp:840
virtual void loaded()
Definition: animmodel.hpp:1298
matrix4 camprojmatrix
Definition: rendergl.cpp:976
static float lastalphatest
Definition: animmodel.hpp:1307
GLuint ebuf
Definition: explosion.cpp:36
static Texture * lasttex
Definition: animmodel.hpp:1309
#define ANIM_DIR
Definition: ents.hpp:217
ushort closestenvmap(const vec &o)
Definition: cubemap.cpp:319
const T & max(const inexor::rpc::SharedVar< T > &a, const T &b)
Definition: SharedVar.hpp:224
char * name
Definition: model.hpp:42
static bool htcmp(const animmodel::shaderparams &x, const animmodel::shaderparams &y)
Definition: animmodel.hpp:1386
void preloadBIH()
Definition: animmodel.hpp:719
void bindtc(void *v, int stride)
Definition: animmodel.hpp:522
void preloadmeshes()
Definition: animmodel.hpp:729
Shader * lookupshaderbyname(const char *name)
Definition: shader.cpp:73
#define loopvj(v)
Definition: cube_loops.hpp:22
void transposedtransformnormal(const vec &in, vec &out) const
Definition: geom.hpp:1841
vec b
Definition: geom.hpp:670
GLuint lookupenvmap(Slot &slot)
Definition: cubemap.cpp:346
virtual void cleanup()
Definition: animmodel.hpp:630
void startrender() override
Definition: animmodel.hpp:1313
float glowpulse
Definition: animmodel.hpp:70
virtual int linktype(animmodel *m) const
Definition: animmodel.hpp:969
void * lastmodel
Definition: ents.hpp:246
static void clearvbo()
Definition: glemu.hpp:103
virtual void preloadBIH()
Definition: model.hpp:79
static void setscroll(char *meshname, float *scrollu, float *scrollv)
Definition: animmodel.hpp:1513
void genBIH(vector< BIH::mesh > &bih)
Definition: animmodel.hpp:1148
int lastswitch
Definition: ents.hpp:245
unsigned int uint
Definition: cube_types.hpp:9
void initskins(Texture *tex=notexture, Texture *masks=notexture, int limit=0)
Definition: animmodel.hpp:691
#define ANIM_FLAGS
Definition: ents.hpp:228
Definition: animmodel.hpp:465
Definition: bih.hpp:16
float specglare
Definition: animmodel.hpp:70
int version
Definition: animmodel.hpp:80
part * p
Definition: animmodel.hpp:600
#define ANIM_START
Definition: ents.hpp:213
static GLuint lastxbuf
Definition: animmodel.hpp:1308
bool unlink(part *p)
Definition: animmodel.hpp:1177
#define loopskins(meshname, s, body)
Definition: animmodel.hpp:1431
#define glActiveTexture_
OpenGL extension checks: check whether certain features are available for your graphics-hardware/plat...
Definition: glexts.hpp:10
void transposedtransform(const vec &in, vec &out) const
Definition: geom.hpp:1833
#define ANIM_INDEX
Definition: ents.hpp:211
Texture * masks
Definition: animmodel.hpp:107
Definition: animmodel.hpp:598
static vec lightdir
Definition: animmodel.hpp:1306
animinterpinfo animinterp[MAXANIMPARTS]
Definition: ents.hpp:263
static void invalidate()
Definition: animmodel.hpp:98
bool operator!=(const animstate &a) const
Definition: animmodel.hpp:62
animpos cur
Definition: animmodel.hpp:58
part * owner
Definition: animmodel.hpp:57
int frame
Definition: animmodel.hpp:7
static Logger std
Logger for everything not fitting elsewhere.
Definition: Logging.hpp:89
meshgroup * sharemeshes(const char *name,...)
Definition: animmodel.hpp:583
void disablepolygonoffset(GLenum type)
Definition: rendergl.cpp:1038
void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight)
Definition: animmodel.hpp:312
void settranslation(const vec &v)
Definition: geom.hpp:1661
static GLuint lastebuf
Definition: animmodel.hpp:1308
static void disablebones()
Definition: animmodel.hpp:1324
float pitchmin
Definition: animmodel.hpp:618
Texture * envmap
Definition: animmodel.hpp:107
uchar * loadalphamask(Texture *t)
Definition: texture.cpp:477
static void setglare(char *meshname, float *specglare, float *glowglare)
Definition: animmodel.hpp:1471
int basetime
Definition: animmodel.hpp:601
Definition: model.hpp:40
vec & mul(const vec &o)
scalar multiplication
Definition: geom.hpp:168
meshgroup * meshes
Definition: animmodel.hpp:613
Definition: animmodel.hpp:104
static bool animated()
Definition: animmodel.hpp:1399
vector< skin > skins
Definition: animmodel.hpp:615
Definition: bih.hpp:56
void setfullbright(float fullbright) override
Definition: animmodel.hpp:1272
static hashtable< shaderparams, shaderparamskey > keys
Definition: animmodel.hpp:77
Definition: cubemap.cpp:202
int range
Definition: ents.hpp:232
static bool enablecullface
Definition: animmodel.hpp:1305
static GLuint lastenvmaptex
Definition: animmodel.hpp:1308
static void bindvbo(GLuint vbo)
Definition: glemu.hpp:102
bool hasframes(int i, int n) const
Definition: animmodel.hpp:499
void cleanup() override
Definition: animmodel.hpp:1129
2-dimensional float vectors
Definition: geom.hpp:38
bool cullface
Definition: animmodel.hpp:109
int index
Definition: animmodel.hpp:612
virtual void setshader(Shader *s)
Definition: animmodel.hpp:306
#define ANIM_NOPITCH
Definition: ents.hpp:226
float offsetpitch
Definition: model.hpp:43
bool hasframe(int i) const
Definition: animmodel.hpp:498
#define ANIM_SETSPEED
Definition: ents.hpp:225
float alphatest
Definition: animmodel.hpp:70
virtual int totalframes() const
Definition: animmodel.hpp:497
void setalphatest(float alphatest) override
Definition: animmodel.hpp:1260
static GLuint lastnbuf
Definition: animmodel.hpp:1308
int numanimparts
Definition: animmodel.hpp:617
void setalphablend(bool alphablend) override
Definition: animmodel.hpp:1266
#define ANIM_FULLBRIGHT
Definition: ents.hpp:221
virtual void getdefaultanim(animinfo &info, int anim, uint varseed, dynent *d)
Definition: animmodel.hpp:734
#define ANIM_REVERSE
Definition: ents.hpp:215
meshgroup * next
Definition: animmodel.hpp:467
static float transparent
Definition: animmodel.hpp:1307
static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin)
Definition: animmodel.hpp:1433
int frame
Definition: ents.hpp:232
bool link(part *p, const char *tag, const vec &translate=vec(0, 0, 0), int anim=-1, int basetime=0, vec *pos=nullptr)
Definition: animmodel.hpp:666
SharedVar< char * > modeldir
partrenderer * parts[24]
Definition: renderparticles.cpp:735
char * name
Definition: animmodel.hpp:469
static uint memhash(const void *ptr, int len)
Legacy Hashing algorithms and hashmap-implementation.
Definition: cube_hash.hpp:14
static MDL * loading
Definition: animmodel.hpp:1396
void preloadshaders(bool force)
Definition: animmodel.hpp:724
int numverts
Definition: explosion.cpp:35
void bindtangents(void *v, int stride)
Definition: animmodel.hpp:550
virtual void genBIH(BIH::mesh &m)
Definition: animmodel.hpp:294
int anim
Definition: ents.hpp:232
float scale
Definition: model.hpp:45
animinfo cur
Definition: ents.hpp:244
meshgroup()
Definition: animmodel.hpp:472
bool masked() const
Definition: animmodel.hpp:114
int clipframes(int i, int n) const
Definition: animmodel.hpp:500
float spec
Definition: animmodel.hpp:70
part * owner
Definition: animmodel.hpp:106
void rotate_around_z(float ck, float sk)
Definition: geom.hpp:1634
meshgroup * group
Definition: animmodel.hpp:279
#define ANIM_LOOP
Definition: ents.hpp:212
static GLuint lastvbuf
Definition: animmodel.hpp:1308
Definition: geom.hpp:668
Definition: animmodel.hpp:55
void setvariant(int col, int row, Shader *fallbackshader)
Definition: shader.hpp:243
bool fading
Definition: water.cpp:820
Definition: animmodel.hpp:965
bool depthoffset
Definition: model.hpp:44
vec4 & mul3(float f)
basic algebraic methods
Definition: geom.hpp:398
vec c
Definition: geom.hpp:670
Shader * loadshader()
Definition: animmodel.hpp:164
static void clearebo()
Definition: glemu.hpp:101
char * name
Definition: animmodel.hpp:280
static void setalphatest(char *meshname, float *cutoff)
Definition: animmodel.hpp:1476
Texture * textureload(const char *name, int clamp, bool mipit, bool msg, bool threadsafe)
Definition: texture.cpp:501
#define ANIM_ALL
Definition: ents.hpp:210
void scale(float x, float y, float z)
Definition: geom.hpp:937
virtual meshgroup * loadmeshes(const char *name, va_list args)
Definition: animmodel.hpp:581
void setshader(mesh *m, const animstate *as)
Definition: animmodel.hpp:207
int flags
Definition: bih.hpp:71
Definition: ents.hpp:230
bool reflecting
Definition: water.cpp:820
ICOMMAND * f(float *a, float *b), floatret(*a **b)
bool checkversion()
Definition: animmodel.hpp:84
void bindpos(GLuint ebuf, GLuint vbuf, void *v, int stride)
Definition: animmodel.hpp:506
static int firstversion
Definition: animmodel.hpp:78
static void setfullbright(char *meshname, float *fullbright)
Definition: animmodel.hpp:1503
float scrollv
Definition: animmodel.hpp:70
matrix4 matrix
Definition: animmodel.hpp:604
void setshaderparams(mesh *m, const animstate *as)
Definition: animmodel.hpp:125
static void disablenormals()
Definition: animmodel.hpp:1343
float magnitude() const
vector's magnitude in all 3 (XYZ) dimensions
Definition: geom.hpp:195
typedef GLuint(APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program
Definition: animmodel.hpp:1394
vec & neg()
turn all 3 (XYZ) coordinates into its negative values
Definition: geom.hpp:183
void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes)
Definition: animmodel.hpp:377
void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight)
Definition: animmodel.hpp:360
void render(int anim, int basetime, int basetime2, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, const vec &color, const vec &dir, float trans) override
Definition: animmodel.hpp:1036
bool calcanim(int animpart, int anim, int basetime, int basetime2, dynent *d, int interp, animinfo &info, int &aitime)
Definition: animmodel.hpp:740
bool envmapped()
Definition: animmodel.hpp:115
void genBIH(vector< BIH::mesh > &bih, const matrix4x3 &m)
Definition: animmodel.hpp:651
static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z)
Definition: animmodel.hpp:1523
int fr2
Definition: animmodel.hpp:14
linkedpart()
Definition: animmodel.hpp:606
const void * owner
Definition: shader.hpp:160
else loopi(numargs)
Definition: command.cpp:3019
void transformnormal(const vec &in, vec &out) const
Definition: geom.hpp:1816
animpos prev
Definition: animmodel.hpp:58
uint varseed
Definition: ents.hpp:234
Definition: animmodel.hpp:68
static Shader * lastshader
Definition: shader.hpp:144
bool iszero() const
"do all cartesian coordinates (XYZ) of this vector have the value zero?"
Definition: geom.hpp:157
bool standard
Definition: shader.hpp:156
static bool enablenormals
Definition: animmodel.hpp:1305
int shared
Definition: animmodel.hpp:468
GLuint index
Definition: glexts.hpp:412
static uint hthash(const animmodel::shaderparams &k)
Definition: animmodel.hpp:1381
animmodel(const char *name)
Definition: animmodel.hpp:1120
float dot(const vec &o) const
dot product (line by line) of all 3 dimensions
Definition: geom.hpp:163
Texture * normalmap
Definition: animmodel.hpp:107
void texscroll(float *scrollS, float *scrollT)
Definition: slot.cpp:977
int lastmillis
Definition: legacy_time.cpp:14
int refracting
Definition: water.cpp:818
void setspec(float spec) override
Definition: animmodel.hpp:1225
void translate(const vec &p)
Definition: geom.hpp:949
float pitchoffset
Definition: animmodel.hpp:618
virtual void * animkey()
Definition: animmodel.hpp:496
int anim
Definition: animmodel.hpp:14
void setenvmap(float envmapmin, float envmapmax, Texture *envmap) override
Definition: animmodel.hpp:1210
T & add(const T &x)
Add new index to vector.
Definition: cube_vector.hpp:73
#define loopmeshes(meshname, m, body)
Definition: animmodel.hpp:1418
#define ANIM_CLAMP
Definition: ents.hpp:216
static GLuint closestenvmaptex
Definition: animmodel.hpp:1308
Definition: animmodel.hpp:75
virtual ~mesh()
Definition: animmodel.hpp:287
vector with 3 floats and some useful methods.
Definition: geom.hpp:110
#define DELETEA(p)
Delete Array, Wrapper around delete[], sets pointer to NULL afterwards(!).
Definition: cube_tools.hpp:31
#define ANIM_NOSKIN
Definition: ents.hpp:219
void rotate_around_z(float ck, float sk)
Definition: geom.hpp:1090
int lastrendered
Definition: ents.hpp:266
#define ANIM_SECONDARY
Definition: ents.hpp:218
float ambient
Definition: animmodel.hpp:70
static Texture * lastnormalmap
Definition: animmodel.hpp:1309
virtual void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n)
Definition: animmodel.hpp:484
void shader(int *type, char *name, char *vs, char *ps)
Definition: shader.cpp:1060
float offsetyaw
Definition: model.hpp:43
void preloadshaders(bool force) override
Definition: animmodel.hpp:1194
float envmapmin
Definition: animmodel.hpp:70
static void disablevbo()
Definition: animmodel.hpp:1349
char void formatstring(char(&d)[N], const char *fmt,...) PRINTFARGS(2
void setglow(float glow, float delta, float pulse) override
Definition: animmodel.hpp:1237
Texture * cubemapload(const char *name, bool mipit, bool msg, bool transient)
Definition: cubemap.cpp:179
vec & sub(const vec &o)
scalar subtraction
Definition: geom.hpp:177
Definition: animmodel.hpp:966
const T & min(const inexor::rpc::SharedVar< T > &a, const T &b)
Definition: SharedVar.hpp:210
void setambient(float ambient) override
Definition: animmodel.hpp:1231
bool envmapped() override
Definition: animmodel.hpp:1183
struct MDL::part part
Definition: animmodel.hpp:1409
static void setalphablend(char *meshname, int *blend)
Definition: animmodel.hpp:1481
static GLuint lasttcbuf
Definition: animmodel.hpp:1308
inexor::util::log_manager Log
Definition: Logging.cpp:241
void preloadBIH()
Definition: animmodel.hpp:196
#define loopvrev(v)
Definition: cube_loops.hpp:24
static void setambient(char *meshname, int *percent)
Definition: animmodel.hpp:1454
Definition: geom.hpp:1572
static bool enablebones
Definition: animmodel.hpp:1305
#define MAXANIMPARTS
Definition: ents.hpp:253
bool shadowmapping
Definition: shadowmap.cpp:106
void bind(mesh *b, const animstate *as)
Definition: animmodel.hpp:212
vec4 & neg()
Definition: geom.hpp:409
bool operator!=(const animpos &a) const
Definition: animmodel.hpp:50
vec a
Definition: geom.hpp:670
void enablepolygonoffset(GLenum type)
Definition: rendergl.cpp:1022
animinfo prev
Definition: ents.hpp:244
void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, modelattach *a)
Definition: animmodel.hpp:971
static bool enabletc
Definition: animmodel.hpp:1305
virtual void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m)
Definition: animmodel.hpp:292
bool tangents()
Definition: animmodel.hpp:713
static void setdir(char *name)
Definition: animmodel.hpp:1412
vec translate
Definition: animmodel.hpp:619
#define ANIM_REUSE
Definition: ents.hpp:222
void mul(const matrix4 &x, const matrix3 &y)
Definition: geom.hpp:1591
#define ANIM_GHOST
Definition: ents.hpp:227
bool glaring
Definition: glare.cpp:38
static void disabletc()
Definition: animmodel.hpp:1337
quaternions are number systems that extend complex numbers complex numbers extend the number system o...
Definition: geom.hpp:435
float pitchscale
Definition: animmodel.hpp:618
vec * pos
Definition: animmodel.hpp:603
int length() const
return size of used memory
Definition: cube_vector.hpp:146
void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, animstate *as)
Definition: animmodel.hpp:846
GLuint id
Definition: texture.hpp:45
void cleanup()
Definition: animmodel.hpp:191
const char * tag
Definition: model.hpp:17
void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m)
Definition: animmodel.hpp:636
int d
Definition: octaedit.cpp:1749
float t
Definition: animmodel.hpp:15
void rotate_around_y(float ck, float sk)
Definition: geom.hpp:1080
void t(T x, const char *cmp)
Definition: utilTest.cpp:52
void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight)
Definition: animmodel.hpp:405
void bindnormals(void *v, int stride)
Definition: animmodel.hpp:536
Definition: ents.hpp:258
void setcullface(bool cullface) override
Definition: animmodel.hpp:1278
int type
Definition: texture.hpp:43
static void setnoclip(char *meshname, int *noclip)
Definition: animmodel.hpp:1518
float scrollu
Definition: animmodel.hpp:70
static void setenvmap(char *meshname, char *envmap)
Definition: animmodel.hpp:1491
Definition: animmodel.hpp:964
Definition: shader.hpp:142
void modelcommand(F *fun, const char *suffix, const char *args)
Definition: animmodel.hpp:1530
void genBIH(vector< skin > &skins, vector< BIH::mesh > &bih, const matrix4x3 &t)
Definition: animmodel.hpp:491
#define dir(name, v, d, s, os)
Definition: physics.cpp:2014
#define loopk(m)
Definition: cube_loops.hpp:10
shaderparamskey * key
Definition: animmodel.hpp:110
#define GLOBALPARAM(name, vals)
Definition: shader.hpp:448
vector< part * > parts
Definition: animmodel.hpp:1118
~animmodel() override
Definition: animmodel.hpp:1124
#define DELETEP(p)
Delete Pointer, Wrapper around delete, sets pointer to NULL afterwards(!).
Definition: cube_tools.hpp:28
virtual void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p)
Definition: animmodel.hpp:504
Definition: animmodel.hpp:12
void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight, int numframes)
Definition: animmodel.hpp:459
void preloadmeshes() override
Definition: animmodel.hpp:1199
void translate(const vec &p)
Definition: geom.hpp:1664
Definition: bih.hpp:56
#define ANIM_RAGDOLL
Definition: ents.hpp:224
physent * camera1
special ent that acts as camera, same object as player1 in FPS mode
Definition: rendergl.cpp:868
float envmapmax
Definition: animmodel.hpp:70
static bool enablealphablend
Definition: animmodel.hpp:1305
vec gettranslation() const
Definition: geom.hpp:1861
int priority
Definition: animmodel.hpp:9
void initmatrix(matrix4x3 &m)
Definition: animmodel.hpp:1141
vector< linkedpart > links
Definition: animmodel.hpp:614
#define enumerate(ht, t, e, b)
Definition: cube_hash.hpp:261
static int matrixpos
Definition: animmodel.hpp:1310
T & add(const V &elem)
Definition: cube_hash.hpp:236
char * makerelpath(const char *dir, const char *file, const char *prefix, const char *cmd)
Append a string together but add the prefix in the field.
Definition: stream.cpp:35
shaderparams()
Definition: animmodel.hpp:72
void setframes(const animinfo &info)
Definition: animmodel.hpp:17
Definition: ents.hpp:242
vector< mesh * > meshes
Definition: animmodel.hpp:470
bool tangents()
Definition: animmodel.hpp:117
#define ANIM_NORENDER
Definition: ents.hpp:223
bool noclip
Definition: animmodel.hpp:281
vec o
Definition: ents.hpp:130
struct sphere::vert * verts
Definition: animmodel.hpp:1407
void setanim(int animpart, int num, int frame, int range, float speed, int priority=0)
Definition: animmodel.hpp:939
struct MDL::skin skin
Definition: animmodel.hpp:1410
static void calctangent(V &v, const vec &n, const vec &t, float bt)
Definition: animmodel.hpp:394
Definition: ents.hpp:193
vector< animspec > * anims[MAXANIMPARTS]
Definition: animmodel.hpp:616
int fr1
Definition: animmodel.hpp:14
static bool enabletangents
Definition: animmodel.hpp:1305
vec & add(const vec &o)
scalar sum
Definition: geom.hpp:174
static void disabletangents()
Definition: animmodel.hpp:1331
Definition: animmodel.hpp:609
Texture * tex
Definition: bih.hpp:70
int tag
Definition: animmodel.hpp:601
void calcbb(vec &center, vec &radius) override
Definition: animmodel.hpp:1284
float interp
Definition: animmodel.hpp:59
#define loopj(m)
Definition: cube_loops.hpp:9
int range
Definition: animmodel.hpp:7
static bool multiparted()
Definition: animmodel.hpp:1400
Texture * notexture
Global used to specify this texture has not be found.
Definition: texture.cpp:266
bool alphablend
Definition: animmodel.hpp:109
int anim
Definition: animmodel.hpp:601
T * access(const U &key)
Definition: cube_hash.hpp:135
static void tangent(float x, float y, float z, float w=1.0f)
Definition: glemu.hpp:77
shaderparamskey()
Definition: animmodel.hpp:82
float fullbright
Definition: animmodel.hpp:70
bool link(part *p, const char *tag, const vec &translate=vec(0, 0, 0), int anim=-1, int basetime=0, vec *pos=nullptr)
Definition: animmodel.hpp:1171
#define ANIM_SETTIME
Definition: ents.hpp:220
float glowglare
Definition: animmodel.hpp:70
int basetime
Definition: ents.hpp:232
static void setglow(char *meshname, int *percent, int *delta, float *pulse)
Definition: animmodel.hpp:1462
static Texture * lastmasks
Definition: animmodel.hpp:1309
bool operator==(const animpos &a) const
Definition: animmodel.hpp:49
modelcommands()
Definition: animmodel.hpp:1536
void preloadBIH() override
Definition: animmodel.hpp:1156
static int lastversion
Definition: animmodel.hpp:78
Definition: bih.hpp:58
virtual void preload(part *p)
Definition: animmodel.hpp:503
void setshader(Shader *shader) override
Definition: animmodel.hpp:1204
Texture * tex
Definition: animmodel.hpp:107
vec & div(const vec &o)
scalar division
Definition: geom.hpp:171
vec translate
Definition: animmodel.hpp:602
void scale(float x, float y, float z)
Definition: geom.hpp:1672
static bool enabledepthoffset
Definition: animmodel.hpp:1305
ragdolldata * ragdoll
Definition: ents.hpp:264
Definition: model.hpp:15
static void bindebo(GLuint ebo)
Definition: glemu.hpp:100
float spinyaw
Definition: model.hpp:43
void bindbones(void *wv, void *bv, int stride)
Definition: animmodel.hpp:564
Definition: animmodel.hpp:5
bool alphatested() const
Definition: animmodel.hpp:118
void endrender() override
Definition: animmodel.hpp:1361
static void fixqtangent(quat &q, float bt)
Definition: animmodel.hpp:383
#define defformatstring(d,...)
Definition: cube_formatting.hpp:62
static void color(const bvec &v, uchar alpha=255)
Definition: glemu.hpp:71
part(animmodel *model, int index=0)
Definition: animmodel.hpp:621
void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m)
Definition: animmodel.hpp:486
Definition: cube_hash.hpp:224
virtual bool loaddefaultparts()
Definition: animmodel.hpp:1189
#define SETMODELSHADER(m, name)
static GLuint lastbbuf
Definition: animmodel.hpp:1308
static void setspec(char *meshname, int *percent)
Definition: animmodel.hpp:1446
void identity()
Definition: geom.hpp:983
vec & cross(const A &a, const B &b)
template based vector cross product
Definition: geom.hpp:211
bool bumpmapped()
Definition: animmodel.hpp:116
Definition: cube_hash.hpp:248
void preloadshader(bool force)
Definition: animmodel.hpp:201
virtual ~part()
Definition: animmodel.hpp:625
static bool multimeshed()
Definition: animmodel.hpp:1401
matrix4x3 xform
Definition: bih.hpp:60
static vec lightcolor
Definition: animmodel.hpp:1306
Shader * shader
Definition: animmodel.hpp:108
bool envmapped()
Definition: animmodel.hpp:707
float speed
Definition: animmodel.hpp:8
skin()
Definition: animmodel.hpp:112
bool operator==(const animstate &a) const
Definition: animmodel.hpp:61
#define loopv(v)
Definition: cube_loops.hpp:21
static void setshader(char *meshname, char *shader)
Definition: animmodel.hpp:1508
mesh()
Definition: animmodel.hpp:283
float pitchmax
Definition: animmodel.hpp:618
void set()
Definition: shader.hpp:278
void identity()
Definition: geom.hpp:1653
char * newstring(size_t l)
Definition: cube_tools.hpp:71
vec & normalize()
normalize vector: divide it by its length (magnitude)
Definition: geom.hpp:198
#define ANIM_END
Definition: ents.hpp:214
static string dir
Definition: animmodel.hpp:1397
Definition: animmodel.hpp:3
Definition: random.cpp:21
void setkey()
Definition: animmodel.hpp:120
virtual void loaded()
Definition: animmodel.hpp:955
Definition: animmodel.hpp:277
BIH * setBIH() override
Definition: animmodel.hpp:1162
bool alphadepth
Definition: model.hpp:44
static matrix4 matrixstack[64]
Definition: animmodel.hpp:1311
Definition: bih.hpp:56
#define LOCALPARAMF(name,...)
Definition: shader.hpp:445
virtual int findtag(const char *name)
Definition: animmodel.hpp:483
void genBIH(skin &s, vector< BIH::mesh > &bih, const matrix4x3 &t)
Definition: animmodel.hpp:295
float glow
Definition: animmodel.hpp:70
animmodel * model
Definition: animmodel.hpp:611
bool addcommand(const char *name, identfun fun, const char *args)
Definition: command.cpp:740
static void setcullface(char *meshname, int *cullface)
Definition: animmodel.hpp:1486
BIH * bih
Definition: model.hpp:47
GLuint vbuf
Definition: explosion.cpp:36
float glowdelta
Definition: animmodel.hpp:70
A Texture entry, holding info about a texture on the GPU.
Definition: texture.hpp:27
float speed
Definition: ents.hpp:233
void rotate(float ck, float sk, const vec &axis)
Definition: geom.hpp:1644
matrix4 shadowmatrix
Definition: shadowmap.cpp:108
float spinpitch
Definition: model.hpp:43
virtual ~meshgroup()
Definition: animmodel.hpp:476