X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_brush.c;h=f2f9e833a498cdcb5143684d6ef363f74acfe66c;hb=7b67f537c5328ed9e41846ae2bad4ecc8f9f51cd;hp=d63e9003e230cf8d73a4737adbde42ca89244f70;hpb=584b16bd1bcf1e3683f7c93e93b67d5d7c56cdea;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index d63e9003..f2f9e833 100644 --- a/model_brush.c +++ b/model_brush.c @@ -36,7 +36,7 @@ cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"}; cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"}; cvar_t mod_q3bsp_curves_subdivide_level = {0, "mod_q3bsp_curves_subdivide_level", "2"}; cvar_t mod_q3bsp_curves_collisions = {0, "mod_q3bsp_curves_collisions", "1"}; -cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "1"}; +cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "0"}; void Mod_BrushInit(void) { @@ -169,7 +169,6 @@ static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *in float surfnormal[3]; #endif msurface_t *surf; - surfmesh_t *mesh; for (surfnum = 0, mark = leaf->firstmarksurface;surfnum < leaf->nummarksurfaces;surfnum++, mark++) { surf = info->model->brushq1.surfaces + *mark; @@ -180,103 +179,100 @@ static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *in if (surf->flags & SURF_PLANEBACK) VectorNegate(surfnormal, surfnormal); #endif - for (mesh = surf->mesh;mesh;mesh = mesh->chain) + for (k = 0;k < surf->mesh.num_triangles;k++) { - for (k = 0;k < mesh->numtriangles;k++) + tri = surf->mesh.data_element3i + k * 3; + VectorCopy((surf->mesh.data_vertex3f + tri[0] * 3), vert[0]); + VectorCopy((surf->mesh.data_vertex3f + tri[1] * 3), vert[1]); + VectorCopy((surf->mesh.data_vertex3f + tri[2] * 3), vert[2]); + VectorSubtract(vert[1], vert[0], edge[0]); + VectorSubtract(vert[2], vert[1], edge[1]); + CrossProduct(edge[1], edge[0], facenormal); + if (facenormal[0] || facenormal[1] || facenormal[2]) { - tri = mesh->element3i + k * 3; - VectorCopy((mesh->vertex3f + tri[0] * 3), vert[0]); - VectorCopy((mesh->vertex3f + tri[1] * 3), vert[1]); - VectorCopy((mesh->vertex3f + tri[2] * 3), vert[2]); - VectorSubtract(vert[1], vert[0], edge[0]); - VectorSubtract(vert[2], vert[1], edge[1]); - CrossProduct(edge[1], edge[0], facenormal); - if (facenormal[0] || facenormal[1] || facenormal[2]) + VectorNormalize(facenormal); +#if 0 + if (VectorDistance(facenormal, surfnormal) > 0.01f) + Con_Printf("a2! %f %f %f != %f %f %f\n", facenormal[0], facenormal[1], facenormal[2], surfnormal[0], surfnormal[1], surfnormal[2]); +#endif + f = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal); + if (f <= info->bestdist && f >= -info->bestdist) { - VectorNormalize(facenormal); + VectorSubtract(vert[0], vert[2], edge[2]); + VectorNormalize(edge[0]); + VectorNormalize(edge[1]); + VectorNormalize(edge[2]); + CrossProduct(facenormal, edge[0], edgenormal[0]); + CrossProduct(facenormal, edge[1], edgenormal[1]); + CrossProduct(facenormal, edge[2], edgenormal[2]); #if 0 - if (VectorDistance(facenormal, surfnormal) > 0.01f) - Con_Printf("a2! %f %f %f != %f %f %f\n", facenormal[0], facenormal[1], facenormal[2], surfnormal[0], surfnormal[1], surfnormal[2]); + if (samelevel.integer & 1) + VectorNegate(edgenormal[0], edgenormal[0]); + if (samelevel.integer & 2) + VectorNegate(edgenormal[1], edgenormal[1]); + if (samelevel.integer & 4) + VectorNegate(edgenormal[2], edgenormal[2]); + for (i = 0;i < 3;i++) + if (DotProduct(vert[0], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f + || DotProduct(vert[1], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f + || DotProduct(vert[2], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f) + Con_Printf("a! %i : %f %f %f (%f %f %f)\n", i, edgenormal[i][0], edgenormal[i][1], edgenormal[i][2], facenormal[0], facenormal[1], facenormal[2]); #endif - f = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal); - if (f <= info->bestdist && f >= -info->bestdist) + // face distance + if (DotProduct(info->center, edgenormal[0]) < DotProduct(vert[0], edgenormal[0]) + && DotProduct(info->center, edgenormal[1]) < DotProduct(vert[1], edgenormal[1]) + && DotProduct(info->center, edgenormal[2]) < DotProduct(vert[2], edgenormal[2])) { - VectorSubtract(vert[0], vert[2], edge[2]); - VectorNormalize(edge[0]); - VectorNormalize(edge[1]); - VectorNormalize(edge[2]); - CrossProduct(facenormal, edge[0], edgenormal[0]); - CrossProduct(facenormal, edge[1], edgenormal[1]); - CrossProduct(facenormal, edge[2], edgenormal[2]); -#if 0 - if (samelevel.integer & 1) - VectorNegate(edgenormal[0], edgenormal[0]); - if (samelevel.integer & 2) - VectorNegate(edgenormal[1], edgenormal[1]); - if (samelevel.integer & 4) - VectorNegate(edgenormal[2], edgenormal[2]); + // we got lucky, the center is within the face + dist = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal); + if (dist < 0) + { + dist = -dist; + if (info->bestdist > dist) + { + info->bestdist = dist; + VectorScale(facenormal, (info->radius - -dist), info->nudge); + } + } + else + { + if (info->bestdist > dist) + { + info->bestdist = dist; + VectorScale(facenormal, (info->radius - dist), info->nudge); + } + } + } + else + { + // check which edge or vertex the center is nearest for (i = 0;i < 3;i++) - if (DotProduct(vert[0], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f - || DotProduct(vert[1], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f - || DotProduct(vert[2], edgenormal[i]) > DotProduct(vert[i], edgenormal[i]) + 0.1f) - Con_Printf("a! %i : %f %f %f (%f %f %f)\n", i, edgenormal[i][0], edgenormal[i][1], edgenormal[i][2], facenormal[0], facenormal[1], facenormal[2]); -#endif - // face distance - if (DotProduct(info->center, edgenormal[0]) < DotProduct(vert[0], edgenormal[0]) - && DotProduct(info->center, edgenormal[1]) < DotProduct(vert[1], edgenormal[1]) - && DotProduct(info->center, edgenormal[2]) < DotProduct(vert[2], edgenormal[2])) { - // we got lucky, the center is within the face - dist = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal); - if (dist < 0) + f = DotProduct(info->center, edge[i]); + if (f >= DotProduct(vert[0], edge[i]) + && f <= DotProduct(vert[1], edge[i])) { - dist = -dist; + // on edge + VectorMA(info->center, -f, edge[i], point); + dist = sqrt(DotProduct(point, point)); if (info->bestdist > dist) { info->bestdist = dist; - VectorScale(facenormal, (info->radius - -dist), info->nudge); + VectorScale(point, (info->radius / dist), info->nudge); } + // skip both vertex checks + // (both are further away than this edge) + i++; } else { + // not on edge, check first vertex of edge + VectorSubtract(info->center, vert[i], point); + dist = sqrt(DotProduct(point, point)); if (info->bestdist > dist) { info->bestdist = dist; - VectorScale(facenormal, (info->radius - dist), info->nudge); - } - } - } - else - { - // check which edge or vertex the center is nearest - for (i = 0;i < 3;i++) - { - f = DotProduct(info->center, edge[i]); - if (f >= DotProduct(vert[0], edge[i]) - && f <= DotProduct(vert[1], edge[i])) - { - // on edge - VectorMA(info->center, -f, edge[i], point); - dist = sqrt(DotProduct(point, point)); - if (info->bestdist > dist) - { - info->bestdist = dist; - VectorScale(point, (info->radius / dist), info->nudge); - } - // skip both vertex checks - // (both are further away than this edge) - i++; - } - else - { - // not on edge, check first vertex of edge - VectorSubtract(info->center, vert[i], point); - dist = sqrt(DotProduct(point, point)); - if (info->bestdist > dist) - { - info->bestdist = dist; - VectorScale(point, (info->radius / dist), info->nudge); - } + VectorScale(point, (info->radius / dist), info->nudge); } } } @@ -513,7 +509,7 @@ loc0: return HULLCHECKSTATE_DONE; } -static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) +static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) { // this function currently only supports same size start and end double boxsize[3]; @@ -705,7 +701,7 @@ static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte * { if (in == inend) { - Con_Printf("Mod_Q1BSP_DecompressVis: input underrun\n"); + Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\"\n", loadmodel->name); return; } c = *in++; @@ -713,11 +709,16 @@ static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte * *out++ = c; else { + if (in == inend) + { + Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\"\n", loadmodel->name); + return; + } for (c = *in++;c > 0;c--) { if (out == outend) { - Con_Printf("Mod_Q1BSP_DecompressVis: output overrun\n"); + Con_DPrintf("Mod_Q1BSP_DecompressVis: output overrun on model \"%s\"\n", loadmodel->name); return; } *out++ = 0; @@ -737,15 +738,19 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) loadmodel->brushq1.textures = NULL; - if (!l->filelen) - return; - - m = (dmiptexlump_t *)(mod_base + l->fileofs); - - m->nummiptex = LittleLong (m->nummiptex); - // add two slots for notexture walls and notexture liquids - loadmodel->brushq1.numtextures = m->nummiptex + 2; + if (l->filelen) + { + m = (dmiptexlump_t *)(mod_base + l->fileofs); + m->nummiptex = LittleLong (m->nummiptex); + loadmodel->brushq1.numtextures = m->nummiptex + 2; + } + else + { + m = NULL; + loadmodel->brushq1.numtextures = 2; + } + loadmodel->brushq1.textures = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.numtextures * sizeof(texture_t)); // fill out all slots with notexture @@ -766,6 +771,9 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) tx->currentframe = tx; } + if (!m) + return; + // just to work around bounds checking when debugging with it (array index out of bounds error thing) dofs = m->dataofs; // LordHavoc: mostly rewritten map texture loader @@ -1035,9 +1043,9 @@ static void Mod_Q1BSP_LoadLighting(lump_t *l) else // LordHavoc: bsp version 29 (normal white lighting) { // LordHavoc: hope is not lost yet, check for a .lit file to load - strcpy(litfilename, loadmodel->name); - FS_StripExtension(litfilename, litfilename); - strcat(litfilename, ".lit"); + strlcpy (litfilename, loadmodel->name, sizeof (litfilename)); + FS_StripExtension (litfilename, litfilename, sizeof (litfilename)); + strlcat (litfilename, ".lit", sizeof (litfilename)); data = (qbyte*) FS_LoadFile(litfilename, false); if (data) { @@ -1090,9 +1098,9 @@ static void Mod_Q1BSP_LoadLightList(void) char lightsfilename[1024], *s, *t, *lightsstring; mlight_t *e; - strcpy(lightsfilename, loadmodel->name); - FS_StripExtension(lightsfilename, lightsfilename); - strcat(lightsfilename, ".lights"); + strlcpy (lightsfilename, loadmodel->name, sizeof (lightsfilename)); + FS_StripExtension (lightsfilename, lightsfilename, sizeof(lightsfilename)); + strlcat (lightsfilename, ".lights", sizeof (lightsfilename)); s = lightsstring = (char *) FS_LoadFile(lightsfilename, false); if (s) { @@ -1485,13 +1493,13 @@ static void Mod_Q1BSP_GenerateWarpMesh(msurface_t *surf) Host_Error("Mod_Q1BSP_GenerateWarpMesh: no triangles?\n"); surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + subdivpolytriangles * sizeof(int[3]) + subdivpolyverts * sizeof(surfvertex_t)); - mesh->numverts = subdivpolyverts; - mesh->numtriangles = subdivpolytriangles; + mesh->num_vertices = subdivpolyverts; + mesh->num_triangles = subdivpolytriangles; mesh->vertex = (surfvertex_t *)(mesh + 1); - mesh->index = (int *)(mesh->vertex + mesh->numverts); - memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t)); + mesh->index = (int *)(mesh->vertex + mesh->num_vertices); + memset(mesh->vertex, 0, mesh->num_vertices * sizeof(surfvertex_t)); - for (i = 0;i < mesh->numtriangles;i++) + for (i = 0;i < mesh->num_triangles;i++) for (j = 0;j < 3;j++) mesh->index[i*3+j] = subdivpolyindex[i][j]; @@ -1508,18 +1516,18 @@ static surfmesh_t *Mod_Q1BSP_AllocSurfMesh(int numverts, int numtriangles) { surfmesh_t *mesh; mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + numtriangles * sizeof(int[6]) + numverts * (3 + 2 + 2 + 2 + 3 + 3 + 3 + 1) * sizeof(float)); - mesh->numverts = numverts; - mesh->numtriangles = numtriangles; - mesh->vertex3f = (float *)(mesh + 1); - mesh->texcoordtexture2f = mesh->vertex3f + mesh->numverts * 3; - mesh->texcoordlightmap2f = mesh->texcoordtexture2f + mesh->numverts * 2; - mesh->texcoorddetail2f = mesh->texcoordlightmap2f + mesh->numverts * 2; - mesh->svector3f = (float *)(mesh->texcoorddetail2f + mesh->numverts * 2); - mesh->tvector3f = mesh->svector3f + mesh->numverts * 3; - mesh->normal3f = mesh->tvector3f + mesh->numverts * 3; - mesh->lightmapoffsets = (int *)(mesh->normal3f + mesh->numverts * 3); - mesh->element3i = mesh->lightmapoffsets + mesh->numverts; - mesh->neighbor3i = mesh->element3i + mesh->numtriangles * 3; + mesh->num_vertices = numverts; + mesh->num_triangles = numtriangles; + mesh->data_vertex3f = (float *)(mesh + 1); + mesh->data_texcoordtexture2f = mesh->data_vertex3f + mesh->num_vertices * 3; + mesh->data_texcoordlightmap2f = mesh->data_texcoordtexture2f + mesh->num_vertices * 2; + mesh->data_texcoorddetail2f = mesh->data_texcoordlightmap2f + mesh->num_vertices * 2; + mesh->data_svector3f = (float *)(mesh->data_texcoorddetail2f + mesh->num_vertices * 2); + mesh->data_tvector3f = mesh->data_svector3f + mesh->num_vertices * 3; + mesh->data_normal3f = mesh->data_tvector3f + mesh->num_vertices * 3; + mesh->data_lightmapoffsets = (int *)(mesh->data_normal3f + mesh->num_vertices * 3); + mesh->data_element3i = mesh->data_lightmapoffsets + mesh->num_vertices; + mesh->data_neighbor3i = mesh->data_element3i + mesh->num_triangles * 3; return mesh; } @@ -1658,52 +1666,51 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) } loadmodel->brushq1.entiremesh = Mod_Q1BSP_AllocSurfMesh(totalverts, totaltris); - loadmodel->brushq1.surfmeshes = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) * totalmeshes); 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 = loadmodel->brushq1.surfmeshes + totalmeshes; - mesh->numverts = surf->poly_numverts; - mesh->numtriangles = surf->poly_numverts - 2; - mesh->vertex3f = loadmodel->brushq1.entiremesh->vertex3f + totalverts * 3; - mesh->texcoordtexture2f = loadmodel->brushq1.entiremesh->texcoordtexture2f + totalverts * 2; - mesh->texcoordlightmap2f = loadmodel->brushq1.entiremesh->texcoordlightmap2f + totalverts * 2; - mesh->texcoorddetail2f = loadmodel->brushq1.entiremesh->texcoorddetail2f + totalverts * 2; - mesh->svector3f = loadmodel->brushq1.entiremesh->svector3f + totalverts * 3; - mesh->tvector3f = loadmodel->brushq1.entiremesh->tvector3f + totalverts * 3; - mesh->normal3f = loadmodel->brushq1.entiremesh->normal3f + totalverts * 3; - mesh->lightmapoffsets = loadmodel->brushq1.entiremesh->lightmapoffsets + totalverts; - mesh->element3i = loadmodel->brushq1.entiremesh->element3i + totaltris * 3; - mesh->neighbor3i = loadmodel->brushq1.entiremesh->neighbor3i + totaltris * 3; + mesh = &surf->mesh; + mesh->num_vertices = surf->poly_numverts; + mesh->num_triangles = surf->poly_numverts - 2; + mesh->data_vertex3f = loadmodel->brushq1.entiremesh->data_vertex3f + totalverts * 3; + mesh->data_texcoordtexture2f = loadmodel->brushq1.entiremesh->data_texcoordtexture2f + totalverts * 2; + mesh->data_texcoordlightmap2f = loadmodel->brushq1.entiremesh->data_texcoordlightmap2f + totalverts * 2; + mesh->data_texcoorddetail2f = loadmodel->brushq1.entiremesh->data_texcoorddetail2f + totalverts * 2; + mesh->data_svector3f = loadmodel->brushq1.entiremesh->data_svector3f + totalverts * 3; + mesh->data_tvector3f = loadmodel->brushq1.entiremesh->data_tvector3f + totalverts * 3; + mesh->data_normal3f = loadmodel->brushq1.entiremesh->data_normal3f + totalverts * 3; + mesh->data_lightmapoffsets = loadmodel->brushq1.entiremesh->data_lightmapoffsets + totalverts; + mesh->data_element3i = loadmodel->brushq1.entiremesh->data_element3i + totaltris * 3; + mesh->data_neighbor3i = loadmodel->brushq1.entiremesh->data_neighbor3i + totaltris * 3; surf->lightmaptexturestride = 0; surf->lightmaptexture = NULL; - for (i = 0;i < mesh->numverts;i++) + for (i = 0;i < mesh->num_vertices;i++) { - mesh->vertex3f[i * 3 + 0] = surf->poly_verts[i * 3 + 0]; - mesh->vertex3f[i * 3 + 1] = surf->poly_verts[i * 3 + 1]; - mesh->vertex3f[i * 3 + 2] = surf->poly_verts[i * 3 + 2]; - s = DotProduct((mesh->vertex3f + i * 3), surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; - t = DotProduct((mesh->vertex3f + i * 3), surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; - mesh->texcoordtexture2f[i * 2 + 0] = s / surf->texinfo->texture->width; - mesh->texcoordtexture2f[i * 2 + 1] = t / surf->texinfo->texture->height; - mesh->texcoorddetail2f[i * 2 + 0] = s * (1.0f / 16.0f); - mesh->texcoorddetail2f[i * 2 + 1] = t * (1.0f / 16.0f); - mesh->texcoordlightmap2f[i * 2 + 0] = 0; - mesh->texcoordlightmap2f[i * 2 + 1] = 0; - mesh->lightmapoffsets[i] = 0; + mesh->data_vertex3f[i * 3 + 0] = surf->poly_verts[i * 3 + 0]; + mesh->data_vertex3f[i * 3 + 1] = surf->poly_verts[i * 3 + 1]; + mesh->data_vertex3f[i * 3 + 2] = surf->poly_verts[i * 3 + 2]; + s = DotProduct((mesh->data_vertex3f + i * 3), surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; + t = DotProduct((mesh->data_vertex3f + i * 3), surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; + mesh->data_texcoordtexture2f[i * 2 + 0] = s / surf->texinfo->texture->width; + mesh->data_texcoordtexture2f[i * 2 + 1] = t / surf->texinfo->texture->height; + mesh->data_texcoorddetail2f[i * 2 + 0] = s * (1.0f / 16.0f); + mesh->data_texcoorddetail2f[i * 2 + 1] = t * (1.0f / 16.0f); + mesh->data_texcoordlightmap2f[i * 2 + 0] = 0; + mesh->data_texcoordlightmap2f[i * 2 + 1] = 0; + mesh->data_lightmapoffsets[i] = 0; } - for (i = 0;i < mesh->numtriangles;i++) + for (i = 0;i < mesh->num_triangles;i++) { - mesh->element3i[i * 3 + 0] = 0; - mesh->element3i[i * 3 + 1] = i + 1; - mesh->element3i[i * 3 + 2] = i + 2; + mesh->data_element3i[i * 3 + 0] = 0; + mesh->data_element3i[i * 3 + 1] = i + 1; + mesh->data_element3i[i * 3 + 2] = i + 2; } - Mod_BuildTriangleNeighbors(mesh->neighbor3i, mesh->element3i, mesh->numtriangles); - Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->vertex3f, mesh->texcoordtexture2f, mesh->element3i, mesh->svector3f, mesh->tvector3f, mesh->normal3f); + Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles); + Mod_BuildTextureVectorsAndNormals(mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f); if (surf->texinfo->texture->shader == &Cshader_wall_lightmap) { @@ -1728,16 +1735,16 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) uscale = (uscale - ubase) / (smax + 1); vscale = (vscale - vbase) / (tmax + 1); - for (i = 0;i < mesh->numverts;i++) + for (i = 0;i < mesh->num_vertices;i++) { - u = ((DotProduct((mesh->vertex3f + i * 3), surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) + 8 - surf->texturemins[0]) * (1.0 / 16.0); - v = ((DotProduct((mesh->vertex3f + i * 3), surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) + 8 - surf->texturemins[1]) * (1.0 / 16.0); - mesh->texcoordlightmap2f[i * 2 + 0] = u * uscale + ubase; - mesh->texcoordlightmap2f[i * 2 + 1] = v * vscale + vbase; + u = ((DotProduct((mesh->data_vertex3f + i * 3), surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) + 8 - surf->texturemins[0]) * (1.0 / 16.0); + v = ((DotProduct((mesh->data_vertex3f + i * 3), surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) + 8 - surf->texturemins[1]) * (1.0 / 16.0); + mesh->data_texcoordlightmap2f[i * 2 + 0] = u * uscale + ubase; + mesh->data_texcoordlightmap2f[i * 2 + 1] = v * vscale + vbase; // LordHavoc: calc lightmap data offset for vertex lighting to use iu = (int) u; iv = (int) v; - mesh->lightmapoffsets[i] = (bound(0, iv, tmax) * (smax+1) + bound(0, iu, smax)) * 3; + mesh->data_lightmapoffsets[i] = (bound(0, iv, tmax) * (smax+1) + bound(0, iu, smax)) * 3; } } } @@ -1826,15 +1833,25 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l) out->firstmarksurface = loadmodel->brushq1.marksurfaces + LittleShort(in->firstmarksurface); out->nummarksurfaces = LittleShort(in->nummarksurfaces); + if (out->firstmarksurface < 0 || LittleShort(in->firstmarksurface) + out->nummarksurfaces > loadmodel->brushq1.nummarksurfaces) + { + Con_Printf("Mod_Q1BSP_LoadLeafs: invalid marksurface range %i:%i outside range %i:%i\n", out->firstmarksurface, out->firstmarksurface + out->nummarksurfaces, 0, loadmodel->brushq1.nummarksurfaces); + out->firstmarksurface = NULL; + out->nummarksurfaces = 0; + } out->pvsdata = pvs; + memset(out->pvsdata, 0xFF, pvschainbytes); pvs += pvschainbytes; p = LittleLong(in->visofs); 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 - memset(out->pvsdata, 0xFF, pvschainbytes); + { + if (p >= loadmodel->brushq1.num_compressedpvs) + Con_Printf("Mod_Q1BSP_LoadLeafs: invalid visofs\n"); + else + Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, out->pvsdata, out->pvsdata + pvschainbytes); + } for (j = 0;j < 4;j++) out->ambient_sound_level[j] = in->ambient_level[j]; @@ -2301,9 +2318,9 @@ static void Mod_Q1BSP_RecursiveNodePortals(mnode_t *node) // create the new portal by generating a polygon for the node plane, // and clipping it by all of the other portals(which came from nodes above this one) nodeportal = AllocPortal(); - nodeportal->plane = *node->plane; + nodeportal->plane = *plane; - nodeportalwinding = Winding_NewFromPlane(node->plane->normal[0], node->plane->normal[1], node->plane->normal[2], node->plane->dist); + nodeportalwinding = Winding_NewFromPlane(nodeportal->plane.normal[0], nodeportal->plane.normal[1], nodeportal->plane.normal[2], nodeportal->plane.dist); side = 0; // shut up compiler warning for (portal = (portal_t *)node->portals;portal;portal = portal->next[side]) { @@ -2638,7 +2655,6 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) model_t *originalloadmodel; float dist, modelyawradius, modelradius, *vec; msurface_t *surf; - surfmesh_t *mesh; mod->type = mod_brush; @@ -2649,6 +2665,8 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) Host_Error("Mod_Q1BSP_Load: %s has wrong version number(%i should be %i(Quake) or 30(HalfLife))", mod->name, i, BSPVERSION); mod->brush.ishlbsp = i == 30; + mod->soundfromcenter = true; + mod->TraceBox = Mod_Q1BSP_TraceBox; mod->brush.SuperContentsFromNativeContents = Mod_Q1BSP_SuperContentsFromNativeContents; mod->brush.NativeContentsFromSuperContents = Mod_Q1BSP_NativeContentsFromSuperContents; mod->brush.GetPVS = Mod_Q1BSP_GetPVS; @@ -2656,7 +2674,6 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) mod->brush.BoxTouchingPVS = Mod_Q1BSP_BoxTouchingPVS; mod->brush.LightPoint = Mod_Q1BSP_LightPoint; mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation; - mod->brush.TraceBox = Mod_Q1BSP_TraceBox; mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint; mod->brush.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize; mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf; @@ -2735,7 +2752,6 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) // this gets altered below if sky is used mod->DrawSky = NULL; mod->Draw = R_Model_Brush_Draw; - mod->DrawFakeShadow = NULL; mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume; mod->DrawLight = R_Model_Brush_DrawLight; mod->brushq1.pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->brushq1.numtextures * sizeof(msurface_t **)); @@ -2759,23 +2775,20 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) if (mod->brush.numsubmodels - 1) surf->flags |= SURF_SOLIDCLIP; // calculate bounding shapes - for (mesh = surf->mesh;mesh;mesh = mesh->chain) + for (k = 0, vec = surf->mesh.data_vertex3f;k < surf->mesh.num_vertices;k++, vec += 3) { - for (k = 0, vec = mesh->vertex3f;k < mesh->numverts;k++, vec += 3) - { - if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0]; - if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1]; - if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2]; - if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0]; - if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1]; - if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2]; - dist = vec[0]*vec[0]+vec[1]*vec[1]; - if (modelyawradius < dist) - modelyawradius = dist; - dist += vec[2]*vec[2]; - if (modelradius < dist) - modelradius = dist; - } + if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0]; + if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1]; + if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2]; + if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0]; + if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1]; + if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2]; + dist = vec[0]*vec[0]+vec[1]*vec[1]; + if (modelyawradius < dist) + modelyawradius = dist; + dist += vec[2]*vec[2]; + if (modelradius < dist) + modelradius = dist; } } modelyawradius = sqrt(modelyawradius); @@ -3308,13 +3321,15 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) for (i = 0;i < count;i++, in++, out++) { - strncpy(out->name, in->name, sizeof(out->name) - 1); + strlcpy (out->name, in->name, sizeof (out->name)); out->surfaceflags = LittleLong(in->surfaceflags); out->nativecontents = LittleLong(in->contents); out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, out->nativecontents); out->renderflags = 0; if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")) out->renderflags |= Q3MTEXTURERENDERFLAGS_NODRAW; + if (!strncmp(out->name, "textures/skies/", 15)) + out->renderflags |= Q3MTEXTURERENDERFLAGS_SKY; out->number = i; Mod_LoadSkinFrame(&out->skin, out->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true); @@ -3380,6 +3395,7 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l) q3mbrush_t *out; int i, j, n, c, count, maxplanes; mplane_t *planes; + winding_t *temp1, *temp2; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -3390,6 +3406,9 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l) loadmodel->brushq3.data_brushes = out; loadmodel->brushq3.num_brushes = count; + temp1 = Winding_New(64); + temp2 = Winding_New(64); + maxplanes = 0; planes = NULL; @@ -3420,10 +3439,12 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l) planes[j].dist = out->firstbrushside[j].plane->dist; } // make the colbrush from the planes - out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents); + out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents, temp1, temp2); } if (planes) Mem_Free(planes); + Winding_Free(temp1); + Winding_Free(temp2); } static void Mod_Q3BSP_LoadEffects(lump_t *l) @@ -3443,7 +3464,7 @@ static void Mod_Q3BSP_LoadEffects(lump_t *l) for (i = 0;i < count;i++, in++, out++) { - strncpy(out->shadername, in->shadername, sizeof(out->shadername) - 1); + strlcpy (out->shadername, in->shadername, sizeof (out->shadername)); n = LittleLong(in->brushindex); if (n < 0 || n >= loadmodel->brushq3.num_brushes) Host_Error("Mod_Q3BSP_LoadEffects: invalid brushindex %i (%i brushes)\n", n, loadmodel->brushq3.num_brushes); @@ -3461,13 +3482,13 @@ static void Mod_Q3BSP_LoadVertices(lump_t *l) if (l->filelen % sizeof(*in)) Host_Error("Mod_Q3BSP_LoadVertices: funny lump size in %s",loadmodel->name); loadmodel->brushq3.num_vertices = count = l->filelen / sizeof(*in); - loadmodel->brushq3.data_vertex3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3])); - loadmodel->brushq3.data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2])); - loadmodel->brushq3.data_texcoordlightmap2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2])); - loadmodel->brushq3.data_svector3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3])); - loadmodel->brushq3.data_tvector3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3])); - loadmodel->brushq3.data_normal3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3])); - loadmodel->brushq3.data_color4f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[4])); + loadmodel->brushq3.data_vertex3f = Mem_Alloc(loadmodel->mempool, count * (sizeof(float) * (3 + 2 + 2 + 3 + 3 + 3 + 4))); + loadmodel->brushq3.data_texcoordtexture2f = loadmodel->brushq3.data_vertex3f + count * 3; + loadmodel->brushq3.data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordtexture2f + count * 2; + loadmodel->brushq3.data_svector3f = loadmodel->brushq3.data_texcoordlightmap2f + count * 2; + loadmodel->brushq3.data_tvector3f = loadmodel->brushq3.data_svector3f + count * 3; + loadmodel->brushq3.data_normal3f = loadmodel->brushq3.data_tvector3f + count * 3; + loadmodel->brushq3.data_color4f = loadmodel->brushq3.data_normal3f + count * 3; for (i = 0;i < count;i++, in++) { @@ -3505,11 +3526,11 @@ static void Mod_Q3BSP_LoadTriangles(lump_t *l) if (l->filelen % sizeof(int[3])) Host_Error("Mod_Q3BSP_LoadTriangles: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); - out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out)); + out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out) * 2); loadmodel->brushq3.num_triangles = count / 3; loadmodel->brushq3.data_element3i = out; - loadmodel->brushq3.data_neighbor3i = Mem_Alloc(loadmodel->mempool, count * sizeof(*out)); + loadmodel->brushq3.data_neighbor3i = out + count; for (i = 0;i < count;i++, in++, out++) { @@ -3528,6 +3549,8 @@ static void Mod_Q3BSP_LoadLightmaps(lump_t *l) rtexture_t **out; int i, count; + if (!l->filelen) + return; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error("Mod_Q3BSP_LoadLightmaps: funny lump size in %s",loadmodel->name); @@ -3576,6 +3599,8 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) && out->type != Q3FACETYPE_FLARE) { Con_Printf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, out->type); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } @@ -3584,6 +3609,8 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) if (n < 0 || n >= loadmodel->brushq3.num_textures) { Con_Printf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->brushq3.num_textures); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; n = 0; @@ -3611,42 +3638,47 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) out->lightmaptexture = loadmodel->brushq3.data_lightmaps[n]; out->firstvertex = LittleLong(in->firstvertex); - out->numvertices = LittleLong(in->numvertices); + out->num_vertices = LittleLong(in->numvertices); out->firstelement = LittleLong(in->firstelement); - out->numelements = LittleLong(in->numelements); - out->numtriangles = out->numelements / 3; - if (out->firstvertex < 0 || out->firstvertex + out->numvertices > loadmodel->brushq3.num_vertices) + out->num_triangles = LittleLong(in->numelements) / 3; + if (out->num_triangles * 3 != LittleLong(in->numelements)) { - 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->numvertices, loadmodel->brushq3.num_vertices); + Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, LittleLong(in->numelements)); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } - if (out->firstelement < 0 || out->firstelement + out->numelements > loadmodel->brushq3.num_triangles * 3) + if (out->firstvertex < 0 || out->firstvertex + out->num_vertices > loadmodel->brushq3.num_vertices) { - 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->numelements, loadmodel->brushq3.num_triangles * 3); + Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, out->firstvertex, out->firstvertex + out->num_vertices, loadmodel->brushq3.num_vertices); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } - if (out->numtriangles * 3 != out->numelements) + if (out->firstelement < 0 || out->firstelement + out->num_triangles * 3 > loadmodel->brushq3.num_triangles * 3) { - Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, out->numelements); + Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, out->firstelement, out->firstelement + out->num_triangles * 3, loadmodel->brushq3.num_triangles * 3); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } - out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3; - out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2; - out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2; - out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3; - out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3; - out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3; - out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4; - out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement; - out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement; switch(out->type) { case Q3FACETYPE_POLYGON: case Q3FACETYPE_MESH: // no processing necessary + out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3; + out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2; + out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2; + out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3; + out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3; + out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3; + out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4; + out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement; + out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement; break; case Q3FACETYPE_PATCH: patchsize[0] = LittleLong(in->specific.patch.patchsize[0]); @@ -3654,6 +3686,8 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) if (patchsize[0] < 1 || patchsize[1] < 1) { Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid patchsize %ix%i\n", i, out->texture->name, patchsize[0], patchsize[1]); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } @@ -3664,6 +3698,16 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) finalheight = ((patchsize[1] - 1) << ylevel) + 1; finalvertices = finalwidth * finalheight; finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2; + originalvertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3; + //originalsvector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3; + //originaltvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3; + //originalnormal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3; + originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2; + originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2; + originalcolor4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4; + //originalelement3i = loadmodel->brushq3.data_element3i + out->firstelement; + //originalneighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement; + /* originalvertex3f = out->data_vertex3f; //originalsvector3f = out->data_svector3f; //originaltvector3f = out->data_tvector3f; @@ -3673,21 +3717,21 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) originaltexcoordlightmap2f = out->data_texcoordlightmap2f; //originalelement3i = out->data_element3i; //originalneighbor3i = out->data_neighbor3i; - out->data_vertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[20]) * finalvertices + sizeof(int[6]) * finaltriangles); + */ + out->data_vertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[20]) * finalvertices); out->data_svector3f = out->data_vertex3f + finalvertices * 3; out->data_tvector3f = out->data_svector3f + finalvertices * 3; out->data_normal3f = out->data_tvector3f + finalvertices * 3; out->data_color4f = out->data_normal3f + finalvertices * 3; out->data_texcoordtexture2f = out->data_color4f + finalvertices * 4; out->data_texcoordlightmap2f = out->data_texcoordtexture2f + finalvertices * 2; - out->data_element3i = (int *)(out->data_texcoordlightmap2f + finalvertices * 2); + out->data_element3i = Mem_Alloc(loadmodel->mempool, sizeof(int[6]) * finaltriangles); out->data_neighbor3i = out->data_element3i + finaltriangles * 3; out->type = Q3FACETYPE_MESH; out->firstvertex = -1; - out->numvertices = finalvertices; + out->num_vertices = finalvertices; out->firstelement = -1; - out->numtriangles = finaltriangles; - out->numelements = finaltriangles * 3; + out->num_triangles = finaltriangles; // generate geometry // (note: normals are skipped because they get recalculated) QuadraticSplinePatchSubdivideFloatBuffer(patchsize[0], patchsize[1], xlevel, ylevel, 3, originalvertex3f, out->data_vertex3f); @@ -3712,13 +3756,13 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) row1++; } } - out->numtriangles = Mod_RemoveDegenerateTriangles(out->numtriangles, out->data_element3i, out->data_element3i, out->data_vertex3f); + out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, out->data_element3i, out->data_element3i, out->data_vertex3f); if (developer.integer) { - if (out->numtriangles < 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->numvertices, finaltriangles, finaltriangles - out->numtriangles, out->numtriangles); + 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->numvertices, out->numtriangles); + 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); } // q3map does not put in collision brushes for curves... ugh out->collisions = true; @@ -3726,35 +3770,37 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) case Q3FACETYPE_FLARE: Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name); // don't render it - out->numtriangles = 0; + out->num_vertices = 0; + out->num_triangles = 0; + out->type = 0; break; } - for (j = 0, invalidelements = 0;j < out->numelements;j++) - if (out->data_element3i[j] < 0 || out->data_element3i[j] >= out->numvertices) + 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) { - 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->numvertices, out->firstelement, out->numelements); - for (j = 0;j < out->numelements;j++) + 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); + for (j = 0;j < out->num_triangles * 3;j++) { Con_Printf(" %i", out->data_element3i[j]); - if (out->data_element3i[j] < 0 || out->data_element3i[j] >= out->numvertices) + if (out->data_element3i[j] < 0 || out->data_element3i[j] >= out->num_vertices) out->data_element3i[j] = 0; } Con_Printf("\n"); } // for shadow volumes - Mod_BuildTriangleNeighbors(out->data_neighbor3i, out->data_element3i, out->numtriangles); + Mod_BuildTriangleNeighbors(out->data_neighbor3i, out->data_element3i, out->num_triangles); // for per pixel lighting - Mod_BuildTextureVectorsAndNormals(out->numvertices, out->numtriangles, out->data_vertex3f, out->data_texcoordtexture2f, out->data_element3i, out->data_svector3f, out->data_tvector3f, out->data_normal3f); + 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->numvertices) + 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->numvertices;j++, v += 3) + for (j = 1, v = out->data_vertex3f + 3;j < out->num_vertices;j++, v += 3) { out->mins[0] = min(out->mins[0], v[0]); out->maxs[0] = max(out->maxs[0], v[0]); @@ -3771,6 +3817,95 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) out->maxs[2] += 1.0f; } } + + // LordHavoc: experimental array merger (disabled because it wastes time and uses 2x memory while merging) + /* + { + int totalverts, totaltris; + int originalnum_vertices; + float *originaldata_vertex3f; + float *originaldata_texcoordtexture2f; + float *originaldata_texcoordlightmap2f; + float *originaldata_svector3f; + float *originaldata_tvector3f; + float *originaldata_normal3f; + float *originaldata_color4f; + int originalnum_triangles; + int *originaldata_element3i; + int *originaldata_neighbor3i; + + totalverts = 0; + totaltris = 0; + for (i = 0, out = loadmodel->brushq3.data_faces;i < count;i++, out++) + { + if (!out->type) + continue; + totalverts += out->num_vertices; + totaltris += out->num_triangles; + } + + originalnum_vertices = loadmodel->brushq3.num_vertices; + originaldata_vertex3f = loadmodel->brushq3.data_vertex3f; + originaldata_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f; + originaldata_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f; + originaldata_svector3f = loadmodel->brushq3.data_svector3f; + originaldata_tvector3f = loadmodel->brushq3.data_tvector3f; + originaldata_normal3f = loadmodel->brushq3.data_normal3f; + originaldata_color4f = loadmodel->brushq3.data_color4f; + originalnum_triangles = loadmodel->brushq3.num_triangles; + originaldata_element3i = loadmodel->brushq3.data_element3i; + originaldata_neighbor3i = loadmodel->brushq3.data_neighbor3i; + loadmodel->brushq3.num_vertices = totalverts; + loadmodel->brushq3.data_vertex3f = Mem_Alloc(loadmodel->mempool, totalverts * (sizeof(float) * (3 + 2 + 2 + 3 + 3 + 3 + 4)) + totaltris * (sizeof(int) * (3 * 2))); + loadmodel->brushq3.data_texcoordtexture2f = loadmodel->brushq3.data_vertex3f + totalverts * 3; + loadmodel->brushq3.data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordtexture2f + totalverts * 2; + loadmodel->brushq3.data_svector3f = loadmodel->brushq3.data_texcoordlightmap2f + totalverts * 2; + loadmodel->brushq3.data_tvector3f = loadmodel->brushq3.data_svector3f + totalverts * 3; + loadmodel->brushq3.data_normal3f = loadmodel->brushq3.data_tvector3f + totalverts * 3; + loadmodel->brushq3.data_color4f = loadmodel->brushq3.data_normal3f + totalverts * 3; + loadmodel->brushq3.num_triangles = totaltris; + loadmodel->brushq3.data_element3i = (int *)(loadmodel->brushq3.data_color4f + totalverts * 4); + loadmodel->brushq3.data_neighbor3i = loadmodel->brushq3.data_element3i + totaltris * 3; + totalverts = 0; + totaltris = 0; + for (i = 0, out = loadmodel->brushq3.data_faces;i < count;i++, out++) + { + if (!out->type) + continue; + Con_Printf("totalverts %i, totaltris %i\n", totalverts, totaltris); + memcpy(loadmodel->brushq3.data_vertex3f + totalverts * 3, out->data_vertex3f, out->num_vertices * 3 * sizeof(float)); + memcpy(loadmodel->brushq3.data_texcoordtexture2f + totalverts * 2, out->data_texcoordtexture2f, out->num_vertices * 2 * sizeof(float)); + memcpy(loadmodel->brushq3.data_texcoordlightmap2f + totalverts * 2, out->data_texcoordlightmap2f, out->num_vertices * 2 * sizeof(float)); + memcpy(loadmodel->brushq3.data_svector3f + totalverts * 3, out->data_svector3f, out->num_vertices * 3 * sizeof(float)); + memcpy(loadmodel->brushq3.data_tvector3f + totalverts * 3, out->data_tvector3f, out->num_vertices * 3 * sizeof(float)); + memcpy(loadmodel->brushq3.data_normal3f + totalverts * 3, out->data_normal3f, out->num_vertices * 3 * sizeof(float)); + memcpy(loadmodel->brushq3.data_color4f + totalverts * 4, out->data_color4f, out->num_vertices * 4 * sizeof(float)); + memcpy(loadmodel->brushq3.data_element3i + totaltris * 3, out->data_element3i, out->num_triangles * 3 * sizeof(int)); + memcpy(loadmodel->brushq3.data_neighbor3i + totaltris * 3, out->data_neighbor3i, out->num_triangles * 3 * sizeof(int)); + if (out->firstvertex == -1) + Mem_Free(out->data_vertex3f); + if (out->firstelement == -1) + Mem_Free(out->data_element3i); + out->firstvertex = totalverts; + out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3; + out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2; + out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2; + out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3; + out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3; + out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3; + out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4; + out->firstelement = totaltris * 3; + out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement; + out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement; + //for (j = 0;j < out->numtriangles * 3;j++) + // out->data_element3i[j] += totalverts - out->firstvertex; + totalverts += out->num_vertices; + totaltris += out->num_triangles; + } + Mem_Free(originaldata_vertex3f); + Mem_Free(originaldata_element3i); + } + */ } static void Mod_Q3BSP_LoadModels(lump_t *l) @@ -3970,6 +4105,9 @@ static void Mod_Q3BSP_LoadLightGrid(lump_t *l) q3dlightgrid_t *out; int count; + if (l->filelen == 0) + return; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error("Mod_Q3BSP_LoadLightGrid: funny lump size in %s",loadmodel->name); @@ -4040,17 +4178,17 @@ static void Mod_Q3BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientc // FIXME: write this if (!model->brushq3.num_lightgrid) { - ambientcolor[0] += 128; - ambientcolor[1] += 128; - ambientcolor[2] += 128; + ambientcolor[0] = 1; + ambientcolor[1] = 1; + ambientcolor[2] = 1; return; } Matrix4x4_Transform(&model->brushq3.num_lightgrid_indexfromworld, p, transformed); //Matrix4x4_Print(&model->brushq3.num_lightgrid_indexfromworld); //Con_Printf("%f %f %f transformed %f %f %f clamped ", p[0], p[1], p[2], transformed[0], transformed[1], transformed[2]); - transformed[0] = bound(0, transformed[0], model->brushq3.num_lightgrid_isize[0]); - transformed[1] = bound(0, transformed[1], model->brushq3.num_lightgrid_isize[1]); - transformed[2] = bound(0, transformed[2], model->brushq3.num_lightgrid_isize[2]); + transformed[0] = bound(0, transformed[0], model->brushq3.num_lightgrid_isize[0] - 1); + transformed[1] = bound(0, transformed[1], model->brushq3.num_lightgrid_isize[1] - 1); + transformed[2] = bound(0, transformed[2], model->brushq3.num_lightgrid_isize[2] - 1); index[0] = (int)floor(transformed[0]); index[1] = (int)floor(transformed[1]); index[2] = (int)floor(transformed[2]); @@ -4061,12 +4199,18 @@ static void Mod_Q3BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientc for (k = 0;k < 2;k++) { blend1 = (k ? (transformed[2] - index[2]) : (1 - (transformed[2] - index[2]))); + if (blend1 < 0.001f || index[2] + k >= model->brushq3.num_lightgrid_isize[2]) + continue; for (j = 0;j < 2;j++) { blend2 = blend1 * (j ? (transformed[1] - index[1]) : (1 - (transformed[1] - index[1]))); + if (blend2 < 0.001f || index[1] + j >= model->brushq3.num_lightgrid_isize[1]) + continue; for (i = 0;i < 2;i++) { blend = blend2 * (i ? (transformed[0] - index[0]) : (1 - (transformed[0] - index[0]))); + if (blend < 0.001f || index[0] + i >= model->brushq3.num_lightgrid_isize[0]) + continue; s = a + (k * model->brushq3.num_lightgrid_isize[1] + j) * model->brushq3.num_lightgrid_isize[0] + i; VectorMA(ambientcolor, blend * (1.0f / 128.0f), s->ambientrgb, ambientcolor); VectorMA(diffusecolor, blend * (1.0f / 128.0f), s->diffusergb, diffusecolor); @@ -4149,7 +4293,7 @@ static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, q3mnode_t *node { face->collisionmarkframe = markframe; if (BoxesOverlap(segmentmins, segmentmaxs, face->mins, face->maxs)) - Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, face->numtriangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } @@ -4233,13 +4377,13 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, q3mnode_t *nod face = leaf->firstleafface[i]; // note: this can not be optimized with a face->collisionmarkframe because each triangle of the face would need to be marked as done individually (because each one is bbox culled individually), and if all are marked, then the face could be marked as done if (face->collisions && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs)) - Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->numtriangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } } -static void Mod_Q3BSP_TraceBox(model_t *model, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) +static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) { int i; float segmentmins[3], segmentmaxs[3]; @@ -4272,7 +4416,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, trace_t *trace, const vec3_t boxs { face = model->brushq3.data_thismodel->firstface + i; if (face->collisions) - Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->numtriangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } @@ -4295,7 +4439,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, trace_t *trace, const vec3_t boxs { face = model->brushq3.data_thismodel->firstface + i; if (face->collisions) - Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->numtriangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } @@ -4425,14 +4569,13 @@ static int Mod_Q3BSP_NativeContentsFromSuperContents(model_t *model, int superco return nativecontents; } -//extern void R_Q3BSP_DrawSky(struct entity_render_s *ent); +extern void R_Q3BSP_DrawSky(struct entity_render_s *ent); extern void R_Q3BSP_Draw(struct entity_render_s *ent); -//extern void R_Q3BSP_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; + int i, j; q3dheader_t *header; float corner[3], yawradius, modelradius; @@ -4452,6 +4595,8 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer) R_ResetQuakeSky(); } + mod->soundfromcenter = true; + mod->TraceBox = Mod_Q3BSP_TraceBox; mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents; mod->brush.NativeContentsFromSuperContents = Mod_Q3BSP_NativeContentsFromSuperContents; mod->brush.GetPVS = Mod_Q3BSP_GetPVS; @@ -4459,10 +4604,8 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer) mod->brush.BoxTouchingPVS = Mod_Q3BSP_BoxTouchingPVS; mod->brush.LightPoint = Mod_Q3BSP_LightPoint; mod->brush.FindNonSolidLocation = Mod_Q3BSP_FindNonSolidLocation; - mod->brush.TraceBox = Mod_Q3BSP_TraceBox; //mod->DrawSky = R_Q3BSP_DrawSky; mod->Draw = R_Q3BSP_Draw; - //mod->DrawFakeShadow = R_Q3BSP_DrawFakeShadow; mod->DrawShadowVolume = R_Q3BSP_DrawShadowVolume; mod->DrawLight = R_Q3BSP_DrawLight; @@ -4529,6 +4672,12 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer) mod->yawmaxs[2] = mod->normalmaxs[2]; mod->radius = modelradius; mod->radius2 = modelradius * modelradius; + + for (j = 0;j < mod->brushq3.data_thismodel->numfaces;j++) + if (mod->brushq3.data_thismodel->firstface[j].texture->renderflags & Q3MTEXTURERENDERFLAGS_SKY) + break; + if (j < mod->brushq3.data_thismodel->numfaces) + mod->DrawSky = R_Q3BSP_DrawSky; } }