return (mleaf_t *)node;
}
+static void Mod_Q1BSP_AmbientSoundLevelsForPoint(model_t *model, const vec3_t p, qbyte *out, int outsize)
+{
+ int i;
+ mleaf_t *leaf;
+ leaf = Mod_Q1BSP_PointInLeaf(model, p);
+ if (leaf)
+ {
+ i = min(outsize, (int)sizeof(leaf->ambient_sound_level));;
+ if (i)
+ {
+ memcpy(out, leaf->ambient_sound_level, i);
+ out += i;
+ outsize -= i;
+ }
+ }
+ if (outsize)
+ memset(out, 0, outsize);
+}
+
static int Mod_Q1BSP_BoxTouchingPVS_RecursiveBSPNode(const model_t *model, const mnode_t *node, const qbyte *pvs, const vec3_t mins, const vec3_t maxs)
{
VectorSubtract(boxstartmaxs, boxstartmins, boxsize);
if (boxsize[0] < 3)
rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
- else if (model->brushq1.ishlbsp)
+ else if (model->brush.ishlbsp)
{
if (boxsize[0] <= 32)
{
Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, cl.worldmodel->brushq1.nodes + cl.worldmodel->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
}
-static qbyte *Mod_Q1BSP_DecompressVis(model_t *model, qbyte *in)
+static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *out, qbyte *outend)
{
- static qbyte decompressed[MAX_MAP_LEAFS/8];
int c;
- qbyte *out;
- int row;
-
- row = (model->brushq1.numleafs+7)>>3;
- out = decompressed;
-
- do
+ while (out < outend)
{
- if (*in)
+ if (in == inend)
{
- *out++ = *in++;
- continue;
+ Con_Printf("Mod_Q1BSP_DecompressVis: input underrun\n");
+ return;
}
-
- c = in[1];
- in += 2;
- while (c)
+ c = *in++;
+ if (c)
+ *out++ = c;
+ else
{
- *out++ = 0;
- c--;
+ for (c = *in++;c > 0;c--)
+ {
+ if (out == outend)
+ {
+ Con_Printf("Mod_Q1BSP_DecompressVis: output overrun\n");
+ return;
+ }
+ *out++ = 0;
+ }
}
- } while (out - decompressed < row);
-
- return decompressed;
-}
-
-static qbyte *Mod_Q1BSP_LeafPVS(model_t *model, mleaf_t *leaf)
-{
- if (r_novis.integer || leaf == model->brushq1.leafs || leaf->compressed_vis == NULL)
- return mod_q1bsp_novis;
- return Mod_Q1BSP_DecompressVis(model, leaf->compressed_vis);
+ }
}
static void Mod_Q1BSP_LoadTextures(lump_t *l)
}
// LordHavoc: HL sky textures are entirely different than quake
- if (!loadmodel->brushq1.ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
+ if (!loadmodel->brush.ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
{
if (loadmodel->isworldmodel)
{
if (!Mod_LoadSkinFrame(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true))
{
// did not find external texture, load it from the bsp or wad3
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
{
// internal texture overrides wad
qbyte *pixels, *freepixels, *fogpixels;
qbyte *in, *out, *data, d;
char litfilename[1024];
loadmodel->brushq1.lightdata = NULL;
- if (loadmodel->brushq1.ishlbsp) // LordHavoc: load the colored lighting data straight
+ if (loadmodel->brush.ishlbsp) // LordHavoc: load the colored lighting data straight
{
loadmodel->brushq1.lightdata = Mem_Alloc(loadmodel->mempool, l->filelen);
memcpy(loadmodel->brushq1.lightdata, mod_base + l->fileofs, l->filelen);
}
}
-/*
-static int castshadowcount = 0;
-static void Mod_Q1BSP_ProcessLightList(void)
-{
- int j, k, l, *mark, lnum;
- mlight_t *e;
- msurface_t *surf;
- float dist;
- mleaf_t *leaf;
- qbyte *pvs;
- vec3_t temp;
- float *v, radius2;
- for (lnum = 0, e = loadmodel->brushq1.lights;lnum < loadmodel->brushq1.numlights;lnum++, e++)
- {
- e->cullradius2 = DotProduct(e->light, e->light) / (e->falloff * e->falloff * 8192.0f * 8192.0f * 2.0f * 2.0f);// + 4096.0f;
- if (e->cullradius2 > 4096.0f * 4096.0f)
- e->cullradius2 = 4096.0f * 4096.0f;
- e->cullradius = e->lightradius = sqrt(e->cullradius2);
- leaf = Mod_Q1BSP_PointInLeaf(e->origin, loadmodel);
- if (leaf->compressed_vis)
- pvs = Mod_Q1BSP_DecompressVis(leaf->compressed_vis, loadmodel);
- else
- pvs = mod_q1bsp_novis;
- for (j = 0;j < loadmodel->brushq1.numsurfaces;j++)
- loadmodel->brushq1.surfacevisframes[j] = -1;
- for (j = 0, leaf = loadmodel->brushq1.leafs + 1;j < loadmodel->brushq1.numleafs - 1;j++, leaf++)
- {
- if (pvs[j >> 3] & (1 << (j & 7)))
- {
- for (k = 0, mark = leaf->firstmarksurface;k < leaf->nummarksurfaces;k++, mark++)
- {
- surf = loadmodel->brushq1.surfaces + *mark;
- if (surf->number != *mark)
- Con_Printf("%d != %d\n", surf->number, *mark);
- dist = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
- if (surf->flags & SURF_PLANEBACK)
- dist = -dist;
- if (dist > 0 && dist < e->cullradius)
- {
- temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0];
- temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1];
- temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2];
- if (DotProduct(temp, temp) < lightradius2)
- loadmodel->brushq1.surfacevisframes[*mark] = -2;
- }
- }
- }
- }
- // build list of light receiving surfaces
- e->numsurfaces = 0;
- for (j = 0;j < loadmodel->brushq1.numsurfaces;j++)
- if (loadmodel->brushq1.surfacevisframes[j] == -2)
- e->numsurfaces++;
- e->surfaces = NULL;
- if (e->numsurfaces > 0)
- {
- e->surfaces = Mem_Alloc(loadmodel->mempool, sizeof(msurface_t *) * e->numsurfaces);
- e->numsurfaces = 0;
- for (j = 0;j < loadmodel->brushq1.numsurfaces;j++)
- if (loadmodel->brushq1.surfacevisframes[j] == -2)
- e->surfaces[e->numsurfaces++] = loadmodel->brushq1.surfaces + j;
- }
- // find bounding box and sphere of lit surfaces
- // (these will be used for creating a shape to clip the light)
- radius2 = 0;
- for (j = 0;j < e->numsurfaces;j++)
- {
- surf = e->surfaces[j];
- if (j == 0)
- {
- VectorCopy(surf->poly_verts, e->mins);
- VectorCopy(surf->poly_verts, e->maxs);
- }
- for (k = 0, v = surf->poly_verts;k < surf->poly_numverts;k++, v += 3)
- {
- if (e->mins[0] > v[0]) e->mins[0] = v[0];if (e->maxs[0] < v[0]) e->maxs[0] = v[0];
- if (e->mins[1] > v[1]) e->mins[1] = v[1];if (e->maxs[1] < v[1]) e->maxs[1] = v[1];
- if (e->mins[2] > v[2]) e->mins[2] = v[2];if (e->maxs[2] < v[2]) e->maxs[2] = v[2];
- VectorSubtract(v, e->origin, temp);
- dist = DotProduct(temp, temp);
- if (radius2 < dist)
- radius2 = dist;
- }
- }
- if (e->cullradius2 > radius2)
- {
- e->cullradius2 = radius2;
- e->cullradius = sqrt(e->cullradius2);
- }
- if (e->mins[0] < e->origin[0] - e->lightradius) e->mins[0] = e->origin[0] - e->lightradius;
- if (e->maxs[0] > e->origin[0] + e->lightradius) e->maxs[0] = e->origin[0] + e->lightradius;
- if (e->mins[1] < e->origin[1] - e->lightradius) e->mins[1] = e->origin[1] - e->lightradius;
- if (e->maxs[1] > e->origin[1] + e->lightradius) e->maxs[1] = e->origin[1] + e->lightradius;
- if (e->mins[2] < e->origin[2] - e->lightradius) e->mins[2] = e->origin[2] - e->lightradius;
- if (e->maxs[2] > e->origin[2] + e->lightradius) e->maxs[2] = e->origin[2] + e->lightradius;
- // clip shadow volumes against eachother to remove unnecessary
- // polygons(and sections of polygons)
- {
- //vec3_t polymins, polymaxs;
- int maxverts = 4;
- float *verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- float f, *v0, *v1, projectdistance;
-
- e->shadowvolume = Mod_ShadowMesh_Begin(loadmodel->mempool, 1024);
-#if 0
- {
- vec3_t outermins, outermaxs, innermins, innermaxs;
- innermins[0] = e->mins[0] - 1;
- innermins[1] = e->mins[1] - 1;
- innermins[2] = e->mins[2] - 1;
- innermaxs[0] = e->maxs[0] + 1;
- innermaxs[1] = e->maxs[1] + 1;
- innermaxs[2] = e->maxs[2] + 1;
- outermins[0] = loadmodel->normalmins[0] - 1;
- outermins[1] = loadmodel->normalmins[1] - 1;
- outermins[2] = loadmodel->normalmins[2] - 1;
- outermaxs[0] = loadmodel->normalmaxs[0] + 1;
- outermaxs[1] = loadmodel->normalmaxs[1] + 1;
- outermaxs[2] = loadmodel->normalmaxs[2] + 1;
- // add bounding box around the whole shadow volume set,
- // facing inward to limit light area, with an outer bounding box
- // facing outward (this is needed by the shadow rendering method)
- // X major
- verts[ 0] = innermaxs[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
- verts[ 6] = innermaxs[0];verts[ 7] = innermaxs[1];verts[ 8] = innermins[2];
- verts[ 9] = innermaxs[0];verts[10] = innermaxs[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
- verts[ 6] = outermaxs[0];verts[ 7] = outermins[1];verts[ 8] = outermins[2];
- verts[ 9] = outermaxs[0];verts[10] = outermins[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // X minor
- verts[ 0] = innermins[0];verts[ 1] = innermaxs[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermins[0];verts[ 4] = innermaxs[1];verts[ 5] = innermins[2];
- verts[ 6] = innermins[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
- verts[ 9] = innermins[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermins[0];verts[ 1] = outermins[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermins[0];verts[ 4] = outermins[1];verts[ 5] = outermins[2];
- verts[ 6] = outermins[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
- verts[ 9] = outermins[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Y major
- verts[ 0] = innermaxs[0];verts[ 1] = innermaxs[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermaxs[1];verts[ 5] = innermins[2];
- verts[ 6] = innermins[0];verts[ 7] = innermaxs[1];verts[ 8] = innermins[2];
- verts[ 9] = innermins[0];verts[10] = innermaxs[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermins[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermins[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
- verts[ 6] = outermaxs[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
- verts[ 9] = outermaxs[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Y minor
- verts[ 0] = innermins[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermins[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
- verts[ 6] = innermaxs[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
- verts[ 9] = innermaxs[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermins[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermins[1];verts[ 5] = outermins[2];
- verts[ 6] = outermins[0];verts[ 7] = outermins[1];verts[ 8] = outermins[2];
- verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Z major
- verts[ 0] = innermaxs[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermaxs[1];verts[ 5] = innermaxs[2];
- verts[ 6] = innermins[0];verts[ 7] = innermaxs[1];verts[ 8] = innermaxs[2];
- verts[ 9] = innermins[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermins[1];verts[ 5] = outermaxs[2];
- verts[ 6] = outermins[0];verts[ 7] = outermins[1];verts[ 8] = outermaxs[2];
- verts[ 9] = outermins[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Z minor
- verts[ 0] = innermaxs[0];verts[ 1] = innermaxs[1];verts[ 2] = innermins[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
- verts[ 6] = innermins[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
- verts[ 9] = innermins[0];verts[10] = innermaxs[1];verts[11] = innermins[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermins[1];verts[ 2] = outermins[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
- verts[ 6] = outermins[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
- verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermins[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- }
-#endif
- castshadowcount++;
- for (j = 0;j < e->numsurfaces;j++)
- {
- surf = e->surfaces[j];
- if (surf->flags & SURF_SHADOWCAST)
- surf->castshadow = castshadowcount;
- }
- for (j = 0;j < e->numsurfaces;j++)
- {
- surf = e->surfaces[j];
- if (surf->castshadow != castshadowcount)
- continue;
- f = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
- if (surf->flags & SURF_PLANEBACK)
- f = -f;
- projectdistance = e->lightradius;
- if (maxverts < surf->poly_numverts)
- {
- maxverts = surf->poly_numverts;
- if (verts)
- Mem_Free(verts);
- verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- }
- // copy the original polygon, for the front cap of the volume
- for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
- VectorCopy(v0, v1);
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, surf->poly_numverts, verts);
- // project the original polygon, reversed, for the back cap of the volume
- for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
- {
- VectorSubtract(v0, e->origin, temp);
- VectorNormalize(temp);
- VectorMA(v0, projectdistance, temp, v1);
- }
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, surf->poly_numverts, verts);
- // project the shadow volume sides
- for (l = surf->poly_numverts - 1, k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;l = k, k++, v0 = v1, v1 += 3)
- {
- if (!surf->neighborsurfaces[l] || surf->neighborsurfaces[l]->castshadow != castshadowcount)
- {
- VectorCopy(v1, &verts[0]);
- VectorCopy(v0, &verts[3]);
- VectorCopy(v0, &verts[6]);
- VectorCopy(v1, &verts[9]);
- VectorSubtract(&verts[6], e->origin, temp);
- VectorNormalize(temp);
- VectorMA(&verts[6], projectdistance, temp, &verts[6]);
- VectorSubtract(&verts[9], e->origin, temp);
- VectorNormalize(temp);
- VectorMA(&verts[9], projectdistance, temp, &verts[9]);
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- }
- }
- }
- // build the triangle mesh
- e->shadowvolume = Mod_ShadowMesh_Finish(loadmodel->mempool, e->shadowvolume);
- {
- shadowmesh_t *mesh;
- l = 0;
- for (mesh = e->shadowvolume;mesh;mesh = mesh->next)
- l += mesh->numtriangles;
- Con_Printf("light %i shadow volume built containing %i triangles\n", lnum, l);
- }
- }
- }
-}
-*/
-
-
static void Mod_Q1BSP_LoadVisibility(lump_t *l)
{
- loadmodel->brushq1.visdata = NULL;
+ loadmodel->brushq1.num_compressedpvs = 0;
+ loadmodel->brushq1.data_compressedpvs = NULL;
if (!l->filelen)
return;
- loadmodel->brushq1.visdata = Mem_Alloc(loadmodel->mempool, l->filelen);
- memcpy(loadmodel->brushq1.visdata, mod_base + l->fileofs, l->filelen);
+ loadmodel->brushq1.num_compressedpvs = l->filelen;
+ loadmodel->brushq1.data_compressedpvs = Mem_Alloc(loadmodel->mempool, l->filelen);
+ memcpy(loadmodel->brushq1.data_compressedpvs, mod_base + l->fileofs, l->filelen);
}
// used only for HalfLife maps
strcpy(value, com_token);
if (!strcmp("wad", key)) // for HalfLife maps
{
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
{
j = 0;
for (i = 0;i < 4096;i++)
return;
loadmodel->brush.entities = Mem_Alloc(loadmodel->mempool, l->filelen);
memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen);
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
Mod_Q1BSP_ParseWadsFromEntityLump(loadmodel->brush.entities);
}
out = Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
loadmodel->brushq1.submodels = out;
- loadmodel->brushq1.numsubmodels = count;
+ loadmodel->brush.numsubmodels = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
i = LittleLong(in->lightofs);
if (i == -1)
surf->samples = NULL;
- else if (loadmodel->brushq1.ishlbsp) // LordHavoc: HalfLife map (bsp version 30)
+ else if (loadmodel->brush.ishlbsp) // LordHavoc: HalfLife map (bsp version 30)
surf->samples = loadmodel->brushq1.lightdata + i;
else // LordHavoc: white lighting (bsp version 29)
surf->samples = loadmodel->brushq1.lightdata + (i * 3);
static void Mod_Q1BSP_LoadLeafs(lump_t *l)
{
- dleaf_t *in;
- mleaf_t *out;
- int i, j, count, p;
+ dleaf_t *in;
+ mleaf_t *out;
+ int i, j, count, p, pvschainbytes;
+ qbyte *pvs;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
loadmodel->brushq1.leafs = out;
loadmodel->brushq1.numleafs = count;
+ pvschainbytes = ((loadmodel->brushq1.numleafs - 1)+7)>>3;
+ loadmodel->brushq1.data_decompressedpvs = pvs = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.numleafs * pvschainbytes);
for ( i=0 ; i<count ; i++, in++, out++)
{
out->maxs[j] = LittleShort(in->maxs[j]);
}
- p = LittleLong(in->contents);
- out->contents = p;
+ // FIXME: this function could really benefit from some error checking
+
+ out->contents = LittleLong(in->contents);
- out->firstmarksurface = loadmodel->brushq1.marksurfaces +
- LittleShort(in->firstmarksurface);
+ out->firstmarksurface = loadmodel->brushq1.marksurfaces + LittleShort(in->firstmarksurface);
out->nummarksurfaces = LittleShort(in->nummarksurfaces);
+ out->pvsdata = pvs;
+ pvs += pvschainbytes;
+
p = LittleLong(in->visofs);
- if (p == -1)
- out->compressed_vis = NULL;
+ if (p >= 0)
+ Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, out->pvsdata, out->pvsdata + pvschainbytes);
else
- out->compressed_vis = loadmodel->brushq1.visdata + p;
+ memset(out->pvsdata, 0xFF, pvschainbytes);
- for (j=0 ; j<4 ; j++)
+ for (j = 0;j < 4;j++)
out->ambient_sound_level[j] = in->ambient_level[j];
// FIXME: Insert caustics here
loadmodel->brushq1.clipnodes = out;
loadmodel->brushq1.numclipnodes = count;
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
{
hull = &loadmodel->brushq1.hulls[1];
hull->clipnodes = out;
void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbytes, mnode_t *node)
{
int i;
- qbyte *pvs;
mplane_t *plane;
float d;
// if this is a leaf, accumulate the pvs bits
if (node->contents < 0)
{
- if (node->contents != CONTENTS_SOLID)
- {
- pvs = model->brushq1.LeafPVS(model, (mleaf_t *)node);
+ if (node->contents != CONTENTS_SOLID && ((mleaf_t *)node)->pvsdata)
for (i = 0;i < pvsbytes;i++)
- pvsbuffer[i] |= pvs[i];
- }
+ pvsbuffer[i] |= ((mleaf_t *)node)->pvsdata[i];
return;
}
//of the given point.
int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength)
{
- int bytes = (sv.worldmodel->brushq1.numleafs+31)>>3;
- if (bytes > pvsbufferlength)
- bytes = pvsbufferlength;
+ int bytes = ((model->brushq1.numleafs - 1) + 7) >> 3;
+ bytes = min(bytes, pvsbufferlength);
memset(pvsbuffer, 0, bytes);
Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, bytes, sv.worldmodel->brushq1.nodes);
return bytes;
}
+static void Mod_Q1BSP_RoundUpToHullSize(model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
+{
+ vec3_t size;
+ const hull_t *hull;
+
+ VectorSubtract(inmaxs, inmins, size);
+ if (cmodel->brush.ishlbsp)
+ {
+ if (size[0] < 3)
+ hull = &cmodel->brushq1.hulls[0]; // 0x0x0
+ else if (size[0] <= 32)
+ {
+ if (size[2] < 54) // pick the nearest of 36 or 72
+ hull = &cmodel->brushq1.hulls[3]; // 32x32x36
+ else
+ hull = &cmodel->brushq1.hulls[1]; // 32x32x72
+ }
+ else
+ hull = &cmodel->brushq1.hulls[2]; // 64x64x64
+ }
+ else
+ {
+ if (size[0] < 3)
+ hull = &cmodel->brushq1.hulls[0]; // 0x0x0
+ else if (size[0] <= 32)
+ hull = &cmodel->brushq1.hulls[1]; // 32x32x56
+ else
+ hull = &cmodel->brushq1.hulls[2]; // 64x64x88
+ }
+ VectorCopy(inmins, outmins);
+ VectorAdd(inmins, hull->clip_size, outmaxs);
+}
+
extern void R_Model_Brush_DrawSky(entity_render_t *ent);
extern void R_Model_Brush_Draw(entity_render_t *ent);
extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius);
i = LittleLong(header->version);
if (i != BSPVERSION && i != 30)
Host_Error("Mod_Q1BSP_Load: %s has wrong version number(%i should be %i(Quake) or 30(HalfLife))", mod->name, i, BSPVERSION);
- mod->brushq1.ishlbsp = i == 30;
+ mod->brush.ishlbsp = i == 30;
+ mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
mod->brush.FatPVS = Mod_Q1BSP_FatPVS;
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.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize;
mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
- mod->brushq1.LeafPVS = Mod_Q1BSP_LeafPVS;
mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
if (loadmodel->isworldmodel)
{
- Cvar_SetValue("halflifebsp", mod->brushq1.ishlbsp);
+ Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
// until we get a texture for it...
R_ResetQuakeSky();
}
Mod_Q1BSP_LoadClipnodes(&header->lumps[LUMP_CLIPNODES]);
Mod_Q1BSP_LoadSubmodels(&header->lumps[LUMP_MODELS]);
+ if (mod->brushq1.data_compressedpvs)
+ Mem_Free(mod->brushq1.data_compressedpvs);
+ mod->brushq1.data_compressedpvs = NULL;
+ mod->brushq1.num_compressedpvs = 0;
+
Mod_Q1BSP_MakeHull0();
Mod_Q1BSP_MakePortals();
+ if (developer.integer)
+ Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brushq1.numsurfaces, loadmodel->brushq1.numnodes, loadmodel->brushq1.numleafs, loadmodel->brushq1.numleafs - 1, loadmodel->brushq1.numportals);
+
mod->numframes = 2; // regular and alternate animation
mainmempool = mod->mempool;
//
// set up the submodels(FIXME: this is confusing)
//
- for (i = 0;i < mod->brushq1.numsubmodels;i++)
+ for (i = 0;i < mod->brush.numsubmodels;i++)
{
bm = &mod->brushq1.submodels[i];
if (surf->texinfo->texture->shader == &Cshader_sky)
mod->DrawSky = R_Model_Brush_DrawSky;
// LordHavoc: submodels always clip, even if water
- if (mod->brushq1.numsubmodels - 1)
+ if (mod->brush.numsubmodels - 1)
surf->flags |= SURF_SOLIDCLIP;
// calculate bounding shapes
for (mesh = surf->mesh;mesh;mesh = mesh->chain)
}
Mod_Q1BSP_BuildSurfaceNeighbors(mod->brushq1.surfaces + mod->brushq1.firstmodelsurface, mod->brushq1.nummodelsurfaces, originalloadmodel->mempool);
- mod->brushq1.numleafs = bm->visleafs;
+ mod->brushq1.visleafs = bm->visleafs;
// LordHavoc: only register submodels if it is the world
// (prevents bsp models from replacing world submodels)
- if (loadmodel->isworldmodel && i < (mod->brushq1.numsubmodels - 1))
+ if (loadmodel->isworldmodel && i < (mod->brush.numsubmodels - 1))
{
char name[10];
// duplicate the basic information
i = LittleLong(header->version);
if (i != Q2BSPVERSION)
Host_Error("Mod_Q2BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q2BSPVERSION);
- mod->brushq1.ishlbsp = false;
+ mod->brush.ishlbsp = false;
if (loadmodel->isworldmodel)
{
- Cvar_SetValue("halflifebsp", mod->brushq1.ishlbsp);
+ Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
// until we get a texture for it...
R_ResetQuakeSky();
}
q3mbrush_t *out;
int i, j, k, m, n, c, count, numpoints, numplanes;
winding_t *w;
+ mplane_t plane;
colpointf_t pointsbuf[256*3];
colplanef_t planesbuf[256], colplanef;
numplanes = 0;
for (j = 0;j < out->numbrushsides;j++)
{
+ // for some reason the planes are all flipped compared to what I
+ // would expect, so this has to negate them...
+
// create a huge polygon for the plane
- w = BaseWindingForPlane(out->firstbrushside[j].plane);
+ VectorNegate(out->firstbrushside[j].plane->normal, plane.normal);
+ plane.dist = -out->firstbrushside[j].plane->dist;
+ w = BaseWindingForPlane(&plane);
// clip it by all other planes
for (k = 0;k < out->numbrushsides && w;k++)
+ {
if (k != j)
- w = ClipWinding(w, out->firstbrushside[k].plane, true);
+ {
+ VectorNegate(out->firstbrushside[k].plane->normal, plane.normal);
+ plane.dist = -out->firstbrushside[k].plane->dist;
+ w = ClipWinding(w, &plane, true);
+ }
+ }
// if nothing is left, skip it
// FIXME: should keep count of how many were skipped and report
// it, just for sake of statistics
for (k = 0;k < w->numpoints;k++)
{
for (m = 0;m < numpoints;m++)
- if (VectorDistance2(w->points[k * 3], pointsbuf[m * 3].v) < DIST_EPSILON)
+ if (VectorDistance2(w->points[k], pointsbuf[m].v) < DIST_EPSILON)
break;
if (m == numpoints)
{
goto failedtomakecolbrush;
}
// add the new one
- VectorCopy(w->points[k * 3], pointsbuf[numpoints * 3].v);
+ VectorCopy(w->points[k], pointsbuf[numpoints].v);
numpoints++;
}
}
if (numplanes && numpoints)
{
out->colbrushf = Collision_AllocBrushFloat(loadmodel->mempool, numpoints, numplanes);
- memcpy(out->colbrushf->points, pointsbuf, numpoints * sizeof(float[3]));
- memcpy(out->colbrushf->planes, planesbuf, numplanes * sizeof(mplane_t));
+ memcpy(out->colbrushf->points, pointsbuf, numpoints * sizeof(colpointf_t));
+ memcpy(out->colbrushf->planes, planesbuf, numplanes * sizeof(colplanef_t));
}
// return from errors to here
failedtomakecolbrush:;
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_texturetexcoord2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
- loadmodel->brushq3.data_lightmaptexcoord2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
+ 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_vertex3f[i * 3 + 0] = LittleFloat(in->origin3f[0]);
loadmodel->brushq3.data_vertex3f[i * 3 + 1] = LittleFloat(in->origin3f[1]);
loadmodel->brushq3.data_vertex3f[i * 3 + 2] = LittleFloat(in->origin3f[2]);
- loadmodel->brushq3.data_texturetexcoord2f[i * 2 + 0] = LittleFloat(in->texcoord2f[0]);
- loadmodel->brushq3.data_texturetexcoord2f[i * 2 + 1] = LittleFloat(in->texcoord2f[1]);
- loadmodel->brushq3.data_lightmaptexcoord2f[i * 2 + 0] = LittleFloat(in->lightmap2f[0]);
- loadmodel->brushq3.data_lightmaptexcoord2f[i * 2 + 1] = LittleFloat(in->lightmap2f[1]);
+ loadmodel->brushq3.data_texcoordtexture2f[i * 2 + 0] = LittleFloat(in->texcoord2f[0]);
+ loadmodel->brushq3.data_texcoordtexture2f[i * 2 + 1] = LittleFloat(in->texcoord2f[1]);
+ loadmodel->brushq3.data_texcoordlightmap2f[i * 2 + 0] = LittleFloat(in->lightmap2f[0]);
+ loadmodel->brushq3.data_texcoordlightmap2f[i * 2 + 1] = LittleFloat(in->lightmap2f[1]);
// svector/tvector are calculated later in face loading
loadmodel->brushq3.data_svector3f[i * 3 + 0] = 0;
loadmodel->brushq3.data_svector3f[i * 3 + 1] = 0;
case Q3FACETYPE_POLYGON:
case Q3FACETYPE_MESH:
out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3;
- out->data_texturetexcoord2f = loadmodel->brushq3.data_texturetexcoord2f + out->firstvertex * 2;
- out->data_lightmaptexcoord2f = loadmodel->brushq3.data_lightmaptexcoord2f + out->firstvertex * 2;
+ 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;
q3mleaf_t *leaf;
leaf = (q3mleaf_t *)node;
for (i = 0;i < leaf->numleafbrushes;i++)
- Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, leaf->firstleafbrush[i]->colbrushf, leaf->firstleafbrush[i]->colbrushf);
+ if (leaf->firstleafbrush[i]->colbrushf)
+ Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, leaf->firstleafbrush[i]->colbrushf, leaf->firstleafbrush[i]->colbrushf);
}
}
Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model->brushq3.data_nodes, thisbrush_start, thisbrush_end);
else
for (i = 0;i < model->brushq3.num_brushes;i++)
- Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, model->brushq3.data_brushes[i].colbrushf, model->brushq3.data_brushes[i].colbrushf);
+ if (model->brushq3.data_brushes[i].colbrushf)
+ Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, model->brushq3.data_brushes[i].colbrushf, model->brushq3.data_brushes[i].colbrushf);
}
return pvsbufferlength;
}
+//extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
+extern void R_Q3BSP_Draw(struct entity_render_s *ent);
+//extern void R_Q3BSP_DrawFakeShadow(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;
q3dheader_t *header;
- mod->type = mod_brushq2;
+ mod->type = mod_brushq3;
header = (q3dheader_t *)buffer;
mod->brush.LightPoint = Mod_Q3BSP_LightPoint;
mod->brush.FindNonSolidLocation = Mod_Q3BSP_FindNonSolidLocation;
mod->brush.TraceBox = Mod_Q3BSP_TraceBox;
- //mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
- //mod->brushq1.LeafPVS = Mod_Q1BSP_LeafPVS;
- //mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
+ //mod->DrawSky = R_Q3BSP_DrawSky;
+ mod->Draw = R_Q3BSP_Draw;
+ //mod->DrawFakeShadow = R_Q3BSP_DrawFakeShadow;
+ //mod->DrawShadowVolume = R_Q3BSP_DrawShadowVolume;
+ //mod->DrawLight = R_Q3BSP_DrawLight;
mod_base = (qbyte *)header;
Mod_Q3BSP_LoadNodes(&header->lumps[Q3LUMP_NODES]);
Mod_Q3BSP_LoadLightGrid(&header->lumps[Q3LUMP_LIGHTGRID]);
Mod_Q3BSP_LoadPVS(&header->lumps[Q3LUMP_PVS]);
+ loadmodel->brush.numsubmodels = loadmodel->brushq3.num_models;
+
+ for (i = 0;i < loadmodel->brushq3.num_models;i++)
+ {
+ if (i == 0)
+ mod = loadmodel;
+ else
+ {
+ char name[10];
+ // LordHavoc: only register submodels if it is the world
+ // (prevents bsp models from replacing world submodels)
+ if (!loadmodel->isworldmodel)
+ continue;
+ // duplicate the basic information
+ sprintf(name, "*%i", i);
+ mod = Mod_FindName(name);
+ *mod = *loadmodel;
+ strcpy(mod->name, name);
+ // textures and memory belong to the main model
+ mod->texturepool = NULL;
+ mod->mempool = NULL;
+ }
+ mod->brushq3.data_thismodel = loadmodel->brushq3.data_models + i;
+ }
}
void Mod_IBSP_Load(model_t *mod, void *buffer)