// LordHavoc: modified to start at first clip node,
// in other words: first node of the (sub)model
node = model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode;
- while (node->contents == 0)
+ while (node->plane)
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
return (mleaf_t *)node;
return false;
}
-/*
-static int Mod_Q1BSP_PointContents(model_t *model, const vec3_t p)
-{
- mnode_t *node;
-
- if (model == NULL)
- return CONTENTS_EMPTY;
-
- Mod_CheckLoaded(model);
-
- // LordHavoc: modified to start at first clip node,
- // in other words: first node of the (sub)model
- node = model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode;
- while (node->contents == 0)
- node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
-
- return ((mleaf_t *)node)->contents;
-}
-*/
-
typedef struct findnonsolidlocationinfo_s
{
vec3_t center;
static void Mod_Q1BSP_FindNonSolidLocation_r(findnonsolidlocationinfo_t *info, mnode_t *node)
{
- if (node->contents)
- {
- if (((mleaf_t *)node)->nummarksurfaces)
- Mod_Q1BSP_FindNonSolidLocation_r_Leaf(info, (mleaf_t *)node);
- }
- else
+ if (node->plane)
{
float f = PlaneDiff(info->center, node->plane);
if (f >= -info->bestdist)
if (f <= info->bestdist)
Mod_Q1BSP_FindNonSolidLocation_r(info, node->children[1]);
}
+ else
+ {
+ if (((mleaf_t *)node)->nummarksurfaces)
+ Mod_Q1BSP_FindNonSolidLocation_r_Leaf(info, (mleaf_t *)node);
+ }
}
static void Mod_Q1BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3_t out, float radius)
float mid;
loc0:
- if (node->contents < 0)
+ if (!node->plane)
return false; // didn't hit anything
switch (node->plane->type)
}
// go down front side
- if (node->children[side]->contents >= 0 && Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, node->children[side], x, y, startz, mid))
+ if (node->children[side]->plane && Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, node->children[side], x, y, startz, mid))
return true; // hit something
else
{
loadmodel->brushq1.surfaces = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t));
loadmodel->brushq1.numsurfaces = count;
- loadmodel->brushq1.surfacevisframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
- loadmodel->brushq1.surfacepvsframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
- loadmodel->brushq1.pvssurflist = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
for (surfnum = 0, surf = loadmodel->brushq1.surfaces, totalverts = 0, totaltris = 0, totalmeshes = 0;surfnum < count;surfnum++, totalverts += surf->poly_numverts, totaltris += surf->poly_numverts - 2, totalmeshes++, in++, surf++)
{
}
}
- loadmodel->entiremesh = Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, 0, 0, true, true, false);
+ // TODO: split up into multiple meshes as needed to avoid exceeding 65536
+ // vertex limit
+ loadmodel->nummeshes = 1;
+ loadmodel->meshlist = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *));
+ loadmodel->meshlist[0] = Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, 0, 0, true, true, false);
for (surfnum = 0, surf = loadmodel->brushq1.surfaces, totalverts = 0, totaltris = 0, totalmeshes = 0;surfnum < count;surfnum++, totalverts += surf->poly_numverts, totaltris += surf->poly_numverts - 2, totalmeshes++, surf++)
{
mesh = &surf->mesh;
mesh->num_vertices = surf->poly_numverts;
mesh->num_triangles = surf->poly_numverts - 2;
- mesh->data_vertex3f = loadmodel->entiremesh->data_vertex3f + totalverts * 3;
- mesh->data_texcoordtexture2f = loadmodel->entiremesh->data_texcoordtexture2f + totalverts * 2;
- mesh->data_texcoordlightmap2f = loadmodel->entiremesh->data_texcoordlightmap2f + totalverts * 2;
- mesh->data_texcoorddetail2f = loadmodel->entiremesh->data_texcoorddetail2f + totalverts * 2;
- mesh->data_svector3f = loadmodel->entiremesh->data_svector3f + totalverts * 3;
- mesh->data_tvector3f = loadmodel->entiremesh->data_tvector3f + totalverts * 3;
- mesh->data_normal3f = loadmodel->entiremesh->data_normal3f + totalverts * 3;
- mesh->data_lightmapoffsets = loadmodel->entiremesh->data_lightmapoffsets + totalverts;
- mesh->data_element3i = loadmodel->entiremesh->data_element3i + totaltris * 3;
- mesh->data_neighbor3i = loadmodel->entiremesh->data_neighbor3i + totaltris * 3;
+ mesh->data_vertex3f = loadmodel->meshlist[0]->data_vertex3f + totalverts * 3;
+ mesh->data_texcoordtexture2f = loadmodel->meshlist[0]->data_texcoordtexture2f + totalverts * 2;
+ mesh->data_texcoordlightmap2f = loadmodel->meshlist[0]->data_texcoordlightmap2f + totalverts * 2;
+ mesh->data_texcoorddetail2f = loadmodel->meshlist[0]->data_texcoorddetail2f + totalverts * 2;
+ mesh->data_svector3f = loadmodel->meshlist[0]->data_svector3f + totalverts * 3;
+ mesh->data_tvector3f = loadmodel->meshlist[0]->data_tvector3f + totalverts * 3;
+ mesh->data_normal3f = loadmodel->meshlist[0]->data_normal3f + totalverts * 3;
+ mesh->data_lightmapoffsets = loadmodel->meshlist[0]->data_lightmapoffsets + totalverts;
+ mesh->data_element3i = loadmodel->meshlist[0]->data_element3i + totaltris * 3;
+ mesh->data_neighbor3i = loadmodel->meshlist[0]->data_neighbor3i + totaltris * 3;
surf->lightmaptexturestride = 0;
surf->lightmaptexture = NULL;
static void Mod_Q1BSP_SetParent(mnode_t *node, mnode_t *parent)
{
node->parent = parent;
- if (node->contents < 0)
- return;
- Mod_Q1BSP_SetParent(node->children[0], node);
- Mod_Q1BSP_SetParent(node->children[1], node);
+ if (node->plane)
+ {
+ Mod_Q1BSP_SetParent(node->children[0], node);
+ Mod_Q1BSP_SetParent(node->children[1], node);
+ }
}
static void Mod_Q1BSP_LoadNodes(lump_t *l)
for (i = 0;i < loadmodel->brushq1.numnodes;i++, out++, in++)
{
out->planenum = in->plane - loadmodel->brushq1.planes;
- out->children[0] = in->children[0]->contents < 0 ? in->children[0]->contents : in->children[0] - loadmodel->brushq1.nodes;
- out->children[1] = in->children[1]->contents < 0 ? in->children[1]->contents : in->children[1] - loadmodel->brushq1.nodes;
+ out->children[0] = in->children[0]->plane ? in->children[0] - loadmodel->brushq1.nodes : ((mleaf_t *)in->children[0])->contents;
+ out->children[1] = in->children[1]->plane ? in->children[1] - loadmodel->brushq1.nodes : ((mleaf_t *)in->children[1])->contents;
}
}
static void Mod_Q1BSP_RecursiveRecalcNodeBBox(mnode_t *node)
{
+ // process only nodes (leafs already had their box calculated)
+ if (!node->plane)
+ return;
+
// calculate children first
- if (node->children[0]->contents >= 0)
- Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[0]);
- if (node->children[1]->contents >= 0)
- Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[1]);
+ Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[0]);
+ Mod_Q1BSP_RecursiveRecalcNodeBBox(node->children[1]);
// make combined bounding box from children
node->mins[0] = min(node->children[0]->mins[0], node->children[1]->mins[0]);
{
// note: this check must match the one below or it will usually corrupt memory
// the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
- if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1]
- && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
- && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
+ if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1] && ((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
{
numportals += 2;
numpoints += p->numpoints * 2;
{
pnext = p->chain;
- if (p->numpoints >= 3)
+ // note: this check must match the one above or it will usually corrupt memory
+ // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
+ if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1] && ((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
{
- // note: this check must match the one above or it will usually corrupt memory
- // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
- if (p->nodes[0] != p->nodes[1]
- && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID
- && p->nodes[0]->contents != CONTENTS_SKY && p->nodes[1]->contents != CONTENTS_SKY)
+ // first make the back to front portal(forward portal)
+ portal->points = point;
+ portal->numpoints = p->numpoints;
+ portal->plane.dist = p->plane.dist;
+ VectorCopy(p->plane.normal, portal->plane.normal);
+ portal->here = (mleaf_t *)p->nodes[1];
+ portal->past = (mleaf_t *)p->nodes[0];
+ // copy points
+ for (j = 0;j < portal->numpoints;j++)
{
- // first make the back to front portal(forward portal)
- portal->points = point;
- portal->numpoints = p->numpoints;
- portal->plane.dist = p->plane.dist;
- VectorCopy(p->plane.normal, portal->plane.normal);
- portal->here = (mleaf_t *)p->nodes[1];
- portal->past = (mleaf_t *)p->nodes[0];
- // copy points
- for (j = 0;j < portal->numpoints;j++)
- {
- VectorCopy(p->points + j*3, point->position);
- point++;
- }
- PlaneClassify(&portal->plane);
-
- // link into leaf's portal chain
- portal->next = portal->here->portals;
- portal->here->portals = portal;
-
- // advance to next portal
- portal++;
-
- // then make the front to back portal(backward portal)
- portal->points = point;
- portal->numpoints = p->numpoints;
- portal->plane.dist = -p->plane.dist;
- VectorNegate(p->plane.normal, portal->plane.normal);
- portal->here = (mleaf_t *)p->nodes[0];
- portal->past = (mleaf_t *)p->nodes[1];
- // copy points
- for (j = portal->numpoints - 1;j >= 0;j--)
- {
- VectorCopy(p->points + j*3, point->position);
- point++;
- }
- PlaneClassify(&portal->plane);
+ VectorCopy(p->points + j*3, point->position);
+ point++;
+ }
+ BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
+ PlaneClassify(&portal->plane);
+
+ // link into leaf's portal chain
+ portal->next = portal->here->portals;
+ portal->here->portals = portal;
+
+ // advance to next portal
+ portal++;
+
+ // then make the front to back portal(backward portal)
+ portal->points = point;
+ portal->numpoints = p->numpoints;
+ portal->plane.dist = -p->plane.dist;
+ VectorNegate(p->plane.normal, portal->plane.normal);
+ portal->here = (mleaf_t *)p->nodes[0];
+ portal->past = (mleaf_t *)p->nodes[1];
+ // copy points
+ for (j = portal->numpoints - 1;j >= 0;j--)
+ {
+ VectorCopy(p->points + j*3, point->position);
+ point++;
+ }
+ BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
+ PlaneClassify(&portal->plane);
- // link into leaf's portal chain
- portal->next = portal->here->portals;
- portal->here->portals = portal;
+ // link into leaf's portal chain
+ portal->next = portal->here->portals;
+ portal->here->portals = portal;
- // advance to next portal
- portal++;
- }
+ // advance to next portal
+ portal++;
}
FreePortal(p);
p = pnext;
double frontpoints[3*MAX_PORTALPOINTS], backpoints[3*MAX_PORTALPOINTS];
// if a leaf, we're done
- if (node->contents)
+ if (!node->plane)
return;
plane = node->plane;
}
}
-static void Mod_Q1BSP_BuildPVSTextureChains(model_t *model)
-{
- int i, j;
- for (i = 0;i < model->brushq1.numtextures;i++)
- model->brushq1.pvstexturechainslength[i] = 0;
- for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
- {
- if (model->brushq1.surfacepvsframes[j] == model->brushq1.pvsframecount)
- {
- model->brushq1.pvssurflist[model->brushq1.pvssurflistlength++] = j;
- model->brushq1.pvstexturechainslength[model->brushq1.surfaces[j].texinfo->texture->number]++;
- }
- }
- for (i = 0, j = 0;i < model->brushq1.numtextures;i++)
- {
- if (model->brushq1.pvstexturechainslength[i])
- {
- model->brushq1.pvstexturechains[i] = model->brushq1.pvstexturechainsbuffer + j;
- j += model->brushq1.pvstexturechainslength[i] + 1;
- }
- else
- model->brushq1.pvstexturechains[i] = NULL;
- }
- for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
- if (model->brushq1.surfacepvsframes[j] == model->brushq1.pvsframecount)
- *model->brushq1.pvstexturechains[model->brushq1.surfaces[j].texinfo->texture->number]++ = model->brushq1.surfaces + j;
- for (i = 0;i < model->brushq1.numtextures;i++)
- {
- if (model->brushq1.pvstexturechainslength[i])
- {
- *model->brushq1.pvstexturechains[i] = NULL;
- model->brushq1.pvstexturechains[i] -= model->brushq1.pvstexturechainslength[i];
- }
- }
-}
-
//Returns PVS data for a given point
//(note: can return NULL)
static qbyte *Mod_Q1BSP_GetPVS(model_t *model, const vec3_t p)
mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
mod->brush.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize;
mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
- mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
if (loadmodel->isworldmodel)
Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
mod->brush.LightPoint = NULL;
mod->brush.AmbientSoundLevelsForPoint = NULL;
}
- mod->brushq1.pvstexturechains = Mem_Alloc(loadmodel->mempool, mod->brushq1.numtextures * sizeof(msurface_t **));
- mod->brushq1.pvstexturechainsbuffer = Mem_Alloc(loadmodel->mempool,(mod->nummodelsurfaces + mod->brushq1.numtextures) * sizeof(msurface_t *));
- mod->brushq1.pvstexturechainslength = Mem_Alloc(loadmodel->mempool, mod->brushq1.numtextures * sizeof(int));
- Mod_Q1BSP_BuildPVSTextureChains(mod);
Mod_Q1BSP_BuildLightmapUpdateChains(loadmodel->mempool, mod);
if (mod->nummodelsurfaces)
{
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->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, LittleLong(in->contents));
out->surfaceparms = -1;
}
static void Mod_Q3BSP_LoadFaces(lump_t *l)
{
- q3dface_t *in;
- q3msurface_t *out;
- int i, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xtess, ytess, finalvertices, finaltriangles, firstvertex, firstelement, type, oldnumtriangles, oldnumtriangles2;
+ q3dface_t *in, *oldin;
+ q3msurface_t *out, *oldout;
+ int i, oldi, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xtess, ytess, finalvertices, finaltriangles, firstvertex, firstelement, type, oldnumtriangles, oldnumtriangles2, meshnum, meshvertices, meshtriangles, numvertices, numtriangles;
//int *originalelement3i;
//int *originalneighbor3i;
float *originalvertex3f;
float *originaltexcoordtexture2f;
float *originaltexcoordlightmap2f;
float *v;
+ surfmesh_t *mesh, *tempmeshlist[1024];
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
loadmodel->brushq3.data_faces = out;
loadmodel->brushq3.num_faces = count;
- for (i = 0;i < count;i++, in++, out++)
- {
- // check face type first
- type = LittleLong(in->type);
- if (type != Q3FACETYPE_POLYGON
- && type != Q3FACETYPE_PATCH
- && type != Q3FACETYPE_MESH
- && type != Q3FACETYPE_FLARE)
+ i = 0;
+ for (meshnum = 0;i < count;meshnum++)
+ {
+ oldi = i;
+ oldin = in;
+ oldout = out;
+ meshvertices = 0;
+ meshtriangles = 0;
+ for (;i < count;i++, in++, out++)
{
- Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, type);
- out->num_vertices = 0;
- out->num_triangles = 0;
- type = 0; // error
- continue;
- }
+ // check face type first
+ 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, type);
+ continue;
+ }
- n = LittleLong(in->textureindex);
- if (n < 0 || n >= loadmodel->brushq3.num_textures)
- {
- 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;
- type = 0; // error
- continue;
- n = 0;
- }
- out->texture = loadmodel->brushq3.data_textures + n;
- n = LittleLong(in->effectindex);
- if (n < -1 || n >= loadmodel->brushq3.num_effects)
- {
- if (developer.integer >= 2)
- Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid effectindex %i (%i effects)\n", i, out->texture->name, n, loadmodel->brushq3.num_effects);
- n = -1;
- }
- if (n == -1)
- out->effect = NULL;
- else
- out->effect = loadmodel->brushq3.data_effects + n;
- n = LittleLong(in->lightmapindex);
- if (n >= loadmodel->brushq3.num_lightmaps)
- {
- Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
- n = -1;
- }
- else if (n < 0)
- n = -1;
- if (n == -1)
- out->lightmaptexture = NULL;
- else
- out->lightmaptexture = loadmodel->brushq3.data_lightmaps[n];
+ n = LittleLong(in->textureindex);
+ if (n < 0 || n >= loadmodel->brushq3.num_textures)
+ {
+ Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->brushq3.num_textures);
+ continue;
+ }
+ out->texture = loadmodel->brushq3.data_textures + n;
+ n = LittleLong(in->effectindex);
+ if (n < -1 || n >= loadmodel->brushq3.num_effects)
+ {
+ if (developer.integer >= 2)
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid effectindex %i (%i effects)\n", i, out->texture->name, n, loadmodel->brushq3.num_effects);
+ n = -1;
+ }
+ if (n == -1)
+ out->effect = NULL;
+ else
+ out->effect = loadmodel->brushq3.data_effects + n;
+ n = LittleLong(in->lightmapindex);
+ if (n >= loadmodel->brushq3.num_lightmaps)
+ {
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
+ n = -1;
+ }
+ else if (n < 0)
+ n = -1;
+ if (n == -1)
+ out->lightmaptexture = NULL;
+ else
+ out->lightmaptexture = loadmodel->brushq3.data_lightmaps[n];
- firstvertex = LittleLong(in->firstvertex);
- out->num_vertices = LittleLong(in->numvertices);
- 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;
- type = 0; // error
- continue;
- }
- 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, firstvertex, firstvertex + out->num_vertices, loadmodel->brushq3.num_vertices);
- out->num_vertices = 0;
- out->num_triangles = 0;
- type = 0; // error
- continue;
- }
- 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, firstelement, firstelement + out->num_triangles * 3, loadmodel->brushq3.num_triangles * 3);
- out->num_vertices = 0;
- out->num_triangles = 0;
- type = 0; // error
- continue;
- }
- switch(type)
- {
- case Q3FACETYPE_POLYGON:
- case Q3FACETYPE_MESH:
- // no processing necessary
- 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]);
- patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
- if (patchsize[0] < 3 || patchsize[1] < 3 || !(patchsize[0] & 1) || !(patchsize[1] & 1) || patchsize[0] * patchsize[1] >= min(r_subdivisions_maxvertices.integer, r_subdivisions_collision_maxvertices.integer))
+ firstvertex = LittleLong(in->firstvertex);
+ numvertices = LittleLong(in->numvertices);
+ firstelement = LittleLong(in->firstelement);
+ numtriangles = LittleLong(in->numelements) / 3;
+ if (numtriangles * 3 != LittleLong(in->numelements))
{
- 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;
- type = 0; // error
+ 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));
continue;
}
- 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;
- //originaltvector3f = out->data_tvector3f;
- //originalnormal3f = out->data_normal3f;
- originalcolor4f = out->data_color4f;
- originaltexcoordtexture2f = out->data_texcoordtexture2f;
- originaltexcoordlightmap2f = out->data_texcoordlightmap2f;
- //originalelement3i = out->data_element3i;
- //originalneighbor3i = out->data_neighbor3i;
- */
- // convert patch to Q3FACETYPE_MESH
- xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
- ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
- // bound to user settings
- xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
- ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
- // bound to sanity settings
- xtess = bound(1, xtess, 1024);
- ytess = bound(1, ytess, 1024);
- // bound to user limit on vertices
- while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
+ if (firstvertex < 0 || firstvertex + numvertices > loadmodel->brushq3.num_vertices)
{
- if (xtess > ytess)
- xtess--;
- else
- ytess--;
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, firstvertex, firstvertex + numvertices, loadmodel->brushq3.num_vertices);
+ continue;
}
- finalwidth = ((patchsize[0] - 1) * xtess) + 1;
- finalheight = ((patchsize[1] - 1) * ytess) + 1;
- finalvertices = finalwidth * finalheight;
- finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
- 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 = Mem_Alloc(loadmodel->mempool, sizeof(int[6]) * finaltriangles);
- out->data_neighbor3i = out->data_element3i + finaltriangles * 3;
- type = Q3FACETYPE_MESH;
- firstvertex = -1;
- out->num_vertices = finalvertices;
- firstelement = -1;
- out->num_triangles = finaltriangles;
- // generate geometry
- // (note: normals are skipped because they get recalculated)
- Q3PatchTesselateFloat(3, sizeof(float[3]), out->data_vertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
- Q3PatchTesselateFloat(2, sizeof(float[2]), out->data_texcoordtexture2f, patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordtexture2f, xtess, ytess);
- Q3PatchTesselateFloat(2, sizeof(float[2]), out->data_texcoordlightmap2f, patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordlightmap2f, xtess, ytess);
- Q3PatchTesselateFloat(4, sizeof(float[4]), out->data_color4f, patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
- Q3PatchTriangleElements(out->data_element3i, finalwidth, finalheight);
- if (developer.integer >= 2)
+ if (firstelement < 0 || firstelement + numtriangles * 3 > loadmodel->brushq3.num_triangles * 3)
{
- if (out->num_triangles < finaltriangles)
- Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_vertices, finaltriangles, finaltriangles - out->num_triangles, out->num_triangles);
- else
- Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_vertices, out->num_triangles);
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, firstelement, firstelement + numtriangles * 3, loadmodel->brushq3.num_triangles * 3);
+ continue;
}
- // q3map does not put in collision brushes for curves... ugh
- // build the lower quality collision geometry
- xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
- ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
- // bound to user settings
- xtess = bound(r_subdivisions_collision_mintess.integer, xtess, r_subdivisions_collision_maxtess.integer);
- ytess = bound(r_subdivisions_collision_mintess.integer, ytess, r_subdivisions_collision_maxtess.integer);
- // bound to sanity settings
- xtess = bound(1, xtess, 1024);
- ytess = bound(1, ytess, 1024);
- // bound to user limit on vertices
- while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_collision_maxvertices.integer, 262144))
+ switch(type)
{
- if (xtess > ytess)
- xtess--;
- else
- ytess--;
+ case Q3FACETYPE_POLYGON:
+ case Q3FACETYPE_MESH:
+ // no processing necessary
+ break;
+ case Q3FACETYPE_PATCH:
+ patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
+ patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
+ if (numvertices != (patchsize[0] * patchsize[1]) || patchsize[0] < 3 || patchsize[1] < 3 || !(patchsize[0] & 1) || !(patchsize[1] & 1) || patchsize[0] * patchsize[1] >= min(r_subdivisions_maxvertices.integer, r_subdivisions_collision_maxvertices.integer))
+ {
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid patchsize %ix%i\n", i, out->texture->name, patchsize[0], patchsize[1]);
+ continue;
+ }
+ originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+ // convert patch to Q3FACETYPE_MESH
+ xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+ ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+ // bound to user settings
+ xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
+ ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
+ // bound to sanity settings
+ xtess = bound(1, xtess, 1024);
+ ytess = bound(1, ytess, 1024);
+ // bound to user limit on vertices
+ while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
+ {
+ if (xtess > ytess)
+ xtess--;
+ else
+ ytess--;
+ }
+ finalwidth = ((patchsize[0] - 1) * xtess) + 1;
+ finalheight = ((patchsize[1] - 1) * ytess) + 1;
+ numvertices = finalwidth * finalheight;
+ numtriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+ break;
+ case Q3FACETYPE_FLARE:
+ if (developer.integer >= 2)
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name);
+ // don't render it
+ continue;
}
- finalwidth = ((patchsize[0] - 1) * xtess) + 1;
- finalheight = ((patchsize[1] - 1) * ytess) + 1;
- finalvertices = finalwidth * finalheight;
- finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
-
- out->data_collisionvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * finalvertices);
- out->data_collisionelement3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * finaltriangles);
- out->num_collisionvertices = finalvertices;
- out->num_collisiontriangles = finaltriangles;
- Q3PatchTesselateFloat(3, sizeof(float[3]), out->data_collisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
- Q3PatchTriangleElements(out->data_collisionelement3i, finalwidth, finalheight);
-
- //Mod_SnapVertices(3, out->num_vertices, out->data_vertex3f, 0.25);
- Mod_SnapVertices(3, out->num_collisionvertices, out->data_collisionvertex3f, 1);
-
- oldnumtriangles = out->num_triangles;
- oldnumtriangles2 = out->num_collisiontriangles;
- out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, out->data_element3i, out->data_element3i, out->data_vertex3f);
- out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f);
- if (developer.integer)
- Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->num_vertices, out->num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->num_triangles, oldnumtriangles2 - out->num_collisiontriangles);
- break;
- case Q3FACETYPE_FLARE:
- if (developer.integer >= 2)
- Con_Printf("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;
- type = 0;
- break;
+ out->mesh.num_vertices = numvertices;
+ out->mesh.num_triangles = numtriangles;
+ if (meshvertices + out->mesh.num_vertices > 65536)
+ break;
+ meshvertices += out->mesh.num_vertices;
+ meshtriangles += out->mesh.num_triangles;
}
- for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++)
- if (out->data_element3i[j] < 0 || out->data_element3i[j] >= out->num_vertices)
- invalidelements++;
- if (invalidelements)
+
+ i = oldi;
+ in = oldin;
+ out = oldout;
+ mesh = tempmeshlist[meshnum] = Mod_AllocSurfMesh(loadmodel->mempool, meshvertices, meshtriangles, 0, 0, false, false, true);
+ meshvertices = 0;
+ meshtriangles = 0;
+ for (;i < count && meshvertices + out->mesh.num_vertices <= mesh->num_vertices;i++, in++, out++)
{
- 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++)
+ if (out->mesh.num_vertices < 3 || out->mesh.num_triangles < 1)
+ continue;
+
+ type = LittleLong(in->type);
+ firstvertex = LittleLong(in->firstvertex);
+ firstelement = LittleLong(in->firstelement);
+ out->mesh.data_vertex3f = mesh->data_vertex3f + meshvertices * 3;
+ out->mesh.data_svector3f = mesh->data_svector3f + meshvertices * 3;
+ out->mesh.data_tvector3f = mesh->data_tvector3f + meshvertices * 3;
+ out->mesh.data_normal3f = mesh->data_normal3f + meshvertices * 3;
+ out->mesh.data_texcoordtexture2f = mesh->data_texcoordtexture2f + meshvertices * 2;
+ out->mesh.data_texcoordlightmap2f = mesh->data_texcoordlightmap2f + meshvertices * 2;
+ out->mesh.data_lightmapcolor4f = mesh->data_lightmapcolor4f + meshvertices * 4;
+ out->mesh.data_element3i = mesh->data_element3i + meshtriangles * 3;
+ out->mesh.data_neighbor3i = mesh->data_neighbor3i + meshtriangles * 3;
+ switch(type)
+ {
+ case Q3FACETYPE_POLYGON:
+ case Q3FACETYPE_MESH:
+ // no processing necessary
+ for (j = 0;j < out->mesh.num_vertices;j++)
+ {
+ out->mesh.data_vertex3f[j * 3 + 0] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 0];
+ out->mesh.data_vertex3f[j * 3 + 1] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 1];
+ out->mesh.data_vertex3f[j * 3 + 2] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 2];
+ out->mesh.data_texcoordtexture2f[j * 2 + 0] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 0];
+ out->mesh.data_texcoordtexture2f[j * 2 + 1] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 1];
+ out->mesh.data_texcoordlightmap2f[j * 2 + 0] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 0];
+ out->mesh.data_texcoordlightmap2f[j * 2 + 1] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 1];
+ out->mesh.data_lightmapcolor4f[j * 4 + 0] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 0];
+ out->mesh.data_lightmapcolor4f[j * 4 + 1] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 1];
+ out->mesh.data_lightmapcolor4f[j * 4 + 2] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 2];
+ out->mesh.data_lightmapcolor4f[j * 4 + 3] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 3];
+ }
+ for (j = 0;j < out->mesh.num_triangles*3;j++)
+ out->mesh.data_element3i[j] = loadmodel->brushq3.data_element3i[firstelement + j];
+ break;
+ case Q3FACETYPE_PATCH:
+ patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
+ patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
+ originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+ originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
+ originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
+ originalcolor4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
+ // convert patch to Q3FACETYPE_MESH
+ xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+ ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+ // bound to user settings
+ xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
+ ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
+ // bound to sanity settings
+ xtess = bound(1, xtess, 1024);
+ ytess = bound(1, ytess, 1024);
+ // bound to user limit on vertices
+ while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
+ {
+ if (xtess > ytess)
+ xtess--;
+ else
+ ytess--;
+ }
+ finalwidth = ((patchsize[0] - 1) * xtess) + 1;
+ finalheight = ((patchsize[1] - 1) * ytess) + 1;
+ finalvertices = finalwidth * finalheight;
+ finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+ type = Q3FACETYPE_MESH;
+ // generate geometry
+ // (note: normals are skipped because they get recalculated)
+ Q3PatchTesselateFloat(3, sizeof(float[3]), out->mesh.data_vertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
+ Q3PatchTesselateFloat(2, sizeof(float[2]), out->mesh.data_texcoordtexture2f, patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordtexture2f, xtess, ytess);
+ Q3PatchTesselateFloat(2, sizeof(float[2]), out->mesh.data_texcoordlightmap2f, patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordlightmap2f, xtess, ytess);
+ Q3PatchTesselateFloat(4, sizeof(float[4]), out->mesh.data_lightmapcolor4f, patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
+ Q3PatchTriangleElements(out->mesh.data_element3i, finalwidth, finalheight);
+ out->mesh.num_triangles = Mod_RemoveDegenerateTriangles(out->mesh.num_triangles, out->mesh.data_element3i, out->mesh.data_element3i, out->mesh.data_vertex3f);
+ if (developer.integer >= 2)
+ {
+ if (out->mesh.num_triangles < finaltriangles)
+ Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->mesh.num_vertices, finaltriangles, finaltriangles - out->mesh.num_triangles, out->mesh.num_triangles);
+ else
+ Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->mesh.num_vertices, out->mesh.num_triangles);
+ }
+ // q3map does not put in collision brushes for curves... ugh
+ // build the lower quality collision geometry
+ xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
+ ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
+ // bound to user settings
+ xtess = bound(r_subdivisions_collision_mintess.integer, xtess, r_subdivisions_collision_maxtess.integer);
+ ytess = bound(r_subdivisions_collision_mintess.integer, ytess, r_subdivisions_collision_maxtess.integer);
+ // bound to sanity settings
+ xtess = bound(1, xtess, 1024);
+ ytess = bound(1, ytess, 1024);
+ // bound to user limit on vertices
+ while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_collision_maxvertices.integer, 262144))
+ {
+ if (xtess > ytess)
+ xtess--;
+ else
+ ytess--;
+ }
+ finalwidth = ((patchsize[0] - 1) * xtess) + 1;
+ finalheight = ((patchsize[1] - 1) * ytess) + 1;
+ finalvertices = finalwidth * finalheight;
+ finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+
+ out->mesh.data_collisionvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * finalvertices);
+ out->mesh.data_collisionelement3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * finaltriangles);
+ out->mesh.num_collisionvertices = finalvertices;
+ out->mesh.num_collisiontriangles = finaltriangles;
+ Q3PatchTesselateFloat(3, sizeof(float[3]), out->mesh.data_collisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
+ Q3PatchTriangleElements(out->mesh.data_collisionelement3i, finalwidth, finalheight);
+
+ //Mod_SnapVertices(3, out->mesh.num_vertices, out->mesh.data_vertex3f, 0.25);
+ Mod_SnapVertices(3, out->mesh.num_collisionvertices, out->mesh.data_collisionvertex3f, 1);
+
+ oldnumtriangles = out->mesh.num_triangles;
+ oldnumtriangles2 = out->mesh.num_collisiontriangles;
+ out->mesh.num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->mesh.num_collisiontriangles, out->mesh.data_collisionelement3i, out->mesh.data_collisionelement3i, out->mesh.data_collisionvertex3f);
+ if (developer.integer)
+ Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->mesh.num_vertices, out->mesh.num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->mesh.num_triangles, oldnumtriangles2 - out->mesh.num_collisiontriangles);
+ break;
+ default:
+ break;
+ }
+ meshvertices += out->mesh.num_vertices;
+ meshtriangles += out->mesh.num_triangles;
+ for (j = 0, invalidelements = 0;j < out->mesh.num_triangles * 3;j++)
+ if (out->mesh.data_element3i[j] < 0 || out->mesh.data_element3i[j] >= out->mesh.num_vertices)
+ invalidelements++;
+ if (invalidelements)
{
- Con_Printf(" %i", out->data_element3i[j]);
- if (out->data_element3i[j] < 0 || out->data_element3i[j] >= out->num_vertices)
- out->data_element3i[j] = 0;
+ Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, firstvertex, out->mesh.num_vertices, firstelement, out->mesh.num_triangles * 3);
+ for (j = 0;j < out->mesh.num_triangles * 3;j++)
+ {
+ Con_Printf(" %i", out->mesh.data_element3i[j]);
+ if (out->mesh.data_element3i[j] < 0 || out->mesh.data_element3i[j] >= out->mesh.num_vertices)
+ out->mesh.data_element3i[j] = 0;
+ }
+ Con_Print("\n");
}
- Con_Print("\n");
- }
- // for shadow volumes
- Mod_BuildTriangleNeighbors(out->data_neighbor3i, out->data_element3i, out->num_triangles);
- // for per pixel lighting
- Mod_BuildTextureVectorsAndNormals(out->num_vertices, out->num_triangles, out->data_vertex3f, out->data_texcoordtexture2f, out->data_element3i, out->data_svector3f, out->data_tvector3f, out->data_normal3f);
- // calculate a bounding box
- VectorClear(out->mins);
- VectorClear(out->maxs);
- if (out->num_vertices)
- {
- VectorCopy(out->data_vertex3f, out->mins);
- VectorCopy(out->data_vertex3f, out->maxs);
- for (j = 1, v = out->data_vertex3f + 3;j < out->num_vertices;j++, v += 3)
+ // for shadow volumes
+ Mod_BuildTriangleNeighbors(out->mesh.data_neighbor3i, out->mesh.data_element3i, out->mesh.num_triangles);
+ // for per pixel lighting
+ Mod_BuildTextureVectorsAndNormals(out->mesh.num_vertices, out->mesh.num_triangles, out->mesh.data_vertex3f, out->mesh.data_texcoordtexture2f, out->mesh.data_element3i, out->mesh.data_svector3f, out->mesh.data_tvector3f, out->mesh.data_normal3f);
+ // calculate a bounding box
+ VectorClear(out->mins);
+ VectorClear(out->maxs);
+ if (out->mesh.num_vertices)
{
- out->mins[0] = min(out->mins[0], v[0]);
- out->maxs[0] = max(out->maxs[0], v[0]);
- out->mins[1] = min(out->mins[1], v[1]);
- out->maxs[1] = max(out->maxs[1], v[1]);
- out->mins[2] = min(out->mins[2], v[2]);
- out->maxs[2] = max(out->maxs[2], v[2]);
+ VectorCopy(out->mesh.data_vertex3f, out->mins);
+ VectorCopy(out->mesh.data_vertex3f, out->maxs);
+ for (j = 1, v = out->mesh.data_vertex3f + 3;j < out->mesh.num_vertices;j++, v += 3)
+ {
+ out->mins[0] = min(out->mins[0], v[0]);
+ out->maxs[0] = max(out->maxs[0], v[0]);
+ out->mins[1] = min(out->mins[1], v[1]);
+ out->maxs[1] = max(out->maxs[1], v[1]);
+ out->mins[2] = min(out->mins[2], v[2]);
+ out->maxs[2] = max(out->maxs[2], v[2]);
+ }
+ out->mins[0] -= 1.0f;
+ out->mins[1] -= 1.0f;
+ out->mins[2] -= 1.0f;
+ out->maxs[0] += 1.0f;
+ out->maxs[1] += 1.0f;
+ out->maxs[2] += 1.0f;
}
- out->mins[0] -= 1.0f;
- out->mins[1] -= 1.0f;
- out->mins[2] -= 1.0f;
- out->maxs[0] += 1.0f;
- out->maxs[1] += 1.0f;
- out->maxs[2] += 1.0f;
}
}
- // LordHavoc: experimental array merger (disabled because it wastes time and uses 2x memory while merging)
- /*
+ // now store the completed list of meshes
+ loadmodel->nummeshes = meshnum;
+ if (loadmodel->nummeshes)
{
- 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);
+ loadmodel->meshlist = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *) * loadmodel->nummeshes);
+ memcpy(loadmodel->meshlist, tempmeshlist, sizeof(surfmesh_t *) * loadmodel->nummeshes);
}
- */
}
static void Mod_Q3BSP_LoadModels(lump_t *l)
for (i = 0;i < leaf->numleaffaces;i++)
{
face = leaf->firstleafface[i];
- if (face->num_collisiontriangles && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
+ if (face->mesh.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);
+ Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, face->mesh.num_collisiontriangles, face->mesh.data_collisionelement3i, face->mesh.data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
if (startfrac > trace->realfraction)
return;
}
for (i = 0;i < leaf->numleaffaces;i++)
{
face = leaf->firstleafface[i];
- if (face->num_collisiontriangles && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
+ if (face->mesh.num_collisiontriangles && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs))
{
face->collisionmarkframe = markframe;
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
+ Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->mesh.num_collisiontriangles, face->mesh.data_collisionelement3i, face->mesh.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->num_collisiontriangles)
- Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
+ if (face->mesh.num_collisiontriangles)
+ Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->mesh.num_collisiontriangles, face->mesh.data_collisionelement3i, face->mesh.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->num_collisiontriangles)
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
+ if (face->mesh.num_collisiontriangles)
+ Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->mesh.num_collisiontriangles, face->mesh.data_collisionelement3i, face->mesh.data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs);
}
}
}
static int Mod_Q3BSP_SuperContentsFromNativeContents(model_t *model, int nativecontents)
{
int supercontents = 0;
- if (nativecontents & Q2CONTENTS_SOLID)
+ if (nativecontents & CONTENTSQ3_SOLID)
supercontents |= SUPERCONTENTS_SOLID;
- if (nativecontents & Q2CONTENTS_WATER)
+ if (nativecontents & CONTENTSQ3_WATER)
supercontents |= SUPERCONTENTS_WATER;
- if (nativecontents & Q2CONTENTS_SLIME)
+ if (nativecontents & CONTENTSQ3_SLIME)
supercontents |= SUPERCONTENTS_SLIME;
- if (nativecontents & Q2CONTENTS_LAVA)
+ if (nativecontents & CONTENTSQ3_LAVA)
supercontents |= SUPERCONTENTS_LAVA;
+ if (nativecontents & CONTENTSQ3_BODY)
+ supercontents |= SUPERCONTENTS_BODY;
+ if (nativecontents & CONTENTSQ3_CORPSE)
+ supercontents |= SUPERCONTENTS_CORPSE;
+ if (nativecontents & CONTENTSQ3_NODROP)
+ supercontents |= SUPERCONTENTS_NODROP;
return supercontents;
}
{
int nativecontents = 0;
if (supercontents & SUPERCONTENTS_SOLID)
- nativecontents |= Q2CONTENTS_SOLID;
+ nativecontents |= CONTENTSQ3_SOLID;
if (supercontents & SUPERCONTENTS_WATER)
- nativecontents |= Q2CONTENTS_WATER;
+ nativecontents |= CONTENTSQ3_WATER;
if (supercontents & SUPERCONTENTS_SLIME)
- nativecontents |= Q2CONTENTS_SLIME;
+ nativecontents |= CONTENTSQ3_SLIME;
if (supercontents & SUPERCONTENTS_LAVA)
- nativecontents |= Q2CONTENTS_LAVA;
+ nativecontents |= CONTENTSQ3_LAVA;
+ if (supercontents & SUPERCONTENTS_BODY)
+ nativecontents |= CONTENTSQ3_BODY;
+ if (supercontents & SUPERCONTENTS_CORPSE)
+ nativecontents |= CONTENTSQ3_CORPSE;
+ if (supercontents & SUPERCONTENTS_NODROP)
+ nativecontents |= CONTENTSQ3_NODROP;
return nativecontents;
}
for (j = 0, face = loadmodel->brushq3.data_faces;j < loadmodel->brushq3.num_faces;j++, face++)
{
face->num_firstshadowmeshtriangle = numshadowmeshtriangles;
- numshadowmeshtriangles += face->num_triangles;
+ numshadowmeshtriangles += face->mesh.num_triangles;
}
loadmodel->brush.shadowmesh = Mod_ShadowMesh_Begin(loadmodel->mempool, numshadowmeshtriangles * 3, numshadowmeshtriangles, NULL, NULL, NULL, false, false, true);
for (j = 0, face = loadmodel->brushq3.data_faces;j < loadmodel->brushq3.num_faces;j++, face++)
- Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, face->data_vertex3f, NULL, NULL, NULL, NULL, face->num_triangles, face->data_element3i);
+ Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, face->mesh.data_vertex3f, NULL, NULL, NULL, NULL, face->mesh.num_triangles, face->mesh.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);