home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / vertmodel.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-03  |  19.4 KB  |  590 lines

  1. VARP(dynshadowsize, 4, 5, 8);
  2. VARP(aadynshadow, 0, 2, 3);
  3. VARP(saveshadows, 0, 1, 1);
  4.  
  5. struct vertmodel : model
  6. {
  7.     struct anpos
  8.     {
  9.         int fr1, fr2;
  10.         float t;
  11.                 
  12.         void setframes(const animstate &as)
  13.         {
  14.             int time = lastmillis-as.basetime;
  15.             fr1 = (int)(time/as.speed); // round to full frames
  16.             t = (time-fr1*as.speed)/as.speed; // progress of the frame, value from 0.0f to 1.0f
  17.             ASSERT(t >= 0.0f);
  18.             if(as.anim&ANIM_LOOP)
  19.             {
  20.                 fr1 = fr1%as.range+as.frame;
  21.                 fr2 = fr1+1;
  22.                 if(fr2>=as.frame+as.range) fr2 = as.frame;
  23.             }
  24.             else
  25.             {
  26.                 fr1 = min(fr1, as.range-1)+as.frame;
  27.                 fr2 = min(fr1+1, as.frame+as.range-1);
  28.             }
  29.             if(as.anim&ANIM_REVERSE)
  30.             {
  31.                 fr1 = (as.frame+as.range-1)-(fr1-as.frame);
  32.                 fr2 = (as.frame+as.range-1)-(fr2-as.frame);
  33.             }
  34.         }
  35.  
  36.         bool operator==(const anpos &a) const { return fr1==a.fr1 && fr2==a.fr2 && (fr1==fr2 || t==a.t); }
  37.     };
  38.  
  39.     struct tcvert { float u, v; ushort index; };
  40.     struct tri { ushort vert[3]; };
  41.  
  42.     struct mesh
  43.     {
  44.         char *name;
  45.         vec *verts;
  46.         tcvert *tcverts;
  47.         tri *tris;
  48.         int numverts, numtcverts, numtris;
  49.  
  50.         Texture *skin;
  51.         int tex;
  52.  
  53.         vec *dynbuf;
  54.         ushort *dynidx;
  55.         int dynlen;
  56.         anpos dyncur, dynprev;
  57.         float dynt;
  58.         GLuint statlist;
  59.         int statlen;
  60.  
  61.         mesh() : name(0), verts(0), tcverts(0), tris(0), skin(crosshair), tex(0), dynbuf(0), dynidx(0), statlist(0) 
  62.         {
  63.             dyncur.fr1 = dynprev.fr1 = -1;
  64.         }
  65.  
  66.         ~mesh()
  67.         {
  68.             DELETEA(name);
  69.             DELETEA(verts);
  70.             DELETEA(tcverts);
  71.             DELETEA(tris);
  72.             if(statlist) glDeleteLists(statlist, 1);
  73.             DELETEA(dynidx);
  74.             DELETEA(dynbuf);
  75.         }
  76.  
  77.         void gendyn()
  78.         {
  79.             tristrip ts;
  80.             ts.addtriangles(tris->vert, numtris);
  81.             vector<ushort> idxs;
  82.             ts.buildstrips(idxs);
  83.             dynbuf = new vec[numverts];
  84.             dynidx = new ushort[idxs.length()];
  85.             memcpy(dynidx, idxs.getbuf(), idxs.length()*sizeof(ushort));
  86.             dynlen = idxs.length();
  87.         }
  88.  
  89.         void gendynverts(anpos &cur, anpos *prev, float ai_t)
  90.         {
  91.             vec *vert1 = &verts[cur.fr1 * numverts],
  92.                 *vert2 = &verts[cur.fr2 * numverts],
  93.                 *pvert1 = NULL, *pvert2 = NULL;
  94.             if(prev)
  95.             {
  96.                 if(dynprev==*prev && dyncur==cur && dynt==ai_t) return;
  97.                 dynprev = *prev;
  98.                 dynt = ai_t;
  99.                 pvert1 = &verts[prev->fr1 * numverts];
  100.                 pvert2 = &verts[prev->fr2 * numverts];
  101.             }
  102.             else
  103.             {
  104.                 if(dynprev.fr1<0 && dyncur==cur) return;
  105.                 dynprev.fr1 = -1;
  106.             }
  107.             dyncur = cur;
  108.             loopi(numverts) // vertices
  109.             {
  110.                 vec &v = dynbuf[i];
  111.                 #define ip(p1, p2, t) (p1+t*(p2-p1))
  112.                 #define ip_v(p, c, t) ip(p##1[i].c, p##2[i].c, t)
  113.                 if(prev)
  114.                 {
  115.                     #define ip_v_ai(c) ip( ip_v(pvert, c, prev->t), ip_v(vert, c, cur.t), ai_t)
  116.                     v = vec(ip_v_ai(x), ip_v_ai(y), ip_v_ai(z));
  117.                     #undef ip_v_ai
  118.                 }
  119.                 else
  120.                 {
  121.                     v = vec(ip_v(vert, x, cur.t), ip_v(vert, y, cur.t), ip_v(vert, z, cur.t));
  122.                 }
  123.                 #undef ip
  124.                 #undef ip_v
  125.             }
  126.         }
  127.  
  128.         void render(animstate &as, anpos &cur, anpos *prev, float ai_t)
  129.         {
  130.             if(!dynbuf) return;
  131.  
  132.             if(!(as.anim&ANIM_NOSKIN))
  133.             {
  134.                 int id = tex < 0 ? -tex : skin->id;
  135.                 if(tex > 0)
  136.                 {
  137.                     int xs, ys;
  138.                     id = lookuptexture(tex, xs, ys);
  139.                 }
  140.                 glBindTexture(GL_TEXTURE_2D, id);
  141.             }
  142.  
  143.             bool isstat = as.frame==0 && as.range==1;
  144.             if(isstat && statlist)
  145.             {
  146.                 glCallList(statlist);
  147.                 xtraverts += statlen;
  148.             }
  149.             else
  150.             {
  151.                 if(isstat) glNewList(statlist = glGenLists(1), GL_COMPILE);
  152.                 gendynverts(cur, prev, ai_t);
  153.                 loopj(dynlen)
  154.                 {
  155.                     ushort index = dynidx[j];
  156.                     if(index>=tristrip::RESTART || !j)
  157.                     {
  158.                         if(j) glEnd();
  159.                         glBegin(index==tristrip::LIST ? GL_TRIANGLES : GL_TRIANGLE_STRIP);
  160.                         if(index>=tristrip::RESTART) continue;
  161.                     }
  162.                     tcvert &tc = tcverts[index];
  163.                     if(isstat || !(as.anim&ANIM_NOSKIN)) glTexCoord2f(tc.u, tc.v);
  164.                     glVertex3fv(&dynbuf[tc.index].x);
  165.                 }
  166.                 glEnd();
  167.                 if(isstat)
  168.                 {
  169.                     glEndList();
  170.                     glCallList(statlist);
  171.                     statlen = dynlen;
  172.                 }
  173.                 xtraverts += dynlen;
  174.             }
  175.         }                     
  176.     };
  177.  
  178.     struct animinfo
  179.     {
  180.         int frame, range;
  181.         float speed;
  182.     };
  183.  
  184.     struct tag
  185.     {
  186.         char *name;
  187.         vec pos;
  188.         float transform[3][3];
  189.         
  190.         tag() : name(NULL) {}
  191.         ~tag() { DELETEA(name); }
  192.     };
  193.  
  194.     struct part
  195.     {
  196.         char *filename;
  197.         vertmodel *model;
  198.         int index, numframes;
  199.         vector<mesh *> meshes;
  200.         vector<animinfo> *anims;
  201.         part **links;
  202.         tag *tags;
  203.         int numtags;
  204.         GLuint *shadows;
  205.         float shadowrad;
  206.  
  207.         part() : filename(NULL), anims(NULL), links(NULL), tags(NULL), numtags(0), shadows(NULL), shadowrad(0) {}
  208.         virtual ~part()
  209.         {
  210.             DELETEA(filename);
  211.             meshes.deletecontentsp();
  212.             DELETEA(anims);
  213.             DELETEA(links);
  214.             DELETEA(tags);
  215.             if(shadows) glDeleteTextures(numframes, shadows);
  216.             DELETEA(shadows);
  217.         }
  218.  
  219.         bool link(part *link, const char *tag)
  220.         {
  221.             loopi(numtags) if(!strcmp(tags[i].name, tag))
  222.             {
  223.                 links[i] = link;
  224.                 return true;
  225.             }
  226.             return false;
  227.         }
  228.  
  229.         void scaleverts(const float scale, const vec &translate)
  230.         {
  231.            loopv(meshes)
  232.            {
  233.                mesh &m = *meshes[i];
  234.                loopj(numframes*m.numverts)
  235.                {
  236.                    vec &v = m.verts[j];
  237.                    if(!index) v.add(translate);
  238.                    v.mul(scale);
  239.                }
  240.            }
  241.            loopi(numframes*numtags)
  242.            {
  243.                vec &v = tags[i].pos;
  244.                if(!index) v.add(translate);
  245.                v.mul(scale);
  246.            }
  247.         }
  248.  
  249.         void gendyn()
  250.         {
  251.             loopv(meshes) meshes[i]->gendyn();
  252.         }
  253.             
  254.         virtual void getdefaultanim(animstate &as, int anim, int varseed)
  255.         {
  256.             as.frame = 0;
  257.             as.range = 1;
  258.         }
  259.  
  260.         bool calcanimstate(int anim, int varseed, float speed, int basetime, dynent *d, animstate &as)
  261.         {
  262.             as.anim = anim;
  263.             as.speed = speed<=0 ? 100.0f : speed;
  264.             as.basetime = basetime;
  265.             if((anim&ANIM_INDEX)==ANIM_ALL)
  266.             {
  267.                 as.frame = 0;
  268.                 as.range = numframes;
  269.             }
  270.             else if(anims)
  271.             {
  272.                 vector<animinfo> &ais = anims[anim&ANIM_INDEX];
  273.                 if(ais.length())
  274.                 {
  275.                     animinfo &ai = ais[varseed%ais.length()];
  276.                     as.frame = ai.frame;
  277.                     as.range = ai.range;
  278.                     if(ai.speed>0) as.speed = 1000.0f/ai.speed;
  279.                 }
  280.                 else getdefaultanim(as, anim&ANIM_INDEX, varseed);
  281.             }
  282.             else getdefaultanim(as, anim&ANIM_INDEX, varseed);
  283.             if(anim&(ANIM_START|ANIM_END))
  284.             {
  285.                 if(anim&ANIM_END) as.frame += as.range-1;
  286.                 as.range = 1; 
  287.             }
  288.  
  289.             if(as.frame+as.range>numframes)
  290.             {
  291.                 if(as.frame>=numframes) return false;
  292.                 as.range = numframes-as.frame;
  293.             }
  294.  
  295.             if(d && index<2)
  296.             {
  297.                 if(d->lastmodel[index]!=this || d->lastanimswitchtime[index]==-1)
  298.                 {
  299.                     d->current[index] = as;
  300.                     d->lastanimswitchtime[index] = lastmillis-animationinterpolationtime*2;
  301.                 }
  302.                 else if(d->current[index] != as)
  303.                 {
  304.                     if(lastmillis-d->lastanimswitchtime[index]>animationinterpolationtime/2) d->prev[index] = d->current[index];
  305.                     d->current[index] = as;
  306.                     d->lastanimswitchtime[index] = lastmillis;
  307.                 }
  308.                 d->lastmodel[index] = this;
  309.             }
  310.             return true;
  311.         }
  312.         
  313.         void render(int anim, int varseed, float speed, int basetime, dynent *d)
  314.         {
  315.             if(meshes.empty()) return;
  316.             animstate as;
  317.             if(!calcanimstate(anim, varseed, speed, basetime, d, as)) return;
  318.     
  319.             if(!meshes[0]->dynbuf) gendyn();
  320.     
  321.             anpos prev, cur;
  322.             cur.setframes(d && index<2 ? d->current[index] : as);
  323.     
  324.             float ai_t = 0;
  325.             bool doai = !(anim&ANIM_NOINTERP) && d && index<2 && lastmillis-d->lastanimswitchtime[index]<animationinterpolationtime && d->prev[index].range>0;
  326.             if(doai)
  327.             {
  328.                 prev.setframes(d->prev[index]);
  329.                 ai_t = (lastmillis-d->lastanimswitchtime[index])/(float)animationinterpolationtime;
  330.             }
  331.             
  332.             loopv(meshes) meshes[i]->render(as, cur, doai ? &prev : NULL, ai_t);
  333.  
  334.             loopi(numtags) if(links[i]) // render the linked models - interpolate rotation and position of the 'link-tags'
  335.             {
  336.                 part *link = links[i];
  337.  
  338.                 GLfloat matrix[16];
  339.                 tag *tag1 = &tags[cur.fr1*numtags+i];
  340.                 tag *tag2 = &tags[cur.fr2*numtags+i];
  341.                 #define ip(p1, p2, t) (p1+t*(p2-p1))
  342.                 #define ip_ai_tag(c) ip( ip( tag1p->c, tag2p->c, prev.t), ip( tag1->c, tag2->c, cur.t), ai_t)
  343.                 if(doai)
  344.                 {
  345.                     tag *tag1p = &tags[prev.fr1 * numtags + i];
  346.                     tag *tag2p = &tags[prev.fr2 * numtags + i];
  347.                     loopj(3) matrix[j] = ip_ai_tag(transform[0][j]); // transform
  348.                     loopj(3) matrix[4 + j] = ip_ai_tag(transform[1][j]);
  349.                     loopj(3) matrix[8 + j] = ip_ai_tag(transform[2][j]);
  350.                     loopj(3) matrix[12 + j] = ip_ai_tag(pos[j]); // position      
  351.                 }
  352.                 else
  353.                 {
  354.                     loopj(3) matrix[j] = ip(tag1->transform[0][j], tag2->transform[0][j], cur.t); // transform
  355.                     loopj(3) matrix[4 + j] = ip(tag1->transform[1][j], tag2->transform[1][j], cur.t);
  356.                     loopj(3) matrix[8 + j] = ip(tag1->transform[2][j], tag2->transform[2][j], cur.t);
  357.                     loopj(3) matrix[12 + j] = ip(tag1->pos[j], tag2->pos[j], cur.t); // position
  358.                 }
  359.                 #undef ip_ai_tag
  360.                 #undef ip 
  361.                 matrix[3] = matrix[7] = matrix[11] = 0.0f;
  362.                 matrix[15] = 1.0f;
  363.                 glPushMatrix();
  364.                     glMultMatrixf(matrix);
  365.                     link->render(anim, varseed, speed, basetime, d);
  366.                 glPopMatrix();
  367.             }
  368.         }
  369.  
  370.         void setanim(int num, int frame, int range, float speed)
  371.         {
  372.             if(frame<0 || frame>=numframes || range<=0 || frame+range>numframes) 
  373.             { 
  374.                 conoutf("invalid frame %d, range %d in model %s", frame, range, model->loadname); 
  375.                 return; 
  376.             }
  377.             if(!anims) anims = new vector<animinfo>[NUMANIMS];
  378.             animinfo &ai = anims[num].add();
  379.             ai.frame = frame;
  380.             ai.range = range;
  381.             ai.speed = speed;
  382.         }
  383.  
  384.         virtual void begingenshadow()
  385.         {
  386.         }
  387.  
  388.         virtual void endgenshadow()
  389.         {
  390.         }
  391.  
  392.         void genshadow(int aasize, int frame, gzFile f)
  393.         {
  394.             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  395.  
  396.             render(ANIM_ALL|ANIM_NOINTERP|ANIM_NOSKIN, 0, 1, lastmillis-frame, NULL);
  397.  
  398.             uchar *pixels = new uchar[aasize*aasize];
  399.             glPixelStorei(GL_PACK_ALIGNMENT, 1);
  400.             glReadPixels(0, 0, aasize, aasize, GL_RED, GL_UNSIGNED_BYTE, pixels);
  401. #if 0
  402.             SDL_Surface *img = SDL_CreateRGBSurface(SDL_SWSURFACE, aasize, aasize, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0);
  403.             loopi(aasize*aasize) memset((uchar *)img->pixels + 3*i, pixels[i], 3);
  404.             s_sprintfd(imgname)("%s_%d.bmp", model->loadname, frame);
  405.             for(char *s; (s = strchr(imgname, '/'));) *s = '_';
  406.             SDL_SaveBMP(img, imgname);
  407.             SDL_FreeSurface(img);
  408. #endif
  409.             if(aasize > 1<<dynshadowsize) 
  410.                 gluScaleImage(GL_ALPHA, aasize, aasize, GL_UNSIGNED_BYTE, pixels, 1<<dynshadowsize, 1<<dynshadowsize, GL_UNSIGNED_BYTE, pixels);
  411.  
  412.             int texsize = min(aasize, 1<<dynshadowsize);
  413.             if(f) gzwrite(f, pixels, texsize*texsize);
  414.             createtexture(shadows[frame], texsize, texsize, pixels, 3, true, GL_ALPHA);
  415.         }
  416.  
  417.         struct shadowheader
  418.         {
  419.             ushort size, frames;
  420.             float height, rad;
  421.         };
  422.         
  423.         void genshadows(float height, float rad)
  424.         {
  425.             if(shadows) return;
  426.  
  427.             char *filename = shadowfile();
  428.             if(filename && loadshadows(filename)) return;
  429.  
  430.             shadowrad = rad;
  431.             shadows = new GLuint[numframes];
  432.             glGenTextures(numframes, shadows);
  433.  
  434.             extern int scr_w, scr_h;
  435.             int aasize = 1<<(dynshadowsize + aadynshadow);
  436.             while(aasize > scr_w || aasize > scr_h) aasize /= 2;
  437.  
  438.             gzFile f = filename ? gzopen(filename, "wb9") : NULL;
  439.             if(f)
  440.             {
  441.                 shadowheader hdr;
  442.                 hdr.size = min(aasize, 1<<dynshadowsize);
  443.                 hdr.frames = numframes;
  444.                 hdr.height = height;
  445.                 hdr.rad = rad;
  446.                 endianswap(&hdr.size, sizeof(ushort), 1);
  447.                 endianswap(&hdr.frames, sizeof(ushort), 1);
  448.                 endianswap(&hdr.height, sizeof(float), 1);
  449.                 endianswap(&hdr.rad, sizeof(float), 1);
  450.                 gzwrite(f, &hdr, sizeof(shadowheader));
  451.             }
  452.  
  453.             glViewport(0, 0, aasize, aasize);
  454.             glClearColor(0, 0, 0, 1);
  455.             glDisable(GL_FOG);
  456.             glColor3f(1, 1, 1);
  457.  
  458.             glMatrixMode(GL_PROJECTION);
  459.             glLoadIdentity();
  460.             glOrtho(-rad, rad, -rad, rad, 0.15f, height);
  461.  
  462.             glMatrixMode(GL_MODELVIEW);
  463.             glLoadIdentity();
  464.             glScalef(1, -1, 1);
  465.  
  466.             glTranslatef(0, 0, -height);
  467.             begingenshadow();
  468.             loopi(numframes) genshadow(aasize, i, f);
  469.             endgenshadow();
  470.             
  471.             glEnable(GL_FOG);
  472.             glViewport(0, 0, scr_w, scr_h);
  473.  
  474.             if(f) gzclose(f);
  475.         }
  476.  
  477.         bool loadshadows(const char *filename)
  478.         {
  479.             gzFile f = gzopen(filename, "rb9");
  480.             if(!f) return false;
  481.             shadowheader hdr;
  482.             if(gzread(f, &hdr, sizeof(shadowheader))!=sizeof(shadowheader)) { gzclose(f); return false; }
  483.             endianswap(&hdr.size, sizeof(ushort), 1);
  484.             endianswap(&hdr.frames, sizeof(ushort), 1);
  485.             if(hdr.size!=(1<<dynshadowsize) || hdr.frames!=numframes) { gzclose(f); return false; }
  486.             endianswap(&hdr.height, sizeof(float), 1);
  487.             endianswap(&hdr.rad, sizeof(float), 1);
  488.  
  489.             uchar *buf = new uchar[hdr.size*hdr.size*hdr.frames];
  490.             if(gzread(f, buf, hdr.size*hdr.size*hdr.frames)!=hdr.size*hdr.size*hdr.frames) { gzclose(f); return false; }
  491.  
  492.             shadowrad = hdr.rad;
  493.             shadows = new GLuint[hdr.frames];
  494.             glGenTextures(hdr.frames, shadows);
  495.  
  496.             loopi(hdr.frames) createtexture(shadows[i], hdr.size, hdr.size, &buf[i*hdr.size*hdr.size], 3, true, GL_ALPHA);
  497.             
  498.             delete[] buf;
  499.  
  500.             gzclose(f);
  501.  
  502.             return true;
  503.         }
  504.  
  505.         void rendershadow(int anim, int varseed, float speed, int basetime, const vec &o, float yaw)
  506.         {
  507.             if(!shadows) return;
  508.             animstate as;
  509.             if(!calcanimstate(anim, varseed, speed, basetime, NULL, as)) return;
  510.             anpos cur;
  511.             cur.setframes(as);
  512.  
  513.             glBindTexture(GL_TEXTURE_2D, shadows[cur.fr1]);
  514.  
  515.             glDepthMask(GL_FALSE);
  516.             glEnable(GL_BLEND);
  517.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  518.  
  519.             yaw *= RAD;
  520.             float c = cosf(yaw), s = sinf(yaw);
  521.             float x1 = -shadowrad, x2 = shadowrad;
  522.             float y1 = -shadowrad, y2 = shadowrad;
  523.  
  524.             glBegin(GL_POLYGON);
  525.             glTexCoord2f(0, 1); glVertex3f(x1*c - y1*s + o.x, y1*c + x1*s + o.y, o.z);
  526.             glTexCoord2f(1, 1); glVertex3f(x2*c - y1*s + o.x, y1*c + x2*s + o.y, o.z);
  527.             glTexCoord2f(1, 0); glVertex3f(x2*c - y2*s + o.x, y2*c + x2*s + o.y, o.z);
  528.             glTexCoord2f(0, 0); glVertex3f(x1*c - y2*s + o.x, y2*c + x1*s + o.y, o.z);
  529.             glEnd();
  530.  
  531.             glDepthMask(GL_TRUE);
  532.             glDisable(GL_BLEND);
  533.         }           
  534.  
  535.         char *shadowfile()
  536.         {
  537.             if(!saveshadows || !filename) return NULL;
  538.  
  539.             static string s;
  540.             char *dir = strrchr(filename, PATHDIV);
  541.             if(!dir) s[0] = '\0';
  542.             else s_strncpy(s, filename, dir-filename+2); 
  543.             s_strcat(s, "shadows.dat");
  544.             return s;
  545.         }
  546.     };
  547.  
  548.     bool loaded;
  549.     char *loadname;
  550.     vector<part *> parts;
  551.  
  552.     vertmodel(const char *name) : loaded(false)
  553.     {
  554.         loadname = newstring(name);
  555.     }
  556.  
  557.     ~vertmodel()
  558.     {
  559.         delete[] loadname;
  560.         parts.deletecontentsp();
  561.     }
  562.  
  563.     char *name() { return loadname; }
  564.  
  565.     bool link(part *link, const char *tag)
  566.     {
  567.         loopv(parts) if(parts[i]->link(link, tag)) return true;
  568.         return false;
  569.     }
  570.  
  571.     void setskin(int tex)
  572.     {
  573.         if(parts.length()!=1 || parts[0]->meshes.length()!=1) return;
  574.         mesh &m = *parts[0]->meshes[0]; 
  575.         m.tex = tex;
  576.     }
  577.  
  578.     void genshadows(float height, float rad)
  579.     {
  580.         if(parts.length()>1) return;
  581.         parts[0]->genshadows(height, rad);
  582.     }
  583.  
  584.     bool hasshadows()
  585.     {
  586.         return parts.length()==1 && parts[0]->shadows;
  587.     }
  588. };
  589.  
  590.