Subversion Repositories eduke32

Rev

Rev 5053 | 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
{
5075 terminx 677
    int32_t i, bpl, 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;
5075 terminx 686
    vec2_t siz = { 0, 0 };
1754 helixhorne 687
 
2617 helixhorne 688
    if (m->mdnum == 2)
689
        surf = 0;
109 terminx 690
 
2617 helixhorne 691
    if ((unsigned)pal >= (unsigned)MAXPALOOKUPS)
692
        return 0;
693
 
5 Plagman 694
    i = -1;
695
    for (sk = m->skinmap; sk; sk = sk->next)
696
    {
2617 helixhorne 697
        if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf)
5 Plagman 698
        {
699
            skinfile = sk->fn;
2617 helixhorne 700
            texidx = &sk->texid[hicfxmask(pal)];
2559 helixhorne 701
            Bstrncpyz(fn, skinfile, BMAX_PATH);
5 Plagman 702
            //OSD_Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile);
703
            break;
704
        }
109 terminx 705
        //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005)
2617 helixhorne 706
        else if ((sk->palette ==   0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; }
707
        else if ((sk->palette == pal) && (sk->skinnum ==      0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; }
708
        else if ((sk->palette ==   0) && (sk->skinnum ==      0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; }
709
        else if ((sk->palette ==   0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; }
710
        else if ((sk->palette == pal) && (sk->skinnum ==      0) && (i < 1)) { i = 1; skzero = sk; }
711
        else if ((sk->palette ==   0) && (sk->skinnum ==      0) && (i < 0)) { i = 0; skzero = sk; }
5 Plagman 712
    }
2617 helixhorne 713
 
5 Plagman 714
    if (!sk)
715
    {
499 Plagman 716
        if (pal >= (MAXPALOOKUPS - RESERVEDPALS))
497 Plagman 717
            return (0);
2617 helixhorne 718
 
5 Plagman 719
        if (skzero)
720
        {
721
            skinfile = skzero->fn;
2617 helixhorne 722
            texidx = &skzero->texid[hicfxmask(pal)];
2559 helixhorne 723
            Bstrncpyz(fn, skinfile, BMAX_PATH);
5 Plagman 724
            //OSD_Printf("Using def skin 0,0 as fallback, pal=%d\n", pal);
725
        }
726
        else
3164 hendricks2 727
            return 0;
728
#if 0
5 Plagman 729
        {
3164 hendricks2 730
            // fall back to the model-defined texture
2617 helixhorne 731
            if ((unsigned)number >= (unsigned)m->numskins)
732
                number = 0;
733
 
3164 hendricks2 734
            // m->skinfn is undefined when md3model_t is cast to md2model_t --> crash
5 Plagman 735
            skinfile = m->skinfn + number*64;
2617 helixhorne 736
            texidx = &m->texid[number*(HICEFFECTMASK+1) + hicfxmask(pal)];
2559 helixhorne 737
            Bstrncpyz(fn, m->basepath, BMAX_PATH);
1457 terminx 738
            if ((Bstrlen(fn) + Bstrlen(skinfile)) < BMAX_PATH)
2617 helixhorne 739
                Bstrcat(fn,skinfile);
5 Plagman 740
            //OSD_Printf("Using MD2/MD3 skin (%d) %s, pal=%d\n",number,skinfile,pal);
741
        }
3164 hendricks2 742
#endif
5 Plagman 743
    }
2244 helixhorne 744
 
2617 helixhorne 745
    if (!skinfile[0])
746
        return 0;
5 Plagman 747
 
2617 helixhorne 748
    if (*texidx)
749
        return *texidx;
499 Plagman 750
 
2825 Plagman 751
    // possibly fetch an already loaded multitexture :_)
752
    if (pal >= (MAXPALOOKUPS - RESERVEDPALS))
2800 Plagman 753
        for (i=0; i<nextmodelid; i++)
754
            for (skzero = ((md2model_t *)models[i])->skinmap; skzero; skzero = skzero->next)
755
                if (!Bstrcasecmp(skzero->fn, sk->fn) && skzero->texid[hicfxmask(pal)])
756
                {
757
                    int32_t f = hicfxmask(pal);
2617 helixhorne 758
 
2800 Plagman 759
                    sk->texid[f] = skzero->texid[f];
760
                    return sk->texid[f];
761
                }
499 Plagman 762
 
5 Plagman 763
    *texidx = 0;
764
 
584 terminx 765
    if ((filh = kopen4load(fn, 0)) < 0)
766
    {
2617 helixhorne 767
        OSD_Printf("Skin \"%s\" not found.\n",fn);
109 terminx 768
        skinfile[0] = 0;
769
        return 0;
770
    }
5 Plagman 771
 
2617 helixhorne 772
 
109 terminx 773
    picfillen = kfilelength(filh);
774
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
5 Plagman 775
 
1754 helixhorne 776
    startticks = getticks();
777
 
3758 terminx 778
    gotcache = texcache_readtexheader(fn, picfillen, pal<<8, hicfxmask(pal), &cachead, 1);
2617 helixhorne 779
 
5075 terminx 780
    if (gotcache && !texcache_loadskin(&cachead, &doalloc, texidx, &siz.x, &siz.y))
584 terminx 781
    {
109 terminx 782
        osizx = cachead.xdim;
783
        osizy = cachead.ydim;
4486 helixhorne 784
        hasalpha = (cachead.flags & CACHEAD_HASALPHA) ? 1 : 0;
2617 helixhorne 785
        if (pal < (MAXPALOOKUPS - RESERVEDPALS))
786
            m->usesalpha = hasalpha;
109 terminx 787
        //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
584 terminx 788
    }
789
    else
790
    {
1784 helixhorne 791
        int32_t ret;
2617 helixhorne 792
        intptr_t fptr=0;
1784 helixhorne 793
 
3758 terminx 794
        gotcache = 0;   // the compressed version will be saved to disk
5 Plagman 795
 
2617 helixhorne 796
        if ((filh = kopen4load(fn, 0)) < 0)
797
            return -1;
798
 
5075 terminx 799
        ret = daskinloader(filh,&fptr,&bpl,&siz.x,&siz.y,&osizx,&osizy,&hasalpha,pal,hicfxmask(pal));
2617 helixhorne 800
 
1784 helixhorne 801
        if (ret)
109 terminx 802
        {
803
            kclose(filh);
1784 helixhorne 804
            OSD_Printf("Failed loading skin file \"%s\": error %d\n", fn, ret);
805
            if (ret==-1)
806
                QuitOnFatalError("OUT OF MEMORY in daskinloader!");
807
 
109 terminx 808
            skinfile[0] = 0;
809
            return(0);
584 terminx 810
        }
811
        else kclose(filh);
1754 helixhorne 812
 
813
        willprint = 1;
814
 
2617 helixhorne 815
        if (pal < (MAXPALOOKUPS - RESERVEDPALS))
816
            m->usesalpha = hasalpha;
817
        if ((doalloc&3)==1)
818
            bglGenTextures(1, texidx);
606 terminx 819
 
2617 helixhorne 820
        bglBindTexture(GL_TEXTURE_2D, *texidx);
821
 
606 terminx 822
        //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,xsiz,ysiz,GL_BGRA_EXT,GL_UNSIGNED_BYTE,(char *)fptr);
2617 helixhorne 823
        if (glinfo.texcompr && glusetexcompr)
824
            intexfmt = hasalpha ? GL_COMPRESSED_RGBA_ARB : GL_COMPRESSED_RGB_ARB;
825
        else if (!hasalpha)
826
            intexfmt = GL_RGB;
827
 
828
        if (glinfo.bgra)
829
            texfmt = GL_BGRA;
830
 
5075 terminx 831
        uploadtexture((doalloc&1), siz, intexfmt, texfmt, (coltype *)fptr, siz, DAMETH_HI);
1762 terminx 832
        Bfree((void *)fptr);
109 terminx 833
    }
5 Plagman 834
 
109 terminx 835
    if (!m->skinloaded)
836
    {
5075 terminx 837
        if (siz.x != osizx || siz.y != osizy)
109 terminx 838
        {
839
            float fx, fy;
5075 terminx 840
            fx = ((float)osizx)/((float)siz.x);
841
            fy = ((float)osizy)/((float)siz.y);
109 terminx 842
            if (m->mdnum == 2)
843
            {
1205 terminx 844
                int32_t *lptr;
1229 terminx 845
                for (lptr=m->glcmds; (i=*lptr++);)
846
                    for (i=labs(i); i>0; i--,lptr+=3)
109 terminx 847
                    {
848
                        ((float *)lptr)[0] *= fx;
849
                        ((float *)lptr)[1] *= fy;
850
                    }
851
            }
852
            else if (m->mdnum == 3)
853
            {
1206 terminx 854
                md3model_t *m3 = (md3model_t *)m;
109 terminx 855
                md3surf_t *s;
1205 terminx 856
                int32_t surfi;
1229 terminx 857
                for (surfi=0; surfi<m3->head.numsurfs; surfi++)
109 terminx 858
                {
859
                    s = &m3->head.surfs[surfi];
1229 terminx 860
                    for (i=s->numverts-1; i>=0; i--)
109 terminx 861
                    {
862
                        s->uv[i].u *= fx;
863
                        s->uv[i].v *= fy;
864
                    }
865
                }
866
            }
867
        }
868
        m->skinloaded = 1+number;
869
    }
5 Plagman 870
 
109 terminx 871
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
872
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
5001 terminx 873
#ifndef EDUKE32_GLES
109 terminx 874
    if (glinfo.maxanisotropy > 1.0)
1454 terminx 875
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
5001 terminx 876
#endif
109 terminx 877
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
878
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
879
 
1046 terminx 880
    if (glinfo.texcompr && glusetexcompr && glusetexcache)
3758 terminx 881
        if (!gotcache)
1107 terminx 882
        {
5075 terminx 883
            const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y);
4488 helixhorne 884
 
1107 terminx 885
            // save off the compressed version
886
            cachead.quality = r_downsize;
887
            cachead.xdim = osizx>>cachead.quality;
888
            cachead.ydim = osizy>>cachead.quality;
918 terminx 889
 
4488 helixhorne 890
            cachead.flags = nonpow2*CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0);
4486 helixhorne 891
 
1754 helixhorne 892
///            OSD_Printf("Caching \"%s\"\n",fn);
3758 terminx 893
            texcache_writetex(fn, picfillen, pal<<8, hicfxmask(pal), &cachead);
1754 helixhorne 894
 
895
            if (willprint)
896
            {
1784 helixhorne 897
                int32_t etime = getticks()-startticks;
898
                if (etime>=MIN_CACHETIME_PRINT)
2617 helixhorne 899
                    OSD_Printf("Load skin: p%d-e%d \"%s\"... cached... %d ms\n", pal, hicfxmask(pal), fn, etime);
1754 helixhorne 900
                willprint = 0;
901
            }
902
            else
903
                OSD_Printf("Cached skin \"%s\"\n", fn);
109 terminx 904
        }
905
 
1754 helixhorne 906
    if (willprint)
1784 helixhorne 907
    {
908
        int32_t etime = getticks()-startticks;
909
        if (etime>=MIN_CACHETIME_PRINT)
2617 helixhorne 910
            OSD_Printf("Load skin: p%d-e%d \"%s\"... %d ms\n", pal, hicfxmask(pal), fn, etime);
1784 helixhorne 911
    }
1754 helixhorne 912
 
109 terminx 913
    return(*texidx);
5 Plagman 914
}
915
 
109 terminx 916
//Note: even though it says md2model, it works for both md2model&md3model
4898 terminx 917
void updateanimation(md2model_t *m, const tspritetype *tspr, uint8_t lpal)
5 Plagman 918
{
2338 helixhorne 919
    const mdanim_t *anim;
1205 terminx 920
    int32_t i, j, k;
921
    int32_t fps;
5 Plagman 922
 
2338 helixhorne 923
    int32_t tile, smoothdurationp;
924
    spritesmooth_t *smooth;
925
    spriteext_t *sprext;
926
 
1229 terminx 927
    if (m->numframes < 2)
1172 terminx 928
    {
929
        m->interpol = 0;
930
        return;
931
    }
932
 
2338 helixhorne 933
    tile = Ptile2tile(tspr->picnum,lpal);
934
    m->cframe = m->nframe = tile2model[tile].framenum;
935
#ifdef DEBUGGINGAIDS
936
    if (m->cframe >= m->numframes)
937
        OSD_Printf("1: c > n\n");
938
#endif
334 terminx 939
 
2338 helixhorne 940
    smoothdurationp = (r_animsmoothing && (tile2model[tile].smoothduration != 0));
941
 
942
    smooth = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spritesmooth[tspr->owner] : NULL;
943
    sprext = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spriteext[tspr->owner] : NULL;
944
 
945
    for (anim = m->animations; anim && anim->startframe != m->cframe; anim = anim->next)
946
    {
947
        /* do nothing */;
948
    }
949
 
584 terminx 950
    if (!anim)
951
    {
2338 helixhorne 952
        if (!smoothdurationp || ((smooth->mdoldframe == m->cframe) && (smooth->mdcurframe == m->cframe)))
530 Plagman 953
        {
2338 helixhorne 954
            m->interpol = 0;
955
            return;
956
        }
957
 
958
        // assert(smoothdurationp && ((smooth->mdoldframe != m->cframe) || (smooth->mdcurframe != m->cframe)))
959
 
960
        if (smooth->mdoldframe != m->cframe)
961
        {
962
            if (smooth->mdsmooth == 0)
530 Plagman 963
            {
2338 helixhorne 964
                sprext->mdanimtims = mdtims;
530 Plagman 965
                m->interpol = 0;
2338 helixhorne 966
                smooth->mdsmooth = 1;
967
                smooth->mdcurframe = m->cframe;
530 Plagman 968
            }
2338 helixhorne 969
 
970
            if (smooth->mdcurframe != m->cframe)
530 Plagman 971
            {
2338 helixhorne 972
                sprext->mdanimtims = mdtims;
530 Plagman 973
                m->interpol = 0;
2338 helixhorne 974
                smooth->mdsmooth = 1;
975
                smooth->mdoldframe = smooth->mdcurframe;
976
                smooth->mdcurframe = m->cframe;
530 Plagman 977
            }
978
        }
2338 helixhorne 979
        else  // if (smooth->mdcurframe != m->cframe)
530 Plagman 980
        {
2338 helixhorne 981
            sprext->mdanimtims = mdtims;
530 Plagman 982
            m->interpol = 0;
2338 helixhorne 983
            smooth->mdsmooth = 1;
984
            smooth->mdoldframe = smooth->mdcurframe;
985
            smooth->mdcurframe = m->cframe;
530 Plagman 986
        }
987
    }
2338 helixhorne 988
    else if (/* anim && */ sprext->mdanimcur != anim->startframe)
5 Plagman 989
    {
2338 helixhorne 990
        //if (sprext->flags & SPREXT_NOMDANIM) OSD_Printf("SPREXT_NOMDANIM\n");
991
        //OSD_Printf("smooth launched ! oldanim %i new anim %i\n", sprext->mdanimcur, anim->startframe);
992
        sprext->mdanimcur = (int16_t)anim->startframe;
993
        sprext->mdanimtims = mdtims;
5 Plagman 994
        m->interpol = 0;
2338 helixhorne 995
 
996
        if (!smoothdurationp)
525 Plagman 997
        {
998
            m->cframe = m->nframe = anim->startframe;
2338 helixhorne 999
#ifdef DEBUGGINGAIDS
1000
            if (m->cframe >= m->numframes)
1001
                OSD_Printf("2: c > n\n");
1002
#endif
525 Plagman 1003
            return;
1004
        }
2338 helixhorne 1005
 
530 Plagman 1006
        m->nframe = anim->startframe;
2338 helixhorne 1007
        m->cframe = smooth->mdoldframe;
1008
#ifdef DEBUGGINGAIDS
1009
        if (m->cframe >= m->numframes)
1010
            OSD_Printf("3: c > n\n");
1011
#endif
1012
        smooth->mdsmooth = 1;
530 Plagman 1013
        return;
5 Plagman 1014
    }
1015
 
4658 terminx 1016
    fps = smooth->mdsmooth ? Blrintf((1.0f / (float) (tile2model[tile].smoothduration)) * 66.f) : anim->fpssc;
525 Plagman 1017
 
2338 helixhorne 1018
    i = (mdtims - sprext->mdanimtims)*((fps*timerticspersec)/120);
530 Plagman 1019
 
2338 helixhorne 1020
    if (smooth->mdsmooth)
531 Plagman 1021
        j = 65536;
1022
    else
530 Plagman 1023
        j = ((anim->endframe+1-anim->startframe)<<16);
2338 helixhorne 1024
    // XXX: Just in case you play the game for a VERY long time...
1025
    if (i < 0) { i = 0; sprext->mdanimtims = mdtims; }
109 terminx 1026
    //compare with j*2 instead of j to ensure i stays > j-65536 for MDANIM_ONESHOT
2338 helixhorne 1027
    if (anim && (i >= j+j) && (fps) && !mdpause) //Keep mdanimtims close to mdtims to avoid the use of MOD
1028
        sprext->mdanimtims += j/((fps*timerticspersec)/120);
5 Plagman 1029
 
530 Plagman 1030
    k = i;
1031
 
1032
    if (anim && (anim->flags&MDANIM_ONESHOT))
584 terminx 1033
        { if (i > j-65536) i = j-65536; }
1034
    else { if (i >= j) { i -= j; if (i >= j) i %= j; } }
5 Plagman 1035
 
2338 helixhorne 1036
    if (r_animsmoothing && smooth->mdsmooth)
525 Plagman 1037
    {
2338 helixhorne 1038
        m->nframe = anim ? anim->startframe : smooth->mdcurframe;
1039
        m->cframe = smooth->mdoldframe;
1040
#ifdef DEBUGGINGAIDS
1041
        if (m->cframe >= m->numframes)
1042
            OSD_Printf("4: c > n\n");
1043
#endif
530 Plagman 1044
        //OSD_Printf("smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
1045
        if (k > 65535)
525 Plagman 1046
        {
2338 helixhorne 1047
            sprext->mdanimtims = mdtims;
530 Plagman 1048
            m->interpol = 0;
2338 helixhorne 1049
            smooth->mdsmooth = 0;
1050
            m->cframe = m->nframe; // = anim ? anim->startframe : smooth->mdcurframe;
1051
#ifdef DEBUGGINGAIDS
1052
            if (m->cframe >= m->numframes)
1053
                OSD_Printf("5: c > n\n");
1054
#endif
1055
            smooth->mdoldframe = m->cframe;
530 Plagman 1056
            //OSD_Printf("smooth stopped !\n");
1057
            return;
525 Plagman 1058
        }
1059
    }
1060
    else
1061
    {
1062
        m->cframe = (i>>16)+anim->startframe;
2338 helixhorne 1063
#ifdef DEBUGGINGAIDS
1064
        if (m->cframe >= m->numframes)
1065
            OSD_Printf("6: c > n\n");
1066
#endif
1067
        m->nframe = m->cframe+1;
1068
        if (m->nframe > anim->endframe)  // VERIFY: (!(r_animsmoothing && smooth->mdsmooth)) implies (anim!=NULL) ?
1069
            m->nframe = anim->startframe;
1070
 
1071
        smooth->mdoldframe = m->cframe;
530 Plagman 1072
        //OSD_Printf("not smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
525 Plagman 1073
    }
2338 helixhorne 1074
 
5 Plagman 1075
    m->interpol = ((float)(i&65535))/65536.f;
530 Plagman 1076
    //OSD_Printf("interpol %f\n", m->interpol);
5 Plagman 1077
}
1078
 
519 Plagman 1079
// VBO generation and allocation
1206 terminx 1080
static void mdloadvbos(md3model_t *m)
519 Plagman 1081
{
1205 terminx 1082
    int32_t     i;
519 Plagman 1083
 
4491 helixhorne 1084
    m->vbos = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint));
519 Plagman 1085
    bglGenBuffersARB(m->head.numsurfs, m->vbos);
1086
 
1087
    i = 0;
1088
    while (i < m->head.numsurfs)
1089
    {
1090
        bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->vbos[i]);
1091
        bglBufferDataARB(GL_ARRAY_BUFFER_ARB, m->head.surfs[i].numverts * sizeof(md3uv_t), m->head.surfs[i].uv, GL_STATIC_DRAW_ARB);
1092
        i++;
1093
    }
1094
    bglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1095
}
1096
 
5 Plagman 1097
//--------------------------------------- MD2 LIBRARY BEGINS ---------------------------------------
1206 terminx 1098
static md2model_t *md2load(int32_t fil, const char *filnam)
5 Plagman 1099
{
1206 terminx 1100
    md2model_t *m;
1101
    md3model_t *m3;
262 Plagman 1102
    md3surf_t *s;
1103
    md2frame_t *f;
5 Plagman 1104
    md2head_t head;
654 terminx 1105
    char st[BMAX_PATH];
1205 terminx 1106
    int32_t i, j, k;
5 Plagman 1107
 
2118 helixhorne 1108
    int32_t ournumskins, ournumglcmds;
1109
 
4491 helixhorne 1110
    m = (md2model_t *)Xcalloc(1,sizeof(md2model_t));
1166 terminx 1111
    m->mdnum = 2; m->scale = .01f;
5 Plagman 1112
 
109 terminx 1113
    kread(fil,(char *)&head,sizeof(md2head_t));
4639 terminx 1114
#if B_BIG_ENDIAN != 0
109 terminx 1115
    head.id = B_LITTLE32(head.id);                 head.vers = B_LITTLE32(head.vers);
1116
    head.skinxsiz = B_LITTLE32(head.skinxsiz);     head.skinysiz = B_LITTLE32(head.skinysiz);
1117
    head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins);
1118
    head.numverts = B_LITTLE32(head.numverts);     head.numuv = B_LITTLE32(head.numuv);
1119
    head.numtris = B_LITTLE32(head.numtris);       head.numglcmds = B_LITTLE32(head.numglcmds);
1120
    head.numframes = B_LITTLE32(head.numframes);   head.ofsskins = B_LITTLE32(head.ofsskins);
1121
    head.ofsuv = B_LITTLE32(head.ofsuv);           head.ofstris = B_LITTLE32(head.ofstris);
1122
    head.ofsframes = B_LITTLE32(head.ofsframes);   head.ofsglcmds = B_LITTLE32(head.ofsglcmds);
1123
    head.ofseof = B_LITTLE32(head.ofseof);
4639 terminx 1124
#endif
5 Plagman 1125
 
4639 terminx 1126
    if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { Bfree(m); return(0); } //"IDP2"
5 Plagman 1127
 
2118 helixhorne 1128
    ournumskins = head.numskins ? head.numskins : 1;
1129
    ournumglcmds = head.numglcmds ? head.numglcmds : 1;
1130
 
109 terminx 1131
    m->numskins = head.numskins;
1132
    m->numframes = head.numframes;
1133
    m->numverts = head.numverts;
1134
    m->numglcmds = head.numglcmds;
1135
    m->framebytes = head.framebytes;
262 Plagman 1136
 
4491 helixhorne 1137
    m->frames = (char *)Xmalloc(m->numframes*m->framebytes);
1138
    m->glcmds = (int32_t *)Xmalloc(ournumglcmds*sizeof(int32_t));
1139
    m->tris = (md2tri_t *)Xmalloc(head.numtris*sizeof(md2tri_t));
1140
    m->uv = (md2uv_t *)Xmalloc(head.numuv*sizeof(md2uv_t));
262 Plagman 1141
 
109 terminx 1142
    klseek(fil,head.ofsframes,SEEK_SET);
1143
    if (kread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes)
1643 terminx 1144
        { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
262 Plagman 1145
 
2118 helixhorne 1146
    if (m->numglcmds > 0)
1147
    {
1148
        klseek(fil,head.ofsglcmds,SEEK_SET);
1149
        if (kread(fil,(char *)m->glcmds,m->numglcmds*sizeof(int32_t)) != (int32_t)(m->numglcmds*sizeof(int32_t)))
1150
            { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
1151
    }
109 terminx 1152
 
262 Plagman 1153
    klseek(fil,head.ofstris,SEEK_SET);
1205 terminx 1154
    if (kread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t)))
1643 terminx 1155
        { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
262 Plagman 1156
 
1157
    klseek(fil,head.ofsuv,SEEK_SET);
1205 terminx 1158
    if (kread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t)))
1643 terminx 1159
        { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
262 Plagman 1160
 
5 Plagman 1161
#if B_BIG_ENDIAN != 0
109 terminx 1162
    {
1163
        char *f = (char *)m->frames;
1205 terminx 1164
        int32_t *l,j;
109 terminx 1165
        md2frame_t *fr;
1166
 
584 terminx 1167
        for (i = m->numframes-1; i>=0; i--)
1168
        {
109 terminx 1169
            fr = (md2frame_t *)f;
1205 terminx 1170
            l = (int32_t *)&fr->mul;
1229 terminx 1171
            for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1172
            f += m->framebytes;
1173
        }
1174
 
584 terminx 1175
        for (i = m->numglcmds-1; i>=0; i--)
1176
        {
109 terminx 1177
            m->glcmds[i] = B_LITTLE32(m->glcmds[i]);
1178
        }
1762 terminx 1179
        for (i = head.numtris-1; i>=0; i--)
1180
        {
1181
            m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]);
1182
            m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]);
1183
            m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]);
1184
            m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]);
1185
            m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]);
1186
            m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]);
1187
        }
1188
        for (i = head.numuv-1; i>=0; i--)
1189
        {
1190
            m->uv[i].u = B_LITTLE16(m->uv[i].u);
1191
            m->uv[i].v = B_LITTLE16(m->uv[i].v);
1192
        }
109 terminx 1193
    }
5 Plagman 1194
#endif
1195
 
2617 helixhorne 1196
    Bstrcpy(st,filnam);
1229 terminx 1197
    for (i=strlen(st)-1; i>0; i--)
584 terminx 1198
        if ((st[i] == '/') || (st[i] == '\\')) { i++; break; }
5 Plagman 1199
    if (i<0) i=0;
1200
    st[i] = 0;
4491 helixhorne 1201
    m->basepath = (char *)Xmalloc(i+1);
2617 helixhorne 1202
    Bstrcpy(m->basepath, st);
5 Plagman 1203
 
4491 helixhorne 1204
    m->skinfn = (char *)Xmalloc(ournumskins*64);
2118 helixhorne 1205
    if (m->numskins > 0)
1206
    {
1207
        klseek(fil,head.ofsskins,SEEK_SET);
1208
        if (kread(fil,m->skinfn,64*m->numskins) != 64*m->numskins)
1209
            { Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); }
1210
    }
5 Plagman 1211
 
4491 helixhorne 1212
    m->texid = (GLuint *)Xcalloc(ournumskins, sizeof(GLuint) * (HICEFFECTMASK+1));
5 Plagman 1213
 
283 Plagman 1214
    maxmodelverts = max(maxmodelverts, m->numverts);
519 Plagman 1215
    maxmodeltris = max(maxmodeltris, head.numtris);
283 Plagman 1216
 
1217
    //return(m);
1218
 
262 Plagman 1219
    // the MD2 is now loaded internally - let's begin the MD3 conversion process
1220
    //OSD_Printf("Beginning md3 conversion.\n");
4491 helixhorne 1221
    m3 = (md3model_t *)Xcalloc(1, sizeof(md3model_t));
262 Plagman 1222
    m3->mdnum = 3; m3->texid = 0; m3->scale = m->scale;
4639 terminx 1223
    m3->head.id = IDP3_MAGIC; m3->head.vers = 15;
3588 helixhorne 1224
 
4653 terminx 1225
    m3->head.flags = 0;
3588 helixhorne 1226
 
755 plagman 1227
    m3->head.numframes = m->numframes;
262 Plagman 1228
    m3->head.numtags = 0; m3->head.numsurfs = 1;
1229
    m3->head.numskins = 0;
5 Plagman 1230
 
262 Plagman 1231
    m3->numskins = m3->head.numskins;
1232
    m3->numframes = m3->head.numframes;
5 Plagman 1233
 
4491 helixhorne 1234
    m3->head.frames = (md3frame_t *)Xcalloc(m3->head.numframes, sizeof(md3frame_t));
4639 terminx 1235
    m3->muladdframes = (vec3f_t *)Xcalloc(m->numframes * 2, sizeof(vec3f_t));
5 Plagman 1236
 
262 Plagman 1237
    f = (md2frame_t *)(m->frames);
5 Plagman 1238
 
262 Plagman 1239
    // frames converting
1240
    i = 0;
1241
    while (i < m->numframes)
109 terminx 1242
    {
262 Plagman 1243
        f = (md2frame_t *)&m->frames[i*m->framebytes];
2617 helixhorne 1244
        Bstrcpy(m3->head.frames[i].nam, f->name);
262 Plagman 1245
        //OSD_Printf("Copied frame %s.\n", m3->head.frames[i].nam);
294 Plagman 1246
        m3->muladdframes[i*2] = f->mul;
1247
        m3->muladdframes[i*2+1] = f->add;
262 Plagman 1248
        i++;
109 terminx 1249
    }
1250
 
262 Plagman 1251
    m3->head.tags = NULL;
5 Plagman 1252
 
4491 helixhorne 1253
    m3->head.surfs = (md3surf_t *)Xcalloc(1, sizeof(md3surf_t));
262 Plagman 1254
    s = m3->head.surfs;
5 Plagman 1255
 
262 Plagman 1256
    // model converting
4639 terminx 1257
    s->id = IDP3_MAGIC; s->flags = 0;
262 Plagman 1258
    s->numframes = m->numframes; s->numshaders = 0;
1259
    s->numtris = head.numtris;
1260
    s->numverts = head.numtris * 3; // oh man talk about memory effectiveness :((((
1261
    // MD2 is actually more accurate than MD3 in term of uv-mapping, because each triangle has a triangle counterpart on the UV-map.
1262
    // In MD3, each vertex unique UV coordinates, meaning that you have to duplicate vertices if you need non-seamless UV-mapping.
109 terminx 1263
 
262 Plagman 1264
    maxmodelverts = max(maxmodelverts, s->numverts);
109 terminx 1265
 
2617 helixhorne 1266
    Bstrcpy(s->nam, "Dummy surface from MD2");
109 terminx 1267
 
262 Plagman 1268
    s->shaders = NULL;
109 terminx 1269
 
4491 helixhorne 1270
    s->tris = (md3tri_t *)Xcalloc(head.numtris, sizeof(md3tri_t));
1271
    s->uv = (md3uv_t *)Xcalloc(s->numverts, sizeof(md3uv_t));
1272
    s->xyzn = (md3xyzn_t *)Xcalloc(s->numverts * m->numframes, sizeof(md3xyzn_t));
294 Plagman 1273
 
283 Plagman 1274
    //memoryusage += (s->numverts * m->numframes * sizeof(md3xyzn_t));
1275
    //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
5 Plagman 1276
 
262 Plagman 1277
    //OSD_Printf("Number of frames : %i\n", m->numframes);
1278
    //OSD_Printf("Number of triangles : %i\n", head.numtris);
1279
    //OSD_Printf("Number of vertices : %i\n", s->numverts);
5 Plagman 1280
 
262 Plagman 1281
    // triangle converting
1282
    i = 0;
1283
    while (i < head.numtris)
5 Plagman 1284
    {
262 Plagman 1285
        j = 0;
1286
        //OSD_Printf("Triangle : %i\n", i);
1287
        while (j < 3)
5 Plagman 1288
        {
262 Plagman 1289
            // triangle vertex indexes
1290
            s->tris[i].i[j] = i*3 + j;
5 Plagman 1291
 
262 Plagman 1292
            // uv coords
1293
            s->uv[i*3+j].u = (float)(m->uv[m->tris[i].u[j]].u) / (float)(head.skinxsiz);
1294
            s->uv[i*3+j].v = (float)(m->uv[m->tris[i].u[j]].v) / (float)(head.skinysiz);
5 Plagman 1295
 
262 Plagman 1296
            // vertices for each frame
1297
            k = 0;
1298
            while (k < m->numframes)
1299
            {
1300
                f = (md2frame_t *)&m->frames[k*m->framebytes];
4653 terminx 1301
                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);
1302
                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);
1303
                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 1304
 
262 Plagman 1305
                k++;
1306
            }
1307
            j++;
5 Plagman 1308
        }
262 Plagman 1309
        //OSD_Printf("End triangle.\n");
1310
        i++;
5 Plagman 1311
    }
262 Plagman 1312
    //OSD_Printf("Finished md3 conversion.\n");
5 Plagman 1313
 
265 terminx 1314
    {
1315
        mdskinmap_t *sk;
1316
 
4491 helixhorne 1317
        sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t));
265 terminx 1318
        sk->palette = 0;
1319
        sk->skinnum = 0;
1320
        sk->surfnum = 0;
1321
 
584 terminx 1322
        if (m->numskins > 0)
1323
        {
4491 helixhorne 1324
            sk->fn = (char *)Xmalloc(strlen(m->basepath)+strlen(m->skinfn)+1);
2617 helixhorne 1325
            Bstrcpy(sk->fn, m->basepath);
1326
            Bstrcat(sk->fn, m->skinfn);
355 terminx 1327
        }
265 terminx 1328
        m3->skinmap = sk;
1329
    }
1330
 
4491 helixhorne 1331
    m3->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris);
1332
    m3->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris * 3);
1333
    m3->maxdepths = (float *)Xmalloc(sizeof(float) * s->numtris);
513 Plagman 1334
 
519 Plagman 1335
    m3->vbos = NULL;
1336
 
262 Plagman 1337
    // die MD2 ! DIE !
1643 terminx 1338
    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 1339
 
1206 terminx 1340
    return((md2model_t *)m3);
5 Plagman 1341
}
1342
//---------------------------------------- MD2 LIBRARY ENDS ----------------------------------------
1343
 
4639 terminx 1344
// DICHOTOMIC RECURSIVE SORTING - USED BY MD3DRAW
1205 terminx 1345
int32_t partition(uint16_t *indexes, float *depths, int32_t f, int32_t l)
584 terminx 1346
{
4639 terminx 1347
    int32_t up = f, down = l;
5 Plagman 1348
    float piv = depths[f];
1205 terminx 1349
    uint16_t piv2 = indexes[f];
584 terminx 1350
    do
1351
    {
5 Plagman 1352
        while ((depths[up] <= piv) && (up < l))
1353
            up++;
1354
        while ((depths[down] > piv)  && (down > f))
1355
            down--;
584 terminx 1356
        if (up < down)
5 Plagman 1357
        {
4639 terminx 1358
            swapfloat(&depths[up], &depths[down]);
1359
            swapshort(&indexes[up], &indexes[down]);
5 Plagman 1360
        }
584 terminx 1361
    }
1362
    while (down > up);
4639 terminx 1363
    depths[f] = depths[down], depths[down] = piv;
1364
    indexes[f] = indexes[down], indexes[down] = piv2;
5 Plagman 1365
    return down;
1366
}
1367
 
4639 terminx 1368
static inline void quicksort(uint16_t *indexes, float *depths, int32_t first, int32_t last)
584 terminx 1369
{
4639 terminx 1370
    int32_t pivIndex;
1371
    if (first >= last) return;
1372
    pivIndex = partition(indexes, depths, first, last);
1373
    if (first < (pivIndex-1)) quicksort(indexes, depths, first, (pivIndex-1));
1374
    if ((pivIndex+1) >= last) return;
1375
    quicksort(indexes, depths, (pivIndex+1), last);
5 Plagman 1376
}
1377
// END OF QUICKSORT LIB
1378
 
1379
//--------------------------------------- MD3 LIBRARY BEGINS ---------------------------------------
1380
 
1206 terminx 1381
static md3model_t *md3load(int32_t fil)
5 Plagman 1382
{
1205 terminx 1383
    int32_t i, surfi, ofsurf, offs[4], leng[4];
1384
    int32_t maxtrispersurf;
1206 terminx 1385
    md3model_t *m;
109 terminx 1386
    md3surf_t *s;
5 Plagman 1387
 
4491 helixhorne 1388
    m = (md3model_t *)Xcalloc(1,sizeof(md3model_t));
1454 terminx 1389
    m->mdnum = 3; m->texid = 0; m->scale = .01f;
5 Plagman 1390
 
294 Plagman 1391
    m->muladdframes = NULL;
1392
 
738 plagman 1393
    kread(fil,&m->head,SIZEOF_MD3HEAD_T);
4639 terminx 1394
 
1395
#if B_BIG_ENDIAN != 0
109 terminx 1396
    m->head.id = B_LITTLE32(m->head.id);             m->head.vers = B_LITTLE32(m->head.vers);
1397
    m->head.flags = B_LITTLE32(m->head.flags);       m->head.numframes = B_LITTLE32(m->head.numframes);
1398
    m->head.numtags = B_LITTLE32(m->head.numtags);   m->head.numsurfs = B_LITTLE32(m->head.numsurfs);
738 plagman 1399
    m->head.numskins = B_LITTLE32(m->head.numskins); m->head.ofsframes = B_LITTLE32(m->head.ofsframes);
1400
    m->head.ofstags = B_LITTLE32(m->head.ofstags); m->head.ofssurfs = B_LITTLE32(m->head.ofssurfs);
109 terminx 1401
    m->head.eof = B_LITTLE32(m->head.eof);
4639 terminx 1402
#endif
5 Plagman 1403
 
4639 terminx 1404
    if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { Bfree(m); return(0); } //"IDP3"
109 terminx 1405
 
5 Plagman 1406
    m->numskins = m->head.numskins; //<- dead code?
1407
    m->numframes = m->head.numframes;
1408
 
739 plagman 1409
    ofsurf = m->head.ofssurfs;
5 Plagman 1410
 
738 plagman 1411
    klseek(fil,m->head.ofsframes,SEEK_SET); i = m->head.numframes*sizeof(md3frame_t);
4491 helixhorne 1412
    m->head.frames = (md3frame_t *)Xmalloc(i);
5 Plagman 1413
    kread(fil,m->head.frames,i);
1414
 
1415
    if (m->head.numtags == 0) m->head.tags = NULL;
584 terminx 1416
    else
1417
    {
738 plagman 1418
        klseek(fil,m->head.ofstags,SEEK_SET); i = m->head.numtags*sizeof(md3tag_t);
4491 helixhorne 1419
        m->head.tags = (md3tag_t *)Xmalloc(i);
5 Plagman 1420
        kread(fil,m->head.tags,i);
1421
    }
1422
 
4980 helixhorne 1423
    klseek(fil,m->head.ofssurfs,SEEK_SET);
1424
    m->head.surfs = (md3surf_t *)Xcalloc(m->head.numsurfs, sizeof(md3surf_t));
1425
    // NOTE: We assume that NULL is represented by all-zeros.
1426
    // surfs[0].geometry is for POLYMER_MD_PROCESS_CHECK (else: crashes).
1427
    // surfs[i].geometry is for FREE_SURFS_GEOMETRY.
1428
    Bassert(m->head.surfs[0].geometry == NULL);
5 Plagman 1429
 
1430
#if B_BIG_ENDIAN != 0
109 terminx 1431
    {
1903 helixhorne 1432
        int32_t j, *l;
109 terminx 1433
 
584 terminx 1434
        for (i = m->head.numframes-1; i>=0; i--)
1435
        {
1205 terminx 1436
            l = (int32_t *)&m->head.frames[i].min;
1229 terminx 1437
            for (j=3+3+3+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1438
        }
1439
 
584 terminx 1440
        for (i = m->head.numtags-1; i>=0; i--)
1441
        {
1205 terminx 1442
            l = (int32_t *)&m->head.tags[i].p;
1229 terminx 1443
            for (j=3+3+3+3-1; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1444
        }
1445
    }
5 Plagman 1446
#endif
1447
 
513 Plagman 1448
    maxtrispersurf = 0;
1449
 
1229 terminx 1450
    for (surfi=0; surfi<m->head.numsurfs; surfi++)
109 terminx 1451
    {
1452
        s = &m->head.surfs[surfi];
738 plagman 1453
        klseek(fil,ofsurf,SEEK_SET); kread(fil,s,SIZEOF_MD3SURF_T);
5 Plagman 1454
 
1455
#if B_BIG_ENDIAN != 0
109 terminx 1456
        {
1903 helixhorne 1457
            int32_t j, *l;
109 terminx 1458
            s->id = B_LITTLE32(s->id);
1205 terminx 1459
            l = (int32_t *)&s->flags;
1229 terminx 1460
            for (j=1+1+1+1+1+1+1+1+1+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]);
109 terminx 1461
        }
5 Plagman 1462
#endif
1463
 
4639 terminx 1464
        offs[0] = ofsurf+s->ofstris;
1465
        offs[1] = ofsurf+s->ofsshaders;
1466
        offs[2] = ofsurf+s->ofsuv;
1467
        offs[3] = ofsurf+s->ofsxyzn;
1468
 
1469
        leng[0] = s->numtris*sizeof(md3tri_t);
1470
        leng[1] = s->numshaders*sizeof(md3shader_t);
1471
        leng[2] = s->numverts*sizeof(md3uv_t);
1472
        leng[3] = s->numframes*s->numverts*sizeof(md3xyzn_t);
1473
 
283 Plagman 1474
        //memoryusage += (s->numverts * s->numframes * sizeof(md3xyzn_t));
1475
        //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
5 Plagman 1476
 
4639 terminx 1477
        s->tris = (md3tri_t *)Xmalloc((leng[0] + leng[1]) + (leng[2] + leng[3]));
283 Plagman 1478
 
740 plagman 1479
        s->shaders = (md3shader_t *)(((intptr_t)s->tris)+leng[0]);
1762 terminx 1480
        s->uv      = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]);
1481
        s->xyzn    = (md3xyzn_t *)(((intptr_t)s->uv)+leng[2]);
5 Plagman 1482
 
1483
        klseek(fil,offs[0],SEEK_SET); kread(fil,s->tris   ,leng[0]);
1484
        klseek(fil,offs[1],SEEK_SET); kread(fil,s->shaders,leng[1]);
1485
        klseek(fil,offs[2],SEEK_SET); kread(fil,s->uv     ,leng[2]);
1486
        klseek(fil,offs[3],SEEK_SET); kread(fil,s->xyzn   ,leng[3]);
1487
 
1488
#if B_BIG_ENDIAN != 0
109 terminx 1489
        {
1903 helixhorne 1490
            int32_t j, *l;
109 terminx 1491
 
1229 terminx 1492
            for (i=s->numtris-1; i>=0; i--)
584 terminx 1493
            {
1229 terminx 1494
                for (j=2; j>=0; j--) s->tris[i].i[j] = B_LITTLE32(s->tris[i].i[j]);
109 terminx 1495
            }
1229 terminx 1496
            for (i=s->numshaders-1; i>=0; i--)
584 terminx 1497
            {
109 terminx 1498
                s->shaders[i].i = B_LITTLE32(s->shaders[i].i);
1499
            }
1229 terminx 1500
            for (i=s->numverts-1; i>=0; i--)
584 terminx 1501
            {
1762 terminx 1502
                l = (int32_t *)&s->uv[i].u;
109 terminx 1503
                l[0] = B_LITTLE32(l[0]);
1504
                l[1] = B_LITTLE32(l[1]);
1505
            }
1229 terminx 1506
            for (i=s->numframes*s->numverts-1; i>=0; i--)
584 terminx 1507
            {
1205 terminx 1508
                s->xyzn[i].x = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].x);
1509
                s->xyzn[i].y = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].y);
1510
                s->xyzn[i].z = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].z);
109 terminx 1511
            }
1512
        }
5 Plagman 1513
#endif
109 terminx 1514
        maxmodelverts = max(maxmodelverts, s->numverts);
519 Plagman 1515
        maxmodeltris = max(maxmodeltris, s->numtris);
513 Plagman 1516
        maxtrispersurf = max(maxtrispersurf, s->numtris);
109 terminx 1517
        ofsurf += s->ofsend;
1518
    }
5 Plagman 1519
 
4491 helixhorne 1520
    m->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf);
1521
    m->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf * 3);
1522
    m->maxdepths = (float *)Xmalloc(sizeof(float) * maxtrispersurf);
513 Plagman 1523
 
519 Plagman 1524
    m->vbos = NULL;
1525
 
5 Plagman 1526
    return(m);
1527
}
1528
 
1762 terminx 1529
static inline void  invertmatrix(float *m, float *out)
1594 plagman 1530
{
1531
    float det;
1532
 
4639 terminx 1533
    det  = (m[0] * (m[4]*m[8] - m[5] * m[7]))
1534
         - (m[1] * (m[3]*m[8] - m[5] * m[6]))
1535
         + (m[2] * (m[3]*m[7] - m[4] * m[6]));
1594 plagman 1536
 
4639 terminx 1537
    if (det == 0.0f)
2007 helixhorne 1538
    {
4639 terminx 1539
        Bmemset(out, 0, sizeof(float) * 9);
1540
        out[8] = out[4] = out[0] = 1.f;
1541
        return;
1542
    }
1594 plagman 1543
 
4639 terminx 1544
    det = 1.0f / det;
1699 plagman 1545
 
4639 terminx 1546
    out[0] = det * (m[4] * m[8] - m[5] * m[7]);
1547
    out[1] = det * (m[2] * m[7] - m[1] * m[8]);
1548
    out[2] = det * (m[1] * m[5] - m[2] * m[4]);
1549
    out[3] = det * (m[5] * m[6] - m[3] * m[8]);
1550
    out[4] = det * (m[0] * m[8] - m[2] * m[6]);
1551
    out[5] = det * (m[2] * m[3] - m[0] * m[5]);
1552
    out[6] = det * (m[3] * m[7] - m[1] * m[6]);
1553
    out[7] = det * (m[1] * m[6] - m[0] * m[7]);
1554
    out[8] = det * (m[0] * m[4] - m[1] * m[3]);
1594 plagman 1555
}
1556
 
1762 terminx 1557
static inline void  normalize(float *vec)
1594 plagman 1558
{
4639 terminx 1559
    float norm;
1594 plagman 1560
 
4639 terminx 1561
    if ((norm = vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]) == 0.f)
1562
        return;
1594 plagman 1563
 
5075 terminx 1564
    norm = polymost_invsqrt_approximation(norm);
4639 terminx 1565
    vec[0] *= norm;
1566
    vec[1] *= norm;
1567
    vec[2] *= norm;
1594 plagman 1568
}
1569
 
1762 terminx 1570
static void      md3postload_common(md3model_t *m)
1237 plagman 1571
{
1744 helixhorne 1572
    int         framei, surfi, verti;
1594 plagman 1573
    md3frame_t  *frame;
1237 plagman 1574
    md3xyzn_t   *frameverts;
1575
 
1576
    // apparently we can't trust loaded models bounding box/sphere information,
1577
    // so let's compute it ourselves
1578
 
1579
    framei = 0;
4639 terminx 1580
    do // while (++framei < m->head.numframes);
1237 plagman 1581
    {
1594 plagman 1582
        frame = &m->head.frames[framei];
4639 terminx 1583
        Bmemset(&frame->min, 0, sizeof(vec3f_t) * 2);
1594 plagman 1584
        frame->r        = 0.0f;
1585
 
1237 plagman 1586
        surfi = 0;
4639 terminx 1587
        do // while (++surfi < m->head.numsurfs);
1237 plagman 1588
        {
1589
            frameverts = &m->head.surfs[surfi].xyzn[framei * m->head.surfs[surfi].numverts];
1590
 
1591
            verti = 0;
4639 terminx 1592
 
1593
            if (!surfi)
1237 plagman 1594
            {
4639 terminx 1595
                frame->min.x = (float)frameverts[0].x;
1596
                frame->min.y = (float)frameverts[0].y;
1597
                frame->min.z = (float)frameverts[0].z;
1598
                frame->max = frame->min;
1599
            }
1237 plagman 1600
 
4639 terminx 1601
            do // while(++verti < m->head.surfs[surfi].numverts);
1602
            {
4771 hendricks2 1603
                vec3f_t f = { (float)frameverts[verti].x, (float)frameverts[verti].y, (float)frameverts[verti].z };
1237 plagman 1604
 
4639 terminx 1605
                if (!verti && !surfi)
1606
                    continue;
1237 plagman 1607
 
4639 terminx 1608
                frame->min.x = max(frame->min.x, f.x);
1609
                frame->min.y = max(frame->min.y, f.y);
1610
                frame->min.z = max(frame->min.z, f.z);
1611
                frame->max.x = max(frame->max.x, f.x);
1612
                frame->max.y = max(frame->max.y, f.y);
1613
                frame->max.z = max(frame->max.z, f.z);
1237 plagman 1614
            }
4639 terminx 1615
            while(++verti < m->head.surfs[surfi].numverts);
1237 plagman 1616
        }
4639 terminx 1617
        while (++surfi < m->head.numsurfs);
1237 plagman 1618
 
4639 terminx 1619
        frame->cen.x = (frame->min.x + frame->max.x) * .5f;
1620
        frame->cen.y = (frame->min.y + frame->max.y) * .5f;
1621
        frame->cen.z = (frame->min.z + frame->max.z) * .5f;
1237 plagman 1622
 
1623
        surfi = 0;
4639 terminx 1624
        do // while (++surfi < m->head.numsurfs);
1237 plagman 1625
        {
4639 terminx 1626
            float       vec1[4];
1627
 
1237 plagman 1628
            frameverts = &m->head.surfs[surfi].xyzn[framei * m->head.surfs[surfi].numverts];
1629
 
1630
            verti = 0;
4639 terminx 1631
            do // while (++verti < m->head.surfs[surfi].numverts);
1237 plagman 1632
            {
1594 plagman 1633
                vec1[0] = frameverts[verti].x - frame->cen.x;
1634
                vec1[1] = frameverts[verti].y - frame->cen.y;
1635
                vec1[2] = frameverts[verti].z - frame->cen.z;
1237 plagman 1636
 
4639 terminx 1637
                vec1[3] = (vec1[0] * vec1[0]) + (vec1[1] * vec1[1]) + (vec1[2] * vec1[2]);
1240 plagman 1638
 
4639 terminx 1639
                frame->r = max(vec1[3], frame->r);
1237 plagman 1640
            }
4639 terminx 1641
            while (++verti < m->head.surfs[surfi].numverts);
1237 plagman 1642
        }
4639 terminx 1643
        while (++surfi < m->head.numsurfs);
1644
        frame->r = Bsqrtf(frame->r);
1237 plagman 1645
    }
4639 terminx 1646
    while (++framei < m->head.numframes);
1744 helixhorne 1647
}
1238 plagman 1648
 
1744 helixhorne 1649
#ifdef POLYMER
1650
// pre-check success of conversion since it must not fail later.
1651
// keep in sync with md3postload_polymer!
1652
static int md3postload_polymer_check(md3model_t *m)
1653
{
4639 terminx 1654
    uint32_t    surfi, trii;
1744 helixhorne 1655
    md3surf_t   *s;
1656
 
1657
    surfi = 0;
4639 terminx 1658
    do
1744 helixhorne 1659
    {
1660
        s = &m->head.surfs[surfi];
1661
 
1662
        trii = 0;
4639 terminx 1663
        do
1744 helixhorne 1664
        {
1665
            // let the vertices know they're being referenced by a triangle
4639 terminx 1666
            if ((unsigned)s->tris[trii].i[0] >= (unsigned)s->numverts ||
1667
                    (unsigned)s->tris[trii].i[1] >= (unsigned)s->numverts ||
1668
                    (unsigned)s->tris[trii].i[2] >= (unsigned)s->numverts)
1762 terminx 1669
            {
1744 helixhorne 1670
                // corrupt model
2007 helixhorne 1671
                OSD_Printf("%s: Triangle index out of bounds!\n", m->head.nam);
4639 terminx 1672
                return 1;
1744 helixhorne 1673
            }
1674
        }
4639 terminx 1675
        while (++trii < (unsigned)s->numtris);
1744 helixhorne 1676
    }
4639 terminx 1677
    while (++surfi < (unsigned)m->head.numsurfs);
1744 helixhorne 1678
 
4639 terminx 1679
    return 0;
1744 helixhorne 1680
}
4060 helixhorne 1681
 
1682
// Precalculated cos/sin arrays.
4639 terminx 1683
static float g_mdcos[256], g_mdsin[256];
1684
static int32_t mdtrig_init = 0;
4060 helixhorne 1685
 
1686
static void init_mdtrig_arrays(void)
1687
{
1688
    int32_t i;
4656 terminx 1689
    static const float acc = ((2.f * (float)PI) * (1.f/255.f));
4639 terminx 1690
    float ang = 0.f;
4060 helixhorne 1691
 
1692
    for (i=0; i<256; i++)
1693
    {
4639 terminx 1694
        g_mdcos[i] = cosf(ang);
1695
        g_mdsin[i] = sinf(ang);
1696
        ang += acc;
4060 helixhorne 1697
    }
4639 terminx 1698
 
1699
    mdtrig_init = 1;
4060 helixhorne 1700
}
1744 helixhorne 1701
#endif
1702
 
1762 terminx 1703
int      md3postload_polymer(md3model_t *m)
1744 helixhorne 1704
{
1705
#ifdef POLYMER
1706
    int         framei, surfi, verti, trii, i;
4060 helixhorne 1707
    float       vec1[5], vec2[5], mat[9], r;
1744 helixhorne 1708
 
4952 helixhorne 1709
    // POLYMER_MD_PROCESS_CHECK
1910 helixhorne 1710
    if (m->head.surfs[0].geometry)
1711
        return -1;  // already postprocessed
1712
 
4639 terminx 1713
    if (!mdtrig_init)
1714
        init_mdtrig_arrays();
4060 helixhorne 1715
 
1238 plagman 1716
    // let's also repack the geometry to more usable formats
1717
 
1718
    surfi = 0;
4639 terminx 1719
    do // while (++surfi < m->head.numsurfs)
1238 plagman 1720
    {
4639 terminx 1721
        handleevents();
1722
 
4952 helixhorne 1723
        md3surf_t *const s = &m->head.surfs[surfi];
1910 helixhorne 1724
#ifdef DEBUG_MODEL_MEM
1725
        i = (m->head.numframes * s->numverts * sizeof(float) * 15);
1726
        if (i > 1<<20)
1727
            initprintf("size %d (%d fr, %d v): md %s surf %d/%d\n", i, m->head.numframes, s->numverts,
2007 helixhorne 1728
                       m->head.nam, surfi, m->head.numsurfs);
1910 helixhorne 1729
#endif
4639 terminx 1730
        s->geometry = (float *)Xcalloc(m->head.numframes * s->numverts * 15, sizeof(float));
1594 plagman 1731
 
4639 terminx 1732
        if (s->numverts > tribufverts)
1733
        {
1734
            tribuf = (int32_t *) Xrealloc(tribuf, s->numverts * sizeof(int32_t));
1735
            Bmemset(tribuf, 0, s->numverts * sizeof(int32_t));
1736
            tribufverts = s->numverts;
1737
        }
1594 plagman 1738
 
1238 plagman 1739
        verti = 0;
4639 terminx 1740
        do // while (++verti < (m->head.numframes * s->numverts))
1238 plagman 1741
        {
4060 helixhorne 1742
            // normal extraction from packed spherical coordinates
1743
            // FIXME: swapping lat and lng because of npherno's compiler
1744
            uint8_t lat = s->xyzn[verti].nlng;
1745
            uint8_t lng = s->xyzn[verti].nlat;
4639 terminx 1746
            uint32_t verti15 = (verti<<4)-verti;
4060 helixhorne 1747
 
4639 terminx 1748
            s->geometry[verti15 + 0] = s->xyzn[verti].x;
1749
            s->geometry[verti15 + 1] = s->xyzn[verti].y;
1750
            s->geometry[verti15 + 2] = s->xyzn[verti].z;
1238 plagman 1751
 
4639 terminx 1752
            s->geometry[verti15 + 3] = g_mdcos[lat] * g_mdsin[lng];
1753
            s->geometry[verti15 + 4] = g_mdsin[lat] * g_mdsin[lng];
1754
            s->geometry[verti15 + 5] = g_mdcos[lng];
1238 plagman 1755
        }
4639 terminx 1756
        while (++verti < (m->head.numframes * s->numverts));
1594 plagman 1757
 
1758
        trii = 0;
4639 terminx 1759
        do // while (++trii < s->numtris)
1594 plagman 1760
        {
4639 terminx 1761
            uint32_t       tris15[3];
1762
 
1594 plagman 1763
            // let the vertices know they're being referenced by a triangle
4639 terminx 1764
            if ((unsigned) s->tris[trii].i[0] >= (unsigned) s->numverts ||
1765
                (unsigned) s->tris[trii].i[1] >= (unsigned) s->numverts ||
1766
                (unsigned) s->tris[trii].i[2] >= (unsigned) s->numverts)
1762 terminx 1767
            {
1623 plagman 1768
                // corrupt model
1769
                return 0;
1770
            }
4639 terminx 1771
            tribuf[s->tris[trii].i[0]]++;
1772
            tribuf[s->tris[trii].i[1]]++;
1773
            tribuf[s->tris[trii].i[2]]++;
1594 plagman 1774
 
4639 terminx 1775
            tris15[0] = (s->tris[trii].i[0]<<4)-s->tris[trii].i[0];
1776
            tris15[1] = (s->tris[trii].i[1]<<4)-s->tris[trii].i[1];
1777
            tris15[2] = (s->tris[trii].i[2]<<4)-s->tris[trii].i[2];
1778
 
1779
 
1594 plagman 1780
            framei = 0;
4639 terminx 1781
            do // while (++framei < m->head.numframes)
1594 plagman 1782
            {
4639 terminx 1783
                const uint32_t verti15 = framei * s->numverts * 15;
1784
 
1785
                vec1[0] = s->geometry[verti15 + tris15[1]]     - s->geometry[verti15 + tris15[0]];
1786
                vec1[1] = s->geometry[verti15 + tris15[1] + 1] - s->geometry[verti15 + tris15[0] + 1];
1787
                vec1[2] = s->geometry[verti15 + tris15[1] + 2] - s->geometry[verti15 + tris15[0] + 2];
1594 plagman 1788
                vec1[3] = s->uv[s->tris[trii].i[1]].u - s->uv[s->tris[trii].i[0]].u;
1789
                vec1[4] = s->uv[s->tris[trii].i[1]].v - s->uv[s->tris[trii].i[0]].v;
1790
 
4639 terminx 1791
                vec2[0] = s->geometry[verti15 + tris15[2]    ] - s->geometry[verti15 + tris15[1]];
1792
                vec2[1] = s->geometry[verti15 + tris15[2] + 1] - s->geometry[verti15 + tris15[1] + 1];
1793
                vec2[2] = s->geometry[verti15 + tris15[2] + 2] - s->geometry[verti15 + tris15[1] + 2];
1594 plagman 1794
                vec2[3] = s->uv[s->tris[trii].i[2]].u - s->uv[s->tris[trii].i[1]].u;
1795
                vec2[4] = s->uv[s->tris[trii].i[2]].v - s->uv[s->tris[trii].i[1]].v;
1796
 
2007 helixhorne 1797
                r = (vec1[3] * vec2[4] - vec2[3] * vec1[4]);
1798
                if (r != 0.0f)
1799
                {
4639 terminx 1800
                    r = 1.f/r;
1594 plagman 1801
 
2007 helixhorne 1802
                    // tangent
1803
                    mat[0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r;
1804
                    mat[1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r;
1805
                    mat[2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r;
1594 plagman 1806
 
2007 helixhorne 1807
                    normalize(&mat[0]);
1594 plagman 1808
 
2007 helixhorne 1809
                    // bitangent
1810
                    mat[3] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r;
1811
                    mat[4] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
1812
                    mat[5] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
1594 plagman 1813
 
2007 helixhorne 1814
                    normalize(&mat[3]);
1815
                }
4639 terminx 1816
                else Bmemset(mat, 0, sizeof(float) * 6);
1594 plagman 1817
 
1818
                // T and B are shared for the three vertices in that triangle
1819
                i = 0;
4639 terminx 1820
                do
1594 plagman 1821
                {
4639 terminx 1822
                    const uint32_t offs = (framei * s->numverts * 15) + i + 6;
1823
 
1824
                    s->geometry[offs + tris15[0]] += mat[i];
1825
                    s->geometry[offs + tris15[1]] += mat[i];
1826
                    s->geometry[offs + tris15[2]] += mat[i];
1594 plagman 1827
                }
4639 terminx 1828
                while (++i < 6);
1594 plagman 1829
            }
4639 terminx 1830
            while (++framei < m->head.numframes);
1594 plagman 1831
        }
4639 terminx 1832
        while (++trii < s->numtris);
1594 plagman 1833
 
1834
        // now that we accumulated the TBNs, average and invert them for each vertex
4639 terminx 1835
        verti = (m->head.numframes * s->numverts)-1;
1836
 
1837
        do // while (verti-- > 0)
1594 plagman 1838
        {
4639 terminx 1839
            const int32_t curnumtris = tribuf[verti % s->numverts];
1840
            const uint32_t verti15 = (verti<<4) - verti;
2007 helixhorne 1841
 
1842
            if (curnumtris > 0)
1594 plagman 1843
            {
4639 terminx 1844
                const float rfcurnumtris = 1.f/(float)curnumtris;
2007 helixhorne 1845
                i = 6;
4639 terminx 1846
                do {
1847
                    s->geometry[verti15 + i] *= rfcurnumtris;
1848
                } while (++i < 12);
1594 plagman 1849
            }
2007 helixhorne 1850
#ifdef DEBUG_MODEL_MEM
1851
            else if (verti == verti%s->numverts)
1852
            {
1853
                OSD_Printf("%s: vert %d is unused\n", m->head.nam, verti);
1854
            }
1855
#endif
1594 plagman 1856
            // copy N over
4639 terminx 1857
            Bmemcpy(&s->geometry[verti15 + 12], &s->geometry[verti15 + 3], sizeof(float) * 3);
1858
            invertmatrix(&s->geometry[verti15 + 6], mat);
1859
            Bmemcpy(&s->geometry[verti15 + 6], mat, sizeof(float) * 9);
1594 plagman 1860
        }
4639 terminx 1861
        while (verti-- > 0);
1238 plagman 1862
    }
4639 terminx 1863
    while (++surfi < m->head.numsurfs);
1623 plagman 1864
 
1809 plagman 1865
#else
1866
    UNREFERENCED_PARAMETER(m);
1867
#endif
1868
 
1623 plagman 1869
    return 1;
1237 plagman 1870
}
1871
 
1744 helixhorne 1872
 
4898 terminx 1873
void md3_vox_calcmat_common(const tspritetype *tspr, const vec3f_t *a0, float f, float mat[16])
2922 helixhorne 1874
{
1875
    float g;
1876
    float k0, k1, k2, k3, k4, k5, k6, k7;
1877
 
4639 terminx 1878
    k0 = ((float)(tspr->x-globalposx))*f*(1.f/1024.f);
1879
    k1 = ((float)(tspr->y-globalposy))*f*(1.f/1024.f);
2922 helixhorne 1880
    f = gcosang2*gshang;
1881
    g = gsinang2*gshang;
4639 terminx 1882
    k4 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+1024)&2047] * (1.f/16384.f);
1883
    k5 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+ 512)&2047] * (1.f/16384.f);
2922 helixhorne 1884
    k2 = k0*(1-k4)+k1*k5;
1885
    k3 = k1*(1-k4)-k0*k5;
1886
    k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
1887
    mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
1888
    k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
1889
    mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
1890
    k6 =           gcosang2*gchang; k7 =           gsinang2*gchang;
1891
    mat[2] = k4*k6 + k5*k7; mat[6] =-gshang;        mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
1892
 
4639 terminx 1893
    mat[12] = (mat[12] + a0->y*mat[0]) + (a0->z*mat[4] + a0->x*mat[ 8]);
1894
    mat[13] = (mat[13] + a0->y*mat[1]) + (a0->z*mat[5] + a0->x*mat[ 9]);
1895
    mat[14] = (mat[14] + a0->y*mat[2]) + (a0->z*mat[6] + a0->x*mat[10]);
2922 helixhorne 1896
}
1897
 
4653 terminx 1898
static void md3draw_handle_triangles(const md3surf_t *s, uint16_t *indexhandle,
3585 helixhorne 1899
                                            int32_t texunits, const md3model_t *M)
1900
{
4639 terminx 1901
    int32_t i;
3585 helixhorne 1902
 
1903
    if (r_vertexarrays)
1904
    {
1905
        int32_t k = 0;
4639 terminx 1906
 
4652 terminx 1907
        if (M == NULL)
3585 helixhorne 1908
        {
4652 terminx 1909
            for (i=s->numtris-1; i>=0; i--, k+=3)
1910
            {
1911
                indexhandle[k]   = s->tris[i].i[0];
1912
                indexhandle[k+1] = s->tris[i].i[1];
1913
                indexhandle[k+2] = s->tris[i].i[2];
1914
            }
1915
            return;
1916
        }
3585 helixhorne 1917
 
4652 terminx 1918
 
1919
        for (i=s->numtris-1; i>=0; i--, k+=3)
1920
        {
1921
            uint16_t tri = M->indexes[i];
1922
 
4639 terminx 1923
            indexhandle[k]   = s->tris[tri].i[0];
1924
            indexhandle[k+1] = s->tris[tri].i[1];
1925
            indexhandle[k+2] = s->tris[tri].i[2];
3585 helixhorne 1926
        }
4639 terminx 1927
        return;
3585 helixhorne 1928
    }
4639 terminx 1929
 
1930
    bglBegin(GL_TRIANGLES);
1931
    for (i=s->numtris-1; i>=0; i--)
3585 helixhorne 1932
    {
4639 terminx 1933
        uint16_t tri = M ? M->indexes[i] : i;
1934
        int32_t j;
1935
 
1936
        for (j=0; j<3; j++)
3585 helixhorne 1937
        {
4639 terminx 1938
            int32_t k = s->tris[tri].i[j];
3585 helixhorne 1939
 
4639 terminx 1940
            if (texunits > GL_TEXTURE0_ARB)
3585 helixhorne 1941
            {
4639 terminx 1942
                int32_t l = GL_TEXTURE0_ARB;
1943
                while (l <= texunits)
1944
                    bglMultiTexCoord2fARB(l++, s->uv[k].u, s->uv[k].v);
1945
            }
1946
            else
1947
                bglTexCoord2f(s->uv[k].u, s->uv[k].v);
3585 helixhorne 1948
 
4639 terminx 1949
            bglVertex3fv((float *) &vertlist[k]);
3585 helixhorne 1950
        }
1951
    }
4639 terminx 1952
    bglEnd();
3585 helixhorne 1953
}
1954
 
4898 terminx 1955
static int32_t polymost_md3draw(md3model_t *m, const tspritetype *tspr)
5 Plagman 1956
{
4639 terminx 1957
    vec3f_t m0, m1, a0;
109 terminx 1958
    md3xyzn_t *v0, *v1;
3585 helixhorne 1959
    int32_t i, surfi;
2937 helixhorne 1960
    float f, g, k0, k1, k2=0, k3=0, mat[16];  // inits: compiler-happy
654 terminx 1961
    GLfloat pc[4];
4488 helixhorne 1962
    int32_t texunits = GL_TEXTURE0_ARB;
3585 helixhorne 1963
 
3587 helixhorne 1964
    const int32_t owner = tspr->owner;
1965
    // PK: XXX: These owner bound checks are redundant because sext is
1966
    // dereferenced unconditionally below anyway.
1967
    const spriteext_t *const sext = ((unsigned)owner < MAXSPRITES+MAXUNIQHUDID) ? &spriteext[owner] : NULL;
1968
    const uint8_t lpal = ((unsigned)owner < MAXSPRITES) ? sprite[tspr->owner].pal : tspr->pal;
4623 terminx 1969
    const int32_t sizyrep = tilesiz[tspr->picnum].y*tspr->yrepeat;
5 Plagman 1970
 
519 Plagman 1971
    if (r_vbos && (m->vbos == NULL))
1972
        mdloadvbos(m);
5 Plagman 1973
 
109 terminx 1974
    //    if ((tspr->cstat&48) == 32) return 0;
5 Plagman 1975
 
2277 helixhorne 1976
    updateanimation((md2model_t *)m, tspr, lpal);
5 Plagman 1977
 
109 terminx 1978
    //create current&next frame's vertex list from whole list
5 Plagman 1979
 
4656 terminx 1980
    f = m->interpol; g = 1.f - f;
294 Plagman 1981
 
4656 terminx 1982
    if (m->interpol < 0.f || m->interpol > 1.f ||
1983
        (unsigned)m->cframe >= (unsigned)m->numframes ||
1984
            (unsigned)m->nframe >= (unsigned)m->numframes)
971 plagman 1985
    {
2338 helixhorne 1986
#ifdef DEBUGGINGAIDS
2251 helixhorne 1987
        OSD_Printf("%s: mdframe oob: c:%d n:%d total:%d interpol:%.02f\n",
1988
                   m->head.nam, m->cframe, m->nframe, m->numframes, m->interpol);
2338 helixhorne 1989
#endif
4639 terminx 1990
 
1991
        m->interpol = fclamp(m->interpol, 0.f, 1.f);
1992
        m->cframe = clamp(m->cframe, 0, m->numframes-1);
1993
        m->nframe = clamp(m->nframe, 0, m->numframes-1);
971 plagman 1994
    }
1995
 
4656 terminx 1996
    m0.z = m0.y = m0.x = g = m->scale * g * (1.f/64.f);
1997
    m1.z = m1.y = m1.x = f = m->scale * f * (1.f/64.f);
5 Plagman 1998
 
4656 terminx 1999
    a0.x = a0.y = 0;
2000
    a0.z = m->zadd * m->scale;
4639 terminx 2001
 
5 Plagman 2002
    // Parkar: Moved up to be able to use k0 for the y-flipping code
1454 terminx 2003
    k0 = (float)tspr->z;
4058 helixhorne 2004
    if ((globalorientation&128) && !((globalorientation&48)==32))
2005
        k0 += (float)(sizyrep<<1);
5 Plagman 2006
 
2007
    // Parkar: Changed to use the same method as centeroriented sprites
109 terminx 2008
    if (globalorientation&8) //y-flipping
2009
    {
2010
        m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
4058 helixhorne 2011
        k0 -= (float)(sizyrep<<2);
5 Plagman 2012
    }
2013
    if (globalorientation&4) { m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y; } //x-flipping
2014
 
2264 hendricks2 2015
    // yoffset differs from zadd in that it does not follow cstat&8 y-flipping
2016
    a0.z += m->yoffset*m->scale;
2017
 
4639 terminx 2018
    f = ((float)tspr->xrepeat) * (1.f/64.f) * m->bscale;
2019
    m0.x *= f; m0.y *= -f;
2020
    m1.x *= f; m1.y *= -f;
2021
    a0.x *= f; a0.y *= -f;
2022
    f = ((float)tspr->yrepeat) * (1.f/64.f) * m->bscale;
5 Plagman 2023
    m0.z *= f; m1.z *= f; a0.z *= f;
2024
 
109 terminx 2025
    // floor aligned
1454 terminx 2026
    k1 = (float)tspr->y;
331 terminx 2027
    if ((globalorientation&48)==32