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);
+ for (i=0; i<l->filelen; i++)
+ loadmodel->brushq1.lightdata[i] = mod_base[l->fileofs+i] >>= 1;
}
else // LordHavoc: bsp version 29 (normal white lighting)
{
msurface_t *surf;
int numshadowmeshtriangles;
- mod->type = mod_brush;
+ mod->type = mod_brushq1;
header = (dheader_t *)buffer;
// swap all the lumps
mod_base = (qbyte *)header;
- for (i = 0;i < (int) sizeof(dheader_t) / 4;i++)
- ((int *)header)[i] = LittleLong(((int *)header)[i]);
+ header->version = LittleLong(header->version);
+ for (i = 0;i < HEADER_LUMPS;i++)
+ {
+ header->lumps[i].fileofs = LittleLong(header->lumps[i].fileofs);
+ header->lumps[i].filelen = LittleLong(header->lumps[i].filelen);
+ }
// load into heap
// LordHavoc: this code was originally at the end of this loop, but
// has been transformed to something more readable at the start here.
- // LordHavoc: only register submodels if it is the world
- // (prevents external bsp models from replacing world submodels with
- // their own)
- if (loadmodel->isworldmodel && i)
+ if (i > 0)
{
char name[10];
+ // LordHavoc: only register submodels if it is the world
+ // (prevents external bsp models from replacing world submodels with
+ // their own)
+ if (!loadmodel->isworldmodel)
+ continue;
// duplicate the basic information
sprintf(name, "*%i", i);
mod = Mod_FindName(name);
{
q3dface_t *in;
q3msurface_t *out;
- int i, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xlevel, ylevel, row0, row1, x, y, *e, finalvertices, finaltriangles;
+ int i, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xlevel, ylevel, row0, row1, x, y, *e, finalvertices, finaltriangles, firstvertex, firstelement, type;
//int *originalelement3i;
//int *originalneighbor3i;
float *originalvertex3f;
for (i = 0;i < count;i++, in++, out++)
{
// check face type first
- out->type = LittleLong(in->type);
- if (out->type != Q3FACETYPE_POLYGON
- && out->type != Q3FACETYPE_PATCH
- && out->type != Q3FACETYPE_MESH
- && out->type != Q3FACETYPE_FLARE)
+ type = LittleLong(in->type);
+ if (type != Q3FACETYPE_POLYGON
+ && type != Q3FACETYPE_PATCH
+ && type != Q3FACETYPE_MESH
+ && type != Q3FACETYPE_FLARE)
{
- Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, out->type);
+ Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, type);
out->num_vertices = 0;
out->num_triangles = 0;
- out->type = 0; // error
+ type = 0; // error
continue;
}
Con_DPrintf("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
+ type = 0; // error
continue;
n = 0;
}
else
out->lightmaptexture = loadmodel->brushq3.data_lightmaps[n];
- out->firstvertex = LittleLong(in->firstvertex);
+ firstvertex = LittleLong(in->firstvertex);
out->num_vertices = LittleLong(in->numvertices);
- out->firstelement = LittleLong(in->firstelement);
+ firstelement = LittleLong(in->firstelement);
out->num_triangles = LittleLong(in->numelements) / 3;
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
+ type = 0; // error
continue;
}
- if (out->firstvertex < 0 || out->firstvertex + out->num_vertices > loadmodel->brushq3.num_vertices)
+ if (firstvertex < 0 || 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);
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, firstvertex, firstvertex + out->num_vertices, loadmodel->brushq3.num_vertices);
out->num_vertices = 0;
out->num_triangles = 0;
- out->type = 0; // error
+ type = 0; // error
continue;
}
- if (out->firstelement < 0 || out->firstelement + out->num_triangles * 3 > loadmodel->brushq3.num_triangles * 3)
+ if (firstelement < 0 || 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);
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, firstelement, firstelement + out->num_triangles * 3, loadmodel->brushq3.num_triangles * 3);
out->num_vertices = 0;
out->num_triangles = 0;
- out->type = 0; // error
+ type = 0; // error
continue;
}
- switch(out->type)
+ switch(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;
+ out->data_vertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+ out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
+ out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
+ out->data_svector3f = loadmodel->brushq3.data_svector3f + firstvertex * 3;
+ out->data_tvector3f = loadmodel->brushq3.data_tvector3f + firstvertex * 3;
+ out->data_normal3f = loadmodel->brushq3.data_normal3f + firstvertex * 3;
+ out->data_color4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
+ out->data_element3i = loadmodel->brushq3.data_element3i + firstelement;
+ out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + firstelement;
break;
case Q3FACETYPE_PATCH:
patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
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
+ type = 0; // error
continue;
}
- 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 = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+ //originalsvector3f = loadmodel->brushq3.data_svector3f + firstvertex * 3;
+ //originaltvector3f = loadmodel->brushq3.data_tvector3f + firstvertex * 3;
+ //originalnormal3f = loadmodel->brushq3.data_normal3f + firstvertex * 3;
+ originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
+ originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
+ originalcolor4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
+ //originalelement3i = loadmodel->brushq3.data_element3i + firstelement;
+ //originalneighbor3i = loadmodel->brushq3.data_neighbor3i + firstelement;
/*
originalvertex3f = out->data_vertex3f;
//originalsvector3f = out->data_svector3f;
out->data_texcoordlightmap2f = out->data_texcoordtexture2f + 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;
+ type = Q3FACETYPE_MESH;
+ firstvertex = -1;
out->num_vertices = finalvertices;
- out->firstelement = -1;
+ firstelement = -1;
out->num_triangles = finaltriangles;
// generate geometry
// (note: normals are skipped because they get recalculated)
}
// q3map does not put in collision brushes for curves... ugh
// build the lower quality collision geometry
- out->collisions = true;
xlevel = QuadraticBSplinePatchSubdivisionLevelOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value, 10);
ylevel = QuadraticBSplinePatchSubdivisionLevelOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value, 10);
// bound to user settings
// don't render it
out->num_vertices = 0;
out->num_triangles = 0;
- out->type = 0;
+ type = 0;
break;
}
for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++)
invalidelements++;
if (invalidelements)
{
- Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, texture->nativecontents = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, out->type, out->texture->name, out->texture->surfaceflags, out->texture->nativecontents, out->firstvertex, out->num_vertices, out->firstelement, out->num_triangles * 3);
+ Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, texture->nativecontents = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, out->texture->nativecontents, firstvertex, out->num_vertices, firstelement, out->num_triangles * 3);
for (j = 0;j < out->num_triangles * 3;j++)
{
Con_Printf(" %i", out->data_element3i[j]);
loadmodel->brushq3.data_leaffaces = out;
loadmodel->brushq3.num_leaffaces = count;
+ loadmodel->brushq3.data_leaffacenums = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
+
for (i = 0;i < count;i++, in++, out++)
{
n = LittleLong(*in);
if (n < 0 || n >= loadmodel->brushq3.num_faces)
Host_Error("Mod_Q3BSP_LoadLeafFaces: invalid face index %i (%i faces)\n", n, loadmodel->brushq3.num_faces);
*out = loadmodel->brushq3.data_faces + n;
+ loadmodel->brushq3.data_leaffacenums[i] = n;
}
}
if (n < 0 || n + c > loadmodel->brushq3.num_leaffaces)
Host_Error("Mod_Q3BSP_LoadLeafs: invalid leafface range %i : %i (%i leaffaces)\n", n, n + c, loadmodel->brushq3.num_leaffaces);
out->firstleafface = loadmodel->brushq3.data_leaffaces + n;
+ out->firstleaffacenum = loadmodel->brushq3.data_leaffacenums + n;
out->numleaffaces = c;
n = LittleLong(in->firstleafbrush);
c = LittleLong(in->numleafbrushes);
for (i = 0;i < leaf->numleaffaces;i++)
{
face = leaf->firstleafface[i];
- if (face->collisions && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
+ if (face->num_collisiontriangles && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
{
face->collisionmarkframe = markframe;
Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
for (i = 0;i < leaf->numleaffaces;i++)
{
face = leaf->firstleafface[i];
- if (face->collisions && face->markframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
+ if (face->num_collisiontriangles && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
{
- face->markframe = markframe;
+ face->collisionmarkframe = markframe;
Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
}
}
for (i = 0;i < model->brushq3.data_thismodel->numfaces;i++)
{
face = model->brushq3.data_thismodel->firstface + i;
- if (face->collisions)
+ if (face->num_collisiontriangles)
Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
}
}
for (i = 0;i < model->brushq3.data_thismodel->numfaces;i++)
{
face = model->brushq3.data_thismodel->firstface + i;
- if (face->collisions)
+ if (face->num_collisiontriangles)
Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
}
}
}
*/
+void Mod_Q3BSP_BuildTextureFaceLists(void)
+{
+ int i, j;
+ loadmodel->brushq3.data_texturefaces = Mem_Alloc(loadmodel->mempool, loadmodel->nummodelsurfaces * sizeof(q3msurface_t *));
+ loadmodel->brushq3.data_texturefacenums = Mem_Alloc(loadmodel->mempool, loadmodel->nummodelsurfaces * sizeof(int));
+ for (i = 0;i < loadmodel->brushq3.num_textures;i++)
+ loadmodel->brushq3.data_textures[i].numfaces = 0;
+ for (i = 0;i < loadmodel->nummodelsurfaces;i++)
+ loadmodel->brushq3.data_faces[loadmodel->surfacelist[i]].texture->numfaces++;
+ j = 0;
+ for (i = 0;i < loadmodel->brushq3.num_textures;i++)
+ {
+ loadmodel->brushq3.data_textures[i].facelist = loadmodel->brushq3.data_texturefaces + j;
+ loadmodel->brushq3.data_textures[i].facenumlist = loadmodel->brushq3.data_texturefacenums + j;
+ j += loadmodel->brushq3.data_textures[i].numfaces;
+ loadmodel->brushq3.data_textures[i].numfaces = 0;
+ }
+ for (i = 0;i < loadmodel->nummodelsurfaces;i++)
+ {
+ loadmodel->brushq3.data_faces[loadmodel->surfacelist[i]].texture->facenumlist[loadmodel->brushq3.data_faces[loadmodel->surfacelist[i]].texture->numfaces] = loadmodel->surfacelist[i];
+ loadmodel->brushq3.data_faces[loadmodel->surfacelist[i]].texture->facelist[loadmodel->brushq3.data_faces[loadmodel->surfacelist[i]].texture->numfaces++] = loadmodel->brushq3.data_faces + loadmodel->surfacelist[i];
+ }
+}
+
+void Mod_Q3BSP_RecursiveFindNumLeafs(q3mnode_t *node)
+{
+ int numleafs;
+ while (node->plane)
+ {
+ Mod_Q3BSP_RecursiveFindNumLeafs(node->children[0]);
+ node = node->children[1];
+ }
+ numleafs = ((q3mleaf_t *)node - loadmodel->brushq3.data_leafs) + 1;
+ if (loadmodel->brushq3.num_leafs < numleafs)
+ loadmodel->brushq3.num_leafs = numleafs;
+}
+
extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
extern void R_Q3BSP_Draw(struct entity_render_s *ent);
extern void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
mod_base = (qbyte *)header;
// swap all the lumps
- for (i = 0;i < (int) sizeof(*header) / 4;i++)
- ((int *)header)[i] = LittleLong(((int *)header)[i]);
+ header->ident = LittleLong(header->ident);
+ header->version = LittleLong(header->version);
+ for (i = 0;i < Q3HEADER_LUMPS;i++)
+ {
+ header->lumps[i].fileofs = LittleLong(header->lumps[i].fileofs);
+ header->lumps[i].filelen = LittleLong(header->lumps[i].filelen);
+ }
Mod_Q3BSP_LoadEntities(&header->lumps[Q3LUMP_ENTITIES]);
Mod_Q3BSP_LoadTextures(&header->lumps[Q3LUMP_TEXTURES]);
Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, face->data_vertex3f, NULL, NULL, NULL, NULL, face->num_triangles, face->data_element3i);
loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true);
Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles);
-
+
+ loadmodel->brushq3.num_leafs = 0;
+ Mod_Q3BSP_RecursiveFindNumLeafs(loadmodel->brushq3.data_nodes);
+
+ mod = loadmodel;
for (i = 0;i < loadmodel->brushq3.num_models;i++)
{
- if (i == 0)
- mod = loadmodel;
- else
+ if (i > 0)
{
char name[10];
// LordHavoc: only register submodels if it is the world
- // (prevents bsp models from replacing world submodels)
+ // (prevents external bsp models from replacing world submodels with
+ // their own)
if (!loadmodel->isworldmodel)
continue;
// duplicate the basic information
if (j < mod->brushq3.data_thismodel->numfaces)
mod->DrawSky = R_Q3BSP_DrawSky;
}
+
+ Mod_Q3BSP_BuildTextureFaceLists();
}
void Mod_IBSP_Load(model_t *mod, void *buffer)