~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/src/md2.h

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
struct md2;
 
2
 
 
3
md2 *loadingmd2 = 0;
 
4
 
 
5
struct md2 : vertmodel
 
6
{
 
7
    struct md2_header
 
8
    {
 
9
        int magic;
 
10
        int version;
 
11
        int skinwidth, skinheight;
 
12
        int framesize;
 
13
        int numskins, numvertices, numtexcoords;
 
14
        int numtriangles, numglcommands, numframes;
 
15
        int offsetskins, offsettexcoords, offsettriangles;
 
16
        int offsetframes, offsetglcommands, offsetend;
 
17
    };
 
18
 
 
19
    struct md2_vertex
 
20
    {
 
21
        uchar vertex[3], normalindex;
 
22
    };
 
23
 
 
24
    struct md2_frame
 
25
    {
 
26
        float      scale[3];
 
27
        float      translate[3];
 
28
        char       name[16];
 
29
    };
 
30
    
 
31
    md2(const char *name) : vertmodel(name) {}
 
32
 
 
33
    int type() { return MDL_MD2; }
 
34
 
 
35
    struct md2part : part
 
36
    {
 
37
        void gentcverts(int *glcommands, vector<tcvert> &tcverts, vector<ushort> &vindexes, vector<tri> &tris)
 
38
        {
 
39
            hashtable<ivec, int> tchash;
 
40
            vector<ushort> idxs;
 
41
            for(int *command = glcommands; (*command)!=0;)
 
42
            {
 
43
                int numvertex = *command++;
 
44
                bool isfan = numvertex<0;
 
45
                if(isfan) numvertex = -numvertex;
 
46
                idxs.setsizenodelete(0);
 
47
                loopi(numvertex)
 
48
                {
 
49
                    union { int i; float f; } u, v;
 
50
                    u.i = *command++;
 
51
                    v.i = *command++;
 
52
                    int vindex = *command++;
 
53
                    ivec tckey(u.i, v.i, vindex);
 
54
                    int *idx = tchash.access(tckey);
 
55
                    if(!idx)
 
56
                    {
 
57
                        idx = &tchash[tckey];
 
58
                        *idx = tcverts.length();
 
59
                        tcvert &tc = tcverts.add();
 
60
                        tc.u = u.f;
 
61
                        tc.v = v.f;
 
62
                        vindexes.add((ushort)vindex);
 
63
                    }        
 
64
                    idxs.add(*idx);
 
65
                }
 
66
                loopi(numvertex-2) 
 
67
                { 
 
68
                    tri &t = tris.add();
 
69
                    if(isfan)
 
70
                    {
 
71
                        t.vert[0] = idxs[0];
 
72
                        t.vert[1] = idxs[i+1];
 
73
                        t.vert[2] = idxs[i+2];
 
74
                    }
 
75
                    else loopk(3) t.vert[k] = idxs[i&1 && k ? i+(1-(k-1))+1 : i+k];
 
76
                }
 
77
            }
 
78
        }
 
79
        
 
80
        bool load(char *path)
 
81
        {
 
82
            if(filename) return true;
 
83
 
 
84
            FILE *file = openfile(path, "rb");
 
85
            if(!file) return false;
 
86
 
 
87
            md2_header header;
 
88
            fread(&header, sizeof(md2_header), 1, file);
 
89
            endianswap(&header, sizeof(int), sizeof(md2_header)/sizeof(int));
 
90
 
 
91
            if(header.magic!=844121161 || header.version!=8) 
 
92
            {
 
93
                fclose(file);
 
94
                return false;
 
95
            }
 
96
           
 
97
            numframes = header.numframes;
 
98
 
 
99
            mesh &m = *new mesh;
 
100
            meshes.add(&m);
 
101
            m.owner = this;
 
102
 
 
103
            int *glcommands = new int[header.numglcommands];
 
104
            fseek(file, header.offsetglcommands, SEEK_SET);
 
105
            int numglcommands = (int)fread(glcommands, sizeof(int), header.numglcommands, file);
 
106
            endianswap(glcommands, sizeof(int), numglcommands);
 
107
            if(numglcommands < header.numglcommands) memset(&glcommands[numglcommands], 0, (header.numglcommands-numglcommands)*sizeof(int));
 
108
 
 
109
            vector<tcvert> tcgen;
 
110
            vector<ushort> vgen;
 
111
            vector<tri> trigen;
 
112
            gentcverts(glcommands, tcgen, vgen, trigen);
 
113
            delete[] glcommands;
 
114
 
 
115
            m.numverts = tcgen.length();
 
116
            m.tcverts = new tcvert[m.numverts];
 
117
            memcpy(m.tcverts, tcgen.getbuf(), m.numverts*sizeof(tcvert));
 
118
            m.numtris = trigen.length();
 
119
            m.tris = new tri[m.numtris];
 
120
            memcpy(m.tris, trigen.getbuf(), m.numtris*sizeof(tri));
 
121
 
 
122
            m.verts = new vec[m.numverts*numframes+1];
 
123
 
 
124
            md2_vertex *tmpverts = new md2_vertex[header.numvertices];
 
125
            int frame_offset = header.offsetframes;
 
126
            vec *curvert = m.verts;
 
127
            loopi(header.numframes)
 
128
            {
 
129
                md2_frame frame;
 
130
                fseek(file, frame_offset, SEEK_SET);
 
131
                fread(&frame, sizeof(md2_frame), 1, file);
 
132
                endianswap(&frame, sizeof(float), 6);
 
133
 
 
134
                fread(tmpverts, sizeof(md2_vertex), header.numvertices, file);
 
135
                loopj(m.numverts)
 
136
                {
 
137
                    const md2_vertex &v = tmpverts[vgen[j]];
 
138
                    *curvert++ = vec(v.vertex[0]*frame.scale[0]+frame.translate[0],
 
139
                                   -(v.vertex[1]*frame.scale[1]+frame.translate[1]),
 
140
                                     v.vertex[2]*frame.scale[2]+frame.translate[2]);
 
141
                }
 
142
                frame_offset += header.framesize;
 
143
            }
 
144
            delete[] tmpverts;
 
145
 
 
146
            fclose(file);
 
147
          
 
148
            filename = newstring(path);
 
149
            return true;
 
150
        }
 
151
 
 
152
        void getdefaultanim(animstate &as, int anim, int varseed)
 
153
        {
 
154
            //                      0   1   2   3   4   5   6   7   8   9  10  11  12   13  14  15  16  17 18  19  20   21  21  23  24     
 
155
            //                      I   R   A   P   P   P   J   L   F   S   T   W   P   CI  CW  CA  CP  CD  D   D   D   LD  LD  LD   F
 
156
            static int frame[] =  { 0,  40, 46, 54, 58, 62, 66, 69, 72, 84, 95, 112,123,135,154,160,169,173,178,184,190,183,189,197, 0 };
 
157
            static int range[] =  { 40, 6,  8,  4,  4,  4,  3,  3,  12, 11, 17, 11, 12, 19, 6,  9,  4,  5,  6,  6,  8,  1,  1,  1,   7 };
 
158
            static int animfr[] = { 0,  1,  2,  3,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 24 };
 
159
 
 
160
            if((size_t)anim >= sizeof(animfr)/sizeof(animfr[0]))
 
161
            {
 
162
                as.frame = 0;
 
163
                as.range = 1;
 
164
                return;
 
165
            }
 
166
            int n = animfr[anim];
 
167
            if(anim==ANIM_PAIN || anim==ANIM_DEATH || anim==ANIM_LYING_DEAD) n += uint(varseed)%3;
 
168
            as.frame = frame[n];
 
169
            as.range = range[n];
 
170
        }
 
171
 
 
172
        void begingenshadow()
 
173
        {
 
174
            matrixpos = 0;
 
175
            matrixstack[0].identity();
 
176
            matrixstack[0].rotate_around_z(180*RAD);
 
177
        }
 
178
    };
 
179
 
 
180
    void render(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, float scale)
 
181
    {
 
182
        if(!loaded) return;
 
183
 
 
184
        if(a) for(int i = 0; a[i].tag; i++)
 
185
        {
 
186
            if(a[i].pos) link(NULL, a[i].tag, a[i].pos);
 
187
        }
 
188
 
 
189
        if(!cullface) glDisable(GL_CULL_FACE);
 
190
        else if(anim&ANIM_MIRROR) glCullFace(GL_BACK);
 
191
 
 
192
        if(stenciling && !parts[0]->index)
 
193
        {
 
194
            shadowdir = vec(0, 1/SQRT2, -1/SQRT2);
 
195
            shadowdir.rotate_around_z((-shadowyaw-yaw-180.0f)*RAD);
 
196
            shadowdir.rotate_around_y(-pitch*RAD);
 
197
            (shadowpos = shadowdir).mul(shadowdist);
 
198
        }
 
199
 
 
200
        modelpos = o;
 
201
        modelyaw = yaw;
 
202
        modelpitch = pitch;
 
203
 
 
204
        matrixpos = 0;
 
205
        matrixstack[0].identity();
 
206
        matrixstack[0].translate(o);
 
207
        matrixstack[0].rotate_around_z((yaw+180)*RAD);
 
208
        matrixstack[0].rotate_around_y(-pitch*RAD);
 
209
        if(anim&ANIM_MIRROR || scale!=1) matrixstack[0].scale(scale, anim&ANIM_MIRROR ? -scale : scale, scale);
 
210
        parts[0]->render(anim, varseed, speed, basetime, d);
 
211
 
 
212
        if(!cullface) glEnable(GL_CULL_FACE);
 
213
        else if(anim&ANIM_MIRROR) glCullFace(GL_FRONT);
 
214
 
 
215
        if(a) for(int i = 0; a[i].tag; i++)
 
216
        {
 
217
            if(a[i].pos) link(NULL, a[i].tag, NULL);
 
218
 
 
219
            vertmodel *m = (vertmodel *)a[i].m;
 
220
            if(!m) continue;
 
221
            m->parts[0]->index = parts.length()+i;
 
222
            m->setskin();
 
223
            m->render(anim, varseed, speed, basetime, o, yaw, pitch, d, NULL, scale);
 
224
        }
 
225
 
 
226
        if(d) d->lastrendered = lastmillis;
 
227
    }
 
228
 
 
229
    void rendershadow(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, modelattach *a)
 
230
    {
 
231
        parts[0]->rendershadow(anim, varseed, speed, basetime, o, yaw);
 
232
        if(a) for(int i = 0; a[i].tag; i++)
 
233
        {
 
234
            vertmodel *m = (vertmodel *)a[i].m;
 
235
            if(!m) continue;
 
236
            part *p = m->parts[0];
 
237
            p->rendershadow(anim, varseed, speed, basetime, o, yaw);
 
238
        }
 
239
    }
 
240
 
 
241
    bool load()
 
242
    { 
 
243
        if(loaded) return true;
 
244
        md2part &mdl = *new md2part;
 
245
        parts.add(&mdl);
 
246
        mdl.model = this;
 
247
        mdl.index = 0;
 
248
        const char *pname = parentdir(loadname);
 
249
        s_sprintfd(name1)("packages/models/%s/tris.md2", loadname);
 
250
        if(!mdl.load(path(name1)))
 
251
        {
 
252
            s_sprintf(name1)("packages/models/%s/tris.md2", pname);    // try md2 in parent folder (vert sharing)
 
253
            if(!mdl.load(path(name1))) return false;
 
254
        }
 
255
        Texture *skin;
 
256
        loadskin(loadname, pname, skin);
 
257
        loopv(mdl.meshes) mdl.meshes[i]->skin  = skin;
 
258
        if(skin==notexture) conoutf("could not load model skin for %s", name1);
 
259
        loadingmd2 = this;
 
260
        s_sprintfd(name2)("packages/models/%s/md2.cfg", loadname);
 
261
        persistidents = false;
 
262
        if(!execfile(name2))
 
263
        {
 
264
            s_sprintf(name2)("packages/models/%s/md2.cfg", pname);
 
265
            execfile(name2);
 
266
        }
 
267
        persistidents = true;
 
268
        loadingmd2 = 0;
 
269
        loopv(parts) parts[i]->scaleverts(scale/16.0f, vec(translate.x, -translate.y, translate.z));
 
270
        radius = calcradius();
 
271
        if(shadowdist) calcneighbors();
 
272
        calcbbs();
 
273
        return loaded = true;
 
274
    }
 
275
};
 
276
 
 
277
void md2anim(char *anim, char *frame, char *range, char *speed)
 
278
{
 
279
    if(!loadingmd2 || loadingmd2->parts.empty()) { conoutf("not loading an md2"); return; }
 
280
    int num = findanim(anim);
 
281
    if(num<0) { conoutf("could not find animation %s", anim); return; }
 
282
    loadingmd2->parts.last()->setanim(num, atoi(frame), atoi(range), atof(speed));
 
283
}
 
284
 
 
285
void md2tag(char *name, char *vert1, char *vert2, char *vert3, char *vert4)
 
286
{
 
287
    if(!loadingmd2 || loadingmd2->parts.empty()) { conoutf("not loading an md2"); return; }
 
288
    md2::part &mdl = *loadingmd2->parts.last();
 
289
    int indexes[4] = { -1, -1, -1, -1 }, numverts = 0;
 
290
    loopi(4)
 
291
    {
 
292
        char *vert = NULL;
 
293
        switch(i)
 
294
        {
 
295
            case 0: vert = vert1; break;
 
296
            case 1: vert = vert2; break;
 
297
            case 2: vert = vert3; break;
 
298
            case 3: vert = vert4; break;
 
299
        }
 
300
        if(!vert[0]) break;
 
301
        if(isdigit(vert[0])) indexes[i] = ATOI(vert);
 
302
        else
 
303
        {
 
304
            int axis = 0, dir = 1;
 
305
            for(char *s = vert; *s; s++) switch(*s)
 
306
            {
 
307
                case '+': dir = 1; break;
 
308
                case '-': dir = -1; break;
 
309
                case 'x':
 
310
                case 'X': axis = 0; break;
 
311
                case 'y':
 
312
                case 'Y': axis = 1; break;
 
313
                case 'z':
 
314
                case 'Z': axis = 2; break;
 
315
            }
 
316
            if(!mdl.meshes.empty()) indexes[i] = mdl.meshes[0]->findvert(axis, dir);
 
317
        }
 
318
        if(indexes[i] < 0) { conoutf("could not find vertex %s", vert); return; }
 
319
        numverts = i + 1;
 
320
    }
 
321
    if(!mdl.gentag(name, indexes, numverts)) { conoutf("could not generate tag %s", name); return; }
 
322
}
 
323
 
 
324
void md2emit(char *tag, char *type, char *arg1, char *arg2)
 
325
{
 
326
    if(!loadingmd2 || loadingmd2->parts.empty()) { conoutf("not loading an md2"); return; };
 
327
    md2::part &mdl = *loadingmd2->parts.last();
 
328
    if(!mdl.addemitter(tag, ATOI(type), ATOI(arg1), ATOI(arg2))) { conoutf("could not find tag %s", tag); return; }
 
329
}
 
330
 
 
331
COMMAND(md2anim, ARG_4STR);
 
332
COMMAND(md2tag, ARG_5STR);
 
333
COMMAND(md2emit, ARG_4STR);
 
334