Subversion Repositories eduke32

Rev

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