double t1, t2;
// variables that need to be stored on the stack when recursing
- dclipnode_t *node;
+ mclipnode_t *node;
int side;
double midf, mid[3];
#else
RecursiveHullCheckTraceInfo_t rhc;
static hull_t box_hull;
- static dclipnode_t box_clipnodes[6];
+ static mclipnode_t box_clipnodes[6];
static mplane_t box_planes[6];
// fill in a default trace
memset(&rhc, 0, sizeof(rhc));
if (strncmp(tx->name,"*lava",5)
&& strncmp(tx->name,"*teleport",9)
&& strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
- tx->basematerialflags |= MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW;
+ {
+ tx->basematerialflags |= MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW | MATERIALFLAG_WATERSHADER;
+ VectorSet(tx->reflectcolor, 1, 1, 1);
+ VectorSet(tx->refractcolor, 1, 1, 1);
+ tx->reflectfactor = 1;
+ tx->refractfactor = 1;
+ }
tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_NOSHADOW;
}
else if (!strncmp(tx->name, "sky", 3))
int i, j, k;
if (!data)
return;
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
return; // error
if (com_token[0] != '{')
return; // error
while (1)
{
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
return; // error
if (com_token[0] == '}')
break; // end of worldspawn
strlcpy(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
return; // error
dpsnprintf(value, sizeof(value), "%s", com_token);
if (!strcmp("wad", key)) // for HalfLife maps
totaltris = 0;
for (surfacenum = 0, in = (dface_t *)(mod_base + l->fileofs);surfacenum < count;surfacenum++, in++)
{
- numedges = LittleShort(in->numedges);
+ numedges = (unsigned short)LittleShort(in->numedges);
totalverts += numedges;
totaltris += numedges - 2;
}
// FIXME: validate edges, texinfo, etc?
firstedge = LittleLong(in->firstedge);
- numedges = LittleShort(in->numedges);
+ numedges = (unsigned short)LittleShort(in->numedges);
if ((unsigned int) firstedge > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges)
Host_Error("Mod_Q1BSP_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)", firstedge, numedges, loadmodel->brushq1.numsurfedges);
- i = LittleShort(in->texinfo);
+ i = (unsigned short)LittleShort(in->texinfo);
if ((unsigned int) i >= (unsigned int) loadmodel->brushq1.numtexinfo)
Host_Error("Mod_Q1BSP_LoadFaces: invalid texinfo index %i(model has %i texinfos)", i, loadmodel->brushq1.numtexinfo);
surface->lightmapinfo->texinfo = loadmodel->brushq1.texinfo + i;
surface->texture = surface->lightmapinfo->texinfo->texture;
- planenum = LittleShort(in->planenum);
+ planenum = (unsigned short)LittleShort(in->planenum);
if ((unsigned int) planenum >= (unsigned int) loadmodel->brush.num_planes)
Host_Error("Mod_Q1BSP_LoadFaces: invalid plane index %i (model has %i planes)", planenum, loadmodel->brush.num_planes);
p = LittleLong(in->planenum);
out->plane = loadmodel->brush.data_planes + p;
- out->firstsurface = LittleShort(in->firstface);
- out->numsurfaces = LittleShort(in->numfaces);
+ out->firstsurface = (unsigned short)LittleShort(in->firstface);
+ out->numsurfaces = (unsigned short)LittleShort(in->numfaces);
for (j=0 ; j<2 ; j++)
{
- p = LittleShort(in->children[j]);
- if (p >= 0)
- out->children[j] = loadmodel->brush.data_nodes + p;
+ // LordHavoc: this code supports broken bsp files produced by
+ // arguire qbsp which can produce more than 32768 nodes, any value
+ // below count is assumed to be a node number, any other value is
+ // assumed to be a leaf number
+ p = (unsigned short)LittleShort(in->children[j]);
+ if (p < count)
+ {
+ if (p < loadmodel->brush.num_nodes)
+ out->children[j] = loadmodel->brush.data_nodes + p;
+ else
+ {
+ Con_Printf("Mod_Q1BSP_LoadNodes: invalid node index %i (file has only %i nodes)\n", p, loadmodel->brush.num_nodes);
+ // map it to the solid leaf
+ out->children[j] = (mnode_t *)loadmodel->brush.data_leafs;
+ }
+ }
else
- out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + (-1 - p));
+ {
+ // note this uses 65535 intentionally, -1 is leaf 0
+ p = 65535 - p;
+ if (p < loadmodel->brush.num_leafs)
+ out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + p);
+ else
+ {
+ Con_Printf("Mod_Q1BSP_LoadNodes: invalid leaf index %i (file has only %i leafs)\n", p, loadmodel->brush.num_leafs);
+ // map it to the solid leaf
+ out->children[j] = (mnode_t *)loadmodel->brush.data_leafs;
+ }
+ }
}
}
out->contents = LittleLong(in->contents);
- out->firstleafsurface = loadmodel->brush.data_leafsurfaces + LittleShort(in->firstmarksurface);
- out->numleafsurfaces = LittleShort(in->nummarksurfaces);
- if (out->firstleafsurface < 0 || LittleShort(in->firstmarksurface) + out->numleafsurfaces > loadmodel->brush.num_leafsurfaces)
+ out->firstleafsurface = loadmodel->brush.data_leafsurfaces + (unsigned short)LittleShort(in->firstmarksurface);
+ out->numleafsurfaces = (unsigned short)LittleShort(in->nummarksurfaces);
+ if (out->firstleafsurface < 0 || (unsigned short)LittleShort(in->firstmarksurface) + out->numleafsurfaces > loadmodel->brush.num_leafsurfaces)
{
Con_Printf("Mod_Q1BSP_LoadLeafs: invalid leafsurface range %i:%i outside range %i:%i\n", (int)(out->firstleafsurface - loadmodel->brush.data_leafsurfaces), (int)(out->firstleafsurface + out->numleafsurfaces - loadmodel->brush.data_leafsurfaces), 0, loadmodel->brush.num_leafsurfaces);
out->firstleafsurface = NULL;
static void Mod_Q1BSP_LoadClipnodes(lump_t *l, hullinfo_t *hullinfo)
{
- dclipnode_t *in, *out;
+ dclipnode_t *in;
+ mclipnode_t *out;
int i, count;
hull_t *hull;
if (l->filelen % sizeof(*in))
Host_Error("Mod_Q1BSP_LoadClipnodes: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
- out = (dclipnode_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
+ out = (mclipnode_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
loadmodel->brushq1.clipnodes = out;
loadmodel->brushq1.numclipnodes = count;
for (i=0 ; i<count ; i++, out++, in++)
{
out->planenum = LittleLong(in->planenum);
- out->children[0] = LittleShort(in->children[0]);
- out->children[1] = LittleShort(in->children[1]);
+ // LordHavoc: this code supports arguire qbsp's broken clipnodes indices (more than 32768 clipnodes), values above count are assumed to be contents values
+ out->children[0] = (unsigned short)LittleShort(in->children[0]);
+ out->children[1] = (unsigned short)LittleShort(in->children[1]);
+ if (out->children[0] >= count)
+ out->children[0] -= 65536;
+ if (out->children[1] >= count)
+ out->children[1] -= 65536;
if (out->planenum < 0 || out->planenum >= loadmodel->brush.num_planes)
Host_Error("Corrupt clipping hull(out of range planenum)");
- if (out->children[0] >= count || out->children[1] >= count)
- Host_Error("Corrupt clipping hull(out of range child)");
}
}
static void Mod_Q1BSP_MakeHull0(void)
{
mnode_t *in;
- dclipnode_t *out;
+ mclipnode_t *out;
int i;
hull_t *hull;
hull = &loadmodel->brushq1.hulls[0];
in = loadmodel->brush.data_nodes;
- out = (dclipnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_nodes * sizeof(dclipnode_t));
+ out = (mclipnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_nodes * sizeof(*out));
hull->clipnodes = out;
hull->firstclipnode = 0;
for (i = 0;i < loadmodel->brush.num_leafsurfaces;i++)
{
- j = (unsigned) LittleShort(in[i]);
+ j = (unsigned short) LittleShort(in[i]);
if (j >= loadmodel->num_surfaces)
Host_Error("Mod_Q1BSP_LoadLeaffaces: bad surface number");
loadmodel->brush.data_leafsurfaces[i] = j;
if (!maptext)
return;
text = maptext;
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
return; // error
submodel = 0;
for (;;)
{
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
break;
if (com_token[0] != '{')
return; // error
brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
for (;;)
{
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
return; // error
if (com_token[0] == '}')
break; // end of entity
}
for (;;)
{
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
return; // error
if (com_token[0] == '}')
break; // end of brush
// FIXME: support hl .map format
for (pointnum = 0;pointnum < 3;pointnum++)
{
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
for (componentnum = 0;componentnum < 3;componentnum++)
{
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
point[pointnum][componentnum] = atof(com_token);
}
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
}
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
strlcpy(facetexture, com_token, sizeof(facetexture));
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
//scroll_s = atof(com_token);
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
//scroll_t = atof(com_token);
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
//rotate = atof(com_token);
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
//scale_s = atof(com_token);
- COM_ParseToken_Simple(&data, false);
+ COM_ParseToken_Simple(&data, false, false);
//scale_t = atof(com_token);
TriangleNormal(point[0], point[1], point[2], planenormal);
VectorNormalizeDouble(planenormal);
//Calculates a PVS that is the inclusive or of all leafs within radius pixels
//of the given point.
-static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsigned char *pvsbuffer, int pvsbufferlength)
+static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsigned char *pvsbuffer, int pvsbufferlength, qboolean merge)
{
int bytes = model->brush.num_pvsclusterbytes;
bytes = min(bytes, pvsbufferlength);
memset(pvsbuffer, 0xFF, bytes);
return bytes;
}
- memset(pvsbuffer, 0, bytes);
+ if (!merge)
+ memset(pvsbuffer, 0, bytes);
Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, bytes, model->brush.data_nodes);
return bytes;
}
for (j = 0;j < mod->nummodelsurfaces;j++)
mod->surfacelist[j] = mod->firstmodelsurface + j;
- // this gets altered below if sky is used
+ // this gets altered below if sky or water is used
mod->DrawSky = NULL;
+ mod->DrawAddWaterPlanes = NULL;
mod->Draw = R_Q1BSP_Draw;
mod->DrawDepth = R_Q1BSP_DrawDepth;
+ mod->DrawDebug = R_Q1BSP_DrawDebug;
mod->GetLightInfo = R_Q1BSP_GetLightInfo;
mod->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
mod->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
// we only need to have a drawsky function if it is used(usually only on world model)
if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
mod->DrawSky = R_Q1BSP_DrawSky;
+ if (surface->texture->basematerialflags & MATERIALFLAG_WATERALPHA)
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
// calculate bounding shapes
for (k = 0, vec = (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex);k < surface->num_vertices;k++, vec += 3)
{
memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen);
data = loadmodel->brush.entities;
// some Q3 maps override the lightgrid_cellsize with a worldspawn key
- if (data && COM_ParseToken_Simple(&data, false) && com_token[0] == '{')
+ if (data && COM_ParseToken_Simple(&data, false, false) && com_token[0] == '{')
{
while (1)
{
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
break; // error
if (com_token[0] == '}')
break; // end of worldspawn
strlcpy(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken_Simple(&data, false))
+ if (!COM_ParseToken_Simple(&data, false, false))
break; // error
strlcpy(value, com_token, sizeof(value));
if (!strcmp("gridsize", key))
mod->brush.PointInLeaf = Mod_Q1BSP_PointInLeaf;
mod->Draw = R_Q1BSP_Draw;
mod->DrawDepth = R_Q1BSP_DrawDepth;
+ mod->DrawDebug = R_Q1BSP_DrawDebug;
mod->GetLightInfo = R_Q1BSP_GetLightInfo;
mod->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
mod->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
mod->DrawLight = R_Q1BSP_DrawLight;
+ mod->DrawAddWaterPlanes = NULL;
mod_base = (unsigned char *)header;
mod->radius2 = modelradius * modelradius;
for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->surfaceflags & Q3SURFACEFLAG_SKY)
+ if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY)
break;
if (j < mod->nummodelsurfaces)
mod->DrawSky = R_Q1BSP_DrawSky;
else
mod->DrawSky = NULL;
+
+ for (j = 0;j < mod->nummodelsurfaces;j++)
+ if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_WATERALPHA)
+ break;
+ if (j < mod->nummodelsurfaces)
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ else
+ mod->DrawAddWaterPlanes = NULL;
}
}