[Gtkradiant] ECLASS.CPP: LoadModel() can now load RtCW .mdc files

TiCaL gtkradiant@zerowing.idsoftware.com
Wed, 20 Mar 2002 16:50:48 +0800


This is a multi-part message in MIME format.

------=_NextPart_000_0013_01C1D02F.631A68C0
Content-Type: multipart/alternative;
	boundary="----=_NextPart_001_0014_01C1D02F.631A68C0"


------=_NextPart_001_0014_01C1D02F.631A68C0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Hello,
I've just modified the LoadModel function to load .mdc as well as the =
.md3 model file format. It compiles fine but haven't had a chance to =
test it yet. Find the new ECLASS.cpp with the new version of LoadModel =
function and qfiles.h (MDC File specs) attached. I'm new to GtkRadiant =
programming so if I'm doing something wrong let me know :)

Regards,
TiCaL

------=_NextPart_001_0014_01C1D02F.631A68C0
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2713.1100" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#fffcf0>
<DIV><FONT face=3DArial size=3D2>Hello,</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>I've just modified the LoadModel =
function to load=20
.mdc as well as the .md3&nbsp;model file format. It compiles fine but =
haven't=20
had a chance to test it yet. Find the new ECLASS.cpp with the new =
version of=20
LoadModel function and qfiles.h (MDC File specs) attached. I'm new to =
GtkRadiant=20
programming so if I'm doing something wrong let me know :)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Regards,</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>TiCaL</FONT></DIV></BODY></HTML>

------=_NextPart_001_0014_01C1D02F.631A68C0--

------=_NextPart_000_0013_01C1D02F.631A68C0
Content-Type: application/octet-stream;
	name="ECLASS.cpp"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ECLASS.cpp"

/*
This code is based on source provided under the terms of the Id Software =

LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with =
the
GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of=20
LICENSE_ID, please contact Id Software immediately at =
info@idsoftware.com.

All changes and additions to the original source which have been =
developed by
other contributors (see CONTRIBUTORS) are provided under the terms of =
the
license the contributors choose (see LICENSE), to the extent permitted =
by the
LICENSE_ID. If you did not receive a copy of the contributor license,
please contact the GtkRadiant maintainers at info@gtkradiant.com =
immediately.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS =
IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR =
ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL =
DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR =
SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED =
AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF =
THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "stdafx.h"
#include <sys/stat.h>
#if defined (__linux__) || defined (__APPLE__)
#include <dirent.h>
#endif
#include "assert.h"

eclass_t	*eclass =3D NULL;
eclass_t	*eclass_bad =3D NULL;
const vec3_t smallbox[2] =3D {{-8,-8,-8},{8,8,8}};
char		eclass_directory[1024];

qboolean parsing_single =3D false;
eclass_t *eclass_e;

/*!
implementation of the EClass manager API
*/
eclass_t** Get_EClass_E()
{
  return &eclass_e;
}

void Set_Eclass_Found(qboolean b)
{
  eclass_found =3D b;
}

qboolean Get_Parsing_Single()
{
  return parsing_single;
}


// md3 cache for misc_models
//eclass_t *g_md3Cache =3D NULL;

/*

the classname, color triple, and bounding box are parsed out of comments
A ? size means take the exact brush size.

/ *QUAKED <classname> (0 0 0) ?
/ *QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)

Flag names can follow the size description:

/ *QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK =
GOLD_KEY SILVER_KEY

*/

void CleanEntityList(eclass_t *&pList)
{
  while (pList)
  {
    eclass_t* pTemp =3D pList->next;

    entitymodel *model =3D pList->model;
    while (model !=3D NULL)
    {
      delete []model->pTriList;
      if (model->strSkin)
        g_string_free( (GString *)model->strSkin, TRUE );
      model->strSkin =3D NULL;
      model =3D model->pNext;
    }
   =20
    if (pList->modelpath)
      free(pList->modelpath);
	  if (pList->skinpath)			// PGM
		  free(pList->skinpath);		// PGM
   =20
    free(pList->name);
    free(pList->comments);
    free(pList);
    pList =3D pTemp;
  }

  pList =3D NULL;

}


void CleanUpEntities()
{
  // NOTE: maybe some leak checks needed .. older versions of Radiant =
looked like they were freezing more stuff
  CleanEntityList(eclass);
  //CleanEntityList(g_md3Cache);
  if (eclass_bad)
  {
    free(eclass_bad->name);
    free(eclass_bad->comments);
    free(eclass_bad);
    eclass_bad =3D NULL;
  }
}

void ExtendBounds(vec3_t v, vec3_t &vMin, vec3_t &vMax)
{
	for (int i =3D 0 ;i < 3 ;i++)
	{
		vec_t f =3D v[i];
	=09
    if (f < vMin[i])
    {
			vMin[i] =3D f;
    }

    if (f > vMax[i])
    {
			vMax[i] =3D f;
    }
	}
}

void DecodeNormal(byte bytes[2], float normal[3])
{
  //if (!bytes) return;
  float lat, lng;
  int a, b;
  b =3D (int)bytes[0];
  a =3D (int)bytes[1];

  // decode the lat/lng normal to a 3 float normal
	lat =3D (float)a * Q_PI/128.0f;
	lng =3D (float)b * Q_PI/128.0f;

	normal[0] =3D cos(lat) * sin(lng);
	normal[1] =3D sin(lat) * sin(lng);
	normal[2] =3D cos(lng);
}

// Take a pointer to a file location, a pointer to  an eclass, an AABB, =
a pointer to an entitymodel
// Open the file using VFS
// Read each surface into an entitymodel and add the entitymodel to the =
front of a list
// return a pointer to the first model in the list
// TTimo: removed old support for .md2 and .ase
// NOTE: pSkin is no longer used, does nothing
// we expect the relative path to the .md3 file
// TiCaL: 20/03/2002 : added .mdc file support
entitymodel *LoadModel(const char *pLocation, eclass_t *e, vec3_t &vMin, =
vec3_t &vMax, entitymodel *pModel)
{
    int i, j;
    int nTris, nVerts;
    int modeltype; /* TiCaL: MD3||MDC */
    entitymodel *newModel;
   =20
    md3Triangle_t *pTris;=20
    md3XyzNormal_t *pXyz;=20
    md3St_t *pST;=20
   =20
    /* TiCaL: mdc file structs */
    /* look at qfiles.h for MDC File specs */
    mdcTriangle_t *pcTris;=20
    mdcXyzNormal_t *pcXyz;
    mdcSt_t *pcST;
   =20
    vMin[0] =3D vMin[1] =3D vMin[2] =3D g_MaxWorldCoord+1;
    vMax[0] =3D vMax[1] =3D vMax[2] =3D g_MinWorldCoord-1;
   =20
    /* TiCaL: Find out what we are dealing with */
    if (strstr(pLocation, ".md3"))
    {
        modeltype =3D MD3;
    }
    else if(strstr(pLocation, ".mdc"))
    {
        modeltype =3D MDC;
    }
    else
    {
        Sys_Printf("ERROR: unknown model type: %s\n", pLocation );
        return pModel;
    }
   =20
    unsigned char* p =3D NULL;
    bool bOpen;
    bOpen =3D (vfsLoadFile(pLocation, reinterpret_cast<void**>(&p)) > =
0);
    if (bOpen)
        Sys_Printf("Loaded model: %s\n", pLocation);
   =20
    if (bOpen)
    {
       =20
        //TiCaL: If its a MD3 file do this
        if(modeltype=3D=3DMD3)
        {
            md3Header_t header =3D *(md3Header_t *)p;
           =20
            // check for IDP3
            int ident =3D LittleLong(header.ident);
            if (ident !=3D MD3_IDENT)
            {
                Sys_Printf( "LoadModel: %s has wrong ident (%i should be =
%i)\n",
                    pLocation, ident, MD3_IDENT);
                return pModel;
            }
           =20
            md3Surface_t *pSurface =3D (md3Surface_t *) (p + =
header.ofsSurfaces);
           =20
            for (int z =3D 0; z < header.numSurfaces; z++ )
            {
                nTris =3D pSurface->numTriangles;
                nVerts =3D pSurface->numVerts;
                newModel =3D =
reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
                newModel->pNext =3D pModel;
                pModel =3D newModel;
               =20
                if (nTris > 0)
                {
                    pModel->nModelPosition =3D 0;
                    pModel->pTriList =3D new triindex[nTris];
                    pModel->pVertList =3D new vertmodel[nVerts];
                    //pModel->pVertListTF =3D new vertmodel[nVerts];
                    pModel->nTriCount =3D nTris;
                    pModel->numVerts =3D nVerts;
                   =20
                    pTris =3D =
reinterpret_cast<md3Triangle_t*>((reinterpret_cast<unsigned =
char*>(pSurface) + pSurface->ofsTriangles));
                    pXyz =3D =
reinterpret_cast<md3XyzNormal_t*>((reinterpret_cast<unsigned =
char*>(pSurface) + pSurface->ofsXyzNormals));
                    pST =3D =
reinterpret_cast<md3St_t*>((reinterpret_cast<unsigned char*>(pSurface) + =
pSurface->ofsSt));=20
                   =20
                    // not used?
                    if (e->nFrame < pSurface->numFrames)
                    {
                        pXyz +=3D (e->nFrame * pSurface->numVerts);
                    }
                   =20
                    // read verts into vertex list - xyz, st, normal
                    for (i =3D 0; i < nVerts; i++)
                    {
                        for (j =3D 0; j < 3; j++)
                        {
                            pModel->pVertList[i].v[j] =3D pXyz[i].xyz[j] =
* MD3_XYZ_SCALE;
                        }
                        ExtendBounds (pModel->pVertList[i].v, vMin, =
vMax);
                        pModel->pVertList[i].st[0] =3D pST[i].st[0];
                        pModel->pVertList[i].st[1] =3D pST[i].st[1];
                        DecodeNormal((byte *)&pXyz[i].normal, =
pModel->pVertList[i].normal);
                    }
                   =20
                    // copy md3 triangle index list to internal triangle =
index list - both types are struct { int indexes[3] };
                    memcpy(pModel->pTriList, pTris, =
(sizeof(md3Triangle_t) * nTris));
                }
               =20
               =20
                md3Shader_t *pShader =3D =
reinterpret_cast<md3Shader_t*>((reinterpret_cast<unsigned =
char*>(pSurface) + pSurface->ofsShaders));=20
                pModel->nTextureBind =3D Texture_LoadSkin(pShader->name, =
&pModel->nSkinWidth, &pModel->nSkinHeight);
                // we store the shader name, we need to reload it in =
sleep mode
                pModel->strSkin =3D g_string_new(NULL);
                g_string_assign( (GString *)pModel->strSkin, =
pShader->name );
                if (pModel->nTextureBind =3D=3D -1)
                {
                    Sys_Printf("Model skin load failed on texture %s\n", =
pShader->name);
                }
               =20
                // increment pSurface
                pSurface =3D (md3Surface_t *) ((( char * ) pSurface) + =
pSurface->ofsEnd);
            }
            vfsFreeFile(p);
        }
        //TiCaL : if its a MDC file do this
        else if(modeltype=3D=3DMDC)
        {
            mdcHeader_t header =3D *(mdcHeader_t *)p;
           =20
            // check for IDPC
            int ident =3D LittleLong(header.ident);
            if (ident !=3D MDC_IDENT)
            {
                Sys_Printf( "LoadModel: %s has wrong ident (%i should be =
%i)\n",
                    pLocation, ident, MDC_IDENT);
                return pModel;
            }
           =20
            mdcSurface_t *pcSurface =3D (mdcSurface_t *) (p + =
header.ofsSurfaces);
           =20
            for (int z =3D 0; z < header.numSurfaces; z++ )
            {
                nTris =3D pcSurface->numTriangles;
                nVerts =3D pcSurface->numVerts;
                newModel =3D =
reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
                newModel->pNext =3D pModel;
                pModel =3D newModel;
               =20
                if (nTris > 0)
                {
                    pModel->nModelPosition =3D 0;
                    pModel->pTriList =3D new triindex[nTris];
                    pModel->pVertList =3D new vertmodel[nVerts];
                    pModel->nTriCount =3D nTris;
                    pModel->numVerts =3D nVerts;
                   =20
                    pcTris =3D =
reinterpret_cast<mdcTriangle_t*>((reinterpret_cast<unsigned =
char*>(pcSurface) + pcSurface->ofsTriangles));
                    pcXyz =3D =
reinterpret_cast<mdcXyzNormal_t*>((reinterpret_cast<unsigned =
char*>(pcSurface) + pcSurface->ofsXyzNormals));
                    pcST =3D =
reinterpret_cast<mdcSt_t*>((reinterpret_cast<unsigned char*>(pcSurface) =
+ pcSurface->ofsSt));=20
                   =20
                    // not used?
                    if (e->nFrame < =
pcSurface->numBaseFrames+pcSurface->numCompFrames)
                    {
                        pcXyz +=3D (e->nFrame * pcSurface->numVerts);
                    }
                   =20
                    // read verts into vertex list - xyz, st, normal
                    for (i =3D 0; i < nVerts; i++)
                    {
                        for (j =3D 0; j < 3; j++)
                        {
                            pModel->pVertList[i].v[j] =3D =
pcXyz[i].xyz[j] * MDC_XYZ_SCALE;
                        }
                        ExtendBounds (pModel->pVertList[i].v, vMin, =
vMax);
                        pModel->pVertList[i].st[0] =3D pcST[i].st[0];
                        pModel->pVertList[i].st[1] =3D pcST[i].st[1];
                        DecodeNormal((byte *)&pcXyz[i].normal, =
pModel->pVertList[i].normal);
                    }
                   =20
                    // copy mdc triangle index list to internal triangle =
index list - both types are struct { int indexes[3] };
                    memcpy(pModel->pTriList, pcTris, =
(sizeof(mdcTriangle_t) * nTris));
                }
               =20
               =20
                mdcShader_t *pcShader =3D =
reinterpret_cast<mdcShader_t*>((reinterpret_cast<unsigned =
char*>(pcSurface) + pcSurface->ofsShaders));=20
                pModel->nTextureBind =3D =
Texture_LoadSkin(pcShader->name, &pModel->nSkinWidth, =
&pModel->nSkinHeight);
                // we store the shader name, we need to reload it in =
sleep mode
                pModel->strSkin =3D g_string_new(NULL);
                g_string_assign( (GString *)pModel->strSkin, =
pcShader->name );
                if (pModel->nTextureBind =3D=3D -1)
                {
                    Sys_Printf("Model skin load failed on texture %s\n", =
pcShader->name);
                }
               =20
                // increment pSurface
                pcSurface =3D (mdcSurface_t *) ((( char * ) pcSurface) + =
pcSurface->ofsEnd);
            }
            vfsFreeFile(p);
        }
   }
   //else model not found
   else
   {
       Sys_Printf("NOT FOUND: %s\n", pLocation);
   }
   return pModel;
}


// check if this eclass has a model, and load it if necessary
qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax)
{
  int i;
  entitymodel *pModel;
  char *pModelBuff, *pToken;

  if (e->modelpath !=3D NULL) // an eclass has a valid modelpath only =
until the model is loaded
  {
    pModelBuff =3D strdup(e->modelpath);

    GSList *Models =3D NULL, /* *Skins =3D NULL,*/ *lst;
    pToken =3D strtok(pModelBuff, ";\0"); // reads model paths separated =
by ';' into a list
    while (pToken !=3D NULL)
    {
      Models =3D g_slist_append (Models, strdup (pToken));
      pToken =3D strtok(NULL, ";\0");
    }
   =20
#ifdef _DEBUG
    if (e->model)
      Sys_Printf("WARNING: unexpected e->model !=3D NULL in =
EClass_hasModel\n");
#endif
    // for each md3 specified in modelpath
    // result is one large entitymodel linked list, containing multiple =
md3surfaces from one or more md3s
    //e->model =3D =
reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
    //entitymodel *model =3D e->model;
    pModel =3D NULL;
    for (i =3D 0, lst =3D Models; lst !=3D NULL; lst =3D g_slist_next =
(lst))
    {
      pModel =3D LoadModel((char*)lst->data, e, vMin, vMax, pModel);=20
    }
    e->model =3D pModel;

    for (lst =3D Models; lst !=3D NULL; lst =3D g_slist_next (lst))
      free (lst->data);
    g_slist_free (Models);

    // at this poitn vMin and vMax contain the min max of the model
    // which needs to be centered at origin 0, 0, 0

    VectorSnap(vMin);
    VectorSnap(vMax);

    if (vMax[0] - vMin[0] < 2)
    {
      vMin[0] -=3D 1;
      vMax[0] +=3D 1;
    }

    if (vMin[1] - vMax[1] < 2)
    {
      vMin[1] -=3D 1;
      vMax[1] +=3D 1;
    }

    if (vMax[2] - vMin[2] < 2)
    {
      vMax[2] -=3D 1;
      vMax[2] +=3D 1;
    }

    free(pModelBuff);
    free(e->modelpath);
    e->modelpath =3D NULL;	 =20

  }
  return (e->model !=3D NULL && e->model->nTriCount > 0);
}


void EClass_InsertSortedList(eclass_t *&pList, eclass_t *e)
{
	eclass_t	*s;
=09
	if (!pList)
	{
		pList =3D e;
		return;
	}


	s =3D pList;
	if (stricmp (e->name, s->name) < 0)
	{
		e->next =3D s;
		pList =3D e;
		return;
	}

	do
	{
		if (!s->next || stricmp (e->name, s->next->name) < 0)
		{
			e->next =3D s->next;
			s->next =3D e;
			return;
		}
		s=3Ds->next;
	} while (1);
}

/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Eclass_InsertAlphabetized
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
*/
void Eclass_InsertAlphabetized (eclass_t *e)
{
#if 1
  EClass_InsertSortedList(eclass, e);
#else
	eclass_t	*s;
=09
	if (!eclass)
	{
		eclass =3D e;
		return;
	}


	s =3D eclass;
	if (stricmp (e->name, s->name) < 0)
	{
		e->next =3D s;
		eclass =3D e;
		return;
	}

	do
	{
		if (!s->next || stricmp (e->name, s->next->name) < 0)
		{
			e->next =3D s->next;
			s->next =3D e;
			return;
		}
		s=3Ds->next;
	} while (1);
#endif
}

void EClass_InitForFileList(GSList *pFiles, _EClassTable *pTable)
{
  GSList *pFile =3D pFiles;
  while (pFile)
  {
    // for a given name, we grab the first .def in the vfs
    // this allows to override baseq3/scripts/entities.def for instance
    int count;
    char relPath[PATH_MAX];
    strcpy(relPath, "scripts/");
    strcat(relPath, (char*)pFile->data);
    // FIXME TTimo =
http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=3D130
    if (!vfsGetFullPath(relPath, 0))
    {
      Sys_FPrintf(SYS_ERR, "Failed to find the full path for \"%s\" in =
the VFS\n", relPath);
      Sys_FPrintf(SYS_ERR, "did you hit bug =
http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=3D130 ?\n");
    }
    else
      pTable->m_pfnEClass_ScanFile(vfsGetFullPath(relPath, 0));
    pFile =3D pFile->next;
  }
}

/*!
Manually create an eclass_t, for when no modules exist.
this replaces and centralizes the eclass_t allocation
*/
eclass_t * EClass_Create( const char *name, float col1, float col2, =
float col3, const vec3_t *mins, const vec3_t *maxs, const char *comments =
)
{
  eclass_t *e;
	char	color[128];

  e =3D (eclass_t*)malloc(sizeof(*e));
	memset (e, 0, sizeof(*e));

  e->name =3D strdup(name);

  // grab the color, reformat as texture name
	e->color[0] =3D col1;
  e->color[1] =3D col2;
  e->color[2] =3D col3;
	sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
	e->texdef.SetName(color);

  // supplied size ?
  if (mins && maxs)
  {
    // Hydra:
    // If we set worldspawn to be a fixed-size all the textures are
    // displayed as flat-shaded.  This is a KLUDGE now that we have
    // multiple game support as the worldspawn entity is game specific.
    // Note that this is only ever fixed for the user if a definition
    // for the worldspawn entity was not loaded, this can happen for
    // several reasons:
    // a) no entity definition plugin exists
    // b) no entity definition files were found
    // c) no entity definition file contained an entry for worldspawn.

    if (stricmp(name,"worldspawn") !=3D 0) e->fixedsize =3D true;

    // copy the sizes..
    memcpy(e->mins,mins,sizeof(vec3_t));
    memcpy(e->maxs,maxs,sizeof(vec3_t));
  }

  if (comments)
    e->comments =3D strdup(comments);
  else
  {
    e->comments =3D (char*)malloc(1);
    e->comments[0] =3D '\0';
  }

  return e;
}

void Eclass_Init ()
{
  CleanUpEntities();
  eclass =3D NULL;
  GSList *pFiles;
  // read optional format
  if (g_bHaveEClassExt)
  {
    pFiles =3D =
vfsGetFileList("scripts",g_EClassExtTable.m_pfnGet_Extension());
    if (pFiles)
    {
      EClass_InitForFileList(pFiles, &g_EClassDefTable);
      vfsClearFileDirList(&pFiles);
      pFiles =3D NULL;
    }   =20
  }
  // read in all scripts/*.def
  pFiles =3D =
vfsGetFileList("scripts",g_EClassDefTable.m_pfnGet_Extension());
  if (pFiles)
  {
    EClass_InitForFileList(pFiles, &g_EClassDefTable);
    vfsClearFileDirList(&pFiles);
    pFiles =3D NULL;
  }
  else
    Sys_FPrintf(SYS_ERR, "Didn't find any scripts/*.def files to load =
EClass information\n");

  //NOTE: this call assumes the .def plugin is loaded, if it's not we =
get a crash when a brush is created/loaded
  //To fix this issue replace this call with a function that manually =
builds an eclass_t.
  //e.g. EClass_Create()
  //eclass_bad =3D EClass_InitFromText("def","/*QUAKED UNKNOWN_CLASS (0 =
0.5 0) ?");

  // Using EClass_Create()
  eclass_bad =3D EClass_Create("UNKNOWN_CLASS" , 0, 0.5, =
0,NULL,NULL,NULL);
}

eclass_t *Eclass_ForName (char *name, qboolean has_brushes)
{
	eclass_t	*e;
	char		init[1024];

  if (!name || *name =3D=3D '\0')
    return eclass_bad;

#ifdef _DEBUG
  // grouping stuff, not an eclass
  if (strcmp(name, "group_info")=3D=3D0)
    Sys_Printf("WARNING: unexpected group_info entity in =
Eclass_ForName\n");
#endif

	if (!name)
		return eclass_bad;

	for (e=3Declass ; e ; e=3De->next)
		if (!strcmp (name, e->name))
			return e;

	// create a new class for it
	if (has_brushes)
	{
    // Using EClass_Create
		// sprintf (init, "/*QUAKED %s (0 0.5 0) ?\nNot found in source.\n", =
name);
    // e =3D EClass_InitFromText("def",init);
    e =3D EClass_Create(name , 0, 0.5, 0,NULL,NULL,"Not found in =
source.");
	}
	else
	{
    // Using EClass_Create
		// sprintf (init, "/*QUAKED %s (0 0.5 0) (-8 -8 -8) (8 8 8)\nNot found =
in source.\n", name);
    // e =3D EClass_InitFromText("def",init);
    e =3D EClass_Create(name , 0, 0.5, 0,&smallbox[0],&smallbox[1],"Not =
found in source.");
	}

	Eclass_InsertAlphabetized (e);

	return e;
}


------=_NextPart_000_0013_01C1D02F.631A68C0
Content-Type: application/octet-stream;
	name="qfiles.h"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="qfiles.h"

/*
This code is based on source provided under the terms of the Id Software =

LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with =
the
GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of=20
LICENSE_ID, please contact Id Software immediately at =
info@idsoftware.com.

All changes and additions to the original source which have been =
developed by
other contributors (see CONTRIBUTORS) are provided under the terms of =
the
license the contributors choose (see LICENSE), to the extent permitted =
by the
LICENSE_ID. If you did not receive a copy of the contributor license,
please contact the GtkRadiant maintainers at info@gtkradiant.com =
immediately.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS =
IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR =
ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL =
DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR =
SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED =
AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF =
THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//

/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

.MD2 triangle model file format

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
*/

#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
#define ALIAS_VERSION	8

#define	MAX_TRIANGLES	4096
#define MAX_VERTS		2048
#define MAX_FRAMES		512
#define MAX_MD2SKINS	32
#define	MAX_SKINNAME	64

typedef struct
{
	short	s;
	short	t;
} dstvert_t;

typedef struct=20
{
	short	index_xyz[3];
	short	index_st[3];
} dtriangle_t;

typedef struct
{
	byte	v[3];			// scaled byte to fit in frame mins/maxs
	byte	lightnormalindex;
} dtrivertx_t;

typedef struct
{
	float		scale[3];	// multiply byte verts by this
	float		translate[3];	// then add this
	char		name[16];	// frame name from grabbing
	dtrivertx_t	verts[1];	// variable sized
} daliasframe_t;


// the glcmd format:
// a positive integer starts a tristrip command, followed by that many
// vertex structures.
// a negative integer starts a trifan command, followed by -x vertexes
// a zero indicates the end of the command list.
// a vertex consists of a floating point s, a floating point t,
// and an integer vertex index.


typedef struct
{
	int			ident;
	int			version;

	int			skinwidth;
	int			skinheight;
	int			framesize;		// byte size of each frame

	int			num_skins;
	int			num_xyz;
	int			num_st;			// greater than num_xyz for seams
	int			num_tris;
	int			num_glcmds;		// dwords in strip/fan command list
	int			num_frames;

	int			ofs_skins;		// each skin is a MAX_SKINNAME string
	int			ofs_st;			// byte offset from start for stverts
	int			ofs_tris;		// offset for dtriangles
	int			ofs_frames;		// offset for first frame
	int			ofs_glcmds;=09
	int			ofs_end;		// end of file

} dmdl_t;


/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

.MD3 triangle model file format

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
*/
#define MD3_IDENT			(('3'<<24)+('P'<<16)+('D'<<8)+'I')
#define	MAX_QPATH			64		// max length of a quake game pathname
#define	MD3_XYZ_SCALE		(1.0/64)
#define MD3 0

typedef struct {
	int			ident;
	int			version;

	char		name[MAX_QPATH];	// model name

	int			flags;

	int			numFrames;
	int			numTags;		=09
	int			numSurfaces;

	int			numSkins;

	int			ofsFrames;			// offset for first frame
	int			ofsTags;			// numFrames * numTags
	int			ofsSurfaces;		// first surface, others follow

	int			ofsEnd;				// end of file
} md3Header_t;

typedef struct {
	int		ident;				//=20

	char	name[MAX_QPATH];	// polyset name

	int		flags;
	int		numFrames;			// all surfaces in a model should have the same

	int		numShaders;			// all surfaces in a model should have the same
	int		numVerts;

	int		numTriangles;
	int		ofsTriangles;

	int		ofsShaders;			// offset from start of md3Surface_t
	int		ofsSt;				// texture coords are common for all frames
	int		ofsXyzNormals;		// numVerts * numFrames

	int		ofsEnd;				// next surface follows

} md3Surface_t;

typedef struct {
	char			name[MAX_QPATH];
	int				shaderIndex;	// for in-game use
} md3Shader_t;

typedef struct {
	int			indexes[3];
} md3Triangle_t;

typedef struct {
	float		st[2];
} md3St_t;

typedef struct {
	short		xyz[3];
	short		normal;
} md3XyzNormal_t;


typedef struct
{
  float st[2];
  int   nVertIndex;
} glst_t;

typedef struct
{
  int     nCount;
  int     ObjectIndex;
  glst_t  GlSt;
} gl_t;

/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

  .MDC triangle model file format
 =20
    =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
*/
#define MDC_IDENT			(('C'<<24)+('P'<<16)+('D'<<8)+'I')
#define	MDC_XYZ_SCALE		(1.0/64)
#define MDC 1

typedef struct {
    int			ident;
    int			version;
   =20
    char		name[MAX_QPATH];	// model name
   =20
    int			flags;
   =20
    int			numFrames;
    int			numTags;		=09
    int			numSurfaces;
   =20
    int			numSkins;
   =20
    int			ofsFrames;			// offset for first frame
    int			ofsTagNames;		// tag names in a separate list
    int			ofsTags;			// numFrames * numTags
    int			ofsSurfaces;		// first surface, others follow
   =20
    int			ofsEnd;				// end of file
} mdcHeader_t;

typedef struct {
    int		ident;				//=20
   =20
    char	name[MAX_QPATH];	// polyset name
   =20
    int		flags;
    int		numCompFrames;		// number of compressed frames
    int		numBaseFrames;		// number of base (uncompressed) frames
   =20
    int		numShaders;			// all surfaces in a model should have the same
    int		numVerts;
   =20
    int		numTriangles;
    int		ofsTriangles;
   =20
    int		ofsShaders;			// offset from start of md3Surface_t
    int		ofsSt;				// texture coords are common for all frames
    int		ofsXyzNormals;		// numVerts * numFrames
    int		ofsCompXyzNormals;  // compressed verts
   =20
    int		ofsFrameBaseFrames; // animation frames (uncompressed)
    int		ofsFrameCompFrames; // animation frames (compressed)
   =20
    int		ofsEnd;				// next surface follows
   =20
} mdcSurface_t;

typedef struct {
    char			name[MAX_QPATH];
    int				shaderIndex;	// for in-game use
} mdcShader_t;

typedef struct {
    int			indexes[3];
} mdcTriangle_t;

typedef struct {
    float		st[2];
} mdcSt_t;

typedef struct {
    short		xyz[3];
    short		normal;
} mdcXyzNormal_t;

typedef struct {
    float bboxMins[3];    //xyz
    float bboxMaxs[3];	  //xyz
    float localOrigin[3]; //xyz
    float radius;
    char name[16];        // often creator
} mdcFrame_t;
/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

.SP2 sprite file format

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
*/

#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
		// little-endian "IDS2"
#define SPRITE_VERSION	2

typedef struct
{
	int		width, height;
	int		origin_x, origin_y;		// raster coordinates inside pic
	char	name[MAX_SKINNAME];		// name of pcx file
} dsprframe_t;

typedef struct {
	int			ident;
	int			version;
	int			numframes;
	dsprframe_t	frames[1];			// variable sized
} dsprite_t;

/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D

  .WAL texture file format

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
*/


#define	MIPLEVELS	4
#ifndef __MIPTEX_S_
#define __MIPTEX_S_
typedef struct miptex_s
{
	char		name[32];
	unsigned	width, height;
	unsigned	offsets[MIPLEVELS];		// four mip maps stored
	char		animname[32];			// next frame in animation chain
	int			flags;
	int			contents;
	int			value;
} miptex_t;
#endif


/*
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D

  .BSP file format

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
*/

#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
		// little-endian "IBSP"

#define BSPVERSION	36


// upper design bounds
// leaffaces, leafbrushes, planes, and verts are still bounded by
// 16 bit short limits
#define	MAX_MAP_MODELS		1024
#define	MAX_MAP_BRUSHES		8192
#define	MAX_MAP_ENTITIES	2048
#define	MAX_MAP_ENTSTRING	0x20000
#define	MAX_MAP_TEXINFO		8192

#define	MAX_MAP_PLANES		65536
#define	MAX_MAP_NODES		65536
#define	MAX_MAP_BRUSHSIDES	65536
#define	MAX_MAP_LEAFS		65536
#define	MAX_MAP_VERTS		65536
#define	MAX_MAP_FACES		65536
#define	MAX_MAP_LEAFFACES	65536
#define	MAX_MAP_LEAFBRUSHES 65536
#define	MAX_MAP_PORTALS		65536
#define	MAX_MAP_EDGES		128000
#define	MAX_MAP_SURFEDGES	256000
#define	MAX_MAP_LIGHTING	0x200000
#define	MAX_MAP_VISIBILITY	0x100000

// we are using g_MaxBrushSize now, cleanme
/* #define MAX_BRUSH_SIZE 8192 */

// key / value pair sizes

#define	MAX_KEY		32
#define	MAX_VALUE	1024

//=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D

typedef struct
{
	int		fileofs, filelen;
} lump_t;

#define	LUMP_ENTITIES		0
#define	LUMP_PLANES			1
#define	LUMP_VERTEXES		2
#define	LUMP_VISIBILITY		3
#define	LUMP_NODES			4
#define	LUMP_TEXINFO		5
#define	LUMP_FACES			6
#define	LUMP_LIGHTING		7
#define	LUMP_LEAFS			8
#define	LUMP_LEAFFACES		9
#define	LUMP_LEAFBRUSHES	10
#define	LUMP_EDGES			11
#define	LUMP_SURFEDGES		12
#define	LUMP_MODELS			13
#define	LUMP_BRUSHES		14
#define	LUMP_BRUSHSIDES		15
#define	LUMP_POP			16

#define	HEADER_LUMPS		17

typedef struct
{
	int			ident;
	int			version;=09
	lump_t		lumps[HEADER_LUMPS];
} dheader_t;

typedef struct
{
	float		mins[3], maxs[3];
	float		origin[3];		// for sounds or lights
	int			headnode;
	int			firstface, numfaces;	// submodels just draw faces
										// without walking the bsp tree
} dmodel_t;


typedef struct
{
	float	point[3];
} dvertex_t;


// 0-2 are axial planes
#define	PLANE_X			0
#define	PLANE_Y			1
#define	PLANE_Z			2

// 3-5 are non-axial planes snapped to the nearest
#define	PLANE_ANYX		3
#define	PLANE_ANYY		4
#define	PLANE_ANYZ		5

// planes (x&~1) and (x&~1)+1 are allways opposites

typedef struct
{
	float	normal[3];
	float	dist;
	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;


// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf

// lower bits are stronger, and will eat weaker brushes completely
#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
#define	CONTENTS_WINDOW			2		// translucent, but not watery
#define	CONTENTS_AUX			4
#define	CONTENTS_LAVA			8
#define	CONTENTS_SLIME			16
#define	CONTENTS_WATER			32
#define	CONTENTS_MIST			64
#define	LAST_VISIBLE_CONTENTS	64

// remaining contents are non-visible, and don't eat brushes
#define	CONTENTS_PLAYERCLIP		0x10000
#define	CONTENTS_MONSTERCLIP	0x20000

// currents can be added to any other contents, and may be mixed
#define	CONTENTS_CURRENT_0		0x40000
#define	CONTENTS_CURRENT_90		0x80000
#define	CONTENTS_CURRENT_180	0x100000
#define	CONTENTS_CURRENT_270	0x200000
#define	CONTENTS_CURRENT_UP		0x400000
#define	CONTENTS_CURRENT_DOWN	0x800000

#define	CONTENTS_ORIGIN			    0x1000000	  // removed before bsping an =
entity

#define	CONTENTS_MONSTER		    0x2000000	  // should never be on a brush, =
only in game
#define	CONTENTS_DEADMONSTER	  0x4000000   // corpse
#define	CONTENTS_DETAIL			    0x8000000	  // brushes to be added after =
vis leafs
#define	CONTENTS_TRANSLUCENT	  0x10000000	// auto set if any surface has =
trans
#define	CONTENTS_LADDER         0x20000000	// ladder
#define	CONTENTS_NEGATIVE_CURVE 0x40000000	// reverse inside / outside

#define	CONTENTS_KEEP	(CONTENTS_DETAIL | CONTENTS_NEGATIVE_CURVE)


typedef struct
{
	int			planenum;
	int			children[2];	// negative numbers are -(leafs+1), not nodes
	short		mins[3];		// for frustom culling
	short		maxs[3];
	unsigned short	firstface;
	unsigned short	numfaces;	// counting both sides
} dnode_t;


typedef struct texinfo_s
{
	float		vecs[2][4];		// [s/t][xyz offset]
	int			flags;			// miptex flags + overrides
	int			value;			// light emission, etc
	char		texture[32];	// texture name (textures/*.wal)
	int			nexttexinfo;	// for animations, -1 =3D end of chain
} texinfo_t;


#define	SURF_LIGHT		0x1		// value will hold the light strength

#define	SURF_SLICK		0x2		// effects game physics

#define	SURF_SKY		0x4		// don't draw, but add to skybox
#define	SURF_WARP		0x8		// turbulent water warp
#define	SURF_TRANS33	0x10
#define	SURF_TRANS66	0x20
#define	SURF_FLOWING	0x40	// scroll towards angle
#define	SURF_NODRAW		0x80	// don't bother referencing the texture

#define SURF_PATCH        0x20000000
#define	SURF_CURVE_FAKE		0x40000000
#define	SURF_CURVE		    0x80000000
#define	SURF_KEEP		(SURF_CURVE | SURF_CURVE_FAKE | SURF_PATCH)

// note that edge 0 is never used, because negative edge nums are used =
for
// counterclockwise use of the edge in a face
typedef struct
{
	unsigned short	v[2];		// vertex numbers
} dedge_t;

#define	MAXLIGHTMAPS	4
typedef struct
{
	unsigned short	planenum;
	short		side;

	int			firstedge;		// we must support > 64k edges
	short		numedges;=09
	short		texinfo;

// lighting info
	byte		styles[MAXLIGHTMAPS];
	int			lightofs;		// start of [numstyles*surfsize] samples
} dface_t;

typedef struct
{
	int			contents;			// OR of all brushes (not needed?)

	int			pvsofs;				// -1 =3D no info
	int			phsofs;				// -1 =3D no info

	short		mins[3];			// for frustum culling
	short		maxs[3];

	unsigned short		firstleafface;
	unsigned short		numleaffaces;

	unsigned short		firstleafbrush;
	unsigned short		numleafbrushes;
} dleaf_t;

typedef struct
{
	unsigned short	planenum;		// facing out of the leaf
	short	texinfo;
} dbrushside_t;

typedef struct
{
	int			firstside;
	int			numsides;
	int			contents;
} dbrush_t;

#define	ANGLE_UP	-1
#define	ANGLE_DOWN	-2


------=_NextPart_000_0013_01C1D02F.631A68C0--