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

« back to all changes in this revision

Viewing changes to source/src/md3.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 md3;
 
2
 
 
3
md3 *loadingmd3 = NULL;
 
4
 
 
5
string md3dir;
 
6
 
 
7
struct md3tag
 
8
{
 
9
    char name[64];
 
10
    vec pos;
 
11
    float rotation[3][3];
 
12
};
 
13
 
 
14
struct md3vertex
 
15
{
 
16
    short vertex[3];
 
17
    short normal;
 
18
};
 
19
 
 
20
struct md3triangle
 
21
{
 
22
    int vertexindices[3];
 
23
};
 
24
 
 
25
struct md3header
 
26
{
 
27
    char id[4];
 
28
    int version;
 
29
    char name[64];
 
30
    int flags;
 
31
    int numframes, numtags, nummeshes, numskins;
 
32
    int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets
 
33
};
 
34
 
 
35
struct md3meshheader
 
36
{
 
37
    char id[4];
 
38
    char name[64];
 
39
    int flags;
 
40
    int numframes, numshaders, numvertices, numtriangles;
 
41
    int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets
 
42
};
 
43
 
 
44
struct md3 : vertmodel
 
45
{
 
46
    md3(const char *name) : vertmodel(name) {}
 
47
 
 
48
    int type() { return MDL_MD3; }
 
49
 
 
50
    struct md3part : part
 
51
    {
 
52
        bool load(char *path)
 
53
        {
 
54
            if(filename) return true;
 
55
 
 
56
            FILE *f = openfile(path, "rb");
 
57
            if(!f) return false;
 
58
            md3header header;
 
59
            fread(&header, sizeof(md3header), 1, f);
 
60
            endianswap(&header.version, sizeof(int), 1);
 
61
            endianswap(&header.flags, sizeof(int), 9);
 
62
            if(strncmp(header.id, "IDP3", 4) != 0 || header.version != 15) // header check
 
63
            { 
 
64
                fclose(f);
 
65
                conoutf("md3: corrupted header"); 
 
66
                return false; 
 
67
            }
 
68
 
 
69
            numframes = header.numframes;
 
70
            numtags = header.numtags;        
 
71
            if(numtags)
 
72
            {
 
73
                tags = new tag[numframes*numtags];
 
74
                fseek(f, header.ofs_tags, SEEK_SET);
 
75
                md3tag tag;
 
76
                
 
77
                loopi(header.numframes*header.numtags) 
 
78
                {
 
79
                    fread(&tag, sizeof(md3tag), 1, f);
 
80
                    endianswap(&tag.pos, sizeof(float), 12);
 
81
                    if(tag.name[0] && i<header.numtags) tags[i].name = newstring(tag.name);
 
82
                    tags[i].pos = vec(tag.pos.y, tag.pos.x, tag.pos.z);
 
83
                    memcpy(tags[i].transform, tag.rotation, sizeof(tag.rotation));
 
84
                    // undo the x/y swap
 
85
                    loopj(3) swap(tags[i].transform[0][j], tags[i].transform[1][j]);
 
86
                    // then restore it
 
87
                    loopj(3) swap(tags[i].transform[j][0], tags[i].transform[j][1]);
 
88
                }
 
89
                links = new linkedpart[numtags];
 
90
            }
 
91
 
 
92
            int mesh_offset = header.ofs_meshes;
 
93
            loopi(header.nummeshes)
 
94
            {
 
95
                md3meshheader mheader;
 
96
                fseek(f, mesh_offset, SEEK_SET);
 
97
                fread(&mheader, sizeof(md3meshheader), 1, f);
 
98
                endianswap(&mheader.flags, sizeof(int), 10);
 
99
 
 
100
                if(mheader.numtriangles <= 0)
 
101
                {
 
102
                    mesh_offset += mheader.meshsize;
 
103
                    continue;
 
104
                }
 
105
                
 
106
                mesh &m = *meshes.add(new mesh);
 
107
                m.owner = this;
 
108
                m.name = newstring(mheader.name);
 
109
               
 
110
                m.numtris = mheader.numtriangles; 
 
111
                m.tris = new tri[m.numtris];
 
112
                fseek(f, mesh_offset + mheader.ofs_triangles, SEEK_SET);
 
113
                loopj(mheader.numtriangles)
 
114
                {
 
115
                    md3triangle tri;
 
116
                    fread(&tri, sizeof(md3triangle), 1, f); // read the triangles
 
117
                    endianswap(&tri, sizeof(int), 3);
 
118
                    loopk(3) m.tris[j].vert[k] = (ushort)tri.vertexindices[k];
 
119
                }
 
120
 
 
121
                m.numverts = mheader.numvertices;
 
122
                m.tcverts = new tcvert[m.numverts];
 
123
                fseek(f, mesh_offset + mheader.ofs_uv , SEEK_SET); 
 
124
                fread(m.tcverts, 2*sizeof(float), m.numverts, f); // read the UV data
 
125
                endianswap(m.tcverts, sizeof(float), 2*m.numverts);
 
126
                
 
127
                m.verts = new vec[numframes*m.numverts + 1];
 
128
                fseek(f, mesh_offset + mheader.ofs_vertices, SEEK_SET); 
 
129
                loopj(numframes*mheader.numvertices)
 
130
                {
 
131
                    md3vertex v;
 
132
                    fread(&v, sizeof(md3vertex), 1, f); // read the vertices
 
133
                    endianswap(&v, sizeof(short), 4);
 
134
 
 
135
                    m.verts[j].x = v.vertex[1]/64.0f;
 
136
                    m.verts[j].y = v.vertex[0]/64.0f;
 
137
                    m.verts[j].z = v.vertex[2]/64.0f;
 
138
                }
 
139
 
 
140
                mesh_offset += mheader.meshsize;
 
141
            }
 
142
            fclose(f);
 
143
 
 
144
            filename = newstring(path); 
 
145
            return true;
 
146
        }
 
147
 
 
148
        void begingenshadow()
 
149
        {
 
150
            matrixpos = 0;
 
151
            matrixstack[0].identity();
 
152
            matrixstack[0].rotate_around_z(180*RAD);
 
153
        }
 
154
    };
 
155
   
 
156
    void render(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, float scale)
 
157
    {
 
158
        if(!loaded) return;
 
159
 
 
160
        if(a) for(int i = 0; a[i].tag; i++)
 
161
        {
 
162
            vertmodel *m = (vertmodel *)a[i].m;
 
163
            if(!m)
 
164
            {
 
165
                if(a[i].pos) link(NULL, a[i].tag);
 
166
                continue;
 
167
            }
 
168
            part *p = m->parts[0];
 
169
            if(link(p, a[i].tag, a[i].pos)) p->index = parts.length()+i;
 
170
        }
 
171
 
 
172
        if(!cullface) glDisable(GL_CULL_FACE);
 
173
        else if(anim&ANIM_MIRROR) glCullFace(GL_BACK);
 
174
 
 
175
        if(stenciling)
 
176
        {
 
177
            shadowdir = vec(0, 1/SQRT2, -1/SQRT2);
 
178
            shadowdir.rotate_around_z((-shadowyaw-yaw-180.0f)*RAD);
 
179
            shadowdir.rotate_around_y(-pitch*RAD);
 
180
            (shadowpos = shadowdir).mul(shadowdist);
 
181
        }
 
182
 
 
183
        modelpos = o;
 
184
        modelyaw = yaw;
 
185
        modelpitch = pitch;
 
186
 
 
187
        matrixpos = 0;
 
188
        matrixstack[0].identity();
 
189
        matrixstack[0].translate(o);
 
190
        matrixstack[0].rotate_around_z((yaw+180)*RAD);
 
191
        matrixstack[0].rotate_around_y(-pitch*RAD);
 
192
        if(anim&ANIM_MIRROR || scale!=1) matrixstack[0].scale(scale, anim&ANIM_MIRROR ? -scale : scale, scale);
 
193
        parts[0]->render(anim, varseed, speed, basetime, d);
 
194
 
 
195
        if(!cullface) glEnable(GL_CULL_FACE);
 
196
        else if(anim&ANIM_MIRROR) glCullFace(GL_FRONT);
 
197
 
 
198
        if(a) for(int i = 0; a[i].tag; i++) link(NULL, a[i].tag);
 
199
 
 
200
        if(d) d->lastrendered = lastmillis;
 
201
    }
 
202
 
 
203
    void rendershadow(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, modelattach *a)
 
204
    {
 
205
        if(parts.length()>1) return;
 
206
        parts[0]->rendershadow(anim, varseed, speed, basetime, o, yaw);
 
207
    }
 
208
 
 
209
    bool load()
 
210
    {
 
211
        if(loaded) return true;
 
212
        s_sprintf(md3dir)("packages/models/%s", loadname);
 
213
 
 
214
        const char *pname = parentdir(loadname);
 
215
        s_sprintfd(cfgname)("packages/models/%s/md3.cfg", loadname);
 
216
 
 
217
        loadingmd3 = this;
 
218
        persistidents = false;
 
219
        if(execfile(cfgname) && parts.length()) // configured md3, will call the md3* commands below
 
220
        {
 
221
            persistidents = true;
 
222
            loadingmd3 = NULL;
 
223
            if(parts.empty()) return false;
 
224
            loopv(parts) if(!parts[i]->filename) return false;
 
225
        }
 
226
        else // md3 without configuration, try default tris and skin
 
227
        {
 
228
            persistidents = false;
 
229
            loadingmd3 = NULL;
 
230
            md3part &mdl = *new md3part;
 
231
            parts.add(&mdl);
 
232
            mdl.model = this;
 
233
            mdl.index = 0; 
 
234
            s_sprintfd(name1)("packages/models/%s/tris.md3", loadname);
 
235
            if(!mdl.load(path(name1)))
 
236
            {
 
237
                s_sprintf(name1)("packages/models/%s/tris.md3", pname);    // try md3 in parent folder (vert sharing)
 
238
                if(!mdl.load(path(name1))) return false;
 
239
            };
 
240
            Texture *skin;
 
241
            loadskin(loadname, pname, skin);
 
242
            loopv(mdl.meshes) mdl.meshes[i]->skin  = skin;
 
243
            if(skin==notexture) conoutf("could not load model skin for %s", name1);
 
244
        }
 
245
        loopv(parts) parts[i]->scaleverts(scale/16.0f, vec(translate.x, -translate.y, translate.z));
 
246
        radius = calcradius();
 
247
        if(shadowdist) calcneighbors();
 
248
        calcbbs();
 
249
        return loaded = true;
 
250
    }
 
251
};
 
252
 
 
253
void md3load(char *model)
 
254
{   
 
255
    if(!loadingmd3) { conoutf("not loading an md3"); return; };
 
256
    s_sprintfd(filename)("%s/%s", md3dir, model);
 
257
    md3::md3part &mdl = *new md3::md3part;
 
258
    loadingmd3->parts.add(&mdl);
 
259
    mdl.model = loadingmd3;
 
260
    mdl.index = loadingmd3->parts.length()-1;
 
261
    if(!mdl.load(path(filename))) conoutf("could not load %s", filename); // ignore failure
 
262
}  
 
263
    
 
264
void md3skin(char *objname, char *skin)
 
265
{   
 
266
    if(!objname || !skin) return;
 
267
    if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; };
 
268
    md3::part &mdl = *loadingmd3->parts.last();
 
269
    loopv(mdl.meshes)
 
270
    {   
 
271
        md3::mesh &m = *mdl.meshes[i];
 
272
        if(!strcmp(objname, "*") || !strcmp(m.name, objname))
 
273
        {
 
274
            s_sprintfd(spath)("%s/%s", md3dir, skin);
 
275
            m.skin = textureload(spath);
 
276
        }
 
277
    }
 
278
}
 
279
 
 
280
void md3anim(char *anim, char *startframe, char *range, char *speed)
 
281
{
 
282
    if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; };
 
283
    int num = findanim(anim);
 
284
    if(num<0) { conoutf("could not find animation %s", anim); return; };
 
285
    loadingmd3->parts.last()->setanim(num, atoi(startframe), atoi(range), atof(speed));
 
286
}
 
287
 
 
288
void md3link(char *parentno, char *childno, char *tagname)
 
289
{
 
290
    if(!loadingmd3) { conoutf("not loading an md3"); return; };
 
291
    int parent = ATOI(parentno), child = ATOI(childno);
 
292
    if(!loadingmd3->parts.inrange(parent) || !loadingmd3->parts.inrange(child)) { conoutf("no models loaded to link"); return; }
 
293
    if(!loadingmd3->parts[parent]->link(loadingmd3->parts[child], tagname)) conoutf("could not link model %s", loadingmd3->loadname);
 
294
}
 
295
 
 
296
void md3emit(char *tag, char *type, char *arg1, char *arg2)
 
297
{
 
298
    if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; };
 
299
    md3::part &mdl = *loadingmd3->parts.last();
 
300
    if(!mdl.addemitter(tag, ATOI(type), ATOI(arg1), ATOI(arg2))) { conoutf("could not find tag %s", tag); return; }
 
301
}
 
302
 
 
303
COMMAND(md3load, ARG_1STR);
 
304
COMMAND(md3skin, ARG_2STR);
 
305
COMMAND(md3anim, ARG_4STR);
 
306
COMMAND(md3link, ARG_3STR);
 
307
COMMAND(md3emit, ARG_4STR);
 
308