cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"};
cvar_t mod_q3bsp_curves_subdivide_level = {0, "mod_q3bsp_curves_subdivide_level", "2"};
cvar_t mod_q3bsp_curves_collisions = {0, "mod_q3bsp_curves_collisions", "1"};
-cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "1"};
+cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "0"};
+static void Mod_Q1BSP_Collision_Init (void);
void Mod_BrushInit(void)
{
// Cvar_RegisterVariable(&r_subdivide_size);
Cvar_RegisterVariable(&mod_q3bsp_curves_collisions);
Cvar_RegisterVariable(&mod_q3bsp_optimizedtraceline);
memset(mod_q1bsp_novis, 0xff, sizeof(mod_q1bsp_novis));
+ Mod_Q1BSP_Collision_Init();
}
static mleaf_t *Mod_Q1BSP_PointInLeaf(model_t *model, const vec3_t p)
// if the first leaf is solid, set startsolid
if (t->trace->allsolid)
t->trace->startsolid = true;
+#if COLLISIONPARANOID >= 3
+ Con_Printf("S");
+#endif
return HULLCHECKSTATE_SOLID;
}
else
{
t->trace->allsolid = false;
+#if COLLISIONPARANOID >= 3
+ Con_Printf("E");
+#endif
return HULLCHECKSTATE_EMPTY;
}
}
{
if (t2 < 0)
{
+#if COLLISIONPARANOID >= 3
+ Con_Printf("<");
+#endif
num = node->children[1];
goto loc0;
}
{
if (t2 >= 0)
{
+#if COLLISIONPARANOID >= 3
+ Con_Printf(">");
+#endif
num = node->children[0];
goto loc0;
}
// the line intersects, find intersection point
// LordHavoc: this uses the original trace for maximum accuracy
+#if COLLISIONPARANOID >= 3
+ Con_Printf("M");
+#endif
if (plane->type < 3)
{
t1 = t->start[plane->type] - plane->dist;
midf = t1 / (t1 - t2);
t->trace->fraction = bound(0.0f, midf, 1.0);
+#if COLLISIONPARANOID >= 3
+ Con_Printf("D");
+#endif
return HULLCHECKSTATE_DONE;
}
-static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
+#if COLLISIONPARANOID < 2
+static int Mod_Q1BSP_RecursiveHullCheckPoint(RecursiveHullCheckTraceInfo_t *t, int num)
+{
+ while (num >= 0)
+ num = t->hull->clipnodes[num].children[(t->hull->planes[t->hull->clipnodes[num].planenum].type < 3 ? t->start[t->hull->planes[t->hull->clipnodes[num].planenum].type] : DotProduct(t->hull->planes[t->hull->clipnodes[num].planenum].normal, t->start)) < t->hull->planes[t->hull->clipnodes[num].planenum].dist];
+ num = Mod_Q1BSP_SuperContentsFromNativeContents(NULL, num);
+ t->trace->startsupercontents |= num;
+ if (num & SUPERCONTENTS_LIQUIDSMASK)
+ t->trace->inwater = true;
+ if (num == 0)
+ t->trace->inopen = true;
+ if (num & t->trace->hitsupercontentsmask)
+ {
+ t->trace->allsolid = t->trace->startsolid = true;
+ return HULLCHECKSTATE_SOLID;
+ }
+ else
+ {
+ t->trace->allsolid = t->trace->startsolid = false;
+ return HULLCHECKSTATE_EMPTY;
+ }
+}
+#endif
+
+static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
{
// this function currently only supports same size start and end
double boxsize[3];
rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
else if (model->brush.ishlbsp)
{
- if (boxsize[0] <= 32)
+ // LordHavoc: this has to have a minor tolerance (the .1) because of
+ // minor float precision errors from the box being transformed around
+ if (boxsize[0] < 32.1)
{
if (boxsize[2] < 54) // pick the nearest of 36 or 72
rhc.hull = &model->brushq1.hulls[3]; // 32x32x36
}
else
{
- if (boxsize[0] <= 32)
+ // LordHavoc: this has to have a minor tolerance (the .1) because of
+ // minor float precision errors from the box being transformed around
+ if (boxsize[0] < 32.1)
rhc.hull = &model->brushq1.hulls[1]; // 32x32x56
else
rhc.hull = &model->brushq1.hulls[2]; // 64x64x88
VectorSubtract(boxstartmins, rhc.hull->clip_mins, rhc.start);
VectorSubtract(boxendmins, rhc.hull->clip_mins, rhc.end);
VectorSubtract(rhc.end, rhc.start, rhc.dist);
+#if COLLISIONPARANOID >= 2
+ Con_Printf("t(%f %f %f,%f %f %f,%i %f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2], rhc.hull - model->brushq1.hulls, rhc.hull->clip_mins[0], rhc.hull->clip_mins[1], rhc.hull->clip_mins[2]);
Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+ Con_Printf("\n");
+#else
+ if (DotProduct(rhc.dist, rhc.dist))
+ Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+ else
+ Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
+#endif
+}
+
+static hull_t box_hull;
+static dclipnode_t box_clipnodes[6];
+static mplane_t box_planes[6];
+
+static void Mod_Q1BSP_Collision_Init (void)
+{
+ int i;
+ int side;
+
+ //Set up the planes and clipnodes so that the six floats of a bounding box
+ //can just be stored out and get a proper hull_t structure.
+
+ box_hull.clipnodes = box_clipnodes;
+ box_hull.planes = box_planes;
+ box_hull.firstclipnode = 0;
+ box_hull.lastclipnode = 5;
+
+ for (i = 0;i < 6;i++)
+ {
+ box_clipnodes[i].planenum = i;
+
+ side = i&1;
+
+ box_clipnodes[i].children[side] = CONTENTS_EMPTY;
+ if (i != 5)
+ box_clipnodes[i].children[side^1] = i + 1;
+ else
+ box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
+
+ box_planes[i].type = i>>1;
+ box_planes[i].normal[i>>1] = 1;
+ }
+}
+
+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)
+{
+#if 1
+ colbrushf_t cbox;
+ colplanef_t cbox_planes[6];
+ cbox.supercontents = boxsupercontents;
+ cbox.numplanes = 6;
+ cbox.numpoints = 0;
+ cbox.numtriangles = 0;
+ cbox.planes = cbox_planes;
+ cbox.points = NULL;
+ cbox.elements = NULL;
+ cbox.markframe = 0;
+ cbox.mins[0] = 0;
+ cbox.mins[1] = 0;
+ cbox.mins[2] = 0;
+ cbox.maxs[0] = 0;
+ cbox.maxs[1] = 0;
+ cbox.maxs[2] = 0;
+ cbox_planes[0].normal[0] = 1;cbox_planes[0].normal[1] = 0;cbox_planes[0].normal[2] = 0;cbox_planes[0].dist = cmaxs[0] - mins[0];
+ cbox_planes[1].normal[0] = -1;cbox_planes[1].normal[1] = 0;cbox_planes[1].normal[2] = 0;cbox_planes[1].dist = maxs[0] - cmins[0];
+ cbox_planes[2].normal[0] = 0;cbox_planes[2].normal[1] = 1;cbox_planes[2].normal[2] = 0;cbox_planes[2].dist = cmaxs[1] - mins[1];
+ cbox_planes[3].normal[0] = 0;cbox_planes[3].normal[1] = -1;cbox_planes[3].normal[2] = 0;cbox_planes[3].dist = maxs[1] - cmins[1];
+ cbox_planes[4].normal[0] = 0;cbox_planes[4].normal[1] = 0;cbox_planes[4].normal[2] = 1;cbox_planes[4].dist = cmaxs[2] - mins[2];
+ cbox_planes[5].normal[0] = 0;cbox_planes[5].normal[1] = 0;cbox_planes[5].normal[2] = -1;cbox_planes[5].dist = maxs[2] - cmins[2];
+ memset(trace, 0, sizeof(trace_t));
+ trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->fraction = 1;
+ Collision_TraceLineBrushFloat(trace, start, end, &cbox, &cbox);
+#else
+ RecursiveHullCheckTraceInfo_t rhc;
+ // fill in a default trace
+ memset(&rhc, 0, sizeof(rhc));
+ memset(trace, 0, sizeof(trace_t));
+ //To keep everything totally uniform, bounding boxes are turned into small
+ //BSP trees instead of being compared directly.
+ // create a temp hull from bounding box sizes
+ box_planes[0].dist = cmaxs[0] - mins[0];
+ box_planes[1].dist = cmins[0] - maxs[0];
+ box_planes[2].dist = cmaxs[1] - mins[1];
+ box_planes[3].dist = cmins[1] - maxs[1];
+ box_planes[4].dist = cmaxs[2] - mins[2];
+ box_planes[5].dist = cmins[2] - maxs[2];
+#if COLLISIONPARANOID >= 3
+ Con_Printf("box_planes %f:%f %f:%f %f:%f\ncbox %f %f %f:%f %f %f\nbox %f %f %f:%f %f %f\n", box_planes[0].dist, box_planes[1].dist, box_planes[2].dist, box_planes[3].dist, box_planes[4].dist, box_planes[5].dist, cmins[0], cmins[1], cmins[2], cmaxs[0], cmaxs[1], cmaxs[2], mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2]);
+#endif
+ // trace a line through the generated clipping hull
+ //rhc.boxsupercontents = boxsupercontents;
+ rhc.hull = &box_hull;
+ rhc.trace = trace;
+ rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+ rhc.trace->fraction = 1;
+ rhc.trace->allsolid = true;
+ VectorCopy(start, rhc.start);
+ VectorCopy(end, rhc.end);
+ VectorSubtract(rhc.end, rhc.start, rhc.dist);
+ Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+ VectorMA(rhc.start, rhc.trace->fraction, rhc.dist, rhc.trace->endpos);
+ if (rhc.trace->startsupercontents)
+ rhc.trace->startsupercontents = boxsupercontents;
+#endif
}
static int Mod_Q1BSP_LightPoint_RecursiveBSPNode(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz)
{
if (in == inend)
{
- Con_Printf("Mod_Q1BSP_DecompressVis: input underrun\n");
+ Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\"\n", loadmodel->name);
return;
}
c = *in++;
*out++ = c;
else
{
+ if (in == inend)
+ {
+ Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\"\n", loadmodel->name);
+ return;
+ }
for (c = *in++;c > 0;c--)
{
if (out == outend)
{
- Con_Printf("Mod_Q1BSP_DecompressVis: output overrun\n");
+ Con_DPrintf("Mod_Q1BSP_DecompressVis: output overrun on model \"%s\"\n", loadmodel->name);
return;
}
*out++ = 0;
Host_Error("Mod_Q1BSP_Load: %s has wrong version number(%i should be %i(Quake) or 30(HalfLife))", mod->name, i, BSPVERSION);
mod->brush.ishlbsp = i == 30;
+ mod->soundfromcenter = true;
+ mod->TraceBox = Mod_Q1BSP_TraceBox;
mod->brush.SuperContentsFromNativeContents = Mod_Q1BSP_SuperContentsFromNativeContents;
mod->brush.NativeContentsFromSuperContents = Mod_Q1BSP_NativeContentsFromSuperContents;
mod->brush.GetPVS = Mod_Q1BSP_GetPVS;
mod->brush.BoxTouchingPVS = Mod_Q1BSP_BoxTouchingPVS;
mod->brush.LightPoint = Mod_Q1BSP_LightPoint;
mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
- mod->brush.TraceBox = Mod_Q1BSP_TraceBox;
mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
mod->brush.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize;
mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
q3dtexture_t *in;
q3mtexture_t *out;
int i, count;
+ int j, c;
+ fssearch_t *search;
+ char *f;
+ const char *text;
+ int flags;
+ char shadername[Q3PATHLENGTH];
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
for (i = 0;i < count;i++, in++, out++)
{
+ out->number = i;
strlcpy (out->name, in->name, sizeof (out->name));
out->surfaceflags = LittleLong(in->surfaceflags);
out->nativecontents = LittleLong(in->contents);
out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, out->nativecontents);
- out->renderflags = 0;
- if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk"))
- out->renderflags |= Q3MTEXTURERENDERFLAGS_NODRAW;
- if (!strncmp(out->name, "textures/skies/", 15))
- out->renderflags |= Q3MTEXTURERENDERFLAGS_SKY;
-
- out->number = i;
Mod_LoadSkinFrame(&out->skin, out->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true);
+ out->surfaceparms = -1;
}
+
+ // do a quick parse of shader files to get surfaceparms
+ if ((search = FS_Search("scripts/*.shader", true, false)))
+ {
+ for (i = 0;i < search->numfilenames;i++)
+ {
+ if ((f = FS_LoadFile(search->filenames[i], false)))
+ {
+ text = f;
+ while (COM_ParseToken(&text, false))
+ {
+ snprintf(shadername, sizeof(shadername), "%s", com_token);
+ flags = 0;
+ if (COM_ParseToken(&text, false) && !strcmp(com_token, "{"))
+ {
+ while (COM_ParseToken(&text, false))
+ {
+ if (!strcmp(com_token, "}"))
+ break;
+ else if (!strcmp(com_token, "{"))
+ {
+ while (COM_ParseToken(&text, false))
+ {
+ if (!strcmp(com_token, "}"))
+ break;
+ }
+ }
+ else if (!strcmp(com_token, "surfaceparm"))
+ {
+ if (COM_ParseToken(&text, true) && strcmp(com_token, "\n"))
+ {
+ if (!strcmp(com_token, "alphashadow"))
+ flags |= Q3SURFACEPARM_ALPHASHADOW;
+ else if (!strcmp(com_token, "areaportal"))
+ flags |= Q3SURFACEPARM_AREAPORTAL;
+ else if (!strcmp(com_token, "clusterportal"))
+ flags |= Q3SURFACEPARM_CLUSTERPORTAL;
+ else if (!strcmp(com_token, "detail"))
+ flags |= Q3SURFACEPARM_DETAIL;
+ else if (!strcmp(com_token, "donotenter"))
+ flags |= Q3SURFACEPARM_DONOTENTER;
+ else if (!strcmp(com_token, "fog"))
+ flags |= Q3SURFACEPARM_FOG;
+ else if (!strcmp(com_token, "lava"))
+ flags |= Q3SURFACEPARM_LAVA;
+ else if (!strcmp(com_token, "lightfilter"))
+ flags |= Q3SURFACEPARM_LIGHTFILTER;
+ else if (!strcmp(com_token, "metalsteps"))
+ flags |= Q3SURFACEPARM_METALSTEPS;
+ else if (!strcmp(com_token, "nodamage"))
+ flags |= Q3SURFACEPARM_NODAMAGE;
+ else if (!strcmp(com_token, "nodlight"))
+ flags |= Q3SURFACEPARM_NODLIGHT;
+ else if (!strcmp(com_token, "nodraw"))
+ flags |= Q3SURFACEPARM_NODRAW;
+ else if (!strcmp(com_token, "nodrop"))
+ flags |= Q3SURFACEPARM_NODROP;
+ else if (!strcmp(com_token, "noimpact"))
+ flags |= Q3SURFACEPARM_NOIMPACT;
+ else if (!strcmp(com_token, "nolightmap"))
+ flags |= Q3SURFACEPARM_NOLIGHTMAP;
+ else if (!strcmp(com_token, "nomarks"))
+ flags |= Q3SURFACEPARM_NOMARKS;
+ else if (!strcmp(com_token, "nomipmaps"))
+ flags |= Q3SURFACEPARM_NOMIPMAPS;
+ else if (!strcmp(com_token, "nonsolid"))
+ flags |= Q3SURFACEPARM_NONSOLID;
+ else if (!strcmp(com_token, "origin"))
+ flags |= Q3SURFACEPARM_ORIGIN;
+ else if (!strcmp(com_token, "playerclip"))
+ flags |= Q3SURFACEPARM_PLAYERCLIP;
+ else if (!strcmp(com_token, "sky"))
+ flags |= Q3SURFACEPARM_SKY;
+ else if (!strcmp(com_token, "slick"))
+ flags |= Q3SURFACEPARM_SLICK;
+ else if (!strcmp(com_token, "slime"))
+ flags |= Q3SURFACEPARM_SLIME;
+ else if (!strcmp(com_token, "structural"))
+ flags |= Q3SURFACEPARM_STRUCTURAL;
+ else if (!strcmp(com_token, "trans"))
+ flags |= Q3SURFACEPARM_TRANS;
+ else if (!strcmp(com_token, "water"))
+ flags |= Q3SURFACEPARM_WATER;
+ else
+ Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], com_token);
+ if (!COM_ParseToken(&text, true) || strcmp(com_token, "\n"))
+ {
+ Con_Printf("%s parsing error: surfaceparm only takes one parameter.\n", search->filenames[i]);
+ goto parseerror;
+ }
+ }
+ else
+ {
+ Con_Printf("%s parsing error: surfaceparm expects a parameter.\n", search->filenames[i]);
+ goto parseerror;
+ }
+ }
+ else
+ {
+ // look for linebreak or }
+ while(COM_ParseToken(&text, true) && strcmp(com_token, "\n") && strcmp(com_token, "}"));
+ // break out to top level if it was }
+ if (!strcmp(com_token, "}"))
+ break;
+ }
+ }
+ // add shader to list (shadername and flags)
+ // actually here we just poke into the texture settings
+ for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++)
+ if (!strcmp(out->name, shadername))
+ out->surfaceparms = flags;
+ }
+ else
+ {
+ Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[i], com_token);
+ goto parseerror;
+ }
+ }
+parseerror:
+ Mem_Free(f);
+ }
+ }
+ }
+
+ c = 0;
+ for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++)
+ {
+ if (out->surfaceparms == -1)
+ {
+ c++;
+ Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name);
+ out->surfaceparms = 0;
+ // these are defaults
+ if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")
+ || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw"))
+ out->surfaceparms |= Q3SURFACEPARM_NODRAW;
+ if (!strncmp(out->name, "textures/skies/", 15))
+ out->surfaceparms |= Q3SURFACEPARM_SKY;
+ if (R_TextureHasAlpha(out->skin.base))
+ out->surfaceparms |= Q3SURFACEPARM_TRANS;
+ }
+ }
+ Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
}
static void Mod_Q3BSP_LoadPlanes(lump_t *l)
q3mbrush_t *out;
int i, j, n, c, count, maxplanes;
mplane_t *planes;
+ winding_t *temp1, *temp2;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
loadmodel->brushq3.data_brushes = out;
loadmodel->brushq3.num_brushes = count;
+ temp1 = Winding_New(64);
+ temp2 = Winding_New(64);
+
maxplanes = 0;
planes = NULL;
planes[j].dist = out->firstbrushside[j].plane->dist;
}
// make the colbrush from the planes
- out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents);
+ out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents, temp1, temp2);
}
if (planes)
Mem_Free(planes);
+ Winding_Free(temp1);
+ Winding_Free(temp2);
}
static void Mod_Q3BSP_LoadEffects(lump_t *l)
if (l->filelen % sizeof(*in))
Host_Error("Mod_Q3BSP_LoadVertices: funny lump size in %s",loadmodel->name);
loadmodel->brushq3.num_vertices = count = l->filelen / sizeof(*in);
- loadmodel->brushq3.data_vertex3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
- loadmodel->brushq3.data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
- loadmodel->brushq3.data_texcoordlightmap2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
- loadmodel->brushq3.data_svector3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
- loadmodel->brushq3.data_tvector3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
- loadmodel->brushq3.data_normal3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
- loadmodel->brushq3.data_color4f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[4]));
+ loadmodel->brushq3.data_vertex3f = Mem_Alloc(loadmodel->mempool, count * (sizeof(float) * (3 + 2 + 2 + 3 + 3 + 3 + 4)));
+ loadmodel->brushq3.data_texcoordtexture2f = loadmodel->brushq3.data_vertex3f + count * 3;
+ loadmodel->brushq3.data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordtexture2f + count * 2;
+ loadmodel->brushq3.data_svector3f = loadmodel->brushq3.data_texcoordlightmap2f + count * 2;
+ loadmodel->brushq3.data_tvector3f = loadmodel->brushq3.data_svector3f + count * 3;
+ loadmodel->brushq3.data_normal3f = loadmodel->brushq3.data_tvector3f + count * 3;
+ loadmodel->brushq3.data_color4f = loadmodel->brushq3.data_normal3f + count * 3;
for (i = 0;i < count;i++, in++)
{
if (l->filelen % sizeof(int[3]))
Host_Error("Mod_Q3BSP_LoadTriangles: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
+ out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out) * 2);
loadmodel->brushq3.num_triangles = count / 3;
loadmodel->brushq3.data_element3i = out;
- loadmodel->brushq3.data_neighbor3i = Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
+ loadmodel->brushq3.data_neighbor3i = out + count;
for (i = 0;i < count;i++, in++, out++)
{
rtexture_t **out;
int i, count;
+ if (!l->filelen)
+ return;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Host_Error("Mod_Q3BSP_LoadLightmaps: funny lump size in %s",loadmodel->name);
&& out->type != Q3FACETYPE_FLARE)
{
Con_Printf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, out->type);
+ out->num_vertices = 0;
+ out->num_triangles = 0;
out->type = 0; // error
continue;
}
if (n < 0 || n >= loadmodel->brushq3.num_textures)
{
Con_Printf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->brushq3.num_textures);
+ out->num_vertices = 0;
+ out->num_triangles = 0;
out->type = 0; // error
continue;
n = 0;
if (out->num_triangles * 3 != LittleLong(in->numelements))
{
Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, LittleLong(in->numelements));
+ out->num_vertices = 0;
+ out->num_triangles = 0;
out->type = 0; // error
continue;
}
if (out->firstvertex < 0 || out->firstvertex + out->num_vertices > loadmodel->brushq3.num_vertices)
{
Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, out->firstvertex, out->firstvertex + out->num_vertices, loadmodel->brushq3.num_vertices);
+ out->num_vertices = 0;
+ out->num_triangles = 0;
out->type = 0; // error
continue;
}
if (out->firstelement < 0 || out->firstelement + out->num_triangles * 3 > loadmodel->brushq3.num_triangles * 3)
{
Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, out->firstelement, out->firstelement + out->num_triangles * 3, loadmodel->brushq3.num_triangles * 3);
+ out->num_vertices = 0;
+ out->num_triangles = 0;
out->type = 0; // error
continue;
}
- out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3;
- out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2;
- out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2;
- out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3;
- out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3;
- out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3;
- out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4;
- out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement;
- out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement;
switch(out->type)
{
case Q3FACETYPE_POLYGON:
case Q3FACETYPE_MESH:
// no processing necessary
+ out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3;
+ out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2;
+ out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2;
+ out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3;
+ out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3;
+ out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3;
+ out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4;
+ out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement;
+ out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement;
break;
case Q3FACETYPE_PATCH:
patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
if (patchsize[0] < 1 || patchsize[1] < 1)
{
Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid patchsize %ix%i\n", i, out->texture->name, patchsize[0], patchsize[1]);
+ out->num_vertices = 0;
+ out->num_triangles = 0;
out->type = 0; // error
continue;
}
finalheight = ((patchsize[1] - 1) << ylevel) + 1;
finalvertices = finalwidth * finalheight;
finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+ originalvertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3;
+ //originalsvector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3;
+ //originaltvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3;
+ //originalnormal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3;
+ originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2;
+ originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2;
+ originalcolor4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4;
+ //originalelement3i = loadmodel->brushq3.data_element3i + out->firstelement;
+ //originalneighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement;
+ /*
originalvertex3f = out->data_vertex3f;
//originalsvector3f = out->data_svector3f;
//originaltvector3f = out->data_tvector3f;
originaltexcoordlightmap2f = out->data_texcoordlightmap2f;
//originalelement3i = out->data_element3i;
//originalneighbor3i = out->data_neighbor3i;
- out->data_vertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[20]) * finalvertices + sizeof(int[6]) * finaltriangles);
+ */
+ out->data_vertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[20]) * finalvertices);
out->data_svector3f = out->data_vertex3f + finalvertices * 3;
out->data_tvector3f = out->data_svector3f + finalvertices * 3;
out->data_normal3f = out->data_tvector3f + finalvertices * 3;
out->data_color4f = out->data_normal3f + finalvertices * 3;
out->data_texcoordtexture2f = out->data_color4f + finalvertices * 4;
out->data_texcoordlightmap2f = out->data_texcoordtexture2f + finalvertices * 2;
- out->data_element3i = (int *)(out->data_texcoordlightmap2f + finalvertices * 2);
+ out->data_element3i = Mem_Alloc(loadmodel->mempool, sizeof(int[6]) * finaltriangles);
out->data_neighbor3i = out->data_element3i + finaltriangles * 3;
out->type = Q3FACETYPE_MESH;
out->firstvertex = -1;
case Q3FACETYPE_FLARE:
Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name);
// don't render it
+ out->num_vertices = 0;
out->num_triangles = 0;
+ out->type = 0;
break;
}
for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++)
out->maxs[2] += 1.0f;
}
}
+
+ // LordHavoc: experimental array merger (disabled because it wastes time and uses 2x memory while merging)
+ /*
+ {
+ int totalverts, totaltris;
+ int originalnum_vertices;
+ float *originaldata_vertex3f;
+ float *originaldata_texcoordtexture2f;
+ float *originaldata_texcoordlightmap2f;
+ float *originaldata_svector3f;
+ float *originaldata_tvector3f;
+ float *originaldata_normal3f;
+ float *originaldata_color4f;
+ int originalnum_triangles;
+ int *originaldata_element3i;
+ int *originaldata_neighbor3i;
+
+ totalverts = 0;
+ totaltris = 0;
+ for (i = 0, out = loadmodel->brushq3.data_faces;i < count;i++, out++)
+ {
+ if (!out->type)
+ continue;
+ totalverts += out->num_vertices;
+ totaltris += out->num_triangles;
+ }
+
+ originalnum_vertices = loadmodel->brushq3.num_vertices;
+ originaldata_vertex3f = loadmodel->brushq3.data_vertex3f;
+ originaldata_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f;
+ originaldata_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f;
+ originaldata_svector3f = loadmodel->brushq3.data_svector3f;
+ originaldata_tvector3f = loadmodel->brushq3.data_tvector3f;
+ originaldata_normal3f = loadmodel->brushq3.data_normal3f;
+ originaldata_color4f = loadmodel->brushq3.data_color4f;
+ originalnum_triangles = loadmodel->brushq3.num_triangles;
+ originaldata_element3i = loadmodel->brushq3.data_element3i;
+ originaldata_neighbor3i = loadmodel->brushq3.data_neighbor3i;
+ loadmodel->brushq3.num_vertices = totalverts;
+ loadmodel->brushq3.data_vertex3f = Mem_Alloc(loadmodel->mempool, totalverts * (sizeof(float) * (3 + 2 + 2 + 3 + 3 + 3 + 4)) + totaltris * (sizeof(int) * (3 * 2)));
+ loadmodel->brushq3.data_texcoordtexture2f = loadmodel->brushq3.data_vertex3f + totalverts * 3;
+ loadmodel->brushq3.data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordtexture2f + totalverts * 2;
+ loadmodel->brushq3.data_svector3f = loadmodel->brushq3.data_texcoordlightmap2f + totalverts * 2;
+ loadmodel->brushq3.data_tvector3f = loadmodel->brushq3.data_svector3f + totalverts * 3;
+ loadmodel->brushq3.data_normal3f = loadmodel->brushq3.data_tvector3f + totalverts * 3;
+ loadmodel->brushq3.data_color4f = loadmodel->brushq3.data_normal3f + totalverts * 3;
+ loadmodel->brushq3.num_triangles = totaltris;
+ loadmodel->brushq3.data_element3i = (int *)(loadmodel->brushq3.data_color4f + totalverts * 4);
+ loadmodel->brushq3.data_neighbor3i = loadmodel->brushq3.data_element3i + totaltris * 3;
+ totalverts = 0;
+ totaltris = 0;
+ for (i = 0, out = loadmodel->brushq3.data_faces;i < count;i++, out++)
+ {
+ if (!out->type)
+ continue;
+ Con_Printf("totalverts %i, totaltris %i\n", totalverts, totaltris);
+ memcpy(loadmodel->brushq3.data_vertex3f + totalverts * 3, out->data_vertex3f, out->num_vertices * 3 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_texcoordtexture2f + totalverts * 2, out->data_texcoordtexture2f, out->num_vertices * 2 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_texcoordlightmap2f + totalverts * 2, out->data_texcoordlightmap2f, out->num_vertices * 2 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_svector3f + totalverts * 3, out->data_svector3f, out->num_vertices * 3 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_tvector3f + totalverts * 3, out->data_tvector3f, out->num_vertices * 3 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_normal3f + totalverts * 3, out->data_normal3f, out->num_vertices * 3 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_color4f + totalverts * 4, out->data_color4f, out->num_vertices * 4 * sizeof(float));
+ memcpy(loadmodel->brushq3.data_element3i + totaltris * 3, out->data_element3i, out->num_triangles * 3 * sizeof(int));
+ memcpy(loadmodel->brushq3.data_neighbor3i + totaltris * 3, out->data_neighbor3i, out->num_triangles * 3 * sizeof(int));
+ if (out->firstvertex == -1)
+ Mem_Free(out->data_vertex3f);
+ if (out->firstelement == -1)
+ Mem_Free(out->data_element3i);
+ out->firstvertex = totalverts;
+ out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3;
+ out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2;
+ out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2;
+ out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3;
+ out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3;
+ out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3;
+ out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4;
+ out->firstelement = totaltris * 3;
+ out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement;
+ out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement;
+ //for (j = 0;j < out->numtriangles * 3;j++)
+ // out->data_element3i[j] += totalverts - out->firstvertex;
+ totalverts += out->num_vertices;
+ totaltris += out->num_triangles;
+ }
+ Mem_Free(originaldata_vertex3f);
+ Mem_Free(originaldata_element3i);
+ }
+ */
}
static void Mod_Q3BSP_LoadModels(lump_t *l)
// FIXME: write this
if (!model->brushq3.num_lightgrid)
{
- ambientcolor[0] += 128;
- ambientcolor[1] += 128;
- ambientcolor[2] += 128;
+ ambientcolor[0] = 1;
+ ambientcolor[1] = 1;
+ ambientcolor[2] = 1;
return;
}
Matrix4x4_Transform(&model->brushq3.num_lightgrid_indexfromworld, p, transformed);
}
}
-static void Mod_Q3BSP_TraceBox(model_t *model, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
+static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
{
int i;
float segmentmins[3], segmentmaxs[3];
return nativecontents;
}
-//extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
+extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
extern void R_Q3BSP_Draw(struct entity_render_s *ent);
extern void R_Q3BSP_DrawShadowVolume(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius);
extern void R_Q3BSP_DrawLight(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
void Mod_Q3BSP_Load(model_t *mod, void *buffer)
{
- int i;
+ int i, j;
q3dheader_t *header;
float corner[3], yawradius, modelradius;
R_ResetQuakeSky();
}
+ mod->soundfromcenter = true;
+ mod->TraceBox = Mod_Q3BSP_TraceBox;
mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents;
mod->brush.NativeContentsFromSuperContents = Mod_Q3BSP_NativeContentsFromSuperContents;
mod->brush.GetPVS = Mod_Q3BSP_GetPVS;
mod->brush.BoxTouchingPVS = Mod_Q3BSP_BoxTouchingPVS;
mod->brush.LightPoint = Mod_Q3BSP_LightPoint;
mod->brush.FindNonSolidLocation = Mod_Q3BSP_FindNonSolidLocation;
- mod->brush.TraceBox = Mod_Q3BSP_TraceBox;
//mod->DrawSky = R_Q3BSP_DrawSky;
mod->Draw = R_Q3BSP_Draw;
mod->DrawShadowVolume = R_Q3BSP_DrawShadowVolume;
mod->yawmaxs[2] = mod->normalmaxs[2];
mod->radius = modelradius;
mod->radius2 = modelradius * modelradius;
+
+ for (j = 0;j < mod->brushq3.data_thismodel->numfaces;j++)
+ if (mod->brushq3.data_thismodel->firstface[j].texture->surfaceflags & Q3SURFACEFLAG_SKY)
+ break;
+ if (j < mod->brushq3.data_thismodel->numfaces)
+ mod->DrawSky = R_Q3BSP_DrawSky;
}
}