X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_brush.c;h=13b4df27a227aedfe6ac3ede1aba90fcf226a8a4;hb=6f53a7389f176401a73b425e366498ea6a22f9fd;hp=52c6fb5888c87a2f2f90794ac6e8679e775f8af0;hpb=b372ff212a4b42f4ac857a15e95bf04531fa260d;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index 52c6fb58..13b4df27 100644 --- a/model_brush.c +++ b/model_brush.c @@ -36,8 +36,9 @@ 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"}; +static void Mod_Q1BSP_Collision_Init (void); void Mod_BrushInit(void) { // Cvar_RegisterVariable(&r_subdivide_size); @@ -50,6 +51,7 @@ void Mod_BrushInit(void) Cvar_RegisterVariable(&mod_q3bsp_curves_collisions); Cvar_RegisterVariable(&mod_q3bsp_optimizedtraceline); memset(mod_q1bsp_novis, 0xff, sizeof(mod_q1bsp_novis)); + Mod_Q1BSP_Collision_Init(); } static mleaf_t *Mod_Q1BSP_PointInLeaf(model_t *model, const vec3_t p) @@ -416,11 +418,17 @@ loc0: // if the first leaf is solid, set startsolid if (t->trace->allsolid) t->trace->startsolid = true; +#if COLLISIONPARANOID >= 3 + Con_Printf("S"); +#endif return HULLCHECKSTATE_SOLID; } else { t->trace->allsolid = false; +#if COLLISIONPARANOID >= 3 + Con_Printf("E"); +#endif return HULLCHECKSTATE_EMPTY; } } @@ -444,6 +452,9 @@ loc0: { if (t2 < 0) { +#if COLLISIONPARANOID >= 3 + Con_Printf("<"); +#endif num = node->children[1]; goto loc0; } @@ -453,6 +464,9 @@ loc0: { if (t2 >= 0) { +#if COLLISIONPARANOID >= 3 + Con_Printf(">"); +#endif num = node->children[0]; goto loc0; } @@ -461,6 +475,9 @@ loc0: // the line intersects, find intersection point // LordHavoc: this uses the original trace for maximum accuracy +#if COLLISIONPARANOID >= 3 + Con_Printf("M"); +#endif if (plane->type < 3) { t1 = t->start[plane->type] - plane->dist; @@ -506,10 +523,37 @@ loc0: midf = t1 / (t1 - t2); t->trace->fraction = bound(0.0f, midf, 1.0); +#if COLLISIONPARANOID >= 3 + Con_Printf("D"); +#endif return HULLCHECKSTATE_DONE; } -static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) +#if COLLISIONPARANOID < 2 +static int Mod_Q1BSP_RecursiveHullCheckPoint(RecursiveHullCheckTraceInfo_t *t, int num) +{ + while (num >= 0) + num = t->hull->clipnodes[num].children[(t->hull->planes[t->hull->clipnodes[num].planenum].type < 3 ? t->start[t->hull->planes[t->hull->clipnodes[num].planenum].type] : DotProduct(t->hull->planes[t->hull->clipnodes[num].planenum].normal, t->start)) < t->hull->planes[t->hull->clipnodes[num].planenum].dist]; + num = Mod_Q1BSP_SuperContentsFromNativeContents(NULL, num); + t->trace->startsupercontents |= num; + if (num & SUPERCONTENTS_LIQUIDSMASK) + t->trace->inwater = true; + if (num == 0) + t->trace->inopen = true; + if (num & t->trace->hitsupercontentsmask) + { + t->trace->allsolid = t->trace->startsolid = true; + return HULLCHECKSTATE_SOLID; + } + else + { + t->trace->allsolid = t->trace->startsolid = false; + return HULLCHECKSTATE_EMPTY; + } +} +#endif + +static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) { // this function currently only supports same size start and end double boxsize[3]; @@ -526,7 +570,9 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3 rhc.hull = &model->brushq1.hulls[0]; // 0x0x0 else if (model->brush.ishlbsp) { - if (boxsize[0] <= 32) + // LordHavoc: this has to have a minor tolerance (the .1) because of + // minor float precision errors from the box being transformed around + if (boxsize[0] < 32.1) { if (boxsize[2] < 54) // pick the nearest of 36 or 72 rhc.hull = &model->brushq1.hulls[3]; // 32x32x36 @@ -538,7 +584,9 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3 } else { - if (boxsize[0] <= 32) + // LordHavoc: this has to have a minor tolerance (the .1) because of + // minor float precision errors from the box being transformed around + if (boxsize[0] < 32.1) rhc.hull = &model->brushq1.hulls[1]; // 32x32x56 else rhc.hull = &model->brushq1.hulls[2]; // 64x64x88 @@ -546,7 +594,113 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3 VectorSubtract(boxstartmins, rhc.hull->clip_mins, rhc.start); VectorSubtract(boxendmins, rhc.hull->clip_mins, rhc.end); VectorSubtract(rhc.end, rhc.start, rhc.dist); +#if COLLISIONPARANOID >= 2 + Con_Printf("t(%f %f %f,%f %f %f,%i %f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2], rhc.hull - model->brushq1.hulls, rhc.hull->clip_mins[0], rhc.hull->clip_mins[1], rhc.hull->clip_mins[2]); Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end); + Con_Printf("\n"); +#else + if (DotProduct(rhc.dist, rhc.dist)) + Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end); + else + Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode); +#endif +} + +static hull_t box_hull; +static dclipnode_t box_clipnodes[6]; +static mplane_t box_planes[6]; + +static void Mod_Q1BSP_Collision_Init (void) +{ + int i; + int side; + + //Set up the planes and clipnodes so that the six floats of a bounding box + //can just be stored out and get a proper hull_t structure. + + box_hull.clipnodes = box_clipnodes; + box_hull.planes = box_planes; + box_hull.firstclipnode = 0; + box_hull.lastclipnode = 5; + + for (i = 0;i < 6;i++) + { + box_clipnodes[i].planenum = i; + + side = i&1; + + box_clipnodes[i].children[side] = CONTENTS_EMPTY; + if (i != 5) + box_clipnodes[i].children[side^1] = i + 1; + else + box_clipnodes[i].children[side^1] = CONTENTS_SOLID; + + box_planes[i].type = i>>1; + box_planes[i].normal[i>>1] = 1; + } +} + +void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int boxsupercontents) +{ +#if 1 + colbrushf_t cbox; + colplanef_t cbox_planes[6]; + cbox.supercontents = boxsupercontents; + cbox.numplanes = 6; + cbox.numpoints = 0; + cbox.numtriangles = 0; + cbox.planes = cbox_planes; + cbox.points = NULL; + cbox.elements = NULL; + cbox.markframe = 0; + cbox.mins[0] = 0; + cbox.mins[1] = 0; + cbox.mins[2] = 0; + cbox.maxs[0] = 0; + cbox.maxs[1] = 0; + cbox.maxs[2] = 0; + cbox_planes[0].normal[0] = 1;cbox_planes[0].normal[1] = 0;cbox_planes[0].normal[2] = 0;cbox_planes[0].dist = cmaxs[0] - mins[0]; + cbox_planes[1].normal[0] = -1;cbox_planes[1].normal[1] = 0;cbox_planes[1].normal[2] = 0;cbox_planes[1].dist = maxs[0] - cmins[0]; + cbox_planes[2].normal[0] = 0;cbox_planes[2].normal[1] = 1;cbox_planes[2].normal[2] = 0;cbox_planes[2].dist = cmaxs[1] - mins[1]; + cbox_planes[3].normal[0] = 0;cbox_planes[3].normal[1] = -1;cbox_planes[3].normal[2] = 0;cbox_planes[3].dist = maxs[1] - cmins[1]; + cbox_planes[4].normal[0] = 0;cbox_planes[4].normal[1] = 0;cbox_planes[4].normal[2] = 1;cbox_planes[4].dist = cmaxs[2] - mins[2]; + cbox_planes[5].normal[0] = 0;cbox_planes[5].normal[1] = 0;cbox_planes[5].normal[2] = -1;cbox_planes[5].dist = maxs[2] - cmins[2]; + memset(trace, 0, sizeof(trace_t)); + trace->hitsupercontentsmask = hitsupercontentsmask; + trace->fraction = 1; + Collision_TraceLineBrushFloat(trace, start, end, &cbox, &cbox); +#else + RecursiveHullCheckTraceInfo_t rhc; + // fill in a default trace + memset(&rhc, 0, sizeof(rhc)); + memset(trace, 0, sizeof(trace_t)); + //To keep everything totally uniform, bounding boxes are turned into small + //BSP trees instead of being compared directly. + // create a temp hull from bounding box sizes + box_planes[0].dist = cmaxs[0] - mins[0]; + box_planes[1].dist = cmins[0] - maxs[0]; + box_planes[2].dist = cmaxs[1] - mins[1]; + box_planes[3].dist = cmins[1] - maxs[1]; + box_planes[4].dist = cmaxs[2] - mins[2]; + box_planes[5].dist = cmins[2] - maxs[2]; +#if COLLISIONPARANOID >= 3 + Con_Printf("box_planes %f:%f %f:%f %f:%f\ncbox %f %f %f:%f %f %f\nbox %f %f %f:%f %f %f\n", box_planes[0].dist, box_planes[1].dist, box_planes[2].dist, box_planes[3].dist, box_planes[4].dist, box_planes[5].dist, cmins[0], cmins[1], cmins[2], cmaxs[0], cmaxs[1], cmaxs[2], mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2]); +#endif + // trace a line through the generated clipping hull + //rhc.boxsupercontents = boxsupercontents; + rhc.hull = &box_hull; + rhc.trace = trace; + rhc.trace->hitsupercontentsmask = hitsupercontentsmask; + rhc.trace->fraction = 1; + rhc.trace->allsolid = true; + VectorCopy(start, rhc.start); + VectorCopy(end, rhc.end); + VectorSubtract(rhc.end, rhc.start, rhc.dist); + Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end); + VectorMA(rhc.start, rhc.trace->fraction, rhc.dist, rhc.trace->endpos); + if (rhc.trace->startsupercontents) + rhc.trace->startsupercontents = boxsupercontents; +#endif } static int Mod_Q1BSP_LightPoint_RecursiveBSPNode(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz) @@ -701,7 +855,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++; @@ -709,11 +863,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; @@ -2660,6 +2819,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; @@ -2667,7 +2828,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; @@ -3303,6 +3463,12 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) q3dtexture_t *in; q3mtexture_t *out; int i, count; + int j, c; + fssearch_t *search; + char *f; + const char *text; + int flags; + char shadername[Q3PATHLENGTH]; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -3315,19 +3481,157 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) for (i = 0;i < count;i++, in++, out++) { + out->number = i; strlcpy (out->name, in->name, sizeof (out->name)); out->surfaceflags = LittleLong(in->surfaceflags); out->nativecontents = LittleLong(in->contents); out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, out->nativecontents); - out->renderflags = 0; - if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")) - out->renderflags |= Q3MTEXTURERENDERFLAGS_NODRAW; - if (!strncmp(out->name, "textures/skies/", 15)) - out->renderflags |= Q3MTEXTURERENDERFLAGS_SKY; - - out->number = i; Mod_LoadSkinFrame(&out->skin, out->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true); + out->surfaceparms = -1; } + + // do a quick parse of shader files to get surfaceparms + if ((search = FS_Search("scripts/*.shader", true, false))) + { + for (i = 0;i < search->numfilenames;i++) + { + if ((f = FS_LoadFile(search->filenames[i], false))) + { + text = f; + while (COM_ParseToken(&text, false)) + { + snprintf(shadername, sizeof(shadername), "%s", com_token); + flags = 0; + if (COM_ParseToken(&text, false) && !strcmp(com_token, "{")) + { + while (COM_ParseToken(&text, false)) + { + if (!strcmp(com_token, "}")) + break; + else if (!strcmp(com_token, "{")) + { + while (COM_ParseToken(&text, false)) + { + if (!strcmp(com_token, "}")) + break; + } + } + else if (!strcmp(com_token, "surfaceparm")) + { + if (COM_ParseToken(&text, true) && strcmp(com_token, "\n")) + { + if (!strcmp(com_token, "alphashadow")) + flags |= Q3SURFACEPARM_ALPHASHADOW; + else if (!strcmp(com_token, "areaportal")) + flags |= Q3SURFACEPARM_AREAPORTAL; + else if (!strcmp(com_token, "clusterportal")) + flags |= Q3SURFACEPARM_CLUSTERPORTAL; + else if (!strcmp(com_token, "detail")) + flags |= Q3SURFACEPARM_DETAIL; + else if (!strcmp(com_token, "donotenter")) + flags |= Q3SURFACEPARM_DONOTENTER; + else if (!strcmp(com_token, "fog")) + flags |= Q3SURFACEPARM_FOG; + else if (!strcmp(com_token, "lava")) + flags |= Q3SURFACEPARM_LAVA; + else if (!strcmp(com_token, "lightfilter")) + flags |= Q3SURFACEPARM_LIGHTFILTER; + else if (!strcmp(com_token, "metalsteps")) + flags |= Q3SURFACEPARM_METALSTEPS; + else if (!strcmp(com_token, "nodamage")) + flags |= Q3SURFACEPARM_NODAMAGE; + else if (!strcmp(com_token, "nodlight")) + flags |= Q3SURFACEPARM_NODLIGHT; + else if (!strcmp(com_token, "nodraw")) + flags |= Q3SURFACEPARM_NODRAW; + else if (!strcmp(com_token, "nodrop")) + flags |= Q3SURFACEPARM_NODROP; + else if (!strcmp(com_token, "noimpact")) + flags |= Q3SURFACEPARM_NOIMPACT; + else if (!strcmp(com_token, "nolightmap")) + flags |= Q3SURFACEPARM_NOLIGHTMAP; + else if (!strcmp(com_token, "nomarks")) + flags |= Q3SURFACEPARM_NOMARKS; + else if (!strcmp(com_token, "nomipmaps")) + flags |= Q3SURFACEPARM_NOMIPMAPS; + else if (!strcmp(com_token, "nonsolid")) + flags |= Q3SURFACEPARM_NONSOLID; + else if (!strcmp(com_token, "origin")) + flags |= Q3SURFACEPARM_ORIGIN; + else if (!strcmp(com_token, "playerclip")) + flags |= Q3SURFACEPARM_PLAYERCLIP; + else if (!strcmp(com_token, "sky")) + flags |= Q3SURFACEPARM_SKY; + else if (!strcmp(com_token, "slick")) + flags |= Q3SURFACEPARM_SLICK; + else if (!strcmp(com_token, "slime")) + flags |= Q3SURFACEPARM_SLIME; + else if (!strcmp(com_token, "structural")) + flags |= Q3SURFACEPARM_STRUCTURAL; + else if (!strcmp(com_token, "trans")) + flags |= Q3SURFACEPARM_TRANS; + else if (!strcmp(com_token, "water")) + flags |= Q3SURFACEPARM_WATER; + else + Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], com_token); + if (!COM_ParseToken(&text, true) || strcmp(com_token, "\n")) + { + Con_Printf("%s parsing error: surfaceparm only takes one parameter.\n", search->filenames[i]); + goto parseerror; + } + } + else + { + Con_Printf("%s parsing error: surfaceparm expects a parameter.\n", search->filenames[i]); + goto parseerror; + } + } + else + { + // look for linebreak or } + while(COM_ParseToken(&text, true) && strcmp(com_token, "\n") && strcmp(com_token, "}")); + // break out to top level if it was } + if (!strcmp(com_token, "}")) + break; + } + } + // add shader to list (shadername and flags) + // actually here we just poke into the texture settings + for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++) + if (!strcmp(out->name, shadername)) + out->surfaceparms = flags; + } + else + { + Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[i], com_token); + goto parseerror; + } + } +parseerror: + Mem_Free(f); + } + } + } + + c = 0; + for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++) + { + if (out->surfaceparms == -1) + { + c++; + Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name); + out->surfaceparms = 0; + // these are defaults + if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk") + || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw")) + out->surfaceparms |= Q3SURFACEPARM_NODRAW; + if (!strncmp(out->name, "textures/skies/", 15)) + out->surfaceparms |= Q3SURFACEPARM_SKY; + if (R_TextureHasAlpha(out->skin.base)) + out->surfaceparms |= Q3SURFACEPARM_TRANS; + } + } + Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c); } static void Mod_Q3BSP_LoadPlanes(lump_t *l) @@ -3389,6 +3693,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)) @@ -3399,6 +3704,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; @@ -3429,10 +3737,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) @@ -3470,13 +3780,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++) { @@ -3514,11 +3824,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++) { @@ -3537,6 +3847,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); @@ -3585,6 +3897,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; } @@ -3593,6 +3907,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; @@ -3626,35 +3942,41 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) if (out->num_triangles * 3 != LittleLong(in->numelements)) { Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, LittleLong(in->numelements)); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } if (out->firstvertex < 0 || out->firstvertex + out->num_vertices > loadmodel->brushq3.num_vertices) { Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, out->firstvertex, out->firstvertex + out->num_vertices, loadmodel->brushq3.num_vertices); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } if (out->firstelement < 0 || out->firstelement + out->num_triangles * 3 > loadmodel->brushq3.num_triangles * 3) { Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, out->firstelement, out->firstelement + out->num_triangles * 3, loadmodel->brushq3.num_triangles * 3); + out->num_vertices = 0; + out->num_triangles = 0; out->type = 0; // error continue; } - out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3; - out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2; - out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2; - out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3; - out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3; - out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3; - out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4; - out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement; - out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement; switch(out->type) { case Q3FACETYPE_POLYGON: case Q3FACETYPE_MESH: // no processing necessary + out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3; + out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2; + out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2; + out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3; + out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3; + out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3; + out->data_color4f = loadmodel->brushq3.data_color4f + out->firstvertex * 4; + out->data_element3i = loadmodel->brushq3.data_element3i + out->firstelement; + out->data_neighbor3i = loadmodel->brushq3.data_neighbor3i + out->firstelement; break; case Q3FACETYPE_PATCH: patchsize[0] = LittleLong(in->specific.patch.patchsize[0]); @@ -3662,6 +3984,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; } @@ -3672,6 +3996,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; @@ -3681,14 +4015,15 @@ 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; @@ -3733,7 +4068,9 @@ 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->num_vertices = 0; out->num_triangles = 0; + out->type = 0; break; } for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++) @@ -3778,6 +4115,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) @@ -4050,9 +4476,9 @@ 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); @@ -4255,7 +4681,7 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, q3mnode_t *nod } } -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]; @@ -4441,13 +4867,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_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; @@ -4467,6 +4893,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; @@ -4474,7 +4902,6 @@ 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->DrawShadowVolume = R_Q3BSP_DrawShadowVolume; @@ -4543,6 +4970,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->surfaceflags & Q3SURFACEFLAG_SKY) + break; + if (j < mod->brushq3.data_thismodel->numfaces) + mod->DrawSky = R_Q3BSP_DrawSky; } }