Subversion Repositories eduke32

Rev

Rev 5001 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
//------------------------------------- MD2/MD3 LIBRARY BEGINS -------------------------------------
2
 
1820 terminx 3
#ifdef USE_OPENGL
1176 terminx 4
 
1173 terminx 5
#include "compat.h"
6
#include "build.h"
7
#include "glbuild.h"
8
#include "pragmas.h"
9
#include "baselayer.h"
10
#include "engine_priv.h"
11
#include "hightile.h"
12
#include "polymost.h"
3758 terminx 13
#include "texcache.h"
722 plagman 14
#include "mdsprite.h"
1173 terminx 15
#include "cache1d.h"
16
#include "kplib.h"
4656 terminx 17
#include "common.h"
1173 terminx 18
 
1245 terminx 19
#include <math.h>
4656 terminx 20
#include <float.h>
1245 terminx 21
 
2251 helixhorne 22
static int32_t curextra=MAXTILES;
587 terminx 23
 
2045 helixhorne 24
#define MIN_CACHETIME_PRINT 10
1784 helixhorne 25
 
26
static void QuitOnFatalError(const char *msg)
27
{
28
    if (msg)
29
        initprintf("%s\n", msg);
30
    uninitengine();
4502 hendricks2 31
    Bexit(1);
1784 helixhorne 32
}
33
 
34
 
2237 helixhorne 35
static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet)
587 terminx 36
{
2265 helixhorne 37
    // tile >= 0 && tile < MAXTILES
38
 
654 terminx 39
    UNREFERENCED_PARAMETER(model);
2265 helixhorne 40
    if (curextra==MAXTILES+EXTRATILES-1)
2267 helixhorne 41
    {
42
        initprintf("warning: max EXTRATILES reached\n");
2265 helixhorne 43
        return curextra;
2267 helixhorne 44
    }
2265 helixhorne 45
 
46
    if (tile2model[tile].modelid==-1)
47
    {
48
        tile2model[tile].pal=pallet;
49
        return tile;
50
    }
51
 
52
    if (tile2model[tile].pal==pallet)
53
        return tile;
54
 
605 terminx 55
    while (tile2model[tile].next!=-1)
591 plagman 56
    {
57
        tile=tile2model[tile].next;
2265 helixhorne 58
        if (tile2model[tile].pal==pallet)
59
            return tile;
591 plagman 60
    }
2265 helixhorne 61
 
587 terminx 62
    tile2model[tile].next=curextra;
63
    tile2model[curextra].pal=pallet;
2265 helixhorne 64
 
587 terminx 65
    return curextra++;
66
}
1205 terminx 67
int32_t Ptile2tile(int32_t tile,int32_t pallet)
587 terminx 68
{
1205 terminx 69
    int32_t t=tile;
587 terminx 70
//  if(tile>=1550&&tile<=1589){initprintf("(%d, %d)\n",tile,pallet);pallet=0;}
71
    while ((tile=tile2model[tile].next)!=-1)
72
        if (tile2model[tile].pal==pallet)
73
            return tile;
74
    return t;
75
}
76
 
5 Plagman 77
#define MODELALLOCGROUP 256
2265 helixhorne 78
static int32_t nummodelsalloced = 0;
5 Plagman 79
 
1205 terminx 80
static int32_t maxmodelverts = 0, allocmodelverts = 0;
81
static int32_t maxmodeltris = 0, allocmodeltris = 0;
4639 terminx 82
static vec3f_t *vertlist = NULL; //temp array to store interpolated vertices for drawing
5 Plagman 83
 
1205 terminx 84
static int32_t allocvbos = 0, curvbo = 0;
1762 terminx 85
static GLuint *vertvbos = NULL;
86
static GLuint *indexvbos = NULL;
519 Plagman 87
 
4764 helixhorne 88
#ifdef POLYMER
4639 terminx 89
static int32_t *tribuf = NULL;
90
static int32_t tribufverts = 0;
4764 helixhorne 91
#endif
4639 terminx 92
 
2247 helixhorne 93
static mdmodel_t *mdload(const char *);
2237 helixhorne 94
static void mdfree(mdmodel_t *);
1205 terminx 95
int32_t globalnoeffect=0;
5 Plagman 96
 
1205 terminx 97
extern int32_t timerticspersec;
308 terminx 98
 
4639 terminx 99
void md_freevbos()
1430 terminx 100
{
101
    int32_t i;
102
 
103
    for (i=0; i<nextmodelid; i++)
104
        if (models[i]->mdnum == 3)
105
        {
106
            md3model_t *m = (md3model_t *)models[i];
107
            if (m->vbos)
108
            {
109
                //            OSD_Printf("freeing model %d vbo\n",i);
110
                bglDeleteBuffersARB(m->head.numsurfs, m->vbos);
1643 terminx 111
                Bfree(m->vbos);
1430 terminx 112
                m->vbos = NULL;
113
            }
114
        }
115
 
1440 terminx 116
    if (allocvbos)
117
    {
118
        bglDeleteBuffersARB(allocvbos, indexvbos);
119
        bglDeleteBuffersARB(allocvbos, vertvbos);
120
        allocvbos = 0;
121
    }
1430 terminx 122
}
123
 
1173 terminx 124
void freeallmodels()
5 Plagman 125
{
1205 terminx 126
    int32_t i;
5 Plagman 127
 
128
    if (models)
129
    {
1229 terminx 130
        for (i=0; i<nextmodelid; i++) mdfree(models[i]);
1643 terminx 131
        Bfree(models); models = NULL;
5 Plagman 132
        nummodelsalloced = 0;
133
        nextmodelid = 0;
134
    }
135
 
136
    memset(tile2model,-1,sizeof(tile2model));
587 terminx 137
    curextra=MAXTILES;
5 Plagman 138
 
139
    if (vertlist)
140
    {
1643 terminx 141
        Bfree(vertlist);
5 Plagman 142
        vertlist = NULL;
143
        allocmodelverts = maxmodelverts = 0;
519 Plagman 144
        allocmodeltris = maxmodeltris = 0;
5 Plagman 145
    }
519 Plagman 146
 
4639 terminx 147
    md_freevbos();
4764 helixhorne 148
#ifdef POLYMER
4639 terminx 149
    DO_FREE_AND_NULL(tribuf);
4764 helixhorne 150
#endif
5 Plagman 151
}
152
 
2619 helixhorne 153
 
154
// Skin texture names can be aliased! This is ugly, but at least correct.
155
static void nullskintexids(GLuint texid)
156
{
157
    int32_t i, j;
158
 
159
    for (i=0; i<nextmodelid; i++)
160
    {
161
        mdmodel_t *m = models[i];
162
 
163
        if (m->mdnum == 2 || m->mdnum == 3)
164
        {
165
            mdskinmap_t *sk;
166
            md2model_t *m2 = (md2model_t *)m;
167
 
168
            for (j=0; j<m2->numskins*(HICEFFECTMASK+1); j++)
169
                if (m2->texid[j] == texid)
170
                    m2->texid[j] = 0;
171
 
172
            for (sk=m2->skinmap; sk; sk=sk->next)
173
                for (j=0; j<(HICEFFECTMASK+1); j++)
174
                    if (sk->texid[j] == texid)
175
                        sk->texid[j] = 0;
176
        }
177
    }
178
}
179
 
1173 terminx 180
void clearskins()
5 Plagman 181
{
1205 terminx 182
    int32_t i, j;
5 Plagman 183
 
1229 terminx 184
    for (i=0; i<nextmodelid; i++)
5 Plagman 185
    {
2619 helixhorne 186
        mdmodel_t *m = models[i];
187
 
584 terminx 188
        if (m->mdnum == 1)
189
        {
1762 terminx 190
            voxmodel_t *v = (voxmodel_t *)m;
2619 helixhorne 191
 
1229 terminx 192
            for (j=0; j<MAXPALOOKUPS; j++)
2619 helixhorne 193
                if (v->texid[j])
194
                {
195
                    bglDeleteTextures(1, &v->texid[j]);
196
                    v->texid[j] = 0;
197
                }
584 terminx 198
        }
199
        else if (m->mdnum == 2 || m->mdnum == 3)
200
        {
2619 helixhorne 201
            mdskinmap_t *sk;
1762 terminx 202
            md2model_t *m2 = (md2model_t *)m;
2619 helixhorne 203
 
1229 terminx 204
            for (j=0; j<m2->numskins*(HICEFFECTMASK+1); j++)
2619 helixhorne 205
                if (m2->texid[j])
206
                {
207
                    GLuint otexid = m2->texid[j];
5 Plagman 208
 
2619 helixhorne 209
                    bglDeleteTextures(1, &m2->texid[j]);
210
                    m2->texid[j] = 0;
211
 
212
                    nullskintexids(otexid);
213
                }
214
 
1229 terminx 215
            for (sk=m2->skinmap; sk; sk=sk->next)
216
                for (j=0; j<(HICEFFECTMASK+1); j++)
2619 helixhorne 217
                    if (sk->texid[j])
218
                    {
219
                        GLuint otexid = sk->texid[j];
220
 
221
                        bglDeleteTextures(1, &sk->texid[j]);
222
                        sk->texid[j] = 0;
223
 
224
                        nullskintexids(otexid);
225
                    }
5 Plagman 226
        }
227
    }
228
 
1229 terminx 229
    for (i=0; i<MAXVOXELS; i++)
5 Plagman 230
    {
2619 helixhorne 231
        voxmodel_t *v = voxmodels[i];
232
        if (!v) continue;
233
 
1229 terminx 234
        for (j=0; j<MAXPALOOKUPS; j++)
2619 helixhorne 235
            if (v->texid[j])
236
            {
237
                bglDeleteTextures(1, &v->texid[j]);
238
                v->texid[j] = 0;
239
            }
5 Plagman 240
    }
241
}
242
 
1173 terminx 243
void mdinit()
5 Plagman 244
{
245
    memset(hudmem,0,sizeof(hudmem));
246
    freeallmodels();
247
    mdinited = 1;
248
}
249
 
1205 terminx 250
int32_t md_loadmodel(const char *fn)
5 Plagman 251
{
1206 terminx 252
    mdmodel_t *vm, **ml;
5 Plagman 253
 
254
    if (!mdinited) mdinit();
255
 
256
    if (nextmodelid >= nummodelsalloced)
257
    {
4491 helixhorne 258
        ml = (mdmodel_t **)Xrealloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(void *));
5 Plagman 259
        models = ml; nummodelsalloced += MODELALLOCGROUP;
260
    }
261
 
262
    vm = mdload(fn); if (!vm) return(-1);
263
    models[nextmodelid++] = vm;
264
    return(nextmodelid-1);
265
}
266
 
2264 hendricks2 267
int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, float yoffset, int32_t flags)
5 Plagman 268
{
1206 terminx 269
    mdmodel_t *m;
5 Plagman 270
 
271
    if (!mdinited) mdinit();
272
 
1205 terminx 273
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
5 Plagman 274
    m = models[modelid];
275
    m->bscale = scale;
276
    m->shadeoff = shadeoff;
277
    m->zadd = zadd;
2264 hendricks2 278
    m->yoffset = yoffset;
587 terminx 279
    m->flags = flags;
5 Plagman 280
 
281
    return 0;
282
}
283
 
1206 terminx 284
static int32_t framename2index(mdmodel_t *vm, const char *nam)
5 Plagman 285
{
1205 terminx 286
    int32_t i = 0;
5 Plagman 287
 
331 terminx 288
    switch (vm->mdnum)
5 Plagman 289
    {
109 terminx 290
    case 2:
331 terminx 291
    {
1206 terminx 292
        md2model_t *m = (md2model_t *)vm;
331 terminx 293
        md2frame_t *fr;
1229 terminx 294
        for (i=0; i<m->numframes; i++)
109 terminx 295
        {
331 terminx 296
            fr = (md2frame_t *)&m->frames[i*m->framebytes];
297
            if (!Bstrcmp(fr->name, nam)) break;
109 terminx 298
        }
331 terminx 299
    }
300
    break;
109 terminx 301
    case 3:
331 terminx 302
    {
1206 terminx 303
        md3model_t *m = (md3model_t *)vm;
1229 terminx 304
        for (i=0; i<m->numframes; i++)
331 terminx 305
            if (!Bstrcmp(m->head.frames[i].nam,nam)) break;
5 Plagman 306
    }
331 terminx 307
    break;
308
    }
5 Plagman 309
    return(i);
310
}
311
 
1205 terminx 312
int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, int32_t skinnum, float smoothduration, int32_t pal)
5 Plagman 313
{
1206 terminx 314
    md2model_t *m;
1205 terminx 315
    int32_t i;
5 Plagman 316
 
317
    if (!mdinited) mdinit();
318
 
1205 terminx 319
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return(-1);
320
    if ((uint32_t)tilenume >= (uint32_t)MAXTILES) return(-2);
5 Plagman 321
    if (!framename) return(-3);
322
 
587 terminx 323
    tilenume=addtileP(modelid,tilenume,pal);
1206 terminx 324
    m = (md2model_t *)models[modelid];
584 terminx 325
    if (m->mdnum == 1)
326
    {
5 Plagman 327
        tile2model[tilenume].modelid = modelid;
328
        tile2model[tilenume].framenum = tile2model[tilenume].skinnum = 0;
329
        return 0;
330
    }
331
 
1762 terminx 332
    i = framename2index((mdmodel_t *)m,framename);
5 Plagman 333
    if (i == m->numframes) return(-3);   // frame name invalid
334
 
335
    tile2model[tilenume].modelid = modelid;
336
    tile2model[tilenume].framenum = i;
337
    tile2model[tilenume].skinnum = skinnum;
531 Plagman 338
    tile2model[tilenume].smoothduration = smoothduration;
5 Plagman 339
 
1910 helixhorne 340
    return i;
5 Plagman 341
}
342
 
1205 terminx 343
int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, int32_t fpssc, int32_t flags)
5 Plagman 344
{
1206 terminx 345
    md2model_t *m;
5 Plagman 346
    mdanim_t ma, *map;
1205 terminx 347
    int32_t i;
5 Plagman 348
 
349
    if (!mdinited) mdinit();
350
 
1205 terminx 351
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return(-1);
5 Plagman 352
 
4639 terminx 353
    Bmemset(&ma, 0, sizeof(ma));
1206 terminx 354
    m = (md2model_t *)models[modelid];
5 Plagman 355
    if (m->mdnum < 2) return 0;
356
 
109 terminx 357
    //find index of start frame
1762 terminx 358
    i = framename2index((mdmodel_t *)m,framestart);
5 Plagman 359
    if (i == m->numframes) return -2;
360
    ma.startframe = i;
361
 
109 terminx 362
    //find index of finish frame which must trail start frame
1762 terminx 363
    i = framename2index((mdmodel_t *)m,frameend);
5 Plagman 364
    if (i == m->numframes) return -3;
365
    ma.endframe = i;
366
 
367
    ma.fpssc = fpssc;
368
    ma.flags = flags;
369
 
4491 helixhorne 370
    map = (mdanim_t *)Xmalloc(sizeof(mdanim_t));
371
 
1425 terminx 372
    Bmemcpy(map, &ma, sizeof(ma));
5 Plagman 373
 
374
    map->next = m->animations;
375
    m->animations = map;
376
 
377
    return(0);
378
}
379
 
2251 helixhorne 380
#if 0
381
// FIXME: CURRENTLY DISABLED: interpolation may access frames we consider 'unused'?
1910 helixhorne 382
int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap)
383
{
384
    md3model_t *m;
385
    md3surf_t *s;
386
    mdanim_t *anm;
387
    int32_t i, surfi, sub, usedframes;
388
    static int16_t otonframe[1024];
389
 
390
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
391
    m = (md3model_t *)models[modelid];
392
    if (m->mdnum != 3) return -2;
393
 
394
    for (anm=m->animations; anm; anm=anm->next)
395
    {
396
        if (anm->endframe <= anm->startframe)
397
        {
398
//            initprintf("backward anim %d-%d\n", anm->startframe, anm->endframe);
399
            return -3;
400
        }
401
 
402
        for (i=anm->startframe; i<anm->endframe; i++)
403
            usedframebitmap[i>>3] |= (1<<(i&7));
404
    }
405
 
406
    sub = 0;
407
    for (i=0; i<m->numframes; i++)
408
    {
409
        if (!(usedframebitmap[i>>3]&(1<<(i&7))))
410
        {
411
            sub++;
412
            otonframe[i] = -1;
413
            continue;
414
        }
415
 
416
        otonframe[i] = i-sub;
417
    }
418
 
419
    usedframes = m->numframes - sub;
420
    if (usedframes==0 || usedframes==m->numframes)
421
        return usedframes;
422
 
423
    //// THIN OUT! ////
424
 
425
    for (i=0; i<m->numframes; i++)
426
    {
427
        if (otonframe[i]>=0 && otonframe[i] != i)
428
        {
429
            if (m->muladdframes)
4639 terminx 430
                Bmemcpy(&m->muladdframes[2*otonframe[i]], &m->muladdframes[2*i], 2*sizeof(vec3f_t));
1910 helixhorne 431
            Bmemcpy(&m->head.frames[otonframe[i]], &m->head.frames[i], sizeof(md3frame_t));
432
        }
433
    }
434
 
435
    for (surfi=0; surfi < m->head.numsurfs; surfi++)
436
    {
437
        s = &m->head.surfs[surfi];
438
 
439
        for (i=0; i<m->numframes; i++)
440
            if (otonframe[i]>=0 && otonframe[i] != i)
441
                Bmemcpy(&s->xyzn[otonframe[i]*s->numverts], &s->xyzn[i*s->numverts], s->numverts*sizeof(md3xyzn_t));
442
    }
443
 
444
    ////// tweak frame indices in various places
445
 
446
    for (anm=m->animations; anm; anm=anm->next)
447
    {
448
        if (otonframe[anm->startframe]==-1 || otonframe[anm->endframe-1]==-1)
449
            initprintf("md %d WTF: anm %d %d\n", modelid, anm->startframe, anm->endframe);
450
 
451
        anm->startframe = otonframe[anm->startframe];
452
        anm->endframe = otonframe[anm->endframe-1];
453
    }
454
 
455
    for (i=0; i<MAXTILES+EXTRATILES; i++)
456
        if (tile2model[i].modelid == modelid)
457
        {
458
            if (otonframe[tile2model[i].framenum]==-1)
459
                initprintf("md %d WTF: tile %d, fr %d\n", modelid, i, tile2model[i].framenum);
460
            tile2model[i].framenum = otonframe[tile2model[i].framenum];
461
        }
462
 
463
    ////// realloc & change "numframes" everywhere
464
 
465
    if (m->muladdframes)
4639 terminx 466
        m->muladdframes = Xrealloc(m->muladdframes, 2*sizeof(vec3f_t)*usedframes);
4491 helixhorne 467
    m->head.frames = Xrealloc(m->head.frames, sizeof(md3frame_t)*usedframes);
1910 helixhorne 468
 
469
    for (surfi=0; surfi < m->head.numsurfs; surfi++)
470
    {
471
        m->head.surfs[surfi].numframes = usedframes;
472
        // CAN'T do that because xyzn is offset from a larger block when loaded from md3:
4491 helixhorne 473
//        m->head.surfs[surfi].xyzn = Xrealloc(m->head.surfs[surfi].xyzn, s->numverts*usedframes*sizeof(md3xyzn_t));
1910 helixhorne 474
    }
475
 
476
    m->head.numframes = usedframes;
477
    m->numframes = usedframes;
478
 
479
    ////////////
480
    return usedframes;
481
}
2251 helixhorne 482
#endif
1910 helixhorne 483
 
1279 plagman 484
int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor)
5 Plagman 485
{
486
    mdskinmap_t *sk, *skl;
1206 terminx 487
    md2model_t *m;
5 Plagman 488
 
489
    if (!mdinited) mdinit();
490
 
1205 terminx 491
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
5 Plagman 492
    if (!skinfn) return -2;
493
    if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3;
494
 
1206 terminx 495
    m = (md2model_t *)models[modelid];
5 Plagman 496
    if (m->mdnum < 2) return 0;
497
    if (m->mdnum == 2) surfnum = 0;
498
 
499
    skl = NULL;
500
    for (sk = m->skinmap; sk; skl = sk, sk = sk->next)
2619 helixhorne 501
        if (sk->palette == (uint8_t)palnum && skinnum == sk->skinnum && surfnum == sk->surfnum)
502
            break;
584 terminx 503
    if (!sk)
504
    {
4491 helixhorne 505
        sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t));
5 Plagman 506
 
507
        if (!skl) m->skinmap = sk;
508
        else skl->next = sk;
584 terminx 509
    }
1643 terminx 510
    else if (sk->fn) Bfree(sk->fn);
5 Plagman 511
 
1205 terminx 512
    sk->palette = (uint8_t)palnum;
5 Plagman 513
    sk->skinnum = skinnum;
514
    sk->surfnum = surfnum;
501 Plagman 515
    sk->param = param;
1279 plagman 516
    sk->specpower = specpower;
517
    sk->specfactor = specfactor;
4491 helixhorne 518
    sk->fn = Xstrdup(skinfn);
5 Plagman 519
 
520
    return 0;
521
}
522
 
4607 terminx 523
int32_t md_definehud(int32_t modelid, int32_t tilex, float xadd, float yadd, float zadd, int32_t angadd, int32_t flags, int32_t fov)
5 Plagman 524
{
525
    if (!mdinited) mdinit();
526
 
1205 terminx 527
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
528
    if ((uint32_t)tilex >= (uint32_t)MAXTILES) return -2;
5 Plagman 529
 
4639 terminx 530
    hudmem[(flags>>2)&1][tilex].add.x = xadd;
531
    hudmem[(flags>>2)&1][tilex].add.y = yadd;
532
    hudmem[(flags>>2)&1][tilex].add.z = zadd;
1205 terminx 533
    hudmem[(flags>>2)&1][tilex].angadd = ((int16_t)angadd)|2048;
534
    hudmem[(flags>>2)&1][tilex].flags = (int16_t)flags;
1814 plagman 535
    hudmem[(flags>>2)&1][tilex].fov = (int16_t)fov;
5 Plagman 536
 
537
    return 0;
538
}
539
 
1205 terminx 540
int32_t md_undefinetile(int32_t tile)
5 Plagman 541
{
542
    if (!mdinited) return 0;
543
    if ((unsigned)tile >= (unsigned)MAXTILES) return -1;
544
 
545
    tile2model[tile].modelid = -1;
587 terminx 546
    tile2model[tile].next=-1;
5053 hendricks2 547
    hudmem[0][tile].angadd = 0;
548
    hudmem[1][tile].angadd = 0;
549
 
5 Plagman 550
    return 0;
551
}
552
 
2237 helixhorne 553
/* this function is problematic, it leaves NULL holes in model[]
554
 * (which runs from 0 to nextmodelid-1) */
1205 terminx 555
int32_t md_undefinemodel(int32_t modelid)
5 Plagman 556
{
1205 terminx 557
    int32_t i;
5 Plagman 558
    if (!mdinited) return 0;
1205 terminx 559
    if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
5 Plagman 560
 
587 terminx 561
    for (i=MAXTILES+EXTRATILES-1; i>=0; i--)
5 Plagman 562
        if (tile2model[i].modelid == modelid)
563
            tile2model[i].modelid = -1;
564
 
584 terminx 565
    if (models)
566
    {
5 Plagman 567
        mdfree(models[modelid]);
568
        models[modelid] = NULL;
569
    }
570
 
571
    return 0;
572
}
573
 
4488 helixhorne 574
static int32_t daskinloader(int32_t filh, intptr_t *fptr, int32_t *bpl, int32_t *sizx, int32_t *sizy,
575
                            int32_t *osizx, int32_t *osizy, char *hasalpha, int32_t pal, char effect)
587 terminx 576
{
1205 terminx 577
    int32_t picfillen, j,y,x;
109 terminx 578
    char *picfil,*cptr,al=255;
579
    coltype *pic;
1205 terminx 580
    int32_t xsiz, ysiz, tsizx, tsizy;
581
    int32_t r, g, b;
5 Plagman 582
 
109 terminx 583
    picfillen = kfilelength(filh);
4491 helixhorne 584
    picfil = (char *)Xmalloc(picfillen+1);
109 terminx 585
    kread(filh, picfil, picfillen);
5 Plagman 586
 
587
    // tsizx/y = replacement texture's natural size
588
    // xsiz/y = 2^x size of replacement
589
 
590
    kpgetdim(picfil,picfillen,&tsizx,&tsizy);
1851 terminx 591
    if (tsizx == 0 || tsizy == 0) { Bfree(picfil); return -2; }
5 Plagman 592
 
584 terminx 593
    if (!glinfo.texnpot)
594
    {
1229 terminx 595
        for (xsiz=1; xsiz<tsizx; xsiz+=xsiz);
596
        for (ysiz=1; ysiz<tsizy; ysiz+=ysiz);
584 terminx 597
    }
598
    else
599
    {
5 Plagman 600
        xsiz = tsizx;
601
        ysiz = tsizy;
602
    }
603
    *osizx = tsizx; *osizy = tsizy;
4491 helixhorne 604
    pic = (coltype *)Xmalloc(xsiz*ysiz*sizeof(coltype));
605
 
5 Plagman 606
    memset(pic,0,xsiz*ysiz*sizeof(coltype));
607
 
4639 terminx 608
    if (kprender(picfil,picfillen,(intptr_t)pic,xsiz*sizeof(coltype),xsiz,ysiz))
1784 helixhorne 609
        { Bfree(picfil); Bfree(pic); return -2; }
1643 terminx 610
    Bfree(picfil);
5 Plagman 611
 
109 terminx 612
    cptr = &britable[gammabrightness ? 0 : curbrightness][0];
665 terminx 613
    r=(glinfo.bgra)?hictinting[pal].b:hictinting[pal].r;
614
    g=hictinting[pal].g;
615
    b=(glinfo.bgra)?hictinting[pal].r:hictinting[pal].b;
1229 terminx 616
    for (y=0,j=0; y<tsizy; y++,j+=xsiz)
109 terminx 617
    {
618
        coltype *rpptr = &pic[j], tcol;
5 Plagman 619
 
1229 terminx 620
        for (x=0; x<tsizx; x++)
5 Plagman 621
        {
622
            tcol.b = cptr[rpptr[x].b];
623
            tcol.g = cptr[rpptr[x].g];
624
            tcol.r = cptr[rpptr[x].r];
625
 
4486 helixhorne 626
            if (effect & HICTINT_GRAYSCALE)
584 terminx 627
            {
4889 terminx 628
                tcol.g = tcol.r = tcol.b = (uint8_t)((tcol.r * GRAYSCALE_COEFF_RED) + (tcol.g * GRAYSCALE_COEFF_GREEN) +
629
                                                     (tcol.b * GRAYSCALE_COEFF_BLUE));
5 Plagman 630
            }
4889 terminx 631
 
4486 helixhorne 632
            if (effect & HICTINT_INVERT)
584 terminx 633
            {
5 Plagman 634
                tcol.b = 255-tcol.b;
635
                tcol.g = 255-tcol.g;
636
                tcol.r = 255-tcol.r;
637
            }
4889 terminx 638
 
4486 helixhorne 639
            if (effect & HICTINT_COLORIZE)
665 terminx 640
            {
1205 terminx 641
                tcol.b = min((int32_t)(tcol.b)*b/64,255);
642
                tcol.g = min((int32_t)(tcol.g)*g/64,255);
643
                tcol.r = min((int32_t)(tcol.r)*r/64,255);
665 terminx 644
            }
5 Plagman 645
 
646
            rpptr[x].b = tcol.b;
647
            rpptr[x].g = tcol.g;
648
            rpptr[x].r = tcol.r;
649
            al &= rpptr[x].a;
650
        }
651
    }
584 terminx 652
    if (!glinfo.bgra)
653
    {
1229 terminx 654
        for (j=xsiz*ysiz-1; j>=0; j--)
584 terminx 655
        {
5 Plagman 656
            swapchar(&pic[j].r, &pic[j].b);
657
        }
658
    }
659
 
660
    *sizx = xsiz;
661
    *sizy = ysiz;
662
    *bpl = xsiz;
739 plagman 663
    *fptr = (intptr_t)pic;
5 Plagman 664
    *hasalpha = (al != 255);
1754 helixhorne 665
 
5 Plagman 666
    return 0;
667
}
668
 
2617 helixhorne 669
static inline int32_t hicfxmask(int32_t pal)
670
{
4488 helixhorne 671
    return globalnoeffect ? 0 : (hictinting[pal].f & HICEFFECTMASK);
2617 helixhorne 672
}
673
 
109 terminx 674
//Note: even though it says md2model, it works for both md2model&md3model
1206 terminx 675
int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf)
5 Plagman 676
{
4488 helixhorne 677
    int32_t i, bpl, xsiz=0, ysiz=0, osizx, osizy, texfmt = GL_RGBA, intexfmt = GL_RGBA;
1457 terminx 678
    char *skinfile, hasalpha, fn[BMAX_PATH];
109 terminx 679
    GLuint *texidx = NULL;
680
    mdskinmap_t *sk, *skzero = NULL;
1205 terminx 681
    int32_t doalloc = 1, filh;
3758 terminx 682
    int32_t gotcache, picfillen;
109 terminx 683
    texcacheheader cachead;
5 Plagman 684
 
1754 helixhorne 685
    int32_t startticks, willprint=0;
686
 
2617 helixhorne 687
    if (m->mdnum == 2)
688
        surf = 0;
109 terminx 689
 
2617 helixhorne 690
    if ((unsigned)pal >= (unsigned)MAXPALOOKUPS)
691
        return 0;
692
 
5 Plagman 693
    i = -1;
694
    for (sk = m->skinmap; sk; sk = sk->next)
695
    {
2617 helixhorne 696
        if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf)
5 Plagman 697
        {
698
            skinfile = sk->fn;
2617 helixhorne 699
            texidx = &sk->texid[hicfxmask(pal)];
2559 helixhorne 700
            Bstrncpyz(fn, skinfile, BMAX_PATH);
5 Plagman 701
            //OSD_Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile);
702
            break;
703
        }
109 terminx 704
        //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005)
2617 helixhorne 705
        else if ((sk->palette ==   0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; }
706
        else if ((sk->palette == pal) && (sk->skinnum ==      0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; }
707
        else if ((sk->palette ==   0) && (sk->skinnum ==      0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; }
708
        else if ((sk->palette ==   0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; }
709
        else if ((sk->palette == pal) && (sk->skinnum ==      0) && (i < 1)) { i = 1; skzero = sk; }
710
        else if ((sk->palette ==   0) && (sk->skinnum ==      0) && (i < 0)) { i = 0; skzero = sk; }
5 Plagman 711
    }
2617 helixhorne 712
 
5 Plagman 713
    if (!sk)
714
    {
499 Plagman 715
        if (pal >= (MAXPALOOKUPS - RESERVEDPALS))
497 Plagman 716
            return (0);
2617 helixhorne 717
 
5 Plagman 718
        if (skzero)
719
        {
720
            skinfile = skzero->fn;
2617 helixhorne 721
            texidx = &skzero->texid[hicfxmask(pal)];
2559 helixhorne 722
            Bstrncpyz(fn, skinfile, BMAX_PATH);
5 Plagman 723
            //OSD_Printf("Using def skin 0,0 as fallback, pal=%d\n", pal);
724
        }
725
        else
3164 hendricks2 726
            return 0;
727
#if 0
5 Plagman 728
        {
3164 hendricks2 729
            // fall back to the model-defined texture
2617 helixhorne 730
            if ((unsigned)number >= (unsigned)m->numskins)
731
                number = 0;
732
 
3164 hendricks2 733
            // m->skinfn is undefined when md3model_t is cast to md2model_t --> crash
5 Plagman 734
            skinfile = m->skinfn + number*64;
2617 helixhorne 735
            texidx = &m->texid[number*(HICEFFECTMASK+1) + hicfxmask(pal)];
2559 helixhorne 736
            Bstrncpyz(fn, m->basepath, BMAX_PATH);
1457 terminx 737
            if ((Bstrlen(fn) + Bstrlen(skinfile)) < BMAX_PATH)
2617 helixhorne 738
                Bstrcat(fn,skinfile);
5 Plagman 739
            //OSD_Printf("Using MD2/MD3 skin (%d) %s, pal=%d\n",number,skinfile,pal);
740
        }
3164 hendricks2 741
#endif
5 Plagman 742
    }
2244 helixhorne 743
 
2617 helixhorne 744
    if (!skinfile[0])
745
        return 0;
5 Plagman 746
 
2617 helixhorne 747
    if (*texidx)
748
        return *texidx;
499 Plagman 749
 
2825 Plagman 750
    // possibly fetch an already loaded multitexture :_)
751
    if (pal >= (MAXPALOOKUPS - RESERVEDPALS))
2800 Plagman 752
        for (i=0; i<nextmodelid; i++)
753
            for (skzero = ((md2model_t *)models[i])->skinmap; skzero; skzero = skzero->next)
754
                if (!Bstrcasecmp(skzero->fn, sk->fn) && skzero->texid[hicfxmask(pal)])
755
                {
756
                    int32_t f = hicfxmask(pal);
2617 helixhorne 757
 
2800 Plagman 758
                    sk->texid[f] = skzero->texid[f];
759
                    return sk->texid[f];
760
                }
499 Plagman 761
 
5 Plagman 762
    *texidx = 0;
763
 
584 terminx 764
    if ((filh = kopen4load(fn, 0)) < 0)
765
    {
2617 helixhorne 766
        OSD_Printf("Skin \"%s\" not found.\n",fn);
109 terminx 767
        skinfile[0] = 0;
768
        return 0;
769
    }
5 Plagman 770
 
2617 helixhorne 771
 
109 terminx 772
    picfillen = kfilelength(filh);
773
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
5 Plagman 774
 
1754 helixhorne 775
    startticks = getticks();
776
 
3758 terminx 777
    gotcache = texcache_readtexheader(fn, picfillen, pal<<8, hicfxmask(pal), &cachead, 1);
2617 helixhorne 778
 
3758 terminx 779
    if (gotcache && !texcache_loadskin(&cachead, &doalloc, texidx, &xsiz, &ysiz))
584 terminx 780
    {
109 terminx 781
        osizx = cachead.xdim;
782
        osizy = cachead.ydim;
4486 helixhorne 783
        hasalpha = (cachead.flags & CACHEAD_HASALPHA) ? 1 : 0;
2617 helixhorne 784
        if (pal < (MAXPALOOKUPS - RESERVEDPALS))
785
            m->usesalpha = hasalpha;
109 terminx 786
        //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
584 terminx 787
    }
788
    else
789
    {
1784 helixhorne 790
        int32_t ret;
2617 helixhorne 791
        intptr_t fptr=0;
1784 helixhorne 792
 
3758 terminx 793
        gotcache = 0;   // the compressed version will be saved to disk
5 Plagman 794
 
2617 helixhorne 795
        if ((filh = kopen4load(fn, 0)) < 0)
796
            return -1;
797
 
798
        ret = daskinloader(filh,&fptr,&bpl,&xsiz,&ysiz,&osizx,&osizy,&hasalpha,pal,hicfxmask(pal));
799
 
1784 helixhorne 800
        if (ret)
109 terminx 801
        {
802
            kclose(filh);
1784 helixhorne 803
            OSD_Printf("Failed loading skin file \"%s\": error %d\n", fn, ret);
804
            if (ret==-1)
805
                QuitOnFatalError("OUT OF MEMORY in daskinloader!");
806
 
109 terminx 807
            skinfile[0] = 0;
808
            return(0);
584 terminx 809
        }
810
        else kclose(filh);
1754 helixhorne 811
 
812
        willprint = 1;
813
 
2617 helixhorne 814
        if (pal < (MAXPALOOKUPS - RESERVEDPALS))
815
            m->usesalpha = hasalpha;
816
        if ((doalloc&3)==1)
817
            bglGenTextures(1, texidx);
606 terminx 818
 
2617 helixhorne 819
        bglBindTexture(GL_TEXTURE_2D, *texidx);
820
 
606 terminx 821
        //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,xsiz,ysiz,GL_BGRA_EXT,GL_UNSIGNED_BYTE,(char *)fptr);
2617 helixhorne 822
        if (glinfo.texcompr && glusetexcompr)
823
            intexfmt = hasalpha ? GL_COMPRESSED_RGBA_ARB : GL_COMPRESSED_RGB_ARB;
824
        else if (!hasalpha)
825
            intexfmt = GL_RGB;
826
 
827
        if (glinfo.bgra)
828
            texfmt = GL_BGRA;
829
 
4488 helixhorne 830
        uploadtexture((doalloc&1), xsiz, ysiz, intexfmt, texfmt, (coltype *)fptr, xsiz, ysiz, DAMETH_HI);
1762 terminx 831
        Bfree((void *)fptr);
109 terminx 832
    }
5 Plagman 833
 
109 terminx 834
    if (!m->skinloaded)
835
    {
836
        if (xsiz != osizx || ysiz != osizy)
837
        {
838
            float fx, fy;
839
            fx = ((float)osizx)/((float)xsiz);
840
            fy = ((float)osizy)/((float)ysiz);
841
            if (m->mdnum == 2)
842
            {
1205 terminx 843
                int32_t *lptr;
1229 terminx 844
                for (lptr=m->glcmds; (i=*lptr++);)
845
                    for (i=labs(i); i>0; i--,lptr+=3)
109 terminx 846
                    {
847
                        ((float *)lptr)[0] *= fx;
848
                        ((float *)lptr)[1] *= fy;
849
                    }
850
            }
851
            else if (m->mdnum == 3)
852
            {
1206 terminx 853
                md3model_t *m3 = (md3model_t *)m;
109 terminx 854
                md3surf_t *s;
1205 terminx 855
                int32_t surfi;
1229 terminx 856
                for (surfi=0; surfi<m3->head.numsurfs; surfi++)
109 terminx 857
                {
858
                    s = &m3->head.surfs[surfi];
1229 terminx 859
                    for (i=s->numverts-1; i>=0; i--)
109 terminx 860
                    {
861
                        s->uv[i].u *= fx;
862
                        s->uv[i].v *= fy;
863
                    }
864
                }
865
            }
866
        }
867
        m->skinloaded = 1+number;
868
    }
5 Plagman 869
 
109 terminx 870
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
871
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
5001 terminx 872
#ifndef EDUKE32_GLES
109 terminx 873
    if (glinfo.maxanisotropy > 1.0)
1454 terminx 874
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
5001 terminx 875
#endif
109 terminx 876
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
877
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
878
 
1046 terminx 879
    if (glinfo.texcompr && glusetexcompr && glusetexcache)
3758 terminx 880
        if (!gotcache)
1107 terminx 881
        {
4498 helixhorne 882
            const int32_t nonpow2 = check_nonpow2(xsiz) || check_nonpow2(ysiz);
4488 helixhorne 883
 
1107 terminx 884
            // save off the compressed version
885
            cachead.quality = r_downsize;
886
            cachead.xdim = osizx>>cachead.quality;
887
            cachead.ydim = osizy>>cachead.quality;
918 terminx 888
 
4488 helixhorne 889
            cachead.flags = nonpow2*CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0);
4486 helixhorne 890
 
1754 helixhorne 891
///            OSD_Printf("Caching \"%s\"\n",fn);
3758 terminx 892
            texcache_writetex(fn, picfillen, pal<<8, hicfxmask(pal), &cachead);
1754 helixhorne 893
 
894
            if (willprint)
895
            {
1784 helixhorne 896
                int32_t etime = getticks()-startticks;
897
                if (etime>=MIN_CACHETIME_PRINT)
2617 helixhorne 898
                    OSD_Printf("Load skin: p%d-e%d \"%s\"... cached... %d ms\n", pal, hicfxmask(pal), fn, etime);
1754 helixhorne 899
                willprint = 0;
900
            }
901
            else
902
                OSD_Printf("Cached skin \"%s\"\n", fn);
109 terminx 903
        }
904
 
1754 helixhorne 905
    if (willprint)
1784 helixhorne 906
    {
907
        int32_t etime = getticks()-startticks;
908
        if (etime>=MIN_CACHETIME_PRINT)
2617 helixhorne 909
            OSD_Printf("Load skin: p%d-e%d \"%s\"... %d ms\n", pal, hicfxmask(pal), fn, etime);
1784 helixhorne 910
    }
1754 helixhorne 911
 
109 terminx 912
    return(*texidx);
5 Plagman 913
}
914
 
109 terminx 915
//Note: even though it says md2model, it works for both md2model&md3model
4898 terminx 916
void updateanimation(md2model_t *m, const tspritetype *tspr, uint8_t lpal)
5 Plagman 917
{
2338 helixhorne 918
    const mdanim_t *anim;
1205 terminx 919
    int32_t i, j, k;
920
    int32_t fps;
5 Plagman 921
 
2338 helixhorne 922
    int32_t tile, smoothdurationp;
923
    spritesmooth_t *smooth;
924
    spriteext_t *sprext;
925
 
1229 terminx 926
    if (m->numframes < 2)
1172 terminx 927
    {
928
        m->interpol = 0;
929
        return;
930
    }
931
 
2338 helixhorne 932
    tile = Ptile2tile(tspr->picnum,lpal);
933
    m->cframe = m->nframe = tile2model[tile].framenum;
934
#ifdef DEBUGGINGAIDS
935
    if (m->cframe >= m->numframes)
936
        OSD_Printf("1: c > n\n");
937
#endif
334 terminx 938
 
2338 helixhorne 939
    smoothdurationp = (r_animsmoothing && (tile2model[tile].smoothduration != 0));
940
 
941
    smooth = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spritesmooth[tspr->owner] : NULL;
942
    sprext = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spriteext[tspr->owner] : NULL;
943
 
944
    for (anim = m->animations; anim && anim->startframe != m->cframe; anim = anim->next)
945
    {
946
        /* do nothing */;
947
    }
948
 
584 terminx 949
    if (!anim)
950
    {
2338 helixhorne 951
        if (!smoothdurationp || ((smooth->mdoldframe == m->cframe) && (smooth->mdcurframe == m->cframe)))
530 Plagman 952
        {
2338 helixhorne 953
            m->interpol = 0;
954
            return;
955
        }
956
 
957
        // assert(smoothdurationp && ((smooth->mdoldframe != m->cframe) || (smooth->mdcurframe != m->cframe)))
958
 
959
        if (smooth->mdoldframe != m->cframe)
960
        {
961
            if (smooth->mdsmooth == 0)
530 Plagman 962
            {
2338 helixhorne 963
                sprext->mdanimtims = mdtims;
530 Plagman 964
                m->interpol = 0;
2338 helixhorne 965
                smooth->mdsmooth = 1;
966
                smooth->mdcurframe = m->cframe;
530 Plagman 967
            }
2338 helixhorne 968
 
969
            if (smooth->mdcurframe != m->cframe)
530 Plagman 970
            {
2338 helixhorne 971
                sprext->mdanimtims = mdtims;
530 Plagman 972
                m->interpol = 0;
2338 helixhorne 973
                smooth->mdsmooth = 1;
974
                smooth->mdoldframe = smooth->mdcurframe;
975
                smooth->mdcurframe = m->cframe;
530 Plagman 976
            }
977
        }
2338 helixhorne 978
        else  // if (smooth->mdcurframe != m->cframe)
530 Plagman 979
        {
2338 helixhorne 980
            sprext->mdanimtims = mdtims;
530 Plagman 981
            m->interpol = 0;
2338 helixhorne 982
            smooth->mdsmooth = 1;
983
            smooth->mdoldframe = smooth->mdcurframe;
984
            smooth->mdcurframe = m->cframe;
530 Plagman 985
        }
986
    }
2338 helixhorne 987
    else if (/* anim && */ sprext->mdanimcur != anim->startframe)
5 Plagman 988
    {
2338 helixhorne 989
        //if (sprext->flags & SPREXT_NOMDANIM) OSD_Printf("SPREXT_NOMDANIM\n");
990
        //OSD_Printf("smooth launched ! oldanim %i new anim %i\n", sprext->mdanimcur, anim->startframe);
991
        sprext->mdanimcur = (int16_t)anim->startframe;
992
        sprext->mdanimtims = mdtims;
5 Plagman 993
        m->interpol = 0;
2338 helixhorne 994
 
995
        if (!smoothdurationp)
525 Plagman 996
        {
997
            m->cframe = m->nframe = anim->startframe;
2338 helixhorne 998
#ifdef DEBUGGINGAIDS
999
            if (m->cframe >= m->numframes)
1000
                OSD_Printf("2: c > n\n");
1001
#endif
525 Plagman 1002
            return;
1003
        }
2338 helixhorne 1004
 
530 Plagman 1005
        m->nframe = anim->startframe;
2338 helixhorne 1006
        m->cframe = smooth->mdoldframe;
1007
#ifdef DEBUGGINGAIDS
1008
        if (m->cframe >= m->numframes)
1009
            OSD_Printf("3: c > n\n");
1010
#endif
1011
        smooth->mdsmooth = 1;
530 Plagman 1012
        return;
5 Plagman 1013
    }
1014
 
4658 terminx 1015
    fps = smooth->mdsmooth ? Blrintf((1.0f / (float) (tile2model[tile].smoothduration)) * 66.f) : anim->fpssc;
525 Plagman 1016
 
2338 helixhorne 1017
    i = (mdtims - sprext->mdanimtims)*((fps*timerticspersec)/120);
530 Plagman 1018
 
2338 helixhorne 1019
    if (smooth->mdsmooth)
531 Plagman 1020
        j = 65536;
1021
    else
530 Plagman 1022
        j = ((anim->endframe+1-anim->startframe)<<16);
2338 helixhorne 1023
    // XXX: Just in case you play the game for a VERY long time...
1024
    if (i < 0) { i = 0; sprext->mdanimtims = mdtims; }
109 terminx 1025
    //compare with j*2 instead of j to ensure i stays > j-65536 for MDANIM_ONESHOT
2338 helixhorne 1026
    if (anim && (i >= j+j) && (fps) && !mdpause) //Keep mdanimtims close to mdtims to avoid the use of MOD
1027
        sprext->mdanimtims += j/((fps*timerticspersec)/120);
5 Plagman 1028
 
530 Plagman 1029
    k = i;
1030
 
1031
    if (anim && (anim->flags&MDANIM_ONESHOT))
584 terminx 1032
        { if (i > j-65536) i = j-65536; }
1033
    else { if (i >= j) { i -= j; if (i >= j) i %= j; } }
5 Plagman 1034
 
2338 helixhorne 1035
    if (r_animsmoothing && smooth->mdsmooth)
525 Plagman 1036
    {
2338 helixhorne 1037
        m->nframe = anim ? anim->startframe : smooth->mdcurframe;
1038
        m->cframe = smooth->mdoldframe;
1039
#ifdef DEBUGGINGAIDS
1040
        if (m->cframe >= m->numframes)
1041
            OSD_Printf("4: c > n\n");
1042
#endif
530 Plagman 1043
        //OSD_Printf("smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
1044
        if (k > 65535)
525 Plagman 1045
        {
2338 helixhorne 1046
            sprext->mdanimtims = mdtims;
530 Plagman 1047
            m->interpol = 0;
2338 helixhorne 1048
            smooth->mdsmooth = 0;
1049
            m->cframe = m->nframe; // = anim ? anim->startframe : smooth->mdcurframe;
1050
#ifdef DEBUGGINGAIDS
1051
            if (m->cframe >= m->numframes)
1052
                OSD_Printf("5: c > n\n");
1053
#endif
1054
            smooth->mdoldframe = m->cframe;
530 Plagman 1055
            //OSD_Printf("smooth stopped !\n");
1056
            return;
525 Plagman 1057
        }
1058
    }
1059
    else
1060
    {
1061
        m->cframe = (i>>16)+anim->startframe;
2338 helixhorne 1062
#ifdef DEBUGGINGAIDS
1063
        if (m->cframe >= m->numframes)
1064
            OSD_Printf("6: c > n\n");
1065
#endif
1066
        m->nframe = m->cframe+1;
1067
        if (m->nframe > anim->endframe)  // VERIFY: (!(r_animsmoothing && smooth->mdsmooth)) implies (anim!=NULL) ?
1068
            m->nframe = anim->startframe;
1069
 
1070
        smooth->mdoldframe = m->cframe;
530 Plagman 1071
        //OSD_Printf("not smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
525 Plagman 1072
    }
2338 helixhorne 1073
 
5 Plagman 1074
    m->interpol = ((float)(i&65535))/65536.f;
530 Plagman 1075
    //OSD_Printf("interpol %f\n", m->interpol);
5 Plagman 1076
}
1077
 
519 Plagman 1078
// VBO generation and allocation
1206 terminx 1079
static void mdloadvbos(md3model_t *m)
519 Plagman 1080
{
1205 terminx 1081
    int32_t     i;
519 Plagman 1082
 
4491 helixhorne 1083
    m->vbos = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint));
519 Plagman 1084
    bglGenBuffersARB(m->head.numsurfs, m->vbos);
1085
 
1086
    i = 0;
1087
    while (i < m->head.numsurfs)
1088
    {
1089
        bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->vbos[i]);
1090
        bglBufferDataARB(GL_ARRAY_BUFFER_ARB, m->head.surfs[i].numverts * sizeof(md3uv_t), m->head.surfs[i].uv, GL_STATIC_DRAW_ARB);
1091
        i++;
1092
    }
1093
    bglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1094
}
1095
 
5 Plagman 1096
//--------------------------------------- MD2 LIBRARY BEGINS ---------------------------------------
1206 terminx 1097
static md2model_t *md2load(int32_t fil, const char *filnam)
5 Plagman 1098
{
1206 terminx 1099
    md2model_t *m;
1100
    md3model_t *m3;
262 Plagman 1101
    md3surf_t *s;
1102
    md2frame_t *f;
5 Plagman 1103
    md2head_t head;
654 terminx 1104
    char st[BMAX_PATH];
1205 terminx 1105
    int32_t i, j, k;
5 Plagman 1106
 
2118 helixhorne 1107
    int32_t ournumskins, ournumglcmds;
1108
 
4491 helixhorne 1109
    m = (md2model_t *)Xcalloc(1,sizeof(md2model_t));
1166 terminx 1110
    m->mdnum = 2; m->scale = .01f;
5 Plagman 1111
 
109 terminx 1112
    kread(fil,(char *)&head,sizeof(md2head_t));
4639 terminx 1113
#if B_BIG_ENDIAN != 0
109 terminx 1114
    head.id = B_LITTLE32(head.id);                 head.vers = B_LITTLE32(head.vers);
1115
    head.skinxsiz = B_LITTLE32(head.skinxsiz);     head.skinysiz = B_LITTLE32(head.skinysiz);
1116
    head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins);
1117
    head.numverts = B_LITTLE32(head.numverts);     head.numuv = B_LITTLE32(head.numuv);
1118
    head.numtris = B_LITTLE32(head.numtris);       head.numglcmds = B_LITTLE32(head.numglcmds);
1119
    head.numframes = B_LITTLE32(head.numframes);   head.ofsskins = B_LITTLE32(head.ofsskins);
1120
    head.ofsuv = B_LITTLE32(head.ofsuv);           head.ofstris = B_LITTLE32(head.ofstris);
1121
    head.ofsframes = B_LITTLE32(head.ofsframes);   head.ofsglcmds = B_LITTLE32(head.ofsglcmds);
1122
    head.ofseof = B_LITTLE32(head.ofseof);
4639 terminx 1123
#endif
5 Plagman 1124
 
4639 terminx 1125
    if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { Bfree(m); return(0); } //"IDP2"
5 Plagman 1126
 
2118 helixhorne 1127
    ournumskins = head.numskins ? head.numskins : 1;
1128
    ournumglcmds = head.numglcmds ? head.numglcmds : 1;
1129
 
109 terminx 1130
    m->numskins = head.numskins;
1131
    m->numframes = head.numframes;
1132
    m->numverts = head.numverts;
1133
    m->numglcmds = head.numglcmds;
1134
    m->framebytes = head.framebytes;
262 Plagman 1135
 
4491 helixhorne 1136
    m->frames = (char *)Xmalloc(m->numframes*m->framebytes);
1137
    m->glcmds = (int32_t *)Xmalloc(ournumglcmds*sizeof(int32_t));
1138
    m->tris = (md2tri_t *)Xmalloc(head.numtris*sizeof(md2tri_t));
1139
    m->uv = (md2uv_t *)Xmalloc(head.numuv*sizeof(md2uv_t));
262 Plagman 1140
 
109 terminx 1141
    klseek(fil,head.ofsframes,SEEK_SET);
1142
    if (kread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes)
1643 terminx 1143
        { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
262 Plagman 1144
 
2118 helixhorne 1145
    if (m->numglcmds > 0)
1146
    {
1147
        klseek(fil,head.ofsglcmds,SEEK_SET);
1148
        if (kread(fil,(char *)m->glcmds,m->numglcmds*sizeof(int32_t)) != (int32_t)(m->numglcmds*sizeof(int32_t)))
1149
            { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
1150
    }
109 terminx 1151
 
262 Plagman 1152
    klseek(fil,head.ofstris,SEEK_SET);
1205 terminx 1153
    if (kread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t)))
1643 terminx 1154
        { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
262 Plagman 1155
 
1156
    klseek(fil,head.ofsuv,SEEK_SET);
1205 terminx 1157
    if (kread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t)))
1643 terminx 1158
        { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
262 Plagman 1159
 
5 Plagman 1160
#if B_BIG_ENDIAN != 0
109 terminx 1161
    {
1162
        char *f = (char *)m->frames;
1205 terminx 1163
        int32_t *l,j;
109 terminx 1164
        md2frame_t *fr;
1165
 
584 terminx 1166
        for (i = m->numframes-1; i>=0; i--)
1167
        {
109 terminx 1168
            fr = (md2frame_t *)f;
1205 terminx 1169
            l = (int32_t *)&fr->mul;
1229 terminx 1170
            for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1171
            f += m->framebytes;
1172
        }
1173
 
584 terminx 1174
        for (i = m->numglcmds-1; i>=0; i--)
1175
        {
109 terminx 1176
            m->glcmds[i] = B_LITTLE32(m->glcmds[i]);
1177
        }
1762 terminx 1178
        for (i = head.numtris-1; i>=0; i--)
1179
        {
1180
            m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]);
1181
            m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]);
1182
            m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]);
1183
            m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]);
1184
            m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]);
1185
            m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]);
1186
        }
1187
        for (i = head.numuv-1; i>=0; i--)
1188
        {
1189
            m->uv[i].u = B_LITTLE16(m->uv[i].u);
1190
            m->uv[i].v = B_LITTLE16(m->uv[i].v);
1191
        }
109 terminx 1192
    }
5 Plagman 1193
#endif
1194
 
2617 helixhorne 1195
    Bstrcpy(st,filnam);
1229 terminx 1196
    for (i=strlen(st)-1; i>0; i--)
584 terminx 1197
        if ((st[i] == '/') || (st[i] == '\\')) { i++; break; }
5 Plagman 1198
    if (i<0) i=0;
1199
    st[i] = 0;
4491 helixhorne 1200
    m->basepath = (char *)Xmalloc(i+1);
2617 helixhorne 1201
    Bstrcpy(m->basepath, st);
5 Plagman 1202
 
4491 helixhorne 1203
    m->skinfn = (char *)Xmalloc(ournumskins*64);
2118 helixhorne 1204
    if (m->numskins > 0)
1205
    {
1206
        klseek(fil,head.ofsskins,SEEK_SET);
1207
        if (kread(fil,m->skinfn,64*m->numskins) != 64*m->numskins)
1208
            { Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
1209
    }
5 Plagman 1210
 
4491 helixhorne 1211
    m->texid = (GLuint *)Xcalloc(ournumskins, sizeof(GLuint) * (HICEFFECTMASK+1));
5 Plagman 1212
 
283 Plagman 1213
    maxmodelverts = max(maxmodelverts, m->numverts);
519 Plagman 1214
    maxmodeltris = max(maxmodeltris, head.numtris);
283 Plagman 1215
 
1216
    //return(m);
1217
 
262 Plagman 1218
    // the MD2 is now loaded internally - let's begin the MD3 conversion process
1219
    //OSD_Printf("Beginning md3 conversion.\n");
4491 helixhorne 1220
    m3 = (md3model_t *)Xcalloc(1, sizeof(md3model_t));
262 Plagman 1221
    m3->mdnum = 3; m3->texid = 0; m3->scale = m->scale;
4639 terminx 1222
    m3->head.id = IDP3_MAGIC; m3->head.vers = 15;
3588 helixhorne 1223
 
4653 terminx 1224
    m3->head.flags = 0;
3588 helixhorne 1225
 
755 plagman 1226
    m3->head.numframes = m->numframes;
262 Plagman 1227
    m3->head.numtags = 0; m3->head.numsurfs = 1;
1228
    m3->head.numskins = 0;
5 Plagman 1229
 
262 Plagman 1230
    m3->numskins = m3->head.numskins;
1231
    m3->numframes = m3->head.numframes;
5 Plagman 1232
 
4491 helixhorne 1233
    m3->head.frames = (md3frame_t *)Xcalloc(m3->head.numframes, sizeof(md3frame_t));
4639 terminx 1234
    m3->muladdframes = (vec3f_t *)Xcalloc(m->numframes * 2, sizeof(vec3f_t));
5 Plagman 1235
 
262 Plagman 1236
    f = (md2frame_t *)(m->frames);
5 Plagman 1237
 
262 Plagman 1238
    // frames converting
1239
    i = 0;
1240
    while (i < m->numframes)
109 terminx 1241
    {
262 Plagman 1242
        f = (md2frame_t *)&m->frames[i*m->framebytes];
2617 helixhorne 1243
        Bstrcpy(m3->head.frames[i].nam, f->name);
262 Plagman 1244
        //OSD_Printf("Copied frame %s.\n", m3->head.frames[i].nam);
294 Plagman 1245
        m3->muladdframes[i*2] = f->mul;
1246
        m3->muladdframes[i*2+1] = f->add;
262 Plagman 1247
        i++;
109 terminx 1248
    }
1249
 
262 Plagman 1250
    m3->head.tags = NULL;
5 Plagman 1251
 
4491 helixhorne 1252
    m3->head.surfs = (md3surf_t *)Xcalloc(1, sizeof(md3surf_t));
262 Plagman 1253
    s = m3->head.surfs;
5 Plagman 1254
 
262 Plagman 1255
    // model converting
4639 terminx 1256
    s->id = IDP3_MAGIC; s->flags = 0;
262 Plagman 1257
    s->numframes = m->numframes; s->numshaders = 0;
1258
    s->numtris = head.numtris;
1259
    s->numverts = head.numtris * 3; // oh man talk about memory effectiveness :((((
1260
    // MD2 is actually more accurate than MD3 in term of uv-mapping, because each triangle has a triangle counterpart on the UV-map.
1261
    // In MD3, each vertex unique UV coordinates, meaning that you have to duplicate vertices if you need non-seamless UV-mapping.
109 terminx 1262
 
262 Plagman 1263
    maxmodelverts = max(maxmodelverts, s->numverts);
109 terminx 1264
 
2617 helixhorne 1265
    Bstrcpy(s->nam, "Dummy surface from MD2");
109 terminx 1266
 
262 Plagman 1267
    s->shaders = NULL;
109 terminx 1268
 
4491 helixhorne 1269
    s->tris = (md3tri_t *)Xcalloc(head.numtris, sizeof(md3tri_t));
1270
    s->uv = (md3uv_t *)Xcalloc(s->numverts, sizeof(md3uv_t));
1271
    s->xyzn = (md3xyzn_t *)Xcalloc(s->numverts * m->numframes, sizeof(md3xyzn_t));
294 Plagman 1272
 
283 Plagman 1273
    //memoryusage += (s->numverts * m->numframes * sizeof(md3xyzn_t));
1274
    //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
5 Plagman 1275
 
262 Plagman 1276
    //OSD_Printf("Number of frames : %i\n", m->numframes);
1277
    //OSD_Printf("Number of triangles : %i\n", head.numtris);
1278
    //OSD_Printf("Number of vertices : %i\n", s->numverts);
5 Plagman 1279
 
262 Plagman 1280
    // triangle converting
1281
    i = 0;
1282
    while (i < head.numtris)
5 Plagman 1283
    {
262 Plagman 1284
        j = 0;
1285
        //OSD_Printf("Triangle : %i\n", i);
1286
        while (j < 3)
5 Plagman 1287
        {
262 Plagman 1288
            // triangle vertex indexes
1289
            s->tris[i].i[j] = i*3 + j;
5 Plagman 1290
 
262 Plagman 1291
            // uv coords
1292
            s->uv[i*3+j].u = (float)(m->uv[m->tris[i].u[j]].u) / (float)(head.skinxsiz);
1293
            s->uv[i*3+j].v = (float)(m->uv[m->tris[i].u[j]].v) / (float)(head.skinysiz);
5 Plagman 1294
 
262 Plagman 1295
            // vertices for each frame
1296
            k = 0;
1297
            while (k < m->numframes)
1298
            {
1299
                f = (md2frame_t *)&m->frames[k*m->framebytes];
4653 terminx 1300
                s->xyzn[(k*s->numverts) + (i*3) + j].x = (int16_t) (((f->verts[m->tris[i].v[j]].v[0] * f->mul.x) + f->add.x) * 64.f);
1301
                s->xyzn[(k*s->numverts) + (i*3) + j].y = (int16_t) (((f->verts[m->tris[i].v[j]].v[1] * f->mul.y) + f->add.y) * 64.f);
1302
                s->xyzn[(k*s->numverts) + (i*3) + j].z = (int16_t) (((f->verts[m->tris[i].v[j]].v[2] * f->mul.z) + f->add.z) * 64.f);
755 plagman 1303
 
262 Plagman 1304
                k++;
1305
            }
1306
            j++;
5 Plagman 1307
        }
262 Plagman 1308
        //OSD_Printf("End triangle.\n");
1309
        i++;
5 Plagman 1310
    }
262 Plagman 1311
    //OSD_Printf("Finished md3 conversion.\n");
5 Plagman 1312
 
265 terminx 1313
    {
1314
        mdskinmap_t *sk;
1315
 
4491 helixhorne 1316
        sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t));
265 terminx 1317
        sk->palette = 0;
1318
        sk->skinnum = 0;
1319
        sk->surfnum = 0;
1320
 
584 terminx 1321
        if (m->numskins > 0)
1322
        {
4491 helixhorne 1323
            sk->fn = (char *)Xmalloc(strlen(m->basepath)+strlen(m->skinfn)+1);
2617 helixhorne 1324
            Bstrcpy(sk->fn, m->basepath);
1325
            Bstrcat(sk->fn, m->skinfn);
355 terminx 1326
        }
265 terminx 1327
        m3->skinmap = sk;
1328
    }
1329
 
4491 helixhorne 1330
    m3->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris);
1331
    m3->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris * 3);
1332
    m3->maxdepths = (float *)Xmalloc(sizeof(float) * s->numtris);
513 Plagman 1333
 
519 Plagman 1334
    m3->vbos = NULL;
1335
 
262 Plagman 1336
    // die MD2 ! DIE !
1643 terminx 1337
    Bfree(m->texid); Bfree(m->skinfn); Bfree(m->basepath); Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m);
5 Plagman 1338
 
1206 terminx 1339
    return((md2model_t *)m3);
5 Plagman 1340
}
1341
//---------------------------------------- MD2 LIBRARY ENDS ----------------------------------------
1342
 
4639 terminx 1343
// DICHOTOMIC RECURSIVE SORTING - USED BY MD3DRAW
1205 terminx 1344
int32_t partition(uint16_t *indexes, float *depths, int32_t f, int32_t l)
584 terminx 1345
{
4639 terminx 1346
    int32_t up = f, down = l;
5 Plagman 1347
    float piv = depths[f];
1205 terminx 1348
    uint16_t piv2 = indexes[f];
584 terminx 1349
    do
1350
    {
5 Plagman 1351
        while ((depths[up] <= piv) && (up < l))
1352
            up++;
1353
        while ((depths[down] > piv)  && (down > f))
1354
            down--;
584 terminx 1355
        if (up < down)
5 Plagman 1356
        {
4639 terminx 1357
            swapfloat(&depths[up], &depths[down]);
1358
            swapshort(&indexes[up], &indexes[down]);
5 Plagman 1359
        }
584 terminx 1360
    }
1361
    while (down > up);
4639 terminx 1362
    depths[f] = depths[down], depths[down] = piv;
1363
    indexes[f] = indexes[down], indexes[down] = piv2;
5 Plagman 1364
    return down;
1365
}
1366
 
4639 terminx 1367
static inline void quicksort(uint16_t *indexes, float *depths, int32_t first, int32_t last)
584 terminx 1368
{
4639 terminx 1369
    int32_t pivIndex;
1370
    if (first >= last) return;
1371
    pivIndex = partition(indexes, depths, first, last);
1372
    if (first < (pivIndex-1)) quicksort(indexes, depths, first, (pivIndex-1));
1373
    if ((pivIndex+1) >= last) return;
1374
    quicksort(indexes, depths, (pivIndex+1), last);
5 Plagman 1375
}
1376
// END OF QUICKSORT LIB
1377
 
1378
//--------------------------------------- MD3 LIBRARY BEGINS ---------------------------------------
1379
 
1206 terminx 1380
static md3model_t *md3load(int32_t fil)
5 Plagman 1381
{
1205 terminx 1382
    int32_t i, surfi, ofsurf, offs[4], leng[4];
1383
    int32_t maxtrispersurf;
1206 terminx 1384
    md3model_t *m;
109 terminx 1385
    md3surf_t *s;
5 Plagman 1386
 
4491 helixhorne 1387
    m = (md3model_t *)Xcalloc(1,sizeof(md3model_t));
1454 terminx 1388
    m->mdnum = 3; m->texid = 0; m->scale = .01f;
5 Plagman 1389
 
294 Plagman 1390
    m->muladdframes = NULL;
1391
 
738 plagman 1392
    kread(fil,&m->head,SIZEOF_MD3HEAD_T);
4639 terminx 1393
 
1394
#if B_BIG_ENDIAN != 0
109 terminx 1395
    m->head.id = B_LITTLE32(m->head.id);             m->head.vers = B_LITTLE32(m->head.vers);
1396
    m->head.flags = B_LITTLE32(m->head.flags);       m->head.numframes = B_LITTLE32(m->head.numframes);
1397
    m->head.numtags = B_LITTLE32(m->head.numtags);   m->head.numsurfs = B_LITTLE32(m->head.numsurfs);
738 plagman 1398
    m->head.numskins = B_LITTLE32(m->head.numskins); m->head.ofsframes = B_LITTLE32(m->head.ofsframes);
1399
    m->head.ofstags = B_LITTLE32(m->head.ofstags); m->head.ofssurfs = B_LITTLE32(m->head.ofssurfs);
109 terminx 1400
    m->head.eof = B_LITTLE32(m->head.eof);
4639 terminx 1401
#endif
5 Plagman 1402
 
4639 terminx 1403
    if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { Bfree(m); return(0); } //"IDP3"
109 terminx 1404
 
5 Plagman 1405
    m->numskins = m->head.numskins; //<- dead code?
1406
    m->numframes = m->head.numframes;
1407
 
739 plagman 1408
    ofsurf = m->head.ofssurfs;
5 Plagman 1409
 
738 plagman 1410
    klseek(fil,m->head.ofsframes,SEEK_SET); i = m->head.numframes*sizeof(md3frame_t);
4491 helixhorne 1411
    m->head.frames = (md3frame_t *)Xmalloc(i);
5 Plagman 1412
    kread(fil,m->head.frames,i);
1413
 
1414
    if (m->head.numtags == 0) m->head.tags = NULL;
584 terminx 1415
    else
1416
    {
738 plagman 1417
        klseek(fil,m->head.ofstags,SEEK_SET); i = m->head.numtags*sizeof(md3tag_t);
4491 helixhorne 1418
        m->head.tags = (md3tag_t *)Xmalloc(i);
5 Plagman 1419
        kread(fil,m->head.tags,i);
1420
    }
1421
 
4980 helixhorne 1422
    klseek(fil,m->head.ofssurfs,SEEK_SET);
1423
    m->head.surfs = (md3surf_t *)Xcalloc(m->head.numsurfs, sizeof(md3surf_t));
1424
    // NOTE: We assume that NULL is represented by all-zeros.
1425
    // surfs[0].geometry is for POLYMER_MD_PROCESS_CHECK (else: crashes).
1426
    // surfs[i].geometry is for FREE_SURFS_GEOMETRY.
1427
    Bassert(m->head.surfs[0].geometry == NULL);
5 Plagman 1428
 
1429
#if B_BIG_ENDIAN != 0
109 terminx 1430
    {
1903 helixhorne 1431
        int32_t j, *l;
109 terminx 1432
 
584 terminx 1433
        for (i = m->head.numframes-1; i>=0; i--)
1434
        {
1205 terminx 1435
            l = (int32_t *)&m->head.frames[i].min;
1229 terminx 1436
            for (j=3+3+3+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1437
        }
1438
 
584 terminx 1439
        for (i = m->head.numtags-1; i>=0; i--)
1440
        {
1205 terminx 1441
            l = (int32_t *)&m->head.tags[i].p;
1229 terminx 1442
            for (j=3+3+3+3-1; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1443
        }
1444
    }
5 Plagman 1445
#endif
1446
 
513 Plagman 1447
    maxtrispersurf = 0;
1448
 
1229 terminx 1449
    for (surfi=0; surfi<m->head.numsurfs; surfi++)
109 terminx 1450
    {
1451
        s = &m->head.surfs[surfi];
738 plagman 1452
        klseek(fil,ofsurf,SEEK_SET); kread(fil,s,SIZEOF_MD3SURF_T);
5 Plagman 1453
 
1454
#if B_BIG_ENDIAN != 0
109 terminx 1455
        {
1903 helixhorne 1456
            int32_t j, *l;
109 terminx 1457
            s->id = B_LITTLE32(s->id);
1205 terminx 1458
            l = (int32_t *)&s->flags;
1229 terminx 1459
            for (j=1+1+1+1+1+1+1+1+1+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1460
        }
5 Plagman 1461
#endif
1462
 
4639 terminx 1463
        offs[0] = ofsurf+s->ofstris;
1464
        offs[1] = ofsurf+s->ofsshaders;
1465
        offs[2] = ofsurf+s->ofsuv;
1466
        offs[3] = ofsurf+s->ofsxyzn;
1467
 
1468
        leng[0] = s->numtris*sizeof(md3tri_t);
1469
        leng[1] = s->numshaders*sizeof(md3shader_t);
1470
        leng[2] = s->numverts*sizeof(md3uv_t);
1471
        leng[3] = s->numframes*s->numverts*sizeof(md3xyzn_t);
1472
 
283 Plagman 1473
        //memoryusage += (s->numverts * s->numframes * sizeof(md3xyzn_t));
1474
        //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
5 Plagman 1475
 
4639 terminx 1476
        s->tris = (md3tri_t *)Xmalloc((leng[0] + leng[1]) + (leng[2] + leng[3]));
283 Plagman 1477
 
740 plagman 1478
        s->shaders = (md3shader_t *)(((intptr_t)s->tris)+leng[0]);
1762 terminx 1479
        s->uv      = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]);
1480
        s->xyzn    = (md3xyzn_t *)(((intptr_t)s->uv)+leng[2]);
5 Plagman 1481
 
1482
        klseek(fil,offs[0],SEEK_SET); kread(fil,s->tris   ,leng[0]);
1483
        klseek(fil,offs[1],SEEK_SET); kread(fil,s->shaders,leng[1]);
1484
        klseek(fil,offs[2],SEEK_SET); kread(fil,s->uv     ,leng[2]);
1485
        klseek(fil,offs[3],SEEK_SET); kread(fil,s->xyzn   ,leng[3]);
1486
 
1487
#if B_BIG_ENDIAN != 0
109 terminx 1488
        {
1903 helixhorne 1489
            int32_t j, *l;
109 terminx 1490
 
1229 terminx 1491
            for (i=s->numtris-1; i>=0; i--)
584 terminx 1492
            {
1229 terminx 1493
                for (j=2; j>=0; j--) s->tris[i].i[j] = B_LITTLE32(s->tris[i].i[j]);
109 terminx 1494
            }
1229 terminx 1495
            for (i=s->numshaders-1; i>=0; i--)
584 terminx 1496
            {
109 terminx 1497
                s->shaders[i].i = B_LITTLE32(s->shaders[i].i);
1498
            }
1229 terminx 1499
            for (i=s->numverts-1; i>=0; i--)
584 terminx 1500
            {
1762 terminx 1501
                l = (int32_t *)&s->uv[i].u;
109 terminx 1502
                l[0] = B_LITTLE32(l[0]);
1503
                l[1] = B_LITTLE32(l[1]);
1504
            }
1229 terminx 1505
            for (i=s->numframes*s->numverts-1; i>=0; i--)
584 terminx 1506
            {
1205 terminx 1507
                s->xyzn[i].x = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].x);
1508
                s->xyzn[i].y = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].y);
1509
                s->xyzn[i].z = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].z);
109 terminx 1510
            }
1511
        }
5 Plagman 1512
#endif
109 terminx 1513
        maxmodelverts = max(maxmodelverts, s->numverts);
519 Plagman 1514
        maxmodeltris = max(maxmodeltris, s->numtris);
513 Plagman 1515
        maxtrispersurf = max(maxtrispersurf, s->numtris);
109 terminx 1516
        ofsurf += s->ofsend;
1517
    }
5 Plagman 1518
 
4491 helixhorne 1519
    m->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf);
1520
    m->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf * 3);
1521
    m->maxdepths = (float *)Xmalloc(sizeof(float) * maxtrispersurf);
513 Plagman 1522
 
519 Plagman 1523
    m->vbos = NULL;
1524
 
5 Plagman 1525
    return(m);
1526
}
1527
 
1762 terminx 1528
static inline void  invertmatrix(float *m, float *out)
1594 plagman 1529
{
1530
    float det;
1531
 
4639 terminx 1532
    det  = (m[0] * (m[4]*m[8] - m[5] * m[7]))
1533
         - (m[1] * (m[3]*m[8] - m[5] * m[6]))
1534
         + (m[2] * (m[3]*m[7] - m[4] * m[6]));
1594 plagman 1535
 
4639 terminx 1536
    if (det == 0.0f)
2007 helixhorne 1537
    {
4639 terminx 1538
        Bmemset(out, 0, sizeof(float) * 9);
1539
        out[8] = out[4] = out[0] = 1.f;
1540
        return;
1541
    }
1594 plagman 1542
 
4639 terminx 1543
    det = 1.0f / det;
1699 plagman 1544
 
4639 terminx 1545
    out[0] = det * (m[4] * m[8] - m[5] * m[7]);
1546
    out[1] = det * (m[2] * m[7] - m[1] * m[8]);
1547
    out[2] = det * (m[1] * m[5] - m[2] * m[4]);
1548
    out[3] = det * (m[5] * m[6] - m[3] * m[8]);
1549
    out[4] = det * (m[0] * m[8] - m[2] * m[6]);
1550
    out[5] = det * (m[2] * m[3] - m[0] * m[5]);
1551
    out[6] = det * (m[3] * m[7] - m[1] * m[6]);
1552
    out[7] = det * (m[1] * m[6] - m[0] * m[7]);
1553
    out[8] = det * (m[0] * m[4] - m[1] * m[3]);
1594 plagman 1554
}
1555
 
1762 terminx 1556
static inline void  normalize(float *vec)
1594 plagman 1557
{
4639 terminx 1558
    float norm;
1594 plagman 1559
 
4639 terminx 1560
    if ((norm = vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]) == 0.f)
1561
        return;
1594 plagman 1562
 
4639 terminx 1563
    norm = polymost_invsqrt(norm);
1564
    vec[0] *= norm;
1565
    vec[1] *= norm;
1566
    vec[2] *= norm;
1594 plagman 1567
}
1568
 
1762 terminx 1569
static void      md3postload_common(md3model_t *m)
1237 plagman 1570
{
1744 helixhorne 1571
    int         framei, surfi, verti;
1594 plagman 1572
    md3frame_t  *frame;
1237 plagman 1573
    md3xyzn_t   *frameverts;
1574
 
1575
    // apparently we can't trust loaded models bounding box/sphere information,
1576
    // so let's compute it ourselves
1577
 
1578
    framei = 0;
4639 terminx 1579
    do // while (++framei < m->head.numframes);
1237 plagman 1580
    {
1594 plagman 1581
        frame = &m->head.frames[framei];
4639 terminx 1582
        Bmemset(&frame->min, 0, sizeof(vec3f_t) * 2);
1594 plagman 1583
        frame->r        = 0.0f;
1584
 
1237 plagman 1585
        surfi = 0;
4639 terminx 1586
        do // while (++surfi < m->head.numsurfs);
1237 plagman 1587
        {
1588
            frameverts = &m->head.surfs[surfi].xyzn[framei * m->head.surfs[surfi].numverts];
1589
 
1590
            verti = 0;
4639 terminx 1591
 
1592
            if (!surfi)
1237 plagman 1593
            {
4639 terminx 1594
                frame->min.x = (float)frameverts[0].x;
1595
                frame->min.y = (float)frameverts[0].y;
1596
                frame->min.z = (float)frameverts[0].z;
1597
                frame->max = frame->min;
1598
            }
1237 plagman 1599
 
4639 terminx 1600
            do // while(++verti < m->head.surfs[surfi].numverts);
1601
            {
4771 hendricks2 1602
                vec3f_t f = { (float)frameverts[verti].x, (float)frameverts[verti].y, (float)frameverts[verti].z };
1237 plagman 1603
 
4639 terminx 1604
                if (!verti && !surfi)
1605
                    continue;
1237 plagman 1606
 
4639 terminx 1607
                frame->min.x = max(frame->min.x, f.x);
1608
                frame->min.y = max(frame->min.y, f.y);
1609
                frame->min.z = max(frame->min.z, f.z);
1610
                frame->max.x = max(frame->max.x, f.x);
1611
                frame->max.y = max(frame->max.y, f.y);
1612
                frame->max.z = max(frame->max.z, f.z);
1237 plagman 1613
            }
4639 terminx 1614
            while(++verti < m->head.surfs[surfi].numverts);
1237 plagman 1615
        }
4639 terminx 1616
        while (++surfi < m->head.numsurfs);
1237 plagman 1617
 
4639 terminx 1618
        frame->cen.x = (frame->min.x + frame->max.x) * .5f;
1619
        frame->cen.y = (frame->min.y + frame->max.y) * .5f;
1620
        frame->cen.z = (frame->min.z + frame->max.z) * .5f;
1237 plagman 1621
 
1622
        surfi = 0;
4639 terminx 1623
        do // while (++surfi < m->head.numsurfs);
1237 plagman 1624
        {
4639 terminx 1625
            float       vec1[4];
1626
 
1237 plagman 1627
            frameverts = &m->head.surfs[surfi].xyzn[framei * m->head.surfs[surfi].numverts];
1628
 
1629
            verti = 0;
4639 terminx 1630
            do // while (++verti < m->head.surfs[surfi].numverts);
1237 plagman 1631
            {
1594 plagman 1632
                vec1[0] = frameverts[verti].x - frame->cen.x;
1633
                vec1[1] = frameverts[verti].y - frame->cen.y;
1634
                vec1[2] = frameverts[verti].z - frame->cen.z;
1237 plagman 1635
 
4639 terminx 1636
                vec1[3] = (vec1[0] * vec1[0]) + (vec1[1] * vec1[1]) + (vec1[2] * vec1[2]);
1240 plagman 1637
 
4639 terminx 1638
                frame->r = max(vec1[3], frame->r);
1237 plagman 1639
            }
4639 terminx 1640
            while (++verti < m->head.surfs[surfi].numverts);
1237 plagman 1641
        }
4639 terminx 1642
        while (++surfi < m->head.numsurfs);
1643
        frame->r = Bsqrtf(frame->r);
1237 plagman 1644
    }
4639 terminx 1645
    while (++framei < m->head.numframes);
1744 helixhorne 1646
}
1238 plagman 1647
 
1744 helixhorne 1648
#ifdef POLYMER
1649
// pre-check success of conversion since it must not fail later.
1650
// keep in sync with md3postload_polymer!
1651
static int md3postload_polymer_check(md3model_t *m)
1652
{
4639 terminx 1653
    uint32_t    surfi, trii;
1744 helixhorne 1654
    md3surf_t   *s;
1655
 
1656
    surfi = 0;
4639 terminx 1657
    do
1744 helixhorne 1658
    {
1659
        s = &m->head.surfs[surfi];
1660
 
1661
        trii = 0;
4639 terminx 1662
        do
1744 helixhorne 1663
        {
1664
            // let the vertices know they're being referenced by a triangle
4639 terminx 1665
            if ((unsigned)s->tris[trii].i[0] >= (unsigned)s->numverts ||
1666
                    (unsigned)s->tris[trii].i[1] >= (unsigned)s->numverts ||
1667
                    (unsigned)s->tris[trii].i[2] >= (unsigned)s->numverts)
1762 terminx 1668
            {
1744 helixhorne 1669
                // corrupt model
2007 helixhorne 1670
                OSD_Printf("%s: Triangle index out of bounds!\n", m->head.nam);
4639 terminx 1671
                return 1;
1744 helixhorne 1672
            }
1673
        }
4639 terminx 1674
        while (++trii < (unsigned)s->numtris);
1744 helixhorne 1675
    }
4639 terminx 1676
    while (++surfi < (unsigned)m->head.numsurfs);
1744 helixhorne 1677
 
4639 terminx 1678
    return 0;
1744 helixhorne 1679
}
4060 helixhorne 1680
 
1681
// Precalculated cos/sin arrays.
4639 terminx 1682
static float g_mdcos[256], g_mdsin[256];
1683
static int32_t mdtrig_init = 0;
4060 helixhorne 1684
 
1685
static void init_mdtrig_arrays(void)
1686
{
1687
    int32_t i;
4656 terminx 1688
    static const float acc = ((2.f * (float)PI) * (1.f/255.f));
4639 terminx 1689
    float ang = 0.f;
4060 helixhorne 1690
 
1691
    for (i=0; i<256; i++)
1692
    {
4639 terminx 1693
        g_mdcos[i] = cosf(ang);
1694
        g_mdsin[i] = sinf(ang);
1695
        ang += acc;
4060 helixhorne 1696
    }
4639 terminx 1697
 
1698
    mdtrig_init = 1;
4060 helixhorne 1699
}
1744 helixhorne 1700
#endif
1701
 
1762 terminx 1702
int      md3postload_polymer(md3model_t *m)
1744 helixhorne 1703
{
1704
#ifdef POLYMER
1705
    int         framei, surfi, verti, trii, i;
4060 helixhorne 1706
    float       vec1[5], vec2[5], mat[9], r;
1744 helixhorne 1707
 
4952 helixhorne 1708
    // POLYMER_MD_PROCESS_CHECK
1910 helixhorne 1709
    if (m->head.surfs[0].geometry)
1710
        return -1;  // already postprocessed
1711
 
4639 terminx 1712
    if (!mdtrig_init)
1713
        init_mdtrig_arrays();
4060 helixhorne 1714
 
1238 plagman 1715
    // let's also repack the geometry to more usable formats
1716
 
1717
    surfi = 0;
4639 terminx 1718
    do // while (++surfi < m->head.numsurfs)
1238 plagman 1719
    {
4639 terminx 1720
        handleevents();
1721
 
4952 helixhorne 1722
        md3surf_t *const s = &m->head.surfs[surfi];
1910 helixhorne 1723
#ifdef DEBUG_MODEL_MEM
1724
        i = (m->head.numframes * s->numverts * sizeof(float) * 15);
1725
        if (i > 1<<20)
1726
            initprintf("size %d (%d fr, %d v): md %s surf %d/%d\n", i, m->head.numframes, s->numverts,
2007 helixhorne 1727
                       m->head.nam, surfi, m->head.numsurfs);
1910 helixhorne 1728
#endif
4639 terminx 1729
        s->geometry = (float *)Xcalloc(m->head.numframes * s->numverts * 15, sizeof(float));
1594 plagman 1730
 
4639 terminx 1731
        if (s->numverts > tribufverts)
1732
        {
1733
            tribuf = (int32_t *) Xrealloc(tribuf, s->numverts * sizeof(int32_t));
1734
            Bmemset(tribuf, 0, s->numverts * sizeof(int32_t));
1735
            tribufverts = s->numverts;
1736
        }
1594 plagman 1737
 
1238 plagman 1738
        verti = 0;
4639 terminx 1739
        do // while (++verti < (m->head.numframes * s->numverts))
1238 plagman 1740
        {
4060 helixhorne 1741
            // normal extraction from packed spherical coordinates
1742
            // FIXME: swapping lat and lng because of npherno's compiler
1743
            uint8_t lat = s->xyzn[verti].nlng;
1744
            uint8_t lng = s->xyzn[verti].nlat;
4639 terminx 1745
            uint32_t verti15 = (verti<<4)-verti;
4060 helixhorne 1746
 
4639 terminx 1747
            s->geometry[verti15 + 0] = s->xyzn[verti].x;
1748
            s->geometry[verti15 + 1] = s->xyzn[verti].y;
1749
            s->geometry[verti15 + 2] = s->xyzn[verti].z;
1238 plagman 1750
 
4639 terminx 1751
            s->geometry[verti15 + 3] = g_mdcos[lat] * g_mdsin[lng];
1752
            s->geometry[verti15 + 4] = g_mdsin[lat] * g_mdsin[lng];
1753
            s->geometry[verti15 + 5] = g_mdcos[lng];
1238 plagman 1754
        }
4639 terminx 1755
        while (++verti < (m->head.numframes * s->numverts));
1594 plagman 1756
 
1757
        trii = 0;
4639 terminx 1758
        do // while (++trii < s->numtris)
1594 plagman 1759
        {
4639 terminx 1760
            uint32_t       tris15[3];
1761
 
1594 plagman 1762
            // let the vertices know they're being referenced by a triangle
4639 terminx 1763
            if ((unsigned) s->tris[trii].i[0] >= (unsigned) s->numverts ||
1764
                (unsigned) s->tris[trii].i[1] >= (unsigned) s->numverts ||
1765
                (unsigned) s->tris[trii].i[2] >= (unsigned) s->numverts)
1762 terminx 1766
            {
1623 plagman 1767
                // corrupt model
1768
                return 0;
1769
            }
4639 terminx 1770
            tribuf[s->tris[trii].i[0]]++;
1771
            tribuf[s->tris[trii].i[1]]++;
1772
            tribuf[s->tris[trii].i[2]]++;
1594 plagman 1773
 
4639 terminx 1774
            tris15[0] = (s->tris[trii].i[0]<<4)-s->tris[trii].i[0];
1775
            tris15[1] = (s->tris[trii].i[1]<<4)-s->tris[trii].i[1];
1776
            tris15[2] = (s->tris[trii].i[2]<<4)-s->tris[trii].i[2];
1777
 
1778
 
1594 plagman 1779
            framei = 0;
4639 terminx 1780
            do // while (++framei < m->head.numframes)
1594 plagman 1781
            {
4639 terminx 1782
                const uint32_t verti15 = framei * s->numverts * 15;
1783
 
1784
                vec1[0] = s->geometry[verti15 + tris15[1]]     - s->geometry[verti15 + tris15[0]];
1785
                vec1[1] = s->geometry[verti15 + tris15[1] + 1] - s->geometry[verti15 + tris15[0] + 1];
1786
                vec1[2] = s->geometry[verti15 + tris15[1] + 2] - s->geometry[verti15 + tris15[0] + 2];
1594 plagman 1787
                vec1[3] = s->uv[s->tris[trii].i[1]].u - s->uv[s->tris[trii].i[0]].u;
1788
                vec1[4] = s->uv[s->tris[trii].i[1]].v - s->uv[s->tris[trii].i[0]].v;
1789
 
4639 terminx 1790
                vec2[0] = s->geometry[verti15 + tris15[2]    ] - s->geometry[verti15 + tris15[1]];
1791
                vec2[1] = s->geometry[verti15 + tris15[2] + 1] - s->geometry[verti15 + tris15[1] + 1];
1792
                vec2[2] = s->geometry[verti15 + tris15[2] + 2] - s->geometry[verti15 + tris15[1] + 2];
1594 plagman 1793
                vec2[3] = s->uv[s->tris[trii].i[2]].u - s->uv[s->tris[trii].i[1]].u;
1794
                vec2[4] = s->uv[s->tris[trii].i[2]].v - s->uv[s->tris[trii].i[1]].v;
1795
 
2007 helixhorne 1796
                r = (vec1[3] * vec2[4] - vec2[3] * vec1[4]);
1797
                if (r != 0.0f)
1798
                {
4639 terminx 1799
                    r = 1.f/r;
1594 plagman 1800
 
2007 helixhorne 1801
                    // tangent
1802
                    mat[0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r;
1803
                    mat[1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r;
1804
                    mat[2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r;
1594 plagman 1805
 
2007 helixhorne 1806
                    normalize(&mat[0]);
1594 plagman 1807
 
2007 helixhorne 1808
                    // bitangent
1809
                    mat[3] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r;
1810
                    mat[4] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
1811
                    mat[5] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
1594 plagman 1812
 
2007 helixhorne 1813
                    normalize(&mat[3]);
1814
                }
4639 terminx 1815
                else Bmemset(mat, 0, sizeof(float) * 6);
1594 plagman 1816
 
1817
                // T and B are shared for the three vertices in that triangle
1818
                i = 0;
4639 terminx 1819
                do
1594 plagman 1820
                {
4639 terminx 1821
                    const uint32_t offs = (framei * s->numverts * 15) + i + 6;
1822
 
1823
                    s->geometry[offs + tris15[0]] += mat[i];
1824
                    s->geometry[offs + tris15[1]] += mat[i];
1825
                    s->geometry[offs + tris15[2]] += mat[i];
1594 plagman 1826
                }
4639 terminx 1827
                while (++i < 6);
1594 plagman 1828
            }
4639 terminx 1829
            while (++framei < m->head.numframes);
1594 plagman 1830
        }
4639 terminx 1831
        while (++trii < s->numtris);
1594 plagman 1832
 
1833
        // now that we accumulated the TBNs, average and invert them for each vertex
4639 terminx 1834
        verti = (m->head.numframes * s->numverts)-1;
1835
 
1836
        do // while (verti-- > 0)
1594 plagman 1837
        {
4639 terminx 1838
            const int32_t curnumtris = tribuf[verti % s->numverts];
1839
            const uint32_t verti15 = (verti<<4) - verti;
2007 helixhorne 1840
 
1841
            if (curnumtris > 0)
1594 plagman 1842
            {
4639 terminx 1843
                const float rfcurnumtris = 1.f/(float)curnumtris;
2007 helixhorne 1844
                i = 6;
4639 terminx 1845
                do {
1846
                    s->geometry[verti15 + i] *= rfcurnumtris;
1847
                } while (++i < 12);
1594 plagman 1848
            }
2007 helixhorne 1849
#ifdef DEBUG_MODEL_MEM
1850
            else if (verti == verti%s->numverts)
1851
            {
1852
                OSD_Printf("%s: vert %d is unused\n", m->head.nam, verti);
1853
            }
1854
#endif
1594 plagman 1855
            // copy N over
4639 terminx 1856
            Bmemcpy(&s->geometry[verti15 + 12], &s->geometry[verti15 + 3], sizeof(float) * 3);
1857
            invertmatrix(&s->geometry[verti15 + 6], mat);
1858
            Bmemcpy(&s->geometry[verti15 + 6], mat, sizeof(float) * 9);
1594 plagman 1859
        }
4639 terminx 1860
        while (verti-- > 0);
1238 plagman 1861
    }
4639 terminx 1862
    while (++surfi < m->head.numsurfs);
1623 plagman 1863
 
1809 plagman 1864
#else
1865
    UNREFERENCED_PARAMETER(m);
1866
#endif
1867
 
1623 plagman 1868
    return 1;
1237 plagman 1869
}
1870
 
1744 helixhorne 1871
 
4898 terminx 1872
void md3_vox_calcmat_common(const tspritetype *tspr, const vec3f_t *a0, float f, float mat[16])
2922 helixhorne 1873
{
1874
    float g;
1875
    float k0, k1, k2, k3, k4, k5, k6, k7;
1876
 
4639 terminx 1877
    k0 = ((float)(tspr->x-globalposx))*f*(1.f/1024.f);
1878
    k1 = ((float)(tspr->y-globalposy))*f*(1.f/1024.f);
2922 helixhorne 1879
    f = gcosang2*gshang;
1880
    g = gsinang2*gshang;
4639 terminx 1881
    k4 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+1024)&2047] * (1.f/16384.f);
1882
    k5 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+ 512)&2047] * (1.f/16384.f);
2922 helixhorne 1883
    k2 = k0*(1-k4)+k1*k5;
1884
    k3 = k1*(1-k4)-k0*k5;
1885
    k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
1886
    mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
1887
    k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
1888
    mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
1889
    k6 =           gcosang2*gchang; k7 =           gsinang2*gchang;
1890
    mat[2] = k4*k6 + k5*k7; mat[6] =-gshang;        mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
1891
 
4639 terminx 1892
    mat[12] = (mat[12] + a0->y*mat[0]) + (a0->z*mat[4] + a0->x*mat[ 8]);
1893
    mat[13] = (mat[13] + a0->y*mat[1]) + (a0->z*mat[5] + a0->x*mat[ 9]);
1894
    mat[14] = (mat[14] + a0->y*mat[2]) + (a0->z*mat[6] + a0->x*mat[10]);
2922 helixhorne 1895
}
1896
 
4653 terminx 1897
static void md3draw_handle_triangles(const md3surf_t *s, uint16_t *indexhandle,
3585 helixhorne 1898
                                            int32_t texunits, const md3model_t *M)
1899
{
4639 terminx 1900
    int32_t i;
3585 helixhorne 1901
 
1902
    if (r_vertexarrays)
1903
    {
1904
        int32_t k = 0;
4639 terminx 1905
 
4652 terminx 1906
        if (M == NULL)
3585 helixhorne 1907
        {
4652 terminx 1908
            for (i=s->numtris-1; i>=0; i--, k+=3)
1909
            {
1910
                indexhandle[k]   = s->tris[i].i[0];
1911
                indexhandle[k+1] = s->tris[i].i[1];
1912
                indexhandle[k+2] = s->tris[i].i[2];
1913
            }
1914
            return;
1915
        }
3585 helixhorne 1916
 
4652 terminx 1917
 
1918
        for (i=s->numtris-1; i>=0; i--, k+=3)
1919
        {
1920
            uint16_t tri = M->indexes[i];
1921
 
4639 terminx 1922
            indexhandle[k]   = s->tris[tri].i[0];
1923
            indexhandle[k+1] = s->tris[tri].i[1];
1924
            indexhandle[k+2] = s->tris[tri].i[2];
3585 helixhorne 1925
        }
4639 terminx 1926
        return;
3585 helixhorne 1927
    }
4639 terminx 1928
 
1929
    bglBegin(GL_TRIANGLES);
1930
    for (i=s->numtris-1; i>=0; i--)
3585 helixhorne 1931
    {
4639 terminx 1932
        uint16_t tri = M ? M->indexes[i] : i;
1933
        int32_t j;
1934
 
1935
        for (j=0; j<3; j++)
3585 helixhorne 1936
        {
4639 terminx 1937
            int32_t k = s->tris[tri].i[j];
3585 helixhorne 1938
 
4639 terminx 1939
            if (texunits > GL_TEXTURE0_ARB)
3585 helixhorne 1940
            {
4639 terminx 1941
                int32_t l = GL_TEXTURE0_ARB;
1942
                while (l <= texunits)
1943
                    bglMultiTexCoord2fARB(l++, s->uv[k].u, s->uv[k].v);
1944
            }
1945
            else
1946
                bglTexCoord2f(s->uv[k].u, s->uv[k].v);
3585 helixhorne 1947
 
4639 terminx 1948
            bglVertex3fv((float *) &vertlist[k]);
3585 helixhorne 1949
        }
1950
    }
4639 terminx 1951
    bglEnd();
3585 helixhorne 1952
}
1953
 
4898 terminx 1954
static int32_t polymost_md3draw(md3model_t *m, const tspritetype *tspr)
5 Plagman 1955
{
4639 terminx 1956
    vec3f_t m0, m1, a0;
109 terminx 1957
    md3xyzn_t *v0, *v1;
3585 helixhorne 1958
    int32_t i, surfi;
2937 helixhorne 1959
    float f, g, k0, k1, k2=0, k3=0, mat[16];  // inits: compiler-happy
654 terminx 1960
    GLfloat pc[4];
4488 helixhorne 1961
    int32_t texunits = GL_TEXTURE0_ARB;
3585 helixhorne 1962
 
3587 helixhorne 1963
    const int32_t owner = tspr->owner;
1964
    // PK: XXX: These owner bound checks are redundant because sext is
1965
    // dereferenced unconditionally below anyway.
1966
    const spriteext_t *const sext = ((unsigned)owner < MAXSPRITES+MAXUNIQHUDID) ? &spriteext[owner] : NULL;
1967
    const uint8_t lpal = ((unsigned)owner < MAXSPRITES) ? sprite[tspr->owner].pal : tspr->pal;
4623 terminx 1968
    const int32_t sizyrep = tilesiz[tspr->picnum].y*tspr->yrepeat;
5 Plagman 1969
 
519 Plagman 1970
    if (r_vbos && (m->vbos == NULL))
1971
        mdloadvbos(m);
5 Plagman 1972
 
109 terminx 1973
    //    if ((tspr->cstat&48) == 32) return 0;
5 Plagman 1974
 
2277 helixhorne 1975
    updateanimation((md2model_t *)m, tspr, lpal);
5 Plagman 1976
 
109 terminx 1977
    //create current&next frame's vertex list from whole list
5 Plagman 1978
 
4656 terminx 1979
    f = m->interpol; g = 1.f - f;
294 Plagman 1980
 
4656 terminx 1981
    if (m->interpol < 0.f || m->interpol > 1.f ||
1982
        (unsigned)m->cframe >= (unsigned)m->numframes ||
1983
            (unsigned)m->nframe >= (unsigned)m->numframes)
971 plagman 1984
    {
2338 helixhorne 1985
#ifdef DEBUGGINGAIDS
2251 helixhorne 1986
        OSD_Printf("%s: mdframe oob: c:%d n:%d total:%d interpol:%.02f\n",
1987
                   m->head.nam, m->cframe, m->nframe, m->numframes, m->interpol);
2338 helixhorne 1988
#endif
4639 terminx 1989
 
1990
        m->interpol = fclamp(m->interpol, 0.f, 1.f);
1991
        m->cframe = clamp(m->cframe, 0, m->numframes-1);
1992
        m->nframe = clamp(m->nframe, 0, m->numframes-1);
971 plagman 1993
    }
1994
 
4656 terminx 1995
    m0.z = m0.y = m0.x = g = m->scale * g * (1.f/64.f);
1996
    m1.z = m1.y = m1.x = f = m->scale * f * (1.f/64.f);
5 Plagman 1997
 
4656 terminx 1998
    a0.x = a0.y = 0;
1999
    a0.z = m->zadd * m->scale;
4639 terminx 2000
 
5 Plagman 2001
    // Parkar: Moved up to be able to use k0 for the y-flipping code
1454 terminx 2002
    k0 = (float)tspr->z;
4058 helixhorne 2003
    if ((globalorientation&128) && !((globalorientation&48)==32))
2004
        k0 += (float)(sizyrep<<1);
5 Plagman 2005
 
2006
    // Parkar: Changed to use the same method as centeroriented sprites
109 terminx 2007
    if (globalorientation&8) //y-flipping
2008
    {
2009
        m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
4058 helixhorne 2010
        k0 -= (float)(sizyrep<<2);
5 Plagman 2011
    }
2012
    if (globalorientation&4) { m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y; } //x-flipping
2013
 
2264 hendricks2 2014
    // yoffset differs from zadd in that it does not follow cstat&8 y-flipping
2015
    a0.z += m->yoffset*m->scale;
2016
 
4639 terminx 2017
    f = ((float)tspr->xrepeat) * (1.f/64.f) * m->bscale;
2018
    m0.x *= f; m0.y *= -f;
2019
    m1.x *= f; m1.y *= -f;
2020
    a0.x *= f; a0.y *= -f;
2021
    f = ((float)tspr->yrepeat) * (1.f/64.f) * m->bscale;
5 Plagman 2022
    m0.z *= f; m1.z *= f; a0.z *= f;
2023
 
109 terminx 2024
    // floor aligned
1454 terminx 2025
    k1 = (float)tspr->y;
331 terminx 2026
    if ((globalorientation&48)==32)
109 terminx 2027
    {
2028
        m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
2029
        m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y;