X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_brush.c;h=660c4df77dfa7504aea387485d825ca0a106cba0;hb=0dc77d61cf349a3fbe2994cce57f07faa99aab27;hp=0b9653926a319628194e07127f2eee46fe7a0822;hpb=9d6bef38db35fdd649473cad2b698e3fcb898577;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index 0b965392..660c4df7 100644 --- a/model_brush.c +++ b/model_brush.c @@ -31,7 +31,7 @@ cvar_t halflifebsp = {0, "halflifebsp", "0", "indicates the current map is hlbsp cvar_t mcbsp = {0, "mcbsp", "0", "indicates the current map is mcbsp format (useful to know because of different bounding box sizes)"}; cvar_t r_novis = {0, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"}; cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1", "whether to use RGBA (32bit) or RGB (24bit) lightmaps"}; -cvar_t r_picmipworld = {0, "r_picmipworld", "1", "whether gl_picmip shall apply to world textures too"}; +cvar_t r_picmipworld = {CVAR_SAVE, "r_picmipworld", "1", "whether gl_picmip shall apply to world textures too"}; cvar_t r_nosurftextures = {0, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"}; cvar_t r_subdivisions_tolerance = {0, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"}; cvar_t r_subdivisions_mintess = {0, "r_subdivisions_mintess", "1", "minimum number of subdivisions (values above 1 will smooth curves that don't need it)"}; @@ -1748,13 +1748,13 @@ static void Mod_Q1BSP_ParseWadsFromEntityLump(const char *data) int i, j, k; if (!data) return; - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) return; // error if (com_token[0] != '{') return; // error while (1) { - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) return; // error if (com_token[0] == '}') break; // end of worldspawn @@ -1764,7 +1764,7 @@ static void Mod_Q1BSP_ParseWadsFromEntityLump(const char *data) strlcpy(key, com_token, sizeof(key)); while (key[strlen(key)-1] == ' ') // remove trailing spaces key[strlen(key)-1] = 0; - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) return; // error dpsnprintf(value, sizeof(value), "%s", com_token); if (!strcmp("wad", key)) // for HalfLife maps @@ -2660,12 +2660,12 @@ static void Mod_Q1BSP_LoadMapBrushes(void) if (!maptext) return; text = maptext; - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) return; // error submodel = 0; for (;;) { - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) break; if (com_token[0] != '{') return; // error @@ -2676,7 +2676,7 @@ static void Mod_Q1BSP_LoadMapBrushes(void) brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t)); for (;;) { - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) return; // error if (com_token[0] == '}') break; // end of entity @@ -2700,7 +2700,7 @@ static void Mod_Q1BSP_LoadMapBrushes(void) } for (;;) { - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) return; // error if (com_token[0] == '}') break; // end of brush @@ -2709,25 +2709,25 @@ static void Mod_Q1BSP_LoadMapBrushes(void) // FIXME: support hl .map format for (pointnum = 0;pointnum < 3;pointnum++) { - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); for (componentnum = 0;componentnum < 3;componentnum++) { - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); point[pointnum][componentnum] = atof(com_token); } - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); } - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); strlcpy(facetexture, com_token, sizeof(facetexture)); - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); //scroll_s = atof(com_token); - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); //scroll_t = atof(com_token); - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); //rotate = atof(com_token); - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); //scale_s = atof(com_token); - COM_ParseTokenConsole(&data); + COM_ParseToken_Simple(&data, false); //scale_t = atof(com_token); TriangleNormal(point[0], point[1], point[2], planenormal); VectorNormalizeDouble(planenormal); @@ -3538,6 +3538,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) // this gets altered below if sky is used mod->DrawSky = NULL; mod->Draw = R_Q1BSP_Draw; + mod->DrawDepth = R_Q1BSP_DrawDepth; mod->GetLightInfo = R_Q1BSP_GetLightInfo; mod->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; mod->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; @@ -4069,11 +4070,11 @@ static void Mod_Q3BSP_LoadEntities(lump_t *l) memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen); data = loadmodel->brush.entities; // some Q3 maps override the lightgrid_cellsize with a worldspawn key - if (data && COM_ParseTokenConsole(&data) && com_token[0] == '{') + if (data && COM_ParseToken_Simple(&data, false) && com_token[0] == '{') { while (1) { - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) break; // error if (com_token[0] == '}') break; // end of worldspawn @@ -4083,7 +4084,7 @@ static void Mod_Q3BSP_LoadEntities(lump_t *l) strlcpy(key, com_token, sizeof(key)); while (key[strlen(key)-1] == ' ') // remove trailing spaces key[strlen(key)-1] = 0; - if (!COM_ParseTokenConsole(&data)) + if (!COM_ParseToken_Simple(&data, false)) break; // error strlcpy(value, com_token, sizeof(value)); if (!strcmp("gridsize", key)) @@ -4150,7 +4151,7 @@ static void Mod_Q3BSP_LoadShaders(void) text = f = (char *)FS_LoadFile(search->filenames[fileindex], tempmempool, false, NULL); if (!f) continue; - while (COM_ParseToken(&text, false)) + while (COM_ParseToken_QuakeC(&text, false)) { if (q3shaders_numshaders >= Q3SHADER_MAXSHADERS) { @@ -4160,12 +4161,12 @@ static void Mod_Q3BSP_LoadShaders(void) shader = q3shaders_shaders + q3shaders_numshaders++; memset(shader, 0, sizeof(*shader)); strlcpy(shader->name, com_token, sizeof(shader->name)); - if (!COM_ParseToken(&text, false) || strcasecmp(com_token, "{")) + if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{")) { Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[fileindex], com_token); break; } - while (COM_ParseToken(&text, false)) + while (COM_ParseToken_QuakeC(&text, false)) { if (!strcasecmp(com_token, "}")) break; @@ -4181,7 +4182,7 @@ static void Mod_Q3BSP_LoadShaders(void) } else layer = NULL; - while (COM_ParseToken(&text, false)) + while (COM_ParseToken_QuakeC(&text, false)) { if (!strcasecmp(com_token, "}")) break; @@ -4197,7 +4198,7 @@ static void Mod_Q3BSP_LoadShaders(void) strlcpy(parameter[j], com_token, sizeof(parameter[j])); numparameters = j + 1; } - if (!COM_ParseToken(&text, true)) + if (!COM_ParseToken_QuakeC(&text, true)) break; } if (developer.integer >= 100) @@ -4310,7 +4311,7 @@ static void Mod_Q3BSP_LoadShaders(void) strlcpy(parameter[j], com_token, sizeof(parameter[j])); numparameters = j + 1; } - if (!COM_ParseToken(&text, true)) + if (!COM_ParseToken_QuakeC(&text, true)) break; } if (fileindex == 0 && !strcasecmp(com_token, "}")) @@ -4569,7 +4570,10 @@ Q3 shader blendfuncs actually used in the game (* = supported by DP) out->skinframerate = shader->primarylayer->framerate; for (j = 0;j < shader->primarylayer->numframes;j++) if (!(out->skinframes[j] = R_SkinFrame_LoadExternal(shader->primarylayer->texturename[j], ((shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | ((!r_picmipworld.integer || (shader->textureflags & Q3TEXTUREFLAG_NOPICMIP)) ? 0 : TEXF_PICMIP) | (shader->primarylayer->clampmap ? TEXF_CLAMP : 0), false))) + { Con_DPrintf("%s: could not load texture \"%s\" (frame %i) for shader \"%s\"\n", loadmodel->name, shader->primarylayer->texturename[j], j, out->name); + out->skinframes[j] = R_SkinFrame_LoadMissing(); + } } if (shader->backgroundlayer) { @@ -4824,7 +4828,7 @@ static void Mod_Q3BSP_LoadTriangles(lump_t *l) static void Mod_Q3BSP_LoadLightmaps(lump_t *l, lump_t *faceslump) { q3dlightmap_t *in; - int i, j, count, power, power2, mask, endlightmap; + int i, j, count, power, power2, mask, endlightmap, mergewidth, mergeheight; unsigned char *c; if (!l->filelen) @@ -4891,7 +4895,7 @@ static void Mod_Q3BSP_LoadLightmaps(lump_t *l, lump_t *faceslump) // figure out what the most reasonable merge power is within limits loadmodel->brushq3.num_lightmapmergepower = 0; - for (power = 1;power <= mod_q3bsp_lightmapmergepower.integer && (1 << power) <= gl_max_texture_size && (1 << (power * 2)) < 4 * (count >> loadmodel->brushq3.deluxemapping);power++) + for (power = 1;power <= mod_q3bsp_lightmapmergepower.integer && (128 << power) <= gl_max_texture_size && (1 << (power * 2)) < 4 * (count >> loadmodel->brushq3.deluxemapping);power++) loadmodel->brushq3.num_lightmapmergepower = power; loadmodel->brushq3.num_lightmapmerge = 1 << loadmodel->brushq3.num_lightmapmergepower; @@ -4904,25 +4908,54 @@ static void Mod_Q3BSP_LoadLightmaps(lump_t *l, lump_t *faceslump) if (loadmodel->texturepool == NULL && cls.state != ca_dedicated) loadmodel->texturepool = R_AllocTexturePool(); - j = 128 << loadmodel->brushq3.num_lightmapmergepower; - if (loadmodel->brushq3.data_lightmaps) - for (i = 0;i < loadmodel->brushq3.num_mergedlightmaps;i++) - loadmodel->brushq3.data_lightmaps[i] = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%04i", i), j, j, NULL, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL); - - if (loadmodel->brushq3.data_deluxemaps) - for (i = 0;i < loadmodel->brushq3.num_mergedlightmaps;i++) - loadmodel->brushq3.data_deluxemaps[i] = R_LoadTexture2D(loadmodel->texturepool, va("deluxemap%04i", i), j, j, NULL, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL); - - power = loadmodel->brushq3.num_lightmapmergepower; - power2 = power * 2; - mask = (1 << power) - 1; - for (i = 0;i < count;i++) + if (loadmodel->brushq3.num_lightmapmergepower > 0) { - j = i >> loadmodel->brushq3.deluxemapping; - if (loadmodel->brushq3.deluxemapping && (i & 1)) - R_UpdateTexture(loadmodel->brushq3.data_deluxemaps[j >> power2], in[i].rgb, (j & mask) * 128, ((j >> power) & mask) * 128, 128, 128); - else - R_UpdateTexture(loadmodel->brushq3.data_lightmaps [j >> power2], in[i].rgb, (j & mask) * 128, ((j >> power) & mask) * 128, 128, 128); + power = loadmodel->brushq3.num_lightmapmergepower; + power2 = power * 2; + mask = (1 << power) - 1; + for (i = 0;i < count;i++) + { + // figure out which merged lightmap texture this fits into + int lightmapindex = i >> (loadmodel->brushq3.deluxemapping + power2); + // if the lightmap has not been allocated yet, create it + if (!loadmodel->brushq3.data_lightmaps[lightmapindex]) + { + // create a lightmap only as large as necessary to hold the + // remaining 128x128 blocks + // if there are multiple merged lightmap textures then they will + // all be full size except the last one which may be smaller + // because it only needs to the remaining blocks, and it will often + // be odd sizes like 2048x512 due to only being 25% full or so. + j = (count >> loadmodel->brushq3.deluxemapping) - (lightmapindex << power2); + for (mergewidth = 1;mergewidth < j && mergewidth < (1 << power);mergewidth *= 2) + ; + for (mergeheight = 1;mergewidth*mergeheight < j && mergeheight < (1 << power);mergeheight *= 2) + ; + Con_DPrintf("lightmap merge texture #%i is %ix%i (%i of %i used)\n", lightmapindex, mergewidth*128, mergeheight*128, min(j, mergewidth*mergeheight), mergewidth*mergeheight); + loadmodel->brushq3.data_lightmaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%04i", lightmapindex), mergewidth * 128, mergeheight * 128, NULL, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL); + if (loadmodel->brushq3.data_deluxemaps) + loadmodel->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va("deluxemap%04i", lightmapindex), mergewidth * 128, mergeheight * 128, NULL, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL); + } + mergewidth = R_TextureWidth(loadmodel->brushq3.data_lightmaps[lightmapindex]) / 128; + mergeheight = R_TextureHeight(loadmodel->brushq3.data_lightmaps[lightmapindex]) / 128; + j = (i >> loadmodel->brushq3.deluxemapping) & ((1 << power2) - 1); + if (loadmodel->brushq3.deluxemapping && (i & 1)) + R_UpdateTexture(loadmodel->brushq3.data_deluxemaps[lightmapindex], in[i].rgb, (j % mergewidth) * 128, (j / mergewidth) * 128, 128, 128); + else + R_UpdateTexture(loadmodel->brushq3.data_lightmaps [lightmapindex], in[i].rgb, (j % mergewidth) * 128, (j / mergewidth) * 128, 128, 128); + } + } + else + { + for (i = 0;i < count;i++) + { + // figure out which merged lightmap texture this fits into + int lightmapindex = i >> loadmodel->brushq3.deluxemapping; + if (loadmodel->brushq3.deluxemapping && (i & 1)) + loadmodel->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va("deluxemap%04i", lightmapindex), 128, 128, in[i].rgb, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL); + else + loadmodel->brushq3.data_lightmaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%04i", lightmapindex), 128, 128, in[i].rgb, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL); + } } } @@ -4931,7 +4964,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) q3dface_t *in, *oldin; msurface_t *out, *oldout; int i, oldi, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xtess, ytess, finalvertices, finaltriangles, firstvertex, firstelement, type, oldnumtriangles, oldnumtriangles2, meshvertices, meshtriangles, numvertices, numtriangles; - float lightmaptcbase[2], lightmaptcscale; + float lightmaptcbase[2], lightmaptcscale[2]; //int *originalelement3i; //int *originalneighbor3i; float *originalvertex3f; @@ -5228,18 +5261,22 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) VectorClear(out->maxs); if (out->num_vertices) { - int lightmapindex = LittleLong(in->lightmapindex); - if (lightmapindex >= 0 && cls.state != ca_dedicated) + if (cls.state != ca_dedicated && out->lightmaptexture) { - lightmapindex >>= loadmodel->brushq3.deluxemapping; - lightmaptcscale = 1.0f / loadmodel->brushq3.num_lightmapmerge; - lightmaptcbase[0] = ((lightmapindex ) & (loadmodel->brushq3.num_lightmapmerge - 1)) * lightmaptcscale; - lightmaptcbase[1] = ((lightmapindex >> loadmodel->brushq3.num_lightmapmergepower) & (loadmodel->brushq3.num_lightmapmerge - 1)) * lightmaptcscale; + // figure out which part of the merged lightmap this fits into + int lightmapindex = LittleLong(in->lightmapindex) >> loadmodel->brushq3.deluxemapping; + int mergewidth = R_TextureWidth(out->lightmaptexture) / 128; + int mergeheight = R_TextureHeight(out->lightmaptexture) / 128; + lightmapindex &= mergewidth * mergeheight - 1; + lightmaptcscale[0] = 1.0f / mergewidth; + lightmaptcscale[1] = 1.0f / mergeheight; + lightmaptcbase[0] = (lightmapindex % mergewidth) * lightmaptcscale[0]; + lightmaptcbase[1] = (lightmapindex / mergewidth) * lightmaptcscale[1]; // modify the lightmap texcoords to match this region of the merged lightmap for (j = 0, v = loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex;j < out->num_vertices;j++, v += 2) { - v[0] = v[0] * lightmaptcscale + lightmaptcbase[0]; - v[1] = v[1] * lightmaptcscale + lightmaptcbase[1]; + v[0] = v[0] * lightmaptcscale[0] + lightmaptcbase[0]; + v[1] = v[1] * lightmaptcscale[1] + lightmaptcbase[1]; } } VectorCopy((loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex), out->mins); @@ -5545,7 +5582,7 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l) static void Mod_Q3BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal) { int i, j, k, index[3]; - float transformed[3], blend1, blend2, blend, yaw, pitch, sinpitch, stylescale; + float transformed[3], blend1, blend2, blend, stylescale; q3dlightgrid_t *a, *s; // scale lighting by lightstyle[0] so that darkmode in dpmod works properly @@ -5591,12 +5628,12 @@ static void Mod_Q3BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientc 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); - pitch = s->diffusepitch * M_PI / 128; - yaw = s->diffuseyaw * M_PI / 128; - sinpitch = sin(pitch); - diffusenormal[0] += blend * (cos(yaw) * sinpitch); - diffusenormal[1] += blend * (sin(yaw) * sinpitch); - diffusenormal[2] += blend * (cos(pitch)); + // this uses the mod_md3_sin table because the values are + // already in the 0-255 range, the 64+ bias fetches a cosine + // instead of a sine value + diffusenormal[0] += blend * (mod_md3_sin[64 + s->diffuseyaw] * mod_md3_sin[s->diffusepitch]); + diffusenormal[1] += blend * (mod_md3_sin[ s->diffuseyaw] * mod_md3_sin[s->diffusepitch]); + diffusenormal[2] += blend * (mod_md3_sin[64 + s->diffusepitch]); //Con_Printf("blend %f: ambient %i %i %i, diffuse %i %i %i, diffusepitch %i diffuseyaw %i (%f %f, normal %f %f %f)\n", blend, s->ambientrgb[0], s->ambientrgb[1], s->ambientrgb[2], s->diffusergb[0], s->diffusergb[1], s->diffusergb[2], s->diffusepitch, s->diffuseyaw, pitch, yaw, (cos(yaw) * cospitch), (sin(yaw) * cospitch), (-sin(pitch))); } } @@ -5981,6 +6018,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend) mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation; mod->brush.PointInLeaf = Mod_Q1BSP_PointInLeaf; mod->Draw = R_Q1BSP_Draw; + mod->DrawDepth = R_Q1BSP_DrawDepth; mod->GetLightInfo = R_Q1BSP_GetLightInfo; mod->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; mod->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;