cvar_t r_fxaa = {CVAR_SAVE, "r_fxaa", "0", "fast approximate anti aliasing"};
cvar_t mod_noshader_default_offsetmapping = {CVAR_SAVE, "mod_noshader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are not using q3 shader files"};
cvar_t mod_obj_orientation = {0, "mod_obj_orientation", "1", "fix orientation of OBJ models to the usual conventions (if zero, use coordinates as is)"};
+cvar_t mod_q2bsp_littransparentsurfaces = {0, "mod_q2bsp_littransparentsurfaces", "0", "allows lighting on rain in 3v3gloom3 and other cases of transparent surfaces that have lightmaps that were ignored by quake2"};
cvar_t mod_q3bsp_curves_collisions = {0, "mod_q3bsp_curves_collisions", "1", "enables collisions with curves (SLOW)"};
cvar_t mod_q3bsp_curves_collisions_stride = {0, "mod_q3bsp_curves_collisions_stride", "16", "collisions against curves: optimize performance by doing a combined collision check for this triangle amount first (-1 avoids any box tests)"};
cvar_t mod_q3bsp_curves_stride = {0, "mod_q3bsp_curves_stride", "16", "particle effect collisions against curves: optimize performance by doing a combined collision check for this triangle amount first (-1 avoids any box tests)"};
static texture_t mod_q1bsp_texture_slime;
static texture_t mod_q1bsp_texture_water;
-static qboolean Mod_Q3BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end);
+static qboolean Mod_Q3BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs);
void Mod_BrushInit(void)
{
Cvar_RegisterVariable(&r_fxaa);
Cvar_RegisterVariable(&mod_noshader_default_offsetmapping);
Cvar_RegisterVariable(&mod_obj_orientation);
+ Cvar_RegisterVariable(&mod_q2bsp_littransparentsurfaces);
Cvar_RegisterVariable(&mod_q3bsp_curves_collisions);
Cvar_RegisterVariable(&mod_q3bsp_curves_collisions_stride);
Cvar_RegisterVariable(&mod_q3bsp_curves_stride);
}
//#endif
-static void Mod_Q1BSP_TracePoint(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask)
+static void Mod_Q1BSP_TracePoint(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
RecursiveHullCheckTraceInfo_t rhc;
Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
}
-static void Mod_Q1BSP_TraceLineAgainstSurfaces(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask);
+static void Mod_Q1BSP_TraceLineAgainstSurfaces(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask);
-static void Mod_Q1BSP_TraceLine(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+static void Mod_Q1BSP_TraceLine(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
RecursiveHullCheckTraceInfo_t rhc;
if (VectorCompare(start, end))
{
- Mod_Q1BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask);
+ Mod_Q1BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
// sometimes we want to traceline against polygons so we can report the texture that was hit rather than merely a contents, but using this method breaks one of negke's maps so it must be a cvar check...
if (sv_gameplayfix_q1bsptracelinereportstexture.integer)
{
- Mod_Q1BSP_TraceLineAgainstSurfaces(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
+ Mod_Q1BSP_TraceLineAgainstSurfaces(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
memset(trace, 0, sizeof(trace_t));
rhc.trace = trace;
rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
+ rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
rhc.trace->fraction = 1;
rhc.trace->allsolid = true;
rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
memset(&testtrace, 0, sizeof(trace_t));
rhc.trace = &testtrace;
rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
+ rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
rhc.trace->fraction = 1;
rhc.trace->allsolid = true;
VectorCopy(test, rhc.start);
#endif
}
-static void Mod_Q1BSP_TraceBox(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_Q1BSP_TraceBox(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
// this function currently only supports same size start and end
double boxsize[3];
if (VectorCompare(boxmins, boxmaxs))
{
if (VectorCompare(start, end))
- Mod_Q1BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask);
+ Mod_Q1BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
else
- Mod_Q1BSP_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
+ Mod_Q1BSP_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
memset(trace, 0, sizeof(trace_t));
rhc.trace = trace;
rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
+ rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
rhc.trace->fraction = 1;
rhc.trace->allsolid = true;
VectorSubtract(boxmaxs, boxmins, boxsize);
memset(&testtrace, 0, sizeof(trace_t));
rhc.trace = &testtrace;
rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
+ rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
rhc.trace->fraction = 1;
rhc.trace->allsolid = true;
VectorCopy(test, rhc.start);
return Mod_Q1BSP_SuperContentsFromNativeContents(NULL, num);
}
-void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture)
+void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture)
{
#if 1
colbrushf_t cbox;
cbox_planes[5].q3surfaceflags = boxq3surfaceflags;cbox_planes[5].texture = boxtexture;
memset(trace, 0, sizeof(trace_t));
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
trace->fraction = 1;
Collision_TraceLineBrushFloat(trace, start, end, &cbox, &cbox);
#else
rhc.hull = &box_hull;
rhc.trace = trace;
rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
+ rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
rhc.trace->fraction = 1;
rhc.trace->allsolid = true;
VectorCopy(start, rhc.start);
#endif
}
-void Collision_ClipTrace_Point(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture)
+void Collision_ClipTrace_Point(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture)
{
memset(trace, 0, sizeof(trace_t));
trace->fraction = 1;
+ trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
if (BoxesOverlap(start, start, cmins, cmaxs))
{
trace->startsupercontents |= boxsupercontents;
- if (hitsupercontentsmask & boxsupercontents)
+ if ((hitsupercontentsmask & boxsupercontents) && !(skipsupercontentsmask & boxsupercontents))
{
trace->startsolid = true;
trace->allsolid = true;
}
}
-static qboolean Mod_Q1BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end)
+static qboolean Mod_Q1BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
{
trace_t trace;
- Mod_Q1BSP_TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK);
- return trace.fraction == 1;
+ Mod_Q1BSP_TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK, 0, MATERIALFLAGMASK_TRANSLUCENT);
+ return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
}
static int Mod_Q1BSP_LightPoint_RecursiveBSPNode(dp_model_t *model, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz)
// skip faces with contents we don't care about
if (!(t->trace->hitsupercontentsmask & surface->texture->supercontents))
continue;
+ // ignore surfaces matching the skipsupercontentsmask (this is rare)
+ if (t->trace->skipsupercontentsmask & surface->texture->supercontents)
+ continue;
+ // skip surfaces matching the skipmaterialflagsmask (e.g. MATERIALFLAG_NOSHADOW)
+ if (t->trace->skipmaterialflagsmask & surface->texture->currentmaterialflags)
+ continue;
// get the surface normal - since it is flat we know any vertex normal will suffice
VectorCopy(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex, normal);
// skip backfaces
}
}
-static void Mod_Q1BSP_TraceLineAgainstSurfaces(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+static void Mod_Q1BSP_TraceLineAgainstSurfaces(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
RecursiveHullCheckTraceInfo_t rhc;
memset(trace, 0, sizeof(trace_t));
rhc.trace = trace;
rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
+ rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
rhc.trace->fraction = 1;
rhc.trace->allsolid = true;
rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb)
{
- int i, j, k, num, max, altmax, mtwidth, mtheight, doffset, incomplete, nummiptex = 0;
- skinframe_t *skinframe;
- texture_t *tx, *tx2, *anims[10], *altanims[10];
+ int i, j, k, num, max, altmax, mtwidth, mtheight, doffset, incomplete, nummiptex = 0, firstskynoshadowtexture = 0;
+ skinframe_t *skinframemissing;
+ texture_t *tx, *tx2, *anims[10], *altanims[10], *currentskynoshadowtexture;
texture_t backuptex;
unsigned char *data, *mtdata;
const char *s;
loadmodel->data_textures = NULL;
- // add two slots for notexture walls and notexture liquids
+ // add two slots for notexture walls and notexture liquids, and duplicate
+ // all sky textures; sky surfaces can be shadow-casting or not, the surface
+ // loading will choose according to the contents behind the surface
+ // (necessary to support e1m5 logo shadow which has a SKY contents brush,
+ // while correctly treating sky textures as occluders in other situations).
if (sb->cursize)
{
+ int numsky = 0;
+ size_t watermark;
nummiptex = MSG_ReadLittleLong(sb);
loadmodel->num_textures = nummiptex + 2;
- loadmodel->num_texturesperskin = loadmodel->num_textures;
+ // save the position so we can go back to it
+ watermark = sb->readcount;
+ for (i = 0; i < nummiptex; i++)
+ {
+ doffset = MSG_ReadLittleLong(sb);
+ if (r_nosurftextures.integer)
+ continue;
+ if (doffset == -1)
+ {
+ Con_DPrintf("%s: miptex #%i missing\n", loadmodel->name, i);
+ continue;
+ }
+
+ MSG_InitReadBuffer(&miptexsb, sb->data + doffset, sb->cursize - doffset);
+
+ // copy name, but only up to 16 characters
+ // (the output buffer can hold more than this, but the input buffer is
+ // only 16)
+ for (j = 0; j < 16; j++)
+ name[j] = MSG_ReadByte(&miptexsb);
+ name[j] = 0;
+ // pretty up the buffer (replacing any trailing garbage with 0)
+ for (j = (int)strlen(name); j < 16; j++)
+ name[j] = 0;
+
+ if (!strncmp(name, "sky", 3))
+ numsky++;
+ }
+
+ // bump it back to where we started parsing
+ sb->readcount = watermark;
+
+ firstskynoshadowtexture = loadmodel->num_textures;
+ loadmodel->num_textures += numsky;
}
else
{
loadmodel->num_textures = 2;
- loadmodel->num_texturesperskin = loadmodel->num_textures;
+ firstskynoshadowtexture = loadmodel->num_textures;
}
+ loadmodel->num_texturesperskin = loadmodel->num_textures;
loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_textures * sizeof(texture_t));
+ // we'll be writing to these in parallel for sky textures
+ currentskynoshadowtexture = loadmodel->data_textures + firstskynoshadowtexture;
+
// fill out all slots with notexture
- if (cls.state != ca_dedicated)
- skinframe = R_SkinFrame_LoadMissing();
- else
- skinframe = NULL;
+ skinframemissing = R_SkinFrame_LoadMissing();
for (i = 0, tx = loadmodel->data_textures;i < loadmodel->num_textures;i++, tx++)
{
strlcpy(tx->name, "NO TEXTURE FOUND", sizeof(tx->name));
tx->width = 16;
tx->height = 16;
tx->basealpha = 1.0f;
- if (cls.state != ca_dedicated)
- {
- tx->numskinframes = 1;
- tx->skinframerate = 1;
- tx->skinframes[0] = skinframe;
- tx->currentskinframe = tx->skinframes[0];
- }
+ tx->materialshaderpass = tx->shaderpasses[0] = Mod_CreateShaderPass(skinframemissing);
+ tx->materialshaderpass->skinframes[0] = skinframemissing;
+ tx->currentskinframe = skinframemissing;
tx->basematerialflags = MATERIALFLAG_WALL;
if (i == loadmodel->num_textures - 1)
{
s += 5;
FS_StripExtension(s, mapname, sizeof(mapname));
- // just to work around bounds checking when debugging with it (array index out of bounds error thing)
// LordHavoc: mostly rewritten map texture loader
for (i = 0;i < nummiptex;i++)
{
tx->height = mtheight;
tx->basealpha = 1.0f;
+ // start out with no animation
+ tx->currentframe = tx;
+ tx->currentskinframe = tx->materialshaderpass != NULL ? tx->materialshaderpass->skinframes[0] : NULL;
+
if (tx->name[0] == '*')
{
if (!strncmp(tx->name, "*lava", 5))
}
else
{
- skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
+ skinframe_t *skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
if (!skinframe)
skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
if (skinframe)
else if (mtdata) // texture included
skinframe = R_SkinFrame_LoadInternalQuake(tx->name, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP, false, r_fullbrights.integer, mtdata, tx->width, tx->height);
}
- // if skinframe is still NULL the "missing" texture will be used
+ // if skinframe is still NULL the "missing" texture has already been assigned to this
if (skinframe)
- tx->skinframes[0] = skinframe;
+ tx->materialshaderpass->skinframes[0] = skinframe;
}
// LordHavoc: some Tenebrae textures get replaced by black
if (!strncmp(tx->name, "*glassmirror", 12)) // Tenebrae
- tx->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_MIPMAP | TEXF_ALPHA, zerotrans, 1, 1, false);
+ tx->materialshaderpass->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_MIPMAP | TEXF_ALPHA, zerotrans, 1, 1, false);
else if (!strncmp(tx->name, "mirror", 6)) // Tenebrae
- tx->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, 0, zeroopaque, 1, 1, false);
+ tx->materialshaderpass->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, 0, zeroopaque, 1, 1, false);
+ tx->currentskinframe = tx->materialshaderpass->skinframes[0];
}
tx->basematerialflags = MATERIALFLAG_WALL;
tx->basematerialflags |= MATERIALFLAG_WATERSCROLL | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_NOSHADOW;
else
tx->basematerialflags |= MATERIALFLAG_WATERSCROLL | MATERIALFLAG_LIGHTBOTHSIDES | MATERIALFLAG_NOSHADOW | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATERSHADER;
- if (tx->skinframes[0] && tx->skinframes[0]->hasalpha)
+ if (tx->currentskinframe != NULL && tx->currentskinframe->hasalpha)
tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
}
+ else if (tx->name[0] == '{') // fence textures
+ {
+ tx->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_NOSHADOW;
+ }
else if (!strncmp(tx->name, "mirror", 6)) // Tenebrae
{
// replace the texture with black
tx->basematerialflags |= MATERIALFLAG_REFLECTION;
}
else if (!strncmp(tx->name, "sky", 3))
- tx->basematerialflags = MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
+ tx->basematerialflags = MATERIALFLAG_SKY;
else if (!strcmp(tx->name, "caulk"))
tx->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
- else if (tx->skinframes[0] && tx->skinframes[0]->hasalpha)
+ else if (tx->currentskinframe != NULL && tx->currentskinframe->hasalpha)
tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
-
- // start out with no animation
- tx->currentframe = tx;
- tx->currentskinframe = tx->skinframes[0];
tx->currentmaterialflags = tx->basematerialflags;
+
+ // duplicate of sky with NOSHADOW
+ if (tx->basematerialflags & MATERIALFLAG_SKY)
+ {
+ *currentskynoshadowtexture = *tx;
+ currentskynoshadowtexture->basematerialflags |= MATERIALFLAG_NOSHADOW;
+ tx->skynoshadowtexture = currentskynoshadowtexture;
+ currentskynoshadowtexture++;
+ }
}
// sequence the animations
tx = loadmodel->data_textures + i;
if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0)
continue;
+ num = tx->name[1];
+ if ((num < '0' || num > '9') && (num < 'a' || num > 'j'))
+ {
+ Con_Printf("Bad animating texture %s\n", tx->name);
+ continue;
+ }
if (tx->anim_total[0] || tx->anim_total[1])
continue; // already sequenced
anims[num - '0'] = tx2;
else if (num >= 'a' && num <= 'j')
altanims[num - 'a'] = tx2;
- else
- Con_Printf("Bad animating texture %s\n", tx->name);
+ // No need to warn otherwise - we already did above.
}
max = altmax = 0;
if (incomplete)
continue;
+ // If we have exactly one frame, something's wrong.
+ if (max + altmax <= 1)
+ {
+ Con_Printf("Texture %s is animated (leading +) but has only one frame\n", tx->name);
+ }
+
if (altmax < 1)
{
// if there is no alternate animation, duplicate the primary
altanims[k] = anims[k];
}
+ if (max < 1)
+ {
+ // Warn.
+ Con_Printf("Missing frame 0 of %s\n", tx->name);
+
+ // however, we can handle this by duplicating the alternate animation into the primary
+ max = altmax;
+ for (k = 0;k < 10;k++)
+ anims[k] = altanims[k];
+ }
+
+
// link together the primary animation
for (j = 0;j < max;j++)
{
int stainmapsize = 0;
mod_alloclightmap_state_t allocState;
- Mod_AllocLightmap_Init(&allocState, lightmapsize, lightmapsize);
+ Mod_AllocLightmap_Init(&allocState, loadmodel->mempool, lightmapsize, lightmapsize);
for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
{
- int i, iu, iv, lightmapx = 0, lightmapy = 0;
+ int iu, iv, lightmapx = 0, lightmapy = 0;
float u, v, ubase, vbase, uscale, vscale;
if (!loadmodel->brushq1.lightmapupdateflags[surfacenum])
}
}
+// fixes up sky surfaces that have SKY contents behind them, so that they do not cast shadows (e1m5 logo shadow trick).
+static void Mod_Q1BSP_AssignNoShadowSkySurfaces(dp_model_t *mod)
+{
+ int i;
+ msurface_t *surface;
+ vec3_t center;
+ int contents;
+ for (i = 0, surface = mod->data_surfaces + mod->firstmodelsurface; i < mod->nummodelsurfaces; i++, surface++)
+ {
+ if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
+ {
+ // check if the point behind the surface polygon is SOLID or SKY contents
+ VectorMAMAM(0.5f, surface->mins, 0.5f, surface->maxs, -0.25f, mod->surfmesh.data_normal3f + 3*surface->num_firstvertex, center);
+ contents = Mod_Q1BSP_PointSuperContents(mod, 0, center);
+ if (!(contents & SUPERCONTENTS_SOLID))
+ surface->texture = surface->texture->skynoshadowtexture;
+ }
+ }
+}
+
static void Mod_Q1BSP_LoadMapBrushes(void)
{
#if 0
return numshadowmeshtriangles;
}
-void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask);
+void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask);
void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
// set node/leaf parents for this submodel
Mod_Q1BSP_LoadNodes_RecursiveSetParent(mod->brush.data_nodes + mod->brushq1.hulls[0].firstclipnode, NULL);
+ // this has to occur after hull info has been set, as it uses Mod_Q1BSP_PointSuperContents
+ Mod_Q1BSP_AssignNoShadowSkySurfaces(mod);
+
// make the model surface list (used by shadowing/lighting)
mod->sortedmodelsurfaces = (int *)datapointer;datapointer += mod->nummodelsurfaces * sizeof(int);
Mod_MakeSortedSurfaces(mod);
static void Mod_Q2BSP_LoadTexinfo(sizebuf_t *sb)
{
mtexinfo_t *out;
- int i, j, k, l, count;
+ int i, l, count;
int structsize = 76;
int maxtextures = 1024; // hardcoded limit of quake2 engine, so we may as well use it as an upper bound
char filename[MAX_QPATH];
for (i = 0;i < count;i++, out++)
{
+ int j, k;
for (k = 0;k < 2;k++)
for (j = 0;j < 4;j++)
out->vecs[k][j] = MSG_ReadLittleFloat(sb);
// find an existing match for the texture if possible
dpsnprintf(filename, sizeof(filename), "textures/%s.wal", out->q2texture);
for (j = 0;j < loadmodel->num_texturesperskin;j++)
- if (!strcmp(filename, loadmodel->data_textures[j].name) && out->q2flags == loadmodel->data_textures[j].q2flags)
+ if (!strcmp(filename, loadmodel->data_textures[j].name)
+ && out->q2flags == loadmodel->data_textures[j].q2flags
+ && out->q2value == loadmodel->data_textures[j].q2value)
break;
// if we don't find the texture, store the new texture
if (j == loadmodel->num_texturesperskin)
int q2flags = out->q2flags;
unsigned char *walfile = NULL;
fs_offset_t walfilesize = 0;
- Mod_LoadTextureFromQ3Shader(tx, filename, true, true, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
+ Mod_LoadTextureFromQ3Shader(tx, filename, true, true, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
// now read the .wal file to get metadata (even if a .tga was overriding it, we still need the wal data)
walfile = FS_LoadFile(filename, tempmempool, true, &walfilesize);
if (walfile)
{
int w, h;
- char q2animname32c[32];
- LoadWAL_GetMetadata(walfile, (int)walfilesize, &w, &h, &q2flags, &tx->q2value, &tx->q2contents, q2animname32c);
+ LoadWAL_GetMetadata(walfile, (int)walfilesize, &w, &h, NULL, NULL, &tx->q2contents, NULL);
tx->width = w;
tx->height = h;
- tx->q2flags = q2flags;
Mem_Free(walfile);
}
+ else
+ {
+ tx->width = 16;
+ tx->height = 16;
+ }
+ tx->q2flags = out->q2flags;
+ tx->q2value = out->q2value;
// also modify the texture to have the correct contents and such based on flags
// note that we create multiple texture_t structures if q2flags differs
if (q2flags & Q2SURF_LIGHT)
{
// sky is a rather specific thing
q2flags &= ~Q2SURF_NODRAW; // quake2 had a slightly different meaning than we have in mind here...
- tx->basematerialflags = MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
+ tx->basematerialflags = MATERIALFLAG_SKY;
tx->supercontents = SUPERCONTENTS_SKY | SUPERCONTENTS_NODROP | SUPERCONTENTS_OPAQUE;
tx->surfaceflags = Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT | Q3SURFACEFLAG_NOMARKS | Q3SURFACEFLAG_NODLIGHT | Q3SURFACEFLAG_NOLIGHTMAP;
}
if (q2flags & Q2SURF_TRANS33)
{
tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED;
- tx->basealpha = 0.3333f;
+ tx->basealpha = 1.0f / 3.0f;
tx->supercontents &= ~SUPERCONTENTS_OPAQUE;
if (tx->q2contents & Q2CONTENTS_SOLID)
tx->q2contents = (tx->q2contents & ~Q2CONTENTS_SOLID) | Q2CONTENTS_WINDOW;
if (q2flags & Q2SURF_TRANS66)
{
tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED;
- tx->basealpha = 0.6667f;
+ tx->basealpha = 2.0f / 3.0f;
tx->supercontents &= ~SUPERCONTENTS_OPAQUE;
if (tx->q2contents & Q2CONTENTS_SOLID)
tx->q2contents = (tx->q2contents & ~Q2CONTENTS_SOLID) | Q2CONTENTS_WINDOW;
}
- if (q2flags & Q2SURF_FLOWING)
+ if ((q2flags & Q2SURF_FLOWING) && tx->materialshaderpass != NULL)
+ {
+ tx->materialshaderpass->tcmods[0].tcmod = Q3TCMOD_SCROLL;
+ if (q2flags & Q2SURF_WARP)
+ tx->materialshaderpass->tcmods[0].parms[0] = -0.5f;
+ else
+ tx->materialshaderpass->tcmods[0].parms[0] = -1.6f;
+ tx->materialshaderpass->tcmods[0].parms[1] = 0.0f;
+ }
+ if (q2flags & Q2SURF_ALPHATEST)
{
- tx->tcmods[0].tcmod = Q3TCMOD_SCROLL;
- tx->tcmods[0].parms[0] = -1.6f;
- tx->tcmods[0].parms[1] = 0.0f;
+ // KMQUAKE2 and other modded engines added this flag for lit alpha tested surfaces
+ tx->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_NOSHADOW;
+ }
+ else if (q2flags & (Q2SURF_TRANS33 | Q2SURF_TRANS66 | Q2SURF_WARP))
+ {
+ if (!mod_q2bsp_littransparentsurfaces.integer)
+ tx->basematerialflags |= MATERIALFLAG_FULLBRIGHT;
}
if (q2flags & Q2SURF_NODRAW)
{
tx->supercontents = Mod_Q2BSP_SuperContentsFromNativeContents(loadmodel, tx->q2contents);
// set the current values to the base values
tx->currentframe = tx;
- tx->currentskinframe = tx->skinframes[0];
+ tx->currentskinframe = tx->materialshaderpass != NULL ? tx->materialshaderpass->skinframes[0] : NULL;
tx->currentmaterialflags = tx->basematerialflags;
loadmodel->num_texturesperskin++;
loadmodel->num_textures = loadmodel->num_texturesperskin;
// if we encounter the textures out of order, the later ones won't mark the earlier ones in a sequence, so the earlier
for (i = 0, out = loadmodel->brushq1.texinfo;i < count;i++, out++)
{
- int j;
+ int j, k;
texture_t *t = loadmodel->data_textures + out->textureindex;
t->currentframe = t; // fix the reallocated pointer
int i, j, firstside, numsides, contents, count, maxplanes, q3surfaceflags, supercontents;
colplanef_t *planes;
int structsize = 12;
+ qboolean brushmissingtextures;
+ int numbrushesmissingtextures = 0;
+ int numcreatedtextures = 0;
if (sb->cursize % structsize)
Host_Error("Mod_Q2BSP_LoadBrushes: funny lump size in %s",loadmodel->name);
maxplanes = 0;
planes = NULL;
- for (i = 0;i < count;i++, out++)
+ for (i = 0; i < count; i++, out++)
{
firstside = MSG_ReadLittleLong(sb);
numsides = MSG_ReadLittleLong(sb);
out->firstbrushside = loadmodel->brush.data_brushsides + firstside;
out->numbrushsides = numsides;
- // not really the same... we should store the q2 contents
- out->texture = out->firstbrushside->texture;
// convert the contents to our values
supercontents = Mod_Q2BSP_SuperContentsFromNativeContents(loadmodel, contents);
+ // problem: q2bsp brushes have contents but not a texture
+ // problem: q2bsp brushsides *may* have a texture or may not
+ // problem: all brushsides and brushes must have a texture for trace_hittexture functionality to work, and the collision code is engineered around this assumption
+ // solution: nasty hacks
+ brushmissingtextures = false;
+ out->texture = NULL;
+ for (j = 0; j < out->numbrushsides; j++)
+ {
+ if (out->firstbrushside[j].texture == &mod_q1bsp_texture_solid)
+ brushmissingtextures = true;
+ else
+ {
+ // if we can find a matching texture on a brush side we can use it instead of creating one
+ if (out->firstbrushside[j].texture->supercontents == supercontents)
+ out->texture = out->firstbrushside[j].texture;
+ }
+ }
+ if (brushmissingtextures || out->texture == NULL)
+ {
+ numbrushesmissingtextures++;
+ // if we didn't find any appropriate texture (matching contents), we'll have to create one
+ // we could search earlier ones for a matching one but that can be slow
+ if (out->texture == NULL)
+ {
+ texture_t *validtexture;
+ validtexture = (texture_t *)Mem_Alloc(loadmodel->mempool, sizeof(texture_t));
+ dpsnprintf(validtexture->name, sizeof(validtexture->name), "brushcollision%i", numcreatedtextures);
+ validtexture->surfaceflags = 0;
+ validtexture->supercontents = supercontents;
+ numcreatedtextures++;
+ out->texture = validtexture;
+ }
+ // out->texture now contains a texture with appropriate contents, copy onto any missing sides
+ for (j = 0; j < out->numbrushsides; j++)
+ if (out->firstbrushside[j].texture == &mod_q1bsp_texture_solid)
+ out->firstbrushside[j].texture = out->texture;
+ }
+
+ // make a colbrush from the brush
+ q3surfaceflags = 0;
// make a list of mplane_t structs to construct a colbrush from
if (maxplanes < out->numbrushsides)
{
Mem_Free(planes);
planes = (colplanef_t *)Mem_Alloc(tempmempool, sizeof(colplanef_t) * maxplanes);
}
- q3surfaceflags = 0;
for (j = 0;j < out->numbrushsides;j++)
{
VectorCopy(out->firstbrushside[j].plane->normal, planes[j].normal);
planes[j].q3surfaceflags = out->firstbrushside[j].texture->surfaceflags;
planes[j].texture = out->firstbrushside[j].texture;
q3surfaceflags |= planes[j].q3surfaceflags;
- // LordHavoc: kind of a mean hack here, but we want the surfaces to have the brush contents
- out->firstbrushside[j].texture->supercontents = supercontents;
}
- // make the colbrush from the planes
out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents, q3surfaceflags, out->texture, true);
// this whole loop can take a while (e.g. on redstarrepublic4)
}
if (planes)
Mem_Free(planes);
+ if (numcreatedtextures)
+ Con_DPrintf("Mod_Q2BSP_LoadBrushes: %i brushes own sides that lack textures or have differing contents from the brush, %i textures have been created to describe these contents.\n", numbrushesmissingtextures, numcreatedtextures);
}
static void Mod_Q2BSP_LoadPOP(sizebuf_t *sb)
loadmodel->brushq3.data_deluxemaps = (rtexture_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
// allocate a texture pool if we need it
- if (loadmodel->texturepool == NULL && cls.state != ca_dedicated)
+ if (loadmodel->texturepool == NULL)
loadmodel->texturepool = R_AllocTexturePool();
mergedpixels = (unsigned char *) Mem_Alloc(tempmempool, mergedwidth * mergedheight * 4);
//Con_Printf("result: ambient %f %f %f diffuse %f %f %f diffusenormal %f %f %f\n", ambientcolor[0], ambientcolor[1], ambientcolor[2], diffusecolor[0], diffusecolor[1], diffusecolor[2], diffusenormal[0], diffusenormal[1], diffusenormal[2]);
}
-static int Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(mnode_t *node, double p1[3], double p2[3])
+static int Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(mnode_t *node, double p1[3], double p2[3], double endpos[3])
{
double t1, t2;
double midf, mid[3];
// or if start is solid and end is empty
// as these degenerate cases usually indicate the eye is in solid and
// should see the target point anyway
- ret = Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(node->children[side ], p1, mid);
+ ret = Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(node->children[side ], p1, mid, endpos);
if (ret != 0)
return ret;
- ret = Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(node->children[side ^ 1], mid, p2);
+ ret = Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(node->children[side ^ 1], mid, p2, endpos);
if (ret != 1)
return ret;
+ VectorCopy(mid, endpos);
return 2;
}
return ((mleaf_t *)node)->clusterindex < 0;
}
-static qboolean Mod_Q3BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end)
+static qboolean Mod_Q3BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
{
if (model->brush.submodel || mod_q3bsp_tracelineofsight_brushes.integer)
{
trace_t trace;
- model->TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK);
- return trace.fraction == 1;
+ model->TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK, 0, MATERIALFLAGMASK_TRANSLUCENT);
+ return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
}
else
{
- double tracestart[3], traceend[3];
+ double tracestart[3], traceend[3], traceendpos[3];
VectorCopy(start, tracestart);
VectorCopy(end, traceend);
- return !Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(model->brush.data_nodes, tracestart, traceend);
+ VectorCopy(end, traceendpos);
+ Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(model->brush.data_nodes, tracestart, traceend, traceendpos);
+ return BoxesOverlap(traceendpos, traceendpos, acceptmins, acceptmaxs);
}
}
-void Mod_CollisionBIH_TracePoint(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask)
+void Mod_CollisionBIH_TracePoint(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
const bih_t *bih;
const bih_leaf_t *leaf;
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
bih = &model->collision_bih;
if(!bih->nodes)
}
}
-static void Mod_CollisionBIH_TraceLineShared(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, const bih_t *bih)
+static void Mod_CollisionBIH_TraceLineShared(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, const bih_t *bih)
{
const bih_leaf_t *leaf;
const bih_node_t *node;
if (VectorCompare(start, end))
{
- Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask);
+ Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
// push first node
nodestackline[nodestackpos][0] = start[0];
sweepnodemaxs[0] = max(nodestart[0], nodeend[0]) + 1;
sweepnodemaxs[1] = max(nodestart[1], nodeend[1]) + 1;
sweepnodemaxs[2] = max(nodestart[2], nodeend[2]) + 1;
- if (!BoxesOverlap(sweepnodemins, sweepnodemaxs, node->mins, node->maxs))
+ if (!BoxesOverlap(sweepnodemins, sweepnodemaxs, node->mins, node->maxs) && !collision_bih_fullrecursion.integer)
continue;
if (node->type <= BIH_SPLITZ && nodestackpos+2 <= 1024)
{
d2 = node->backmax - nodeend[axis];
d3 = nodestart[axis] - node->frontmin;
d4 = nodeend[axis] - node->frontmin;
+ if (collision_bih_fullrecursion.integer)
+ d1 = d2 = d3 = d4 = 1; // force full recursion
switch((d1 < 0) | ((d2 < 0) << 1) | ((d3 < 0) << 2) | ((d4 < 0) << 3))
{
case 0: /* >>>> */ VectorCopy(nodestart, nodestackline[nodestackpos]); VectorCopy( nodeend, nodestackline[nodestackpos] + 3); nodestack[nodestackpos++] = node->back; VectorCopy(nodestart, nodestackline[nodestackpos]); VectorCopy( nodeend, nodestackline[nodestackpos] + 3); nodestack[nodestackpos++] = node->front; break;
}
}
-void Mod_CollisionBIH_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+void Mod_CollisionBIH_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
if (VectorCompare(start, end))
{
- Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask);
+ Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
- Mod_CollisionBIH_TraceLineShared(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, &model->collision_bih);
+ Mod_CollisionBIH_TraceLineShared(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, &model->collision_bih);
}
-void Mod_CollisionBIH_TraceBrush(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *thisbrush_start, colbrushf_t *thisbrush_end, int hitsupercontentsmask)
+void Mod_CollisionBIH_TraceBrush(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *thisbrush_start, colbrushf_t *thisbrush_end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
const bih_t *bih;
const bih_leaf_t *leaf;
if (mod_q3bsp_optimizedtraceline.integer && VectorCompare(thisbrush_start->mins, thisbrush_start->maxs) && VectorCompare(thisbrush_end->mins, thisbrush_end->maxs))
{
if (VectorCompare(thisbrush_start->mins, thisbrush_end->mins))
- Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, thisbrush_start->mins, hitsupercontentsmask);
+ Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, thisbrush_start->mins, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
else
- Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, thisbrush_start->mins, thisbrush_end->mins, hitsupercontentsmask);
+ Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, thisbrush_start->mins, thisbrush_end->mins, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
// calculate tracebox-like parameters for efficient culling
VectorMAM(0.5f, thisbrush_start->mins, 0.5f, thisbrush_start->maxs, start);
}
}
-void Mod_CollisionBIH_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+void Mod_CollisionBIH_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
colboxbrushf_t thisbrush_start, thisbrush_end;
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
VectorAdd(end, boxmaxs, boxendmaxs);
Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
- Mod_CollisionBIH_TraceBrush(model, frameblend, skeleton, trace, &thisbrush_start.brush, &thisbrush_end.brush, hitsupercontentsmask);
+ Mod_CollisionBIH_TraceBrush(model, frameblend, skeleton, trace, &thisbrush_start.brush, &thisbrush_end.brush, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
}
int Mod_CollisionBIH_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
{
trace_t trace;
- Mod_CollisionBIH_TracePoint(model, NULL, NULL, &trace, point, 0);
+ Mod_CollisionBIH_TracePoint(model, NULL, NULL, &trace, point, 0, 0, 0);
return trace.startsupercontents;
}
-qboolean Mod_CollisionBIH_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end)
+qboolean Mod_CollisionBIH_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
{
trace_t trace;
- Mod_CollisionBIH_TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK);
- return trace.fraction == 1;
+ Mod_CollisionBIH_TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK, 0, MATERIALFLAGMASK_TRANSLUCENT);
+ return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
}
-void Mod_CollisionBIH_TracePoint_Mesh(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask)
+void Mod_CollisionBIH_TracePoint_Mesh(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
#if 0
// broken - needs to be modified to count front faces and backfaces to figure out if it is in solid
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
#if 0
- Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
+ Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
hitsupercontents = trace->hitsupercontents;
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
trace->startsupercontents = hitsupercontents;
#endif
}
VectorSet(end, start[0], start[1], model->normalmins[2]);
memset(&trace, 0, sizeof(trace));
trace.fraction = 1;
- trace.hitsupercontentsmask = 0;
- Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
+ trace.hitsupercontentsmask = hitsupercontentsmask;
+ trace.skipsupercontentsmask = skipsupercontentsmask;
+ trace.skipmaterialflagsmask = skipmaterialflagsmask;
+ Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return trace.hitsupercontents;
#else
return 0;
static int markframe = 0;
-static void Mod_Q3BSP_TracePoint(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask)
+static void Mod_Q3BSP_TracePoint(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
int i;
q3mbrush_t *brush;
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
if (mod_collision_bih.integer)
- Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask);
+ Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
else if (model->brush.submodel)
{
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
Mod_Q3BSP_TracePoint_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, ++markframe);
}
-static void Mod_Q3BSP_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+static void Mod_Q3BSP_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
int i;
float segmentmins[3], segmentmaxs[3];
if (VectorCompare(start, end))
{
- Mod_Q3BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask);
+ Mod_Q3BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
segmentmins[0] = min(start[0], end[0]) - 1;
segmentmins[1] = min(start[1], end[1]) - 1;
segmentmins[2] = min(start[2], end[2]) - 1;
segmentmaxs[1] = max(start[1], end[1]) + 1;
segmentmaxs[2] = max(start[2], end[2]) + 1;
if (mod_collision_bih.integer)
- Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
+ Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
else if (model->brush.submodel)
{
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs);
}
-static void Mod_Q3BSP_TraceBrush(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *start, colbrushf_t *end, int hitsupercontentsmask)
+static void Mod_Q3BSP_TraceBrush(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *start, colbrushf_t *end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
float segmentmins[3], segmentmaxs[3];
int i;
if (mod_q3bsp_optimizedtraceline.integer && VectorCompare(start->mins, start->maxs) && VectorCompare(end->mins, end->maxs))
{
if (VectorCompare(start->mins, end->mins))
- Mod_Q3BSP_TracePoint(model, frameblend, skeleton, trace, start->mins, hitsupercontentsmask);
+ Mod_Q3BSP_TracePoint(model, frameblend, skeleton, trace, start->mins, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
else
- Mod_Q3BSP_TraceLine(model, frameblend, skeleton, trace, start->mins, end->mins, hitsupercontentsmask);
+ Mod_Q3BSP_TraceLine(model, frameblend, skeleton, trace, start->mins, end->mins, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
return;
}
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
segmentmins[0] = min(start->mins[0], end->mins[0]) - 1;
segmentmins[1] = min(start->mins[1], end->mins[1]) - 1;
segmentmins[2] = min(start->mins[2], end->mins[2]) - 1;
segmentmaxs[1] = max(start->maxs[1], end->maxs[1]) + 1;
segmentmaxs[2] = max(start->maxs[2], end->maxs[2]) + 1;
if (mod_collision_bih.integer)
- Mod_CollisionBIH_TraceBrush(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
+ Mod_CollisionBIH_TraceBrush(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
else if (model->brush.submodel)
{
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, end, ++markframe, segmentmins, segmentmaxs);
}
-static void Mod_Q3BSP_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_Q3BSP_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
colboxbrushf_t thisbrush_start, thisbrush_end;
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
VectorAdd(end, boxmaxs, boxendmaxs);
Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
- Mod_Q3BSP_TraceBrush(model, frameblend, skeleton, trace, &thisbrush_start.brush, &thisbrush_end.brush, hitsupercontentsmask);
+ Mod_Q3BSP_TraceBrush(model, frameblend, skeleton, trace, &thisbrush_start.brush, &thisbrush_end.brush, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
}
static int Mod_Q3BSP_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
return supercontents;
}
-void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
{
- Mod_CollisionBIH_TraceLineShared(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, &model->render_bih);
+ Mod_CollisionBIH_TraceLineShared(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, &model->render_bih);
}
int maxvn = 0, numvn = 1;
char *texturenames = NULL;
float dist, modelradius, modelyawradius, yawradius;
- float *v = NULL;
- float *vt = NULL;
- float *vn = NULL;
+ float *obj_v = NULL;
+ float *obj_vt = NULL;
+ float *obj_vn = NULL;
float mins[3];
float maxs[3];
float corner[3];
skinfile_t *skinfiles = NULL;
unsigned char *data = NULL;
int *submodelfirstsurface;
- msurface_t *surface;
+ msurface_t *tempsurface;
msurface_t *tempsurfaces;
memset(&vfirst, 0, sizeof(vfirst));
if (maxv <= numv)
{
maxv = max(maxv * 2, 1024);
- v = (float *)Mem_Realloc(tempmempool, v, maxv * sizeof(float[3]));
+ obj_v = (float *)Mem_Realloc(tempmempool, obj_v, maxv * sizeof(float[3]));
}
if(mod_obj_orientation.integer)
{
- v[numv*3+0] = atof(argv[1]);
- v[numv*3+2] = atof(argv[2]);
- v[numv*3+1] = atof(argv[3]);
+ obj_v[numv*3+0] = atof(argv[1]);
+ obj_v[numv*3+2] = atof(argv[2]);
+ obj_v[numv*3+1] = atof(argv[3]);
}
else
{
- v[numv*3+0] = atof(argv[1]);
- v[numv*3+1] = atof(argv[2]);
- v[numv*3+2] = atof(argv[3]);
+ obj_v[numv*3+0] = atof(argv[1]);
+ obj_v[numv*3+1] = atof(argv[2]);
+ obj_v[numv*3+2] = atof(argv[3]);
}
numv++;
}
if (maxvt <= numvt)
{
maxvt = max(maxvt * 2, 1024);
- vt = (float *)Mem_Realloc(tempmempool, vt, maxvt * sizeof(float[2]));
+ obj_vt = (float *)Mem_Realloc(tempmempool, obj_vt, maxvt * sizeof(float[2]));
}
- vt[numvt*2+0] = atof(argv[1]);
- vt[numvt*2+1] = 1-atof(argv[2]);
+ obj_vt[numvt*2+0] = atof(argv[1]);
+ obj_vt[numvt*2+1] = 1-atof(argv[2]);
numvt++;
}
else if (!strcmp(argv[0], "vn"))
if (maxvn <= numvn)
{
maxvn = max(maxvn * 2, 1024);
- vn = (float *)Mem_Realloc(tempmempool, vn, maxvn * sizeof(float[3]));
+ obj_vn = (float *)Mem_Realloc(tempmempool, obj_vn, maxvn * sizeof(float[3]));
}
if(mod_obj_orientation.integer)
{
- vn[numvn*3+0] = atof(argv[1]);
- vn[numvn*3+2] = atof(argv[2]);
- vn[numvn*3+1] = atof(argv[3]);
+ obj_vn[numvn*3+0] = atof(argv[1]);
+ obj_vn[numvn*3+2] = atof(argv[2]);
+ obj_vn[numvn*3+1] = atof(argv[3]);
}
else
{
- vn[numvn*3+0] = atof(argv[1]);
- vn[numvn*3+1] = atof(argv[2]);
- vn[numvn*3+2] = atof(argv[3]);
+ obj_vn[numvn*3+0] = atof(argv[1]);
+ obj_vn[numvn*3+1] = atof(argv[2]);
+ obj_vn[numvn*3+2] = atof(argv[3]);
}
numvn++;
}
vcurrent.nextindex = -1;
vcurrent.textureindex = textureindex;
vcurrent.submodelindex = submodelindex;
- if (v && index1 >= 0 && index1 < numv)
- VectorCopy(v + 3*index1, vcurrent.v);
- if (vt && index2 >= 0 && index2 < numvt)
- Vector2Copy(vt + 2*index2, vcurrent.vt);
- if (vn && index3 >= 0 && index3 < numvn)
- VectorCopy(vn + 3*index3, vcurrent.vn);
+ if (obj_v && index1 >= 0 && index1 < numv)
+ VectorCopy(obj_v + 3*index1, vcurrent.v);
+ if (obj_vt && index2 >= 0 && index2 < numvt)
+ Vector2Copy(obj_vt + 2*index2, vcurrent.vt);
+ if (obj_vn && index3 >= 0 && index3 < numvn)
+ VectorCopy(obj_vn + 3*index3, vcurrent.vn);
if (numtriangles == 0)
{
VectorCopy(vcurrent.v, mins);
// allocate storage for the worst case number of surfaces, later we resize
tempsurfaces = (msurface_t *)Mem_Alloc(loadmodel->mempool, numtextures * loadmodel->brush.numsubmodels * sizeof(msurface_t));
submodelfirstsurface = (int *)Mem_Alloc(loadmodel->mempool, (loadmodel->brush.numsubmodels+1) * sizeof(int));
- surface = tempsurfaces;
+ tempsurface = tempsurfaces;
for (submodelindex = 0;submodelindex < loadmodel->brush.numsubmodels;submodelindex++)
{
submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
surfacevertices = 0;
surfaceelements = 0;
// we hack in a texture index in the surface to be fixed up later...
- surface->texture = (texture_t *)((size_t)textureindex);
+ tempsurface->texture = (texture_t *)((size_t)textureindex);
// calculate bounds as we go
- VectorCopy(thisvertex->v, surface->mins);
- VectorCopy(thisvertex->v, surface->maxs);
+ VectorCopy(thisvertex->v, tempsurface->mins);
+ VectorCopy(thisvertex->v, tempsurface->maxs);
for (;vertexindex < numtriangles*3;vertexindex++)
{
thisvertex = vertices + vertexindex;
if (thisvertex->textureindex != textureindex)
continue;
// add vertex to surface bounds
- surface->mins[0] = min(surface->mins[0], thisvertex->v[0]);
- surface->mins[1] = min(surface->mins[1], thisvertex->v[1]);
- surface->mins[2] = min(surface->mins[2], thisvertex->v[2]);
- surface->maxs[0] = max(surface->maxs[0], thisvertex->v[0]);
- surface->maxs[1] = max(surface->maxs[1], thisvertex->v[1]);
- surface->maxs[2] = max(surface->maxs[2], thisvertex->v[2]);
+ tempsurface->mins[0] = min(tempsurface->mins[0], thisvertex->v[0]);
+ tempsurface->mins[1] = min(tempsurface->mins[1], thisvertex->v[1]);
+ tempsurface->mins[2] = min(tempsurface->mins[2], thisvertex->v[2]);
+ tempsurface->maxs[0] = max(tempsurface->maxs[0], thisvertex->v[0]);
+ tempsurface->maxs[1] = max(tempsurface->maxs[1], thisvertex->v[1]);
+ tempsurface->maxs[2] = max(tempsurface->maxs[2], thisvertex->v[2]);
// add the vertex if it is not found in the merged set, and
// get its index (triangle element) for the surface
vertexhashindex = (unsigned int)(thisvertex->v[0] * 3571 + thisvertex->v[0] * 1777 + thisvertex->v[0] * 457) % (unsigned int)vertexhashsize;
surfaceelements++;
}
surfacetriangles = surfaceelements / 3;
- surface->num_vertices = surfacevertices;
- surface->num_triangles = surfacetriangles;
- surface->num_firstvertex = firstvertex;
- surface->num_firsttriangle = firsttriangle;
- firstvertex += surface->num_vertices;
- firsttriangle += surface->num_triangles;
- surface++;
+ tempsurface->num_vertices = surfacevertices;
+ tempsurface->num_triangles = surfacetriangles;
+ tempsurface->num_firstvertex = firstvertex;
+ tempsurface->num_firsttriangle = firsttriangle;
+ firstvertex += tempsurface->num_vertices;
+ firsttriangle += tempsurface->num_triangles;
+ tempsurface++;
loadmodel->num_surfaces++;
}
}
// free data
Mem_Free(vertices);
Mem_Free(texturenames);
- Mem_Free(v);
- Mem_Free(vt);
- Mem_Free(vn);
+ Mem_Free(obj_v);
+ Mem_Free(obj_vt);
+ Mem_Free(obj_vn);
Mem_Free(vertexhashtable);
Mem_Free(vertexhashdata);
for (j = 0;j < mod->nummodelsurfaces;j++)
{
const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
- const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
+ const float *v3f = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
int k;
if (!surface->num_vertices)
continue;
if (!l)
{
l = true;
- VectorCopy(v, mod->normalmins);
- VectorCopy(v, mod->normalmaxs);
+ VectorCopy(v3f, mod->normalmins);
+ VectorCopy(v3f, mod->normalmaxs);
}
- for (k = 0;k < surface->num_vertices;k++, v += 3)
+ for (k = 0;k < surface->num_vertices;k++, v3f += 3)
{
- mod->normalmins[0] = min(mod->normalmins[0], v[0]);
- mod->normalmins[1] = min(mod->normalmins[1], v[1]);
- mod->normalmins[2] = min(mod->normalmins[2], v[2]);
- mod->normalmaxs[0] = max(mod->normalmaxs[0], v[0]);
- mod->normalmaxs[1] = max(mod->normalmaxs[1], v[1]);
- mod->normalmaxs[2] = max(mod->normalmaxs[2], v[2]);
+ mod->normalmins[0] = min(mod->normalmins[0], v3f[0]);
+ mod->normalmins[1] = min(mod->normalmins[1], v3f[1]);
+ mod->normalmins[2] = min(mod->normalmins[2], v3f[2]);
+ mod->normalmaxs[0] = max(mod->normalmaxs[0], v3f[0]);
+ mod->normalmaxs[1] = max(mod->normalmaxs[1], v3f[1]);
+ mod->normalmaxs[2] = max(mod->normalmaxs[2], v3f[2]);
}
}
corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));