Forum

Loading a TGA for a Quake model...

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Loading a TGA for a Quake model...

Postby hogsy » Thu Aug 11, 2011 3:24 pm

Hello again, I'm using FitzQuake and would like to know if someone can provide me an example on how to do this. I'd like to basically load and apply a TGA texture to a Quake model. I spent some time doing it myself but I'm obviously doing something wrong :oops:

Edit:
Okay I took a closer look at it and seem to have sorted it although the textures are horribly misaligned.

Image

Edit:
Just to lay things down for people that don't bother reading other posts, the model is from the Daikatana pre-alpha. Currently I'm literally just slapping the texture onto the model as there seems to be a problem with this line:
// emit s/t coords into the commands stream
s = stverts[k].s;
t = stverts[k].t;


For those that want to look into the format itself there's a link here
http://dl.dropbox.com/u/5324043/OpenKatana/dmodel.rar
The header is DKPO, it's version 7 and overall not much different to a Quake model.
Last edited by hogsy on Fri Aug 12, 2011 12:19 pm, edited 1 time in total.
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby revelator » Thu Aug 11, 2011 6:46 pm

someone should put a BIG link to the old quakesrc tutorials ;)

its here somewhere at the top of one of the subforums and it contains a working way to do this (allbeit a bit old now).
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby hogsy » Thu Aug 11, 2011 6:46 pm

I already looked on the QuakeSrc site for a solution.
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby revelator » Thu Aug 11, 2011 6:51 pm

hmm allthough fitzquake should allready have texture loading support ?

dunno havent played a lot with fitz's engine maybe a bug ?
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby hogsy » Thu Aug 11, 2011 6:53 pm

I think this is more down to the model format as I'm trying to get textures working for the "dkpo" models from the Daikatana pre-alpha. The format isn't that much different from Quake's however the textures are loaded differently...
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby revelator » Thu Aug 11, 2011 6:57 pm

baker might have a clue, hees done a load of work on the fitzquake source.

one thing that springs to mind you say you are using tga's ? might be the old bug where tga's get drawn inside out in that case fitz needs to update his code, its been fixed for years.

i doubt fitz function looks anywhere near mine but if it helps to squash the bug heres the tga code with that particular bug fixed.

Code: Select all
/*
=============
TARGA LOADING
=============
*/
#define TGA_MAXCOLORS 16384

/* Definitions for image types. */
#define TGA_Null      0   /* no image data */
#define TGA_Map         1   /* Uncompressed, color-mapped images. */
#define TGA_RGB         2   /* Uncompressed, RGB images. */
#define TGA_Mono      3   /* Uncompressed, black and white images. */
#define TGA_RLEMap      9   /* Runlength encoded color-mapped images. */
#define TGA_RLERGB      10   /* Runlength encoded RGB images. */
#define TGA_RLEMono      11   /* Compressed, black and white images. */
#define TGA_CompMap      32   /* Compressed color-mapped data, using Huffman, Delta, and runlength encoding. */
#define TGA_CompMap4   33   /* Compressed color-mapped data, using Huffman, Delta, and runlength encoding.  4-pass quadtree-type process. */

/* Definitions for interleave flag. */
#define TGA_IL_None      0   /* non-interleaved. */
#define TGA_IL_Two      1   /* two-way (even/odd) interleaving */
#define TGA_IL_Four      2   /* four way interleaving */
#define TGA_IL_Reserved   3   /* reserved */

/* Definitions for origin flag */
#define TGA_O_UPPER      0   /* Origin in lower left-hand corner. */
#define TGA_O_LOWER      1   /* Origin in upper left-hand corner. */

typedef struct _TargaHeader
{
    unsigned char    id_length, colormap_type, image_type;
    unsigned short   colormap_index, colormap_length;
    unsigned char   colormap_size;
    unsigned short   x_origin, y_origin, width, height;
    unsigned char   pixel_size, attributes;
} TargaHeader;

int fgetLittleShort (FILE *f)
{
    byte   b1, b2;

    b1 = fgetc(f);
    b2 = fgetc(f);

    return (short)(b1 + b2*256);
}

int fgetLittleLong (FILE *f)
{
    byte   b1, b2, b3, b4;

    b1 = fgetc(f);
    b2 = fgetc(f);
    b3 = fgetc(f);
    b4 = fgetc(f);

    return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}

/*
=============
LoadTGA
=============
*/
byte *LoadTGA (FILE *fin, char *name)
{
    int         w, h, x, y, realrow, truerow, baserow, i, temp1, temp2, pixel_size, map_idx;
    int         RLE_count, RLE_flag, size, interleave, origin;
    qboolean   mapped, rlencoded;
    byte      *data, *dst, r, g, b, a, j, k, l, *ColorMap;
    TargaHeader   header;

    /* load file */
    if (!fin && COM_FOpenFile(name, &fin)) return NULL;

    header.id_length = fgetc (fin);
    header.colormap_type = fgetc (fin);
    header.image_type = fgetc (fin);

    header.colormap_index = fgetLittleShort (fin);
    header.colormap_length = fgetLittleShort (fin);
    header.colormap_size = fgetc (fin);
    header.x_origin = fgetLittleShort (fin);
    header.y_origin = fgetLittleShort (fin);
    header.width = fgetLittleShort (fin);
    header.height = fgetLittleShort (fin);
    header.pixel_size = fgetc (fin);
    header.attributes = fgetc (fin);

    if (header.id_length != 0)
        fseek (fin, header.id_length, SEEK_CUR);

    /* validate TGA type */
    switch (header.image_type)
    {
    case TGA_Map:
    case TGA_RGB:
    case TGA_Mono:
    case TGA_RLEMap:
    case TGA_RLERGB:
    case TGA_RLEMono:
        break;

    default:
        Con_Printf ("%s : Only type 1 (map), 2 (RGB), 3 (mono), 9 (RLEmap), 10 (RLERGB), 11 (RLEmono) TGA images supported\n", name);
        fclose (fin);
        return NULL;
        break;
    }

    /* validate color depth */
    switch (header.pixel_size)
    {
    case 8:
    case 15:
    case 16:
    case 24:
    case 32:
        break;

    default:
        Con_Printf ("%s : Only 8, 15, 16, 24 or 32 bit images (with colormaps) supported\n", name);
        fclose (fin);
        return NULL;
        break;
    }
    r = g = b = a = l = 0;

    /* if required, read the color map information. */
    ColorMap = NULL;
    mapped = (header.image_type == TGA_Map || header.image_type == TGA_RLEMap) && header.colormap_type == 1;

    if (mapped)
    {
        /* validate colormap size */
        switch (header.colormap_size)
        {
        case 8:
        case 15:
        case 16:
        case 32:
        case 24:
            break;

        default:
            Con_Printf ("%s : Only 8, 15, 16, 24 or 32 bit colormaps supported\n", name);
            fclose (fin);
            return NULL;
            break;
        }
        temp1 = header.colormap_index;
        temp2 = header.colormap_length;

        if ((temp1 + temp2 + 1) >= TGA_MAXCOLORS)
        {
            fclose (fin);
            return NULL;
        }
        ColorMap = malloc (TGA_MAXCOLORS * 4);
        map_idx = 0;

        for (i = temp1 ; i < temp1 + temp2 ; ++i, map_idx += 4)
        {
            /* read appropriate number of bytes, break into rgb & put in map. */
            switch (header.colormap_size)
            {
            case 8:   /* grey scale, read and triplicate. */
                r = g = b = getc (fin);
                a = 255;
                break;

            case 15:   /* 5 bits each of red green and blue. */
                /* watch byte order. */
                j = getc (fin);
                k = getc (fin);
                l = ((unsigned int) k << 8) + j;
                r = (byte) ( ((k & 0x7C) >> 2) << 3 );
                g = (byte) ( (((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3 );
                b = (byte) ( (j & 0x1F) << 3 );
                a = 255;
                break;

            case 16:   /* 5 bits each of red green and blue, 1 alpha bit. */
                /* watch byte order. */
                j = getc (fin);
                k = getc (fin);
                l = ((unsigned int) k << 8) + j;
                r = (byte) ( ((k & 0x7C) >> 2) << 3 );
                g = (byte) ( (((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3 );
                b = (byte) ( (j & 0x1F) << 3 );
                a = (k & 0x80) ? 255 : 0;
                break;

            case 24:   /* 8 bits each of blue, green and red. */
                b = getc (fin);
                g = getc (fin);
                r = getc (fin);
                a = 255;
                l = 0;
                break;

            case 32:   /* 8 bits each of blue, green, red and alpha. */
                b = getc (fin);
                g = getc (fin);
                r = getc (fin);
                a = getc (fin);
                l = 0;
                break;
            }
            ColorMap[map_idx+0] = r;
            ColorMap[map_idx+1] = g;
            ColorMap[map_idx+2] = b;
            ColorMap[map_idx+3] = a;
        }
    }

    /* check run-length encoding. */
    rlencoded = (header.image_type == TGA_RLEMap || header.image_type == TGA_RLERGB || header.image_type == TGA_RLEMono);
    RLE_count = RLE_flag = 0;

    image_width = w = header.width;
    image_height = h = header.height;

    size = w * h * 4;
    data = calloc (size, 1);

    /* read the Targa file body and convert to portable format. */
    pixel_size = header.pixel_size;
    origin = (header.attributes & 0x20) >> 5;
    interleave = (header.attributes & 0xC0) >> 6;
    truerow = 0;
    baserow = 0;

    for (y=0 ; y<h ; y++)
    {
        realrow = truerow;

        if (origin == TGA_O_UPPER)
        {
            realrow = h - realrow - 1;
        }
        dst = data + realrow * w * 4;

        for (x=0 ; x<w ; x++)
        {
            /* check if run length encoded. */
            if (rlencoded)
            {
                if (!RLE_count)
                {
                    /* have to restart run. */
                    i = getc (fin);

                    RLE_flag = (i & 0x80);

                    if (!RLE_flag)   // stream of unencoded pixels
                    {
                        RLE_count = i + 1;
                    }
                    else      // single pixel replicated
                    {
                        RLE_count = i - 127;
                    }

                    /* decrement count & get pixel. */
                    --RLE_count;
                }
                else
                {
                    /* have already read count & (at least) first pixel. */
                    --RLE_count;

                    if (RLE_flag)
                    {
                        /* replicated pixels. */
                        goto PixEncode;
                    }
                }
            }

            /* read appropriate number of bytes, break into RGB. */
            switch (pixel_size)
            {
            case 8:   /* grey scale, read and triplicate. */
                r = g = b = l = getc (fin);
                a = 255;
                break;

            case 15: /* 5 bits each of red green and blue. */
                /* watch byte order. */
                j = getc (fin);
                k = getc (fin);
                l = ((unsigned int) k << 8) + j;
                r = (byte) ( ((k & 0x7C) >> 2) << 3 );
                g = (byte) ( (((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3 );
                b = (byte) ( (j & 0x1F) << 3 );
                a = 255;
                break;

            case 16: /* 5 bits each of red green and blue, 1 alpha bit. */
                /* watch byte order. */
                j = getc (fin);
                k = getc (fin);
                l = ((unsigned int) k << 8) + j;
                r = (byte) ( ((k & 0x7C) >> 2) << 3 );
                g = (byte) ( (((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3 );
                b = (byte) ( (j & 0x1F) << 3 );
                a = (k & 0x80) ? 255 : 0;
                break;

            case 24: /* 8 bits each of blue, green and red. */
                b = getc (fin);
                g = getc (fin);
                r = getc (fin);
                a = 255;
                l = 0;
                break;

            case 32: /* 8 bits each of blue, green, red and alpha. */
                b = getc (fin);
                g = getc (fin);
                r = getc (fin);
                a = getc (fin);
                l = 0;
                break;

            default:
                fclose (fin);
                Con_Printf ("%s : Illegal pixel_size '%d'\n", name, pixel_size);
                if (data)
                {
                    free (data);
                }

                if (mapped)
                {
                    free (ColorMap);
                }
                return NULL;
                break;
            }

PixEncode:
            if (mapped)
            {
                map_idx = l * 4;
                *dst++ = ColorMap[map_idx+0];
                *dst++ = ColorMap[map_idx+1];
                *dst++ = ColorMap[map_idx+2];
                *dst++ = ColorMap[map_idx+3];
            }
            else
            {
                *dst++ = r;
                *dst++ = g;
                *dst++ = b;
                *dst++ = a;
            }
        }

        if (interleave == TGA_IL_Four)
        {
            truerow += 4;
        }
        else if (interleave == TGA_IL_Two)
        {
            truerow += 2;
        }
        else
        {
            truerow++;
        }

        if (truerow >= h)
        {
            truerow = ++baserow;
        }
    }

    if (mapped)
    {
        free (ColorMap);
    }
    fclose (fin);

    return data;
}
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby hogsy » Thu Aug 11, 2011 6:58 pm

Worth a try I guess.
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby revelator » Thu Aug 11, 2011 7:01 pm

ah ok. yeah might be that but lets see what people suggests could be the reason :).
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby hogsy » Thu Aug 11, 2011 7:06 pm

I've uploaded a copy of the model and a TGA version of its texture here: http://dl.dropbox.com/u/5324043/OpenKatana/dmodel.rar
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby metlslime » Thu Aug 11, 2011 7:15 pm

Actually this feature doesn't exist yet... not sure how you got it working :?
metlslime
 
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Postby hogsy » Thu Aug 11, 2011 7:16 pm

Yes it does.
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby metlslime » Thu Aug 11, 2011 7:18 pm

Also, fitzquake already fixed the upside-down tga bug.

One guess is, if you're working with a modified fitzquake with this feature added, there may be UV mapping issues due to the way fitzquake deals with non-power-of-two images. The UVs were probably generated with the original 8-bit texture in mind; if the replacement texture isn't the same size as the original (or a power of two multiple of the original size) the modded fitzquake might not be smart enough to fix the UVs for that case.
metlslime
 
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Postby hogsy » Thu Aug 11, 2011 7:24 pm

Sorry, I had assumed you meant TGA support. This is a feature I'm working on implementing myself (which I thought was quite obvious from my first post :roll: ). The texture scale for all "dkpo" models is 640x480.
There is no original texture stored in the models as the textures are required to be loaded externally for this model format.
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Postby revelator » Thu Aug 11, 2011 7:54 pm

hmm not sure its gonna work without some modification then since quakes texture manager rescales sizes according to the models builtin texture mip's (which in this case wont work).

would probably need something like a shader i reckon ?.

one place to look could be quake2 it does things a little different than quake since its models also rely on external data.
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby hogsy » Thu Aug 11, 2011 7:55 pm

Yeah I've been looking at Quake 2 quite a bit. I'll tell you if I manage to get anywhere.
User avatar
hogsy
 
Posts: 198
Joined: Wed Aug 03, 2011 3:44 pm
Location: UK

Next

Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 1 guest