tx->skinframerate = 1;
tx->currentskinframe = tx->skinframes;
tx->skinframes[0].base = r_texture_notexture;
+ tx->backgroundcurrentskinframe = tx->backgroundskinframes;
tx->basematerialflags = 0;
if (i == loadmodel->num_textures - 1)
{
- tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES;
+ tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_NOSHADOW;
tx->supercontents = mod_q1bsp_texture_water.supercontents;
tx->surfaceflags = mod_q1bsp_texture_water.surfaceflags;
}
if (strncmp(tx->name,"*lava",5)
&& strncmp(tx->name,"*teleport",9)
&& strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
- tx->basematerialflags |= MATERIALFLAG_WATERALPHA;
+ tx->basematerialflags |= MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW;
if (!strncmp(tx->name, "*lava", 5))
{
tx->supercontents = mod_q1bsp_texture_lava.supercontents;
tx->supercontents = mod_q1bsp_texture_water.supercontents;
tx->surfaceflags = mod_q1bsp_texture_water.surfaceflags;
}
- tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES;
+ tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_NOSHADOW;
}
else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y')
{
tx->supercontents = mod_q1bsp_texture_sky.supercontents;
tx->surfaceflags = mod_q1bsp_texture_sky.surfaceflags;
- tx->basematerialflags |= MATERIALFLAG_SKY;
+ tx->basematerialflags |= MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
}
else
{
tx->basematerialflags |= MATERIALFLAG_WALL;
}
if (tx->skinframes[0].fog)
- tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
// start out with no animation
tx->currentframe = tx;
node->parent = parent;
if (node->plane)
{
+ // this is a node, recurse to children
Mod_Q1BSP_LoadNodes_RecursiveSetParent(node->children[0], node);
Mod_Q1BSP_LoadNodes_RecursiveSetParent(node->children[1], node);
+ // combine supercontents of children
+ node->combinedsupercontents = node->children[0]->combinedsupercontents | node->children[1]->combinedsupercontents;
+ }
+ else
+ {
+ int j;
+ mleaf_t *leaf = (mleaf_t *)node;
+ // if this is a leaf, calculate supercontents mask from all collidable
+ // primitives in the leaf (brushes and collision surfaces)
+ // also flag if the leaf contains any collision surfaces
+ leaf->combinedsupercontents = 0;
+ // combine the supercontents values of all brushes in this leaf
+ for (j = 0;j < leaf->numleafbrushes;j++)
+ leaf->combinedsupercontents |= loadmodel->brush.data_brushes[leaf->firstleafbrush[j]].texture->supercontents;
+ // check if this leaf contains any collision surfaces (q3 patches)
+ for (j = 0;j < leaf->numleafsurfaces;j++)
+ {
+ msurface_t *surface = loadmodel->data_surfaces + leaf->firstleafsurface[j];
+ if (surface->num_collisiontriangles)
+ {
+ leaf->containscollisionsurfaces = true;
+ leaf->combinedsupercontents |= surface->texture->supercontents;
+ }
+ }
}
}
}
}
+qboolean Mod_Q1BSP_CheckWaterAlphaSupport(void)
+{
+ int i, j;
+ mleaf_t *leaf;
+ const unsigned char *pvs;
+ // check all liquid leafs to see if they can see into empty leafs, if any
+ // can we can assume this map supports r_wateralpha
+ for (i = 0, leaf = loadmodel->brush.data_leafs;i < loadmodel->brush.num_leafs;i++, leaf++)
+ {
+ if ((leaf->contents == CONTENTS_WATER || leaf->contents == CONTENTS_SLIME) && (leaf->clusterindex >= 0 && loadmodel->brush.data_pvsclusters))
+ {
+ pvs = loadmodel->brush.data_pvsclusters + leaf->clusterindex * loadmodel->brush.num_pvsclusterbytes;
+ for (j = 0;j < loadmodel->brush.num_leafs;j++)
+ if (CHECKPVSBIT(pvs, loadmodel->brush.data_leafs[j].clusterindex) && loadmodel->brush.data_leafs[j].contents == CONTENTS_EMPTY)
+ return true;
+ }
+ }
+ return false;
+}
+
static void Mod_Q1BSP_LoadClipnodes(lump_t *l, hullinfo_t *hullinfo)
{
dclipnode_t *in, *out;
Mod_Q1BSP_LoadNodes(&header->lumps[LUMP_NODES]);
Mod_Q1BSP_LoadClipnodes(&header->lumps[LUMP_CLIPNODES], &hullinfo);
+ // check if the map supports transparent water rendering
+ loadmodel->brush.supportwateralpha = Mod_Q1BSP_CheckWaterAlphaSupport();
+
if (!mod->brushq1.lightdata)
mod->brush.LightPoint = NULL;
{
int i;
layer->numframes = min(numparameters - 2, TEXTURE_MAXFRAMES);
- layer->framerate = atoi(parameter[1]);
+ layer->framerate = atof(parameter[1]);
for (i = 0;i < layer->numframes;i++)
strlcpy(layer->texturename[i], parameter[i + 2], sizeof(layer->texturename));
}
shader->surfaceparms |= Q3SURFACEPARM_WATER;
else if (!strcasecmp(parameter[1], "pointlight"))
shader->surfaceparms |= Q3SURFACEPARM_POINTLIGHT;
+ else if (!strcasecmp(parameter[1], "antiportal"))
+ shader->surfaceparms |= Q3SURFACEPARM_ANTIPORTAL;
else
- Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
+ Con_DPrintf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
}
else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
{
out->basematerialflags = 0;
if (shader->surfaceparms & Q3SURFACEPARM_SKY)
{
- out->basematerialflags |= MATERIALFLAG_SKY;
+ out->basematerialflags |= MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
if (shader->skyboxname[0])
{
// quake3 seems to append a _ to the skybox name, so this must do so as well
}
}
else if ((out->surfaceflags & Q3SURFACEFLAG_NODRAW) || shader->numlayers == 0)
- out->basematerialflags |= MATERIALFLAG_NODRAW;
+ out->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
else if (shader->surfaceparms & Q3SURFACEPARM_LAVA)
- out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_FULLBRIGHT;
+ out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOSHADOW;
else if (shader->surfaceparms & Q3SURFACEPARM_SLIME)
- out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_WATERALPHA;
+ out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW;
else if (shader->surfaceparms & Q3SURFACEPARM_WATER)
- out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_WATERALPHA;
+ out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_WATERALPHA | MATERIALFLAG_NOSHADOW;
else
out->basematerialflags |= MATERIALFLAG_WALL;
if (shader->layers[0].alphatest)
- out->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_TRANSPARENT;
+ out->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
+ if (shader->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+ out->basematerialflags |= MATERIALFLAG_NOSHADOW;
out->customblendfunc[0] = GL_ONE;
out->customblendfunc[1] = GL_ZERO;
if (shader->numlayers > 0)
if (shader->layers[0].blendfunc[0] != GL_ONE || shader->layers[0].blendfunc[1] != GL_ZERO)
{
if (shader->layers[0].blendfunc[0] == GL_ONE && shader->layers[0].blendfunc[1] == GL_ONE)
- out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
else if (shader->layers[0].blendfunc[0] == GL_SRC_ALPHA && shader->layers[0].blendfunc[1] == GL_ONE)
- out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
else if (shader->layers[0].blendfunc[0] == GL_SRC_ALPHA && shader->layers[0].blendfunc[1] == GL_ONE_MINUS_SRC_ALPHA)
- out->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ out->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
else
- out->basematerialflags |= MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ out->basematerialflags |= MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
}
}
if (!shader->lighting)
if (!Mod_LoadSkinFrame(&out->skinframes[j], shader->primarylayer->texturename[j], ((shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (shader->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP) | (shader->primarylayer->clampmap ? TEXF_CLAMP : 0), false, true))
Con_Printf("%s: could not load texture \"%s\" (frame %i) for shader \"%s\"\n", loadmodel->name, shader->primarylayer->texturename[j], j, out->name);
}
+ if (shader->backgroundlayer && cls.state != ca_dedicated)
+ {
+ int j;
+ out->backgroundnumskinframes = shader->backgroundlayer->numframes;
+ out->backgroundskinframerate = shader->backgroundlayer->framerate;
+ for (j = 0;j < shader->backgroundlayer->numframes;j++)
+ if (!Mod_LoadSkinFrame(&out->backgroundskinframes[j], shader->backgroundlayer->texturename[j], ((shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (shader->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP) | (shader->backgroundlayer->clampmap ? TEXF_CLAMP : 0), false, true))
+ Con_Printf("%s: could not load texture \"%s\" (frame %i) for shader \"%s\"\n", loadmodel->name, shader->backgroundlayer->texturename[j], j, out->name);
+ }
}
+ else if (!strcmp(out->name, "noshader"))
+ out->surfaceparms = 0;
else
{
c++;
Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name);
out->surfaceparms = 0;
if (out->surfaceflags & Q3SURFACEFLAG_NODRAW)
- out->basematerialflags |= MATERIALFLAG_NODRAW;
+ out->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
else if (out->surfaceflags & Q3SURFACEFLAG_SKY)
- out->basematerialflags |= MATERIALFLAG_SKY;
+ out->basematerialflags |= MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
else
out->basematerialflags |= MATERIALFLAG_WALL;
// these are defaults
// init the animation variables
out->currentframe = out;
out->currentskinframe = &out->skinframes[0];
+ out->backgroundcurrentskinframe = &out->backgroundskinframes[0];
}
if (c)
Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
// walk the tree until we hit a leaf, recursing for any split cases
while (node->plane)
{
+ // abort if this part of the bsp tree can not be hit by this trace
+// if (!(node->combinedsupercontents & trace->hitsupercontentsmask))
+// return;
plane = node->plane;
// axial planes are much more common than non-axial, so an optimized
// axial case pays off here
return;
}
}
+ // abort if this part of the bsp tree can not be hit by this trace
+// if (!(node->combinedsupercontents & trace->hitsupercontentsmask))
+// return;
// hit a leaf
nodesegmentmins[0] = min(start[0], end[0]) - 1;
nodesegmentmins[1] = min(start[1], end[1]) - 1;
}
}
// can't do point traces on curves (they have no thickness)
- if (mod_q3bsp_curves_collisions.integer && !VectorCompare(start, end))
+ if (leaf->containscollisionsurfaces && mod_q3bsp_curves_collisions.integer && !VectorCompare(start, end))
{
// line trace the curves
for (i = 0;i < leaf->numleafsurfaces;i++)
// walk the tree until we hit a leaf, recursing for any split cases
while (node->plane)
{
+ // abort if this part of the bsp tree can not be hit by this trace
+// if (!(node->combinedsupercontents & trace->hitsupercontentsmask))
+// return;
plane = node->plane;
// axial planes are much more common than non-axial, so an optimized
// axial case pays off here
// take whichever side the segment box is on
node = node->children[sides - 1];
}
+ // abort if this part of the bsp tree can not be hit by this trace
+// if (!(node->combinedsupercontents & trace->hitsupercontentsmask))
+// return;
nodesegmentmins[0] = max(segmentmins[0], node->mins[0] - 1);
nodesegmentmins[1] = max(segmentmins[1], node->mins[1] - 1);
nodesegmentmins[2] = max(segmentmins[2], node->mins[2] - 1);
Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush, brush);
}
}
- if (mod_q3bsp_curves_collisions.integer)
+ if (leaf->containscollisionsurfaces && mod_q3bsp_curves_collisions.integer)
{
for (i = 0;i < leaf->numleafsurfaces;i++)
{
// the MakePortals code works fine on the q3bsp data as well
Mod_Q1BSP_MakePortals();
+ // FIXME: shader alpha should replace r_wateralpha support in q3bsp
+ loadmodel->brush.supportwateralpha = true;
+
// make a single combined shadow mesh to allow optimized shadow volume creation
numshadowmeshtriangles = 0;
for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++)
break;
if (j < mod->nummodelsurfaces)
mod->DrawSky = R_Q1BSP_DrawSky;
+ else
+ mod->DrawSky = NULL;
}
}