diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 5c3553b8..db867b0b 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1580,7 +1580,7 @@ static int CL_Record_Lightstyles(sizebuf_t *buf, int seq) { unsigned int i; // send all current light styles - for (i=0 ; i= MAX_STANDARDLIGHTSTYLES) if (!*cl_lightstyle[i].map) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 8a2311f0..2897846d 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -187,6 +187,7 @@ static void CL_ClearDlight(dlight_t *dl, int key) dl->color[2] = 1; dl->corona = bound(0, 1 * 0.25, 1); dl->coronascale = bound(0, r_flashblendscale.value, 1); + dl->style = -1; #ifdef RTLIGHTS dl->lightcolourscales[0] = r_shadow_realtime_dlight_ambient.value; dl->lightcolourscales[1] = r_shadow_realtime_dlight_diffuse.value; @@ -3788,16 +3789,21 @@ void CL_TransitionEntities (void) nolerp = !CL_MayLerp() && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV; } - //force our emulated time to as late as we can, if we're not using interpolation, which has the effect of disabling all interpolation if (cl.demonudge < 0) - { + { //demo playback allows nudging to earlier frames, generally only when paused though... servertime = cl.inframes[(cls.netchan.incoming_sequence+cl.demonudge)&UPDATE_MASK].packet_entities.servertime; nolerp = true; } else if (nolerp) + { + //force our emulated time to as late as we can, if we're not using interpolation, which has the effect of disabling all interpolation servertime = cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime; + } else + { + //otherwise go for the latest frame we can. servertime = cl.servertime; + } // servertime -= 0.1; @@ -3812,7 +3818,7 @@ void CL_TransitionEntities (void) packnew = &cl.inframes[newf].packet_entities; packold = &cl.inframes[oldf].packet_entities; if (packnew->servertime == packold->servertime) - frac = 1; //lerp totally into the new + frac = 1; //lerp totally into the new (avoid any division-by-0 issues here) else frac = (servertime-packold->servertime)/(packnew->servertime-packold->servertime); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 77c405fd..d30641df 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -234,7 +234,8 @@ client_state_t cl; entity_state_t *cl_baselines; static_entity_t *cl_static_entities; unsigned int cl_max_static_entities; -lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; +lightstyle_t *cl_lightstyle; +size_t cl_max_lightstyles; dlight_t *cl_dlights; size_t cl_maxdlights; /*size of cl_dlights array*/ @@ -1814,9 +1815,9 @@ void CL_ClearState (qboolean gamestart) // clear other arrays // memset (cl_dlights, 0, sizeof(cl_dlights)); - memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); - for (i = 0; i < MAX_LIGHTSTYLES; i++) - R_UpdateLightStyle(i, NULL, 1, 1, 1); + Z_Free(cl_lightstyle); + cl_lightstyle = NULL; + cl_max_lightstyles = 0; rtlights_first = rtlights_max = RTL_FIRST; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index d382789d..1c27d964 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1750,7 +1750,18 @@ void CL_RequestNextDownload (void) break; case DLFAIL_UNTRIED: if (COM_FCheckExists(worldname)) - Con_Printf(CON_ERROR "Couldn't load \"%s\" - corrupt? - cannot fully connect\n", worldname); + { + if (!cl.worldmodel) + Con_Printf(CON_ERROR "Couldn't load \"%s\" - worldmodel not set - cannot fully connect\n", worldname); + else if (cl.worldmodel->loadstate == MLS_FAILED) + Con_Printf(CON_ERROR "Couldn't load \"%s\" - corrupt? - cannot fully connect\n", worldname); + else if (cl.worldmodel->loadstate == MLS_LOADING) + Con_Printf(CON_ERROR "Couldn't load \"%s\" - still loading - cannot fully connect\n", worldname); + else if (cl.worldmodel->loadstate == MLS_NOTLOADED) + Con_Printf(CON_ERROR "Couldn't load \"%s\" - worldmodel not loaded - cannot fully connect\n", worldname); + else + Con_Printf(CON_ERROR "Couldn't load \"%s\" - corrupt? - cannot fully connect\n", worldname); + } else Con_Printf(CON_ERROR "Couldn't find \"%s\" - cannot fully connect\n", worldname); break; @@ -6415,6 +6426,15 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds InfoBuf_SetStarKey(&cl.serverinfo, Cmd_Argv(1), Cmd_Argv(2)); CL_CheckServerInfo(); } + else if (!strncmp(stufftext, "//ls ", 5)) //for extended lightstyles + { + vec3_t rgb; + Cmd_TokenizeString(stufftext+2, false, false); + rgb[0] = ((Cmd_Argc()>3)?atof(Cmd_Argv(3)):1); + rgb[1] = ((Cmd_Argc()>5)?atof(Cmd_Argv(4)):rgb[0]); + rgb[2] = ((Cmd_Argc()>5)?atof(Cmd_Argv(5)):rgb[0]); + R_UpdateLightStyle(atoi(Cmd_Argv(1)), Cmd_Argv(2), rgb[0], rgb[1], rgb[2]); + } #ifdef NQPROT //DP's download protocol @@ -7019,7 +7039,7 @@ void CLQW_ParseServerMessage (void) case svc_lightstyle: i = MSG_ReadByte (); - if (i >= MAX_LIGHTSTYLES) + if (i >= MAX_NET_LIGHTSTYLES) Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); R_UpdateLightStyle(i, MSG_ReadString(), 1, 1, 1); break; @@ -7027,18 +7047,18 @@ void CLQW_ParseServerMessage (void) case svcfte_lightstylecol: if (!(cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL)) Host_EndGame("PEXT_LIGHTSTYLECOL is meant to be disabled\n"); - i = MSG_ReadByte (); - if (i >= MAX_LIGHTSTYLES) - Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); { int bits; vec3_t rgb; + i = MSG_ReadByte (); bits = MSG_ReadByte(); + if (bits & 0x40) + i |= MSG_ReadByte()<<8; //high bits of style index. if (bits & 0x80) { - rgb[0] = MSG_ReadShort()/1024.0; - rgb[1] = MSG_ReadShort()/1024.0; - rgb[2] = MSG_ReadShort()/1024.0; + rgb[0] = (bits&1)?MSG_ReadShort()/1024.0:0; + rgb[1] = (bits&2)?MSG_ReadShort()/1024.0:0; + rgb[2] = (bits&4)?MSG_ReadShort()/1024.0:0; } else { @@ -7046,6 +7066,9 @@ void CLQW_ParseServerMessage (void) rgb[1] = (bits&2)?1:0; rgb[2] = (bits&4)?1:0; } + + if (i >= MAX_NET_LIGHTSTYLES) + Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); R_UpdateLightStyle(i, MSG_ReadString(), rgb[0], rgb[1], rgb[2]); } break; @@ -8159,7 +8182,7 @@ void CLNQ_ParseServerMessage (void) break; case svc_lightstyle: i = MSG_ReadByte (); - if (i >= MAX_LIGHTSTYLES) + if (i >= MAX_NET_LIGHTSTYLES) { Con_Printf("svc_lightstyle: %i >= MAX_LIGHTSTYLES\n", i); MSG_ReadString(); diff --git a/engine/client/client.h b/engine/client/client.h index 5512e8c1..59c6fa1c 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -343,7 +343,7 @@ typedef struct dlight_s struct { float updatetime; } face [6]; - int style; //multiply by style values if > 0 + int style; //multiply by style values if >= 0 && < MAX_LIGHTSTYLES float fov; //spotlight float nearclip; //for spotlights... struct dlight_s *next; @@ -1060,10 +1060,13 @@ typedef struct extern entity_state_t *cl_baselines; extern static_entity_t *cl_static_entities; extern unsigned int cl_max_static_entities; -extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; +extern lightstyle_t *cl_lightstyle; +extern size_t cl_max_lightstyles; extern dlight_t *cl_dlights; extern size_t cl_maxdlights; +extern int d_lightstylevalue[MAX_NET_LIGHTSTYLES]; + extern size_t rtlights_first, rtlights_max; extern int cl_baselines_count; diff --git a/engine/client/console.c b/engine/client/console.c index 0a68dd19..461c3d2a 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -607,13 +607,31 @@ Con_ToggleConsole_f */ void Con_ToggleConsole_Force(void) { + console_t *con = Con_GetMain(); + SCR_EndLoadingPlaque(); Key_ClearTyping (); - if (Key_Dest_Has(kdm_console)) - Key_Dest_Remove(kdm_console); + if (con->flags & CONF_ISWINDOW) + { + if (con_curwindow == con && Key_Dest_Has(kdm_cwindows)) + { + con_curwindow = NULL; + Key_Dest_Remove(kdm_cwindows); + } + else + { + con_curwindow = con; + Key_Dest_Add(kdm_cwindows); + } + } else - Key_Dest_Add(kdm_console); + { + if (Key_Dest_Has(kdm_console)) + Key_Dest_Remove(kdm_console); + else + Key_Dest_Add(kdm_console); + } } void Con_ToggleConsole_f (void) { diff --git a/engine/client/image.c b/engine/client/image.c index 98c14508..c85df2ce 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -513,6 +513,9 @@ void *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t red = *data++; alphabyte = *data++; break; + default: + blue = green = red = alphabyte = 255; + break; } if (*format!=PTI_L8) //keep colours @@ -4153,7 +4156,11 @@ typedef struct { unsigned int dwFlags; unsigned int dwFourCC; - unsigned int unk[5]; + unsigned int bitcount; + unsigned int redmask; + unsigned int greenmask; + unsigned int bluemask; + unsigned int alphamask; } ddspixelformat; typedef struct { @@ -4205,7 +4212,29 @@ static struct pendingtextureinfo *Image_ReadDDSFile(unsigned int flags, const ch if (nummips < 1) nummips = 1; - if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) + if (!(fmtheader.ddpfPixelFormat.dwFlags & 4)) + { +#define IsPacked(bits,r,g,b,a) fmtheader.ddpfPixelFormat.bitcount==bits&&fmtheader.ddpfPixelFormat.redmask==r&&fmtheader.ddpfPixelFormat.greenmask==g&&fmtheader.ddpfPixelFormat.bluemask==b&&fmtheader.ddpfPixelFormat.alphamask==a + if (IsPacked(24, 0xff0000, 0x00ff00, 0x0000ff, 0)) + encoding = PTI_BGR8; + else if (IsPacked(24, 0x000000, 0x00ff00, 0xff0000, 0)) + encoding = PTI_RGB8; + else if (IsPacked(32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000)) + encoding = PTI_BGRA8; + else if (IsPacked(32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) + encoding = PTI_RGBA8; + else if (IsPacked(32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0)) + encoding = PTI_BGRX8; + else if (IsPacked(32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0)) + encoding = PTI_RGBX8; + else + { + Con_Printf("Unsupported non-fourcc dds in %s\n", fname); + return NULL; + } +#undef IsPacked + } + else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) { encoding = PTI_BC1_RGBA; //alpha or not? Assume yes, and let the drivers decide. // pad = 8; diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 788aef4a..9a8d7d0b 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -2878,6 +2878,33 @@ void PM_Command_f(void) Con_Printf("%s may not be used from gamecode\n", Cmd_Argv(0)); return; } + + if (!strcmp(act, "sources") || !strcmp(act, "addsource")) + { +#ifdef WEBCLIENT + if (Cmd_Argc() == 2) + { + int i; + for (i = 0; i < numdownloadablelists; i++) + Con_Printf("%s %s\n", downloadablelist[i].url, downloadablelist[i].save?"(explicit)":"(implicit)"); + Con_Printf("<%i sources>\n", numdownloadablelists); + } + else + { + PM_AddSubList(Cmd_Argv(2), "", true, true); + PM_WriteInstalledPackages(); + } +#endif + } + else if (!strcmp(act, "remsource")) + { +#ifdef WEBCLIENT + PM_RemSubList(Cmd_Argv(2)); + PM_WriteInstalledPackages(); +#endif + } + else + { if (!loadedinstalled) PM_UpdatePackageList(false, false); @@ -2888,6 +2915,8 @@ void PM_Command_f(void) { const char *status; char *markup; + if ((p->flags & DPF_HIDDEN) && !(p->flags & (DPF_MARKED|DPF_ENABLED|DPF_PURGE|DPF_CACHED))) + continue; if (p->flags & DPF_ENABLED) markup = S_COLOR_GREEN; else if (p->flags & DPF_CORRUPT) @@ -3001,28 +3030,6 @@ void PM_Command_f(void) } Con_Printf("\n"); } -#ifdef WEBCLIENT - else if (!strcmp(act, "sources") || !strcmp(act, "addsource")) - { - if (Cmd_Argc() == 2) - { - int i; - for (i = 0; i < numdownloadablelists; i++) - Con_Printf("%s %s\n", downloadablelist[i].url, downloadablelist[i].save?"(explicit)":"(implicit)"); - Con_Printf("<%i sources>\n", numdownloadablelists); - } - else - { - PM_AddSubList(Cmd_Argv(2), "", true, true); - PM_WriteInstalledPackages(); - } - } -#endif - else if (!strcmp(act, "remsource")) - { - PM_RemSubList(Cmd_Argv(2)); - PM_WriteInstalledPackages(); - } else if (!strcmp(act, "apply")) { Con_Printf("Applying package changes\n"); @@ -3128,6 +3135,7 @@ void PM_Command_f(void) } else Con_Printf("%s: Unknown action %s\nShould be one of list, show, search, upgrade, revert, add, rem, del, changes, apply, sources, addsource, remsource\n", Cmd_Argv(0), act); + } } qboolean PM_FindUpdatedEngine(char *syspath, size_t syspathsize) diff --git a/engine/client/merged.h b/engine/client/merged.h index c50700fb..b65407ed 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -297,7 +297,7 @@ struct pendingtextureinfo PTI_2D, PTI_3D, PTI_CUBEMAP, //mips are packed (to make d3d11 happy) - PTI_2D_ARRAY, //looks like a 3d texture, but depth doesn't change. + PTI_2D_ARRAY, //looks like a 3d texture, but depth doesn't change with mips. PTI_CUBEMAP_ARRAY, //looks like PTI_2D_ARRAY, with depth*6 } type; diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 3ffcd481..9d63b6f5 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -1047,6 +1047,7 @@ static void P_ResetToDefaults(part_type_t *ptype) ptype->rotationstartrand = M_PI-ptype->rotationstartmin; ptype->spawnchance = 1; ptype->dl_time = 0; + ptype->dl_lightstyle = -1; VectorSet(ptype->dl_rgb, 1, 1, 1); ptype->dl_corona_intensity = 0.25; ptype->dl_corona_scale = 0.5; @@ -2225,7 +2226,7 @@ parsefluid: else if (!strcmp(var, "lightcubemap")) ptype->dl_cubemapnum = atoi(value); else if (!strcmp(var, "lightstyle")) - ptype->dl_lightstyle = bound(0, atoi(value)+1, 256); + ptype->dl_lightstyle = atoi(value); else if (!strcmp(var, "lightscales")) { //ambient diffuse specular ptype->dl_scales[0] = atof(value); @@ -2584,7 +2585,7 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen) Q_strncatz(outstr, va("lighttime %g\n", ptype->dl_time), outstrlen); Q_strncatz(outstr, va("lightshadows %g\n", (ptype->flags & PT_NODLSHADOW)?0.0f:1.0f), outstrlen); Q_strncatz(outstr, va("lightcubemap %i\n", ptype->dl_cubemapnum), outstrlen); - Q_strncatz(outstr, va("lightstyle %i\n", ptype->dl_lightstyle-1), outstrlen); + Q_strncatz(outstr, va("lightstyle %i\n", ptype->dl_lightstyle), outstrlen); Q_strncatz(outstr, va("lightcorona %g %g\n", ptype->dl_corona_intensity, ptype->dl_corona_scale), outstrlen); Q_strncatz(outstr, va("lightscales %g %g %g\n", ptype->dl_scales[0], ptype->dl_scales[1], ptype->dl_scales[2]), outstrlen); } @@ -4431,8 +4432,7 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t axis[3] dl->flags |= LFLAG_NOSHADOWS; if (ptype->dl_cubemapnum) Q_snprintfz(dl->cubemapname, sizeof(dl->cubemapname), "cubemaps/%i", ptype->dl_cubemapnum); - if (ptype->dl_lightstyle > 0) - dl->style = ptype->dl_lightstyle; + dl->style = ptype->dl_lightstyle; } if (ptype->numsounds) { diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 2201dfe1..87b207e3 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1156,7 +1156,7 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa l->rebuildcache = true; break; case lfield_style: - l->style = G_FLOAT(OFS_PARM2)+1; + l->style = G_FLOAT(OFS_PARM2); break; case lfield_angles: VectorCopy(G_VECTOR(OFS_PARM2), l->angles); @@ -1248,7 +1248,7 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa G_FLOAT(OFS_RETURN) = l->flags; break; case lfield_style: - G_FLOAT(OFS_RETURN) = l->style-1; + G_FLOAT(OFS_RETURN) = l->style; break; case lfield_angles: VectorCopy(l->angles, G_VECTOR(OFS_RETURN)); @@ -4336,7 +4336,7 @@ static void QCBUILTIN PF_cs_lightstyle (pubprogfuncs_t *prinst, struct globalvar if (prinst->callargc >= 3) //fte is a quakeworld engine VectorCopy(G_VECTOR(OFS_PARM2), rgb); - if ((unsigned)stnum >= MAX_LIGHTSTYLES) + if ((unsigned)stnum >= cl_max_lightstyles) { Con_Printf ("PF_cs_lightstyle: stnum > MAX_LIGHTSTYLES"); return; @@ -4348,7 +4348,7 @@ static void QCBUILTIN PF_getlightstyle (pubprogfuncs_t *prinst, struct globalvar { unsigned int stnum = G_FLOAT(OFS_PARM0); - if (stnum >= MAX_LIGHTSTYLES) + if (stnum >= cl_max_lightstyles) { VectorSet(G_VECTOR(OFS_PARM1), 0, 0, 0); G_INT(OFS_RETURN) = 0; @@ -4366,13 +4366,13 @@ static void QCBUILTIN PF_getlightstylergb (pubprogfuncs_t *prinst, struct global unsigned int stnum = G_FLOAT(OFS_PARM0); int value; //could be float, but that would exceed the precision of R_AnimateLight - if (stnum >= MAX_LIGHTSTYLES) + if (stnum >= MAX_NET_LIGHTSTYLES) { Con_Printf ("PF_getlightstyle: stnum > MAX_LIGHTSTYLES"); return; } - if (!cl_lightstyle[stnum].length) + if (stnum < cl_max_lightstyles || !cl_lightstyle[stnum].length) value = ('m'-'a')*22 * r_lightstylescale.value; else if (cl_lightstyle[stnum].map[0] == '=') value = atof(cl_lightstyle[stnum].map+1)*256*r_lightstylescale.value; diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 91b41bc9..ce849c40 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -606,7 +606,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest, vec_t *bnorm; vec3_t temp; - int stride = lm->width*lm->pixbytes; + int stride; if (!dest) return; @@ -643,7 +643,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest, { case LM_E5BGR9: deluxmap = ((surf->samples - wmodel->lightdata)/4)*3 + wmodel->deluxdata; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; for (i=0 ; isamples - wmodel->lightdata + wmodel->deluxdata; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; for (i=0 ; isamples - wmodel->lightdata)*3 + wmodel->deluxdata; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; for (i=0 ; ipixbytes; - - bnorm = blocknormals[0]; - for (i=0 ; ifmt) { - for (j=0 ; jpixbytes; - bnorm+=3; + stride = (lm->width-smax); + bnorm = blocknormals[0]; + for (i=0 ; iwidth-smax)*4; + bnorm = blocknormals[0]; + for (i=0 ; iwidth-smax)*lm->pixbytes; + bnorm = blocknormals[0]; + for (i=0 ; ipixbytes; + bnorm+=3; + } + } + break; } } @@ -785,7 +836,7 @@ static void Surf_PackRGB16F(void *result, int r, int g, int b, int one) ((unsigned short*)result)[0] = Surf_GenHalf(r / (float)one); ((unsigned short*)result)[1] = Surf_GenHalf(g / (float)one); ((unsigned short*)result)[2] = Surf_GenHalf(b / (float)one); - ((unsigned short*)result)[3] = Surf_GenHalf(1.0);//0x0f<<10; //a standard ieee float should have all but the lead bit set of its exponent, and its mantissa 0. + ((unsigned short*)result)[3] = /*Surf_GenHalf(1.0);*/0x0f<<10; //a standard ieee float should have all but the lead bit set of its exponent, and its mantissa 0. #endif } static void Surf_PackRGB32F(void *result, int r, int g, int b, int one) @@ -1416,7 +1467,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map switch(currentmodel->lightmaps.fmt) { case LM_E5BGR9: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; @@ -1436,7 +1487,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map } break; case LM_RGB8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; @@ -1457,7 +1508,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map break; case LM_L8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction @@ -1536,7 +1587,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map switch(currentmodel->lightmaps.fmt) { case LM_E5BGR9: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction @@ -1550,7 +1601,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map } break; case LM_RGB8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction @@ -1561,7 +1612,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map } break; case LM_L8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction @@ -1713,7 +1764,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh else switch(cl.worldmodel->lightmaps.fmt) { case LM_E5BGR9: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; @@ -1733,7 +1784,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh } break; case LM_RGB8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; @@ -1754,7 +1805,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh break; case LM_L8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction @@ -1818,7 +1869,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh switch(cl.worldmodel->lightmaps.fmt) { case LM_E5BGR9: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction @@ -1832,7 +1883,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh } break; case LM_RGB8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction @@ -1843,7 +1894,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh } break; case LM_L8: - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction @@ -1920,7 +1971,7 @@ void Surf_RenderDynamicLightmaps (msurface_t *fa) } else { - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && fa->styles[maps] != 255 ; + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && fa->styles[maps] != INVALID_LIGHTSTYLE ; maps++) if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] || cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps]) @@ -1963,7 +2014,7 @@ static void Surf_RenderDynamicLightmaps_Worker (model_t *wmodel, msurface_t *fa, } else { - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && fa->styles[maps] != 255 ; + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && fa->styles[maps] != INVALID_LIGHTSTYLE ; maps++) if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] || cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps]) @@ -2934,7 +2985,7 @@ struct webostate_s void *ebomem; size_t idxcount; int numbatches; - int lightstylevalues[MAX_LIGHTSTYLES]; //when using workers that only reprocessing lighting at 10fps, things get too ugly when things go out of sync + int lightstylevalues[MAX_NET_LIGHTSTYLES]; //when using workers that only reprocessing lighting at 10fps, things get too ugly when things go out of sync vec3_t lastpos; @@ -3270,14 +3321,14 @@ void Surf_DrawWorld (void) #ifdef Q1BSPS else if (currentmodel->fromgame == fg_quake || currentmodel->fromgame == fg_halflife) { - int i = MAX_LIGHTSTYLES; + int i = cl_max_lightstyles; if (webostate && !webogenerating) - for (i = 0; i < MAX_LIGHTSTYLES; i++) + for (i = 0; i < cl_max_lightstyles; i++) { if (webostate->lightstylevalues[i] != d_lightstylevalue[i]) break; } - if (webostate && i == MAX_LIGHTSTYLES) + if (webostate && i == cl_max_lightstyles) { } else @@ -3304,7 +3355,7 @@ void Surf_DrawWorld (void) webogenerating->cluster[1] = r_viewcluster2; webogenerating->pvs.buffer = (qbyte*)(webogenerating+1) + sizeof(webogenerating->batches[0])*(currentmodel->numbatches-1); webogenerating->pvs.buffersize = currentmodel->pvsbytes; - for (i = 0; i < MAX_LIGHTSTYLES; i++) + for (i = 0; i < cl_max_lightstyles; i++) webogenerating->lightstylevalues[i] = d_lightstylevalue[i]; Q_strncpyz(webogenerating->dbgid, "webostate", sizeof(webogenerating->dbgid)); COM_AddWork(WG_LOADER, R_GenWorldEBO, webogenerating, NULL, 0, 0); @@ -3630,7 +3681,7 @@ uploadfmt_t Surf_NameToFormat(const char *nam) return PTI_RGB565; //boo hiss if (!Q_strcasecmp(nam, "rgba4444") || !Q_strcasecmp(nam, "rgba4")) return PTI_RGBA4444; //erk - if (!Q_strcasecmp(nam, "rgba5551") || !Q_strcasecmp(nam, "rgba51")) + if (!Q_strcasecmp(nam, "rgba5551") || !Q_strcasecmp(nam, "rgba51") || !Q_strcasecmp(nam, "rgb5a1")) return PTI_RGBA5551; if (!Q_strcasecmp(nam, "argb4444")) return PTI_ARGB4444; @@ -3639,7 +3690,7 @@ uploadfmt_t Surf_NameToFormat(const char *nam) if (!Q_strcasecmp(nam, "rgbx8") || !Q_strcasecmp(nam, "bgrx8") || !Q_strcasecmp(nam, "rgba8") || !Q_strcasecmp(nam, "bgra8")) return PTI_BGRX8; //most common formats... if (!Q_strcasecmp(nam, "rgb8") || !Q_strcasecmp(nam, "bgr8")) - return PTI_RGB8; //generally not recommended + return PTI_RGB8; //generally not recommended (misaligned so the gpu has to compensate) if (!Q_strcasecmp(nam, "l8")) return PTI_L8; if (*nam) @@ -3725,7 +3776,9 @@ int Surf_NewLightmaps(int count, int width, int height, uploadfmt_t fmt, qboolea Image_BlockSizeForEncoding(fmt, &pixbytes, &pixw, &pixh); if (pixw != 1 || pixh != 1) return -1; //compressed formats are unsupported - dfmt = PTI_BGRX8; + dfmt = PTI_A2BGR10; //favour this one, because it tends to be slightly faster. + if (!sh_config.texfmt[dfmt]) + dfmt = PTI_BGRX8; if (!sh_config.texfmt[dfmt]) dfmt = PTI_RGBX8; if (!sh_config.texfmt[dfmt]) @@ -3884,6 +3937,8 @@ void Surf_BuildModelLightmaps (model_t *m) COM_WorkerPartialSync(webogenerating, &webogeneratingstate, true); #endif + R_BumpLightstyles(m->lightmaps.maxstyle); //should only really happen with lazy loading + if (m->submodelof && m->fromgame == fg_quake3) //FIXME: should be all bsp formats { if (m->submodelof->loadstate != MLS_LOADED) @@ -4083,7 +4138,17 @@ void Surf_BuildLightmaps (void) extern model_t *mod_known; extern int mod_numknown; - //make sure the lightstyle values are correct. + int maxstyle; + + //make sure the lightstyle values are correct (and be sure that the sizes cover all models). + for (i = 0, maxstyle=0; i < mod_numknown; i++) + { + m = &mod_known[i]; + if (m->loadstate == MLS_LOADED) + if (maxstyle < m->lightmaps.maxstyle) + maxstyle = m->lightmaps.maxstyle; + } + R_BumpLightstyles(maxstyle); //should only really happen with lazy loading R_AnimateLight(); r_framecount = 1; // no dlightcache diff --git a/engine/client/render.h b/engine/client/render.h index 524ba3ff..d70ab64f 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -531,7 +531,9 @@ typedef struct { unsigned int *offsets; unsigned short *extents; - unsigned char *styles; + unsigned char *styles8; + unsigned short *styles16; + unsigned int stylesperface; unsigned char *shifts; unsigned char defaultshift; } lightmapoverrides_t; @@ -555,7 +557,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b); struct relight_ctx_s; struct llightinfo_s; void LightFace (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, int surfnum); //version that is aware of bsp trees -void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, qbyte surf_styles[4], unsigned int *surf_expsamples, qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale); //special version that doesn't know what a face is or anything. +void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, lightstyleindex_t surf_styles[4], unsigned int *surf_expsamples, qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale); //special version that doesn't know what a face is or anything. struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, struct model_s *model, qboolean shadows, qboolean skiplit); void LightReloadEntities(struct relight_ctx_s *ctx, const char *entstring, qboolean ignorestyles); void LightShutdown(struct relight_ctx_s *ctx, struct model_s *mod); @@ -587,6 +589,7 @@ void R_RegisterRenderer(rendererinfo_t *ri); void R_AnimateLight (void); void R_UpdateHDR(vec3_t org); void R_UpdateLightStyle(unsigned int style, const char *stylestring, float r, float g, float b); +void R_BumpLightstyles(unsigned int maxstyle); //bumps the cl_max_lightstyles array size, if needed. struct texture_s *R_TextureAnimation (int frame, struct texture_s *base); //mostly deprecated, only lingers for rtlights so world only. struct texture_s *R_TextureAnimation_Q2 (struct texture_s *base); //mostly deprecated, only lingers for rtlights so world only. void RQ_Init(void); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 5915cba9..3ff6936b 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -68,6 +68,11 @@ void R_ForceSky_f(void) R_SetSky(Cmd_Argv(1)); } } +static void QDECL R_Lightmap_Format_Changed(struct cvar_s *var, char *oldvalue) +{ + if (qrenderer) + Surf_BuildLightmaps(); +} #ifdef FTE_TARGET_WEB //webgl sucks too much to get a stable framerate without vsync. cvar_t vid_vsync = CVARAF ("vid_vsync", "1", @@ -231,7 +236,7 @@ cvar_t r_replacemodels = CVARFD ("r_replacemodels", IFMINIMAL("","md3 md2") cvar_t r_lightmap_nearest = CVARFD ("gl_lightmap_nearest", "0", CVAR_ARCHIVE, "Use nearest sampling for lightmaps. This will give a more blocky look. Meaningless when gl_lightmap_average is enabled."); cvar_t r_lightmap_average = CVARFD ("gl_lightmap_average", "0", CVAR_ARCHIVE, "Determine lightmap values based upon the center of the polygon. This will give a more buggy look, quite probably."); -cvar_t r_lightmap_format = CVARFD ("r_lightmap_format", "", CVAR_ARCHIVE|CVAR_RENDERERCALLBACK, "Overrides the default texture format used for lightmaps. rgb9e5 is a good choice for HDR."); +cvar_t r_lightmap_format = CVARFCD ("r_lightmap_format", "", CVAR_ARCHIVE, R_Lightmap_Format_Changed, "Overrides the default texture format used for lightmaps. rgb9e5 is a good choice for HDR."); //otherwise it would defeat the point. cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1", diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index ff3c3333..f0e8f18a 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -828,6 +828,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_BACKBUFLEN 1200 +#define lightstyleindex_t unsigned short +#define INVALID_LIGHTSTYLE ((lightstyleindex_t)(~0u)) //the style that's invalid, signifying to stop adding more. + // // per-level limits // @@ -837,7 +840,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //#define MAX_EDICTS ((1<<22)-1) // expandable up to 22 bits #define MAX_EDICTS ((1<<18)-1) // expandable up to 22 bits #endif -#define MAX_LIGHTSTYLES 255 // 8bit. 255 = 'invalid', and thus only 0-254 are the valid indexes. +#define MAX_NET_LIGHTSTYLES (INVALID_LIGHTSTYLE+1) // 16bit. the last index MAY be used to signify an invalid lightmap in the bsp, but is still valid for rtlights. #define MAX_STANDARDLIGHTSTYLES 64 #define MAX_PRECACHE_MODELS 4096 // 14bit. #define MAX_PRECACHE_SOUNDS 2048 // 14bit. diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index f2639c54..8483e32c 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -239,7 +239,7 @@ typedef struct #else #define MAXRLIGHTMAPS 1 //max lightmaps mixed by the renderer (rbsp=4, otherwise 1) #endif -#define MAXQ1LIGHTMAPS 4 +#define MAXQ1LIGHTMAPS 16 typedef struct { short planenum; @@ -250,7 +250,7 @@ typedef struct short texinfo; // lighting info - qbyte styles[MAXQ1LIGHTMAPS]; + qbyte styles[4]; int lightofs; // start of [numstyles*surfsize] samples } dsface_t; typedef struct @@ -263,7 +263,7 @@ typedef struct int texinfo; // lighting info - qbyte styles[MAXQ1LIGHTMAPS]; + qbyte styles[4]; int lightofs; // start of [numstyles*surfsize] samples } dlface_t; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 7984c412..48a17249 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1573,30 +1573,19 @@ Mod_LoadFaces ================= */ #ifndef SERVERONLY -static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboolean lightofsisdouble, lightmapoverrides_t *overrides) +static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, lump_t *lightlump, qboolean lightofsisdouble, bspx_header_t *bspx) { dsface_t *in; msurface_t *out; int i, count, surfnum; int planenum, side; int ti; + int style; unsigned short lmshift, lmscale; char buf[64]; - - if (overrides->offsets) - lmshift = overrides->defaultshift; - else - { - lmscale = atoi(Mod_ParseWorldspawnKey(mod, "lightmap_scale", buf, sizeof(buf))); - if (!lmscale) - lmshift = LMSHIFT_DEFAULT; - else - { - for(lmshift = 0; lmscale > 1; lmshift++) - lmscale >>= 1; - } - } + lightmapoverrides_t overrides = {0}; + overrides.defaultshift = LMSHIFT_DEFAULT; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -1610,6 +1599,21 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboo mod->surfaces = out; mod->numsurfaces = count; + Mod_LoadLighting(mod, bspx, mod_base, lightlump, lightofsisdouble, &overrides); + if (overrides.offsets) + lmshift = overrides.defaultshift; + else + { + lmscale = atoi(Mod_ParseWorldspawnKey(mod, "lightmap_scale", buf, sizeof(buf))); + if (!lmscale) + lmshift = LMSHIFT_DEFAULT; + else + { + for(lmshift = 0; lmscale > 1; lmshift++) + lmscale >>= 1; + } + } + for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); @@ -1642,23 +1646,58 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboo } #endif - if (overrides->shifts) - out->lmshift = overrides->shifts[surfnum]; + if (overrides.shifts) + out->lmshift = overrides.shifts[surfnum]; else out->lmshift = lmshift; CalcSurfaceExtents (mod, out); - if (overrides->extents) + if (overrides.extents) { - out->extents[0] = overrides->extents[surfnum*2+0]; - out->extents[1] = overrides->extents[surfnum*2+1]; + out->extents[0] = overrides.extents[surfnum*2+0]; + out->extents[1] = overrides.extents[surfnum*2+1]; } // lighting info - - for (i=0 ; istyles[i] = in->styles[i]; - if (overrides->offsets) - i = overrides->offsets[surfnum]; + if (overrides.styles16) + { + for (i=0 ; ilightmaps.maxstyle < style) + mod->lightmaps.maxstyle = style; + out->styles[i] = style; + } + } + else if (overrides.styles8) + { + for (i=0 ; ilightmaps.maxstyle < style) + mod->lightmaps.maxstyle = style; + out->styles[i] = style; + } + } + else + { + for (i=0 ; i<4 ; i++) + { + style = in->styles[i]; + if (style == 0xff) + style = INVALID_LIGHTSTYLE; + else if (mod->lightmaps.maxstyle < style) + mod->lightmaps.maxstyle = style; + out->styles[i] = style; + } + } + for ( ; istyles[i] = INVALID_LIGHTSTYLE; + if (overrides.offsets) + i = overrides.offsets[surfnum]; else i = LittleLong(in->lightofs); if (i == -1) @@ -1679,12 +1718,6 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboo out->texturemins[i] = -8192; } } - - if (overrides->extents) - { - for (i=0 ; istyles[i] = overrides->extents[surfnum*4+i]; - } } return true; @@ -4631,22 +4664,18 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole #ifndef SERVERONLY default: { - lightmapoverrides_t overrides = {0}; - overrides.defaultshift = LMSHIFT_DEFAULT; // load into heap noerrors = noerrors && Mod_LoadVertexes (mod, mod_base, &header.lumps[Q2LUMP_VERTEXES]); if (header.version == BSPVERSION_Q2W) /*noerrors = noerrors &&*/ Mod_LoadVertexNormals(mod, bspx, mod_base, &header.lumps[19]); noerrors = noerrors && Mod_LoadEdges (mod, mod_base, &header.lumps[Q2LUMP_EDGES], false); noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]); - if (noerrors) - Mod_LoadLighting (mod, bspx, mod_base, &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W, &overrides); noerrors = noerrors && CModQ2_LoadSurfaces (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO]); noerrors = noerrors && CModQ2_LoadPlanes (mod, mod_base, &header.lumps[Q2LUMP_PLANES]); noerrors = noerrors && CModQ2_LoadTexInfo (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO], loadname); if (noerrors) Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); - noerrors = noerrors && CModQ2_LoadFaces (mod, mod_base, &header.lumps[Q2LUMP_FACES], header.version == BSPVERSION_Q2W, &overrides); + noerrors = noerrors && CModQ2_LoadFaces (mod, mod_base, &header.lumps[Q2LUMP_FACES], &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W, bspx); noerrors = noerrors && Mod_LoadMarksurfaces (mod, mod_base, &header.lumps[Q2LUMP_LEAFFACES], false); noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]); noerrors = noerrors && CModQ2_LoadBrushSides (mod, mod_base, &header.lumps[Q2LUMP_BRUSHSIDES]); diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 0447f8b0..c3a3382b 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -5651,7 +5651,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) { if (br->faces[j].relight && dorelight) { - qbyte styles[4] = {0,255,255,255}; + lightstyleindex_t styles[4] = {0,INVALID_LIGHTSTYLE,INVALID_LIGHTSTYLE,INVALID_LIGHTSTYLE}; int texsize[2] = {br->faces[j].lmextents[0]-1, br->faces[j].lmextents[1]-1}; vec2_t exactmins, exactmaxs; int m, k; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index c8f445b8..cec905e2 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -1952,7 +1952,8 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, //surface code needs to know the overrides. overrides->offsets = offsets; overrides->extents = extents; - overrides->styles = styles; + overrides->styles8 = styles; + overrides->stylesperface = 4; overrides->shifts = shifts; //we're now using this amount of data. @@ -2178,12 +2179,25 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, if (size != loadmodel->numsurfaces * sizeof(int)) overrides->offsets = NULL; } - if (!overrides->styles) - { + if (!overrides->styles8 && !overrides->styles16) + { //16bit per-face lightmap styles index int size; - overrides->styles = BSPX_FindLump(bspx, mod_base, "LMSTYLE", &size); - if (size != loadmodel->numsurfaces * sizeof(qbyte)*MAXQ1LIGHTMAPS) - overrides->styles = NULL; + overrides->styles16 = BSPX_FindLump(bspx, mod_base, "LMSTYLE16", &size); + overrides->stylesperface = size / (sizeof(*overrides->styles16)*loadmodel->numsurfaces); //rounding issues will be caught on the next line... + if (!overrides->stylesperface || size != loadmodel->numsurfaces * sizeof(*overrides->styles16)*overrides->stylesperface) + overrides->styles16 = NULL; + else if (overrides->stylesperface > MAXQ1LIGHTMAPS) + Con_Printf(CON_WARNING "LMSTYLE16 lump provides %i styles, only the first %i will be used.\n", overrides->stylesperface, MAXQ1LIGHTMAPS); + } + if (!overrides->styles8 && !overrides->styles16) + { //16bit per-face lightmap styles index + int size; + overrides->styles8 = BSPX_FindLump(bspx, mod_base, "LMSTYLE", &size); + overrides->stylesperface = size / (sizeof(*overrides->styles8)*loadmodel->numsurfaces); //rounding issues will be caught on the next line... + if (!overrides->stylesperface || size != loadmodel->numsurfaces * sizeof(*overrides->styles8)*overrides->stylesperface) + overrides->styles8 = NULL; + else if (overrides->stylesperface > MAXQ1LIGHTMAPS) + Con_Printf(CON_WARNING "LMSTYLE lump provides %i styles, only the first %i will be used.\n", overrides->stylesperface, MAXQ1LIGHTMAPS); } } @@ -4042,8 +4056,8 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, bspx_header_t *bspx, qbyte *m out->firstedge = LittleLong(inl->firstedge); out->numedges = LittleLong(inl->numedges); tn = LittleLong (inl->texinfo); - for (i=0 ; istyles[i] = inl->styles[i]; + for (i=0 ; istyles) ; i++) + out->styles[i] = (i >= countof(inl->styles) || inl->styles[i]>=MAX_NET_LIGHTSTYLES || inl->styles[i]==255)?INVALID_LIGHTSTYLE:inl->styles[i]; lofs = LittleLong(inl->lightofs); inl++; } @@ -4054,8 +4068,8 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, bspx_header_t *bspx, qbyte *m out->firstedge = LittleLong(ins->firstedge); out->numedges = LittleShort(ins->numedges); tn = LittleShort (ins->texinfo); - for (i=0 ; istyles[i] = ins->styles[i]; + for (i=0 ; istyles) ; i++) + out->styles[i] = (i >= countof(ins->styles) || ins->styles[i]>=MAX_NET_LIGHTSTYLES || ins->styles[i]==255)?INVALID_LIGHTSTYLE:ins->styles[i]; lofs = LittleLong(ins->lightofs); ins++; } @@ -4081,9 +4095,19 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, bspx_header_t *bspx, qbyte *m out->lmshift = lmshift; if (overrides.offsets) lofs = overrides.offsets[surfnum]; - if (overrides.styles) - for (i=0 ; istyles[i] = overrides.styles[surfnum*4+i]; + if (overrides.styles16) + { + for (i=0 ; istyles) ; i++) + out->styles[i] = (i>=overrides.stylesperface)?INVALID_LIGHTSTYLE:overrides.styles16[surfnum*overrides.stylesperface+i]; + } + else if (overrides.styles8) + { + for (i=0 ; istyles) ; i++) + out->styles[i] = (i>=overrides.stylesperface)?INVALID_LIGHTSTYLE:((overrides.styles8[surfnum*overrides.stylesperface+i]==255)?~0u:overrides.styles8[surfnum*overrides.stylesperface+i]); + } + for (i=0 ; istyles) && out->styles[i] != INVALID_LIGHTSTYLE; i++) + if (loadmodel->lightmaps.maxstyle < out->styles[i]) + loadmodel->lightmaps.maxstyle = out->styles[i]; CalcSurfaceExtents (loadmodel, out); if (lofs != (unsigned int)-1) diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 6493705d..2980582f 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -140,7 +140,7 @@ typedef struct batch_s image_t *envmap; short lightmap[MAXRLIGHTMAPS]; /*used for shader lightmap textures*/ - unsigned char lmlightstyle[MAXRLIGHTMAPS]; + lightstyleindex_t lmlightstyle[MAXRLIGHTMAPS]; unsigned char vtlightstyle[MAXRLIGHTMAPS]; unsigned int maxmeshes; /*not used by backend*/ @@ -444,7 +444,7 @@ typedef struct msurface_s //static lighting int lightmaptexturenums[MAXRLIGHTMAPS]; //rbsp+fbsp formats have multiple lightmaps - qbyte styles[MAXQ1LIGHTMAPS]; + lightstyleindex_t styles[MAXQ1LIGHTMAPS]; qbyte vlstyles[MAXRLIGHTMAPS]; int cached_light[MAXQ1LIGHTMAPS]; // values currently used in lightmap int cached_colour[MAXQ1LIGHTMAPS]; // values currently used in lightmap @@ -1026,6 +1026,7 @@ typedef struct model_s int width; //x size of lightmaps int height; //y size of lightmaps int surfstyles; //numbers of style per surface. + int maxstyle; //highest (valid) style used (cl_max_lightstyles must be 1+ higher). enum { //vanilla used byte values, with 255 being a value of about 2. //float/hdr formats use 1 to mean 1, however. diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index c860da00..9f660b48 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -28,13 +28,25 @@ extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; extern cvar_t r_hdr_irisadaptation, r_hdr_irisadaptation_multiplier, r_hdr_irisadaptation_minvalue, r_hdr_irisadaptation_maxvalue, r_hdr_irisadaptation_fade_down, r_hdr_irisadaptation_fade_up; int r_dlightframecount; -int d_lightstylevalue[256]; // 8.8 fraction of base light value +int d_lightstylevalue[MAX_NET_LIGHTSTYLES]; // 8.8 fraction of base light value +void R_BumpLightstyles(unsigned int maxstyle) +{ + int style = cl_max_lightstyles; + if (maxstyle >= style) + { + Z_ReallocElements((void**)&cl_lightstyle, &cl_max_lightstyles, maxstyle+1, sizeof(*cl_lightstyle)); + for (; style < cl_max_lightstyles; style++) + VectorSet(cl_lightstyle[style].colours, 1,1,1); + } +} void R_UpdateLightStyle(unsigned int style, const char *stylestring, float r, float g, float b) { - if (style >= MAX_LIGHTSTYLES) + if (style >= MAX_NET_LIGHTSTYLES) return; + R_BumpLightstyles(style); + if (!stylestring) stylestring = ""; @@ -109,7 +121,7 @@ void R_AnimateLight (void) i = (int)f; f -= i; //this can require updates at 1000 times a second.. Depends on your framerate of course - for (j=0 ; jstyle) + if (light->style>=0 && light->style < countof(d_lightstylevalue)) { - colscale *= d_lightstylevalue[light->style-1]/255.0f; + colscale *= d_lightstylevalue[light->style]/255.0f; } VectorSubtract (light->origin, r_origin, v); @@ -527,11 +539,11 @@ void R_GenDlightMesh(struct batch_s *batch) int lightflags = batch->surf_count; VectorCopy(l->color, colour); - if (l->style) + if (l->style>=0 && l->style < cl_max_lightstyles) { - colour[0] *= cl_lightstyle[l->style-1].colours[0] * d_lightstylevalue[l->style-1]/255.0f; - colour[1] *= cl_lightstyle[l->style-1].colours[1] * d_lightstylevalue[l->style-1]/255.0f; - colour[2] *= cl_lightstyle[l->style-1].colours[2] * d_lightstylevalue[l->style-1]/255.0f; + colour[0] *= cl_lightstyle[l->style].colours[0] * d_lightstylevalue[l->style]/255.0f; + colour[1] *= cl_lightstyle[l->style].colours[1] * d_lightstylevalue[l->style]/255.0f; + colour[2] *= cl_lightstyle[l->style].colours[2] * d_lightstylevalue[l->style]/255.0f; } else { @@ -1127,7 +1139,7 @@ qboolean R_ImportRTLights(const char *entlump) dl->flags |= LFLAG_REALTIMEMODE; dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_FLASHBLEND:0; dl->flags |= (pflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0; - dl->style = style+1; + dl->style = style; VectorCopy(colourscales, dl->lightcolourscales); //handle spotlights. @@ -1348,7 +1360,7 @@ qboolean R_LoadRTLights(void) else dl->cubetexture = r_nulltex; - dl->style = style+1; + dl->style = style; dl->customstyle = (*customstyle)?Z_StrDup(customstyle):NULL; } file = end+1; @@ -1402,7 +1414,7 @@ static void R_SaveRTLights_f(void) "%i", (light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], - light->style-1); + light->style); if (ver > 0) VFS_PRINTF(f, " \"%s\" %f %f %f %f", light->cubemapname, light->corona, ang[0], ang[1], ang[2]); if (ver > 1) @@ -1457,7 +1469,7 @@ void R_StaticEntityToRTLight(int i) dl->flags |= (state->lightpflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0; if (state->lightpflags & PFLAGS_CORONA) dl->corona = 1; - dl->style = state->lightstyle+1; + dl->style = state->lightstyle; if (state->lightpflags & PFLAGS_FULLDYNAMIC) { dl->lightcolourscales[0] = r_editlights_import_ambient.value; @@ -1612,7 +1624,7 @@ static int R_EditLight(dlight_t *dl, const char *cmd, int argc, const char *x, c else if (!strcmp(cmd, "radiusscale") || !strcmp(cmd, "sizescale")) dl->radius *= atof(x); else if (!strcmp(cmd, "style")) - dl->style = atoi(x)+1; //fte's styles are internally 1-based, with 0 being a null style that ignores lightstyles entirely, which admittedly isn't often used. + dl->style = atoi(x); else if (!strcmp(cmd, "stylestring")) { Z_Free(dl->customstyle); @@ -1690,7 +1702,7 @@ void R_EditLights_DrawInfo(void) ,dl->origin[0],dl->origin[1],dl->origin[2] ,dl->angles[0],dl->angles[1],dl->angles[2] ,dl->color[0],dl->color[1],dl->color[2] - ,dl->radius, dl->corona, dl->style-1, dl->customstyle?dl->customstyle:"---" + ,dl->radius, dl->corona, dl->style, dl->customstyle?dl->customstyle:"---" ,((dl->flags&LFLAG_NOSHADOWS)?"no":"yes"), dl->cubemapname, dl->coronascale ,dl->lightcolourscales[0], dl->lightcolourscales[1], dl->lightcolourscales[2] ,((dl->flags&LFLAG_NORMALMODE)?"yes":"no"), ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no") @@ -1878,7 +1890,7 @@ static void R_EditLights_Edit_f(void) Con_Printf("Colour : ^[%f %f %f\\type\\r_editlights_edit avel %g %g %g^]\n", dl->color[0],dl->color[1],dl->color[2], dl->color[0],dl->color[1],dl->color[2]); Con_Printf("Radius : ^[%f\\type\\r_editlights_edit radius %g^]\n", dl->radius, dl->radius); Con_Printf("Corona : ^[%f\\type\\r_editlights_edit corona %g^]\n", dl->corona, dl->corona); - Con_Printf("Style : ^[%i\\type\\r_editlights_edit style %i^]\n", dl->style-1, dl->style-1); + Con_Printf("Style : ^[%i\\type\\r_editlights_edit style %i^]\n", dl->style, dl->style); Con_Printf("Style String : ^[%s\\type\\r_editlights_edit stylestring %s^]\n", dl->customstyle?dl->customstyle:"---", dl->customstyle?dl->customstyle:""); Con_Printf("Shadows : ^[%s\\type\\r_editlights_edit shadows %s^]\n", ((dl->flags&LFLAG_NOSHADOWS)?"no":"yes"), ((dl->flags&LFLAG_NOSHADOWS)?"no":"yes")); Con_Printf("Cubemap : ^[\"%s\"\\type\\r_editlights_edit cubemap \"%s\"^]\n", dl->cubemapname, dl->cubemapname); @@ -1968,7 +1980,7 @@ static void R_EditLights_Spawn_f(void) VectorCopy(r_editlights_cursor, dl->origin); dl->radius = 200; - dl->style = 1; //0... gah. match DP's results. + dl->style = 0; //styled, but mostly static (we could use -1, but mneh). dl->lightcolourscales[0] = 0; dl->lightcolourscales[1] = 1; dl->lightcolourscales[2] = 1; @@ -2161,7 +2173,7 @@ static char *r_editlights_current_style(void) return ""; dl = &cl_dlights[i]; - Q_snprintfz (macro_buf, sizeof(macro_buf), "%i", dl->style-1); + Q_snprintfz (macro_buf, sizeof(macro_buf), "%i", dl->style); return macro_buf; } static char *r_editlights_current_shadows(void) @@ -2509,7 +2521,7 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) { case LM_E5BGR9: lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { unsigned int l = *(unsigned int*)lightmap; scale = d_lightstylevalue[surf->styles[maps]]; @@ -2522,7 +2534,7 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) break; case LM_RGB8: lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; r += max3(lightmap[0],lightmap[1],lightmap[2]) * scale; @@ -2531,7 +2543,7 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) break; case LM_L8: lightmap += dt * ((surf->extents[0]>>surf->lmshift)+1) + ds; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; r += *lightmap * scale; @@ -2683,7 +2695,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2; deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<4; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { unsigned int lm = *(unsigned int*)lightmap; scale = d_lightstylevalue[surf->styles[maps]]*overbright; @@ -2708,7 +2720,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; @@ -2731,7 +2743,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds); deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; @@ -2758,7 +2770,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t { case LM_E5BGR9: lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { unsigned int lm = *(unsigned int*)lightmap; scale = d_lightstylevalue[surf->styles[maps]]*overbright; @@ -2774,7 +2786,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t break; case LM_RGB8: lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; @@ -2788,7 +2800,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t break; case LM_L8: lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds); - for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) + for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 4ea86692..41cf12ce 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -3791,11 +3791,11 @@ void Sh_CalcPointLight(vec3_t point, vec3_t light) colour[0] = dl->color[0]; colour[1] = dl->color[1]; colour[2] = dl->color[2]; - if (dl->style) + if (dl->style>=0 && dl->stylestyle-1].colours[0] * d_lightstylevalue[dl->style-1]/255.0f; - colour[1] *= cl_lightstyle[dl->style-1].colours[1] * d_lightstylevalue[dl->style-1]/255.0f; - colour[2] *= cl_lightstyle[dl->style-1].colours[2] * d_lightstylevalue[dl->style-1]/255.0f; + colour[0] *= cl_lightstyle[dl->style].colours[0] * d_lightstylevalue[dl->style]/255.0f; + colour[1] *= cl_lightstyle[dl->style].colours[1] * d_lightstylevalue[dl->style]/255.0f; + colour[2] *= cl_lightstyle[dl->style].colours[2] * d_lightstylevalue[dl->style]/255.0f; } else { @@ -3924,11 +3924,11 @@ void Sh_DrawLights(qbyte *vis) colour[1] *= strength; colour[2] *= strength; } - if (dl->style) + if (dl->style>=0 && dl->style < cl_max_lightstyles) { - colour[0] *= cl_lightstyle[dl->style-1].colours[0] * d_lightstylevalue[dl->style-1]/255.0f; - colour[1] *= cl_lightstyle[dl->style-1].colours[1] * d_lightstylevalue[dl->style-1]/255.0f; - colour[2] *= cl_lightstyle[dl->style-1].colours[2] * d_lightstylevalue[dl->style-1]/255.0f; + colour[0] *= cl_lightstyle[dl->style].colours[0] * d_lightstylevalue[dl->style]/255.0f; + colour[1] *= cl_lightstyle[dl->style].colours[1] * d_lightstylevalue[dl->style]/255.0f; + colour[2] *= cl_lightstyle[dl->style].colours[2] * d_lightstylevalue[dl->style]/255.0f; } else { diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 34b7075a..3e03cbe4 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -322,7 +322,6 @@ extern unsigned int r_viewcontents; int r_viewarea; extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; //q2 extern texture_t *r_notexture_mip; -extern int d_lightstylevalue[256]; // 8.8 fraction of base light value extern texid_t netgraphtexture; // netgraph texture extern shader_t *netgraphshader; diff --git a/engine/gl/ltface.c b/engine/gl/ltface.c index 709e3022..ea7fd00c 100644 --- a/engine/gl/ltface.c +++ b/engine/gl/ltface.c @@ -778,7 +778,7 @@ static unsigned int PackE5BRG9(vec3_t rgb) LightFace ============ */ -void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, qbyte surf_styles[MAXQ1LIGHTMAPS], unsigned int *surf_expsamples, qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale) +void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, lightstyleindex_t surf_styles[MAXQ1LIGHTMAPS], unsigned int *surf_expsamples, qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale) { int s, t; int i,c,ch; @@ -827,7 +827,7 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, qbyte surf_s i = 0; #ifndef UTILITY - for (; surf_styles[i] != 255 && i < MAXQ1LIGHTMAPS; i++) + for (; surf_styles[i] != INVALID_LIGHTSTYLE && i < MAXQ1LIGHTMAPS; i++) { l->lightstyles[i] = surf_styles[i]; memset(&l->lightmaps[i], 0, sizeof(l->lightmaps[i][0])*l->numsurfpt); @@ -836,7 +836,7 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, qbyte surf_s #endif l->numlightstyles = i; for ( ; ilightstyles[i] = 255; + l->lightstyles[i] = INVALID_LIGHTSTYLE; // // cast all lights diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 902eeb93..df8e0f36 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -107,6 +107,7 @@ static cvar_t sv_addon[MAXADDONS]; static char cvargroup_progs[] = "Progs variables"; static evalc_t evalc_idealpitch, evalc_pitch_speed; +static void PR_Lightstyle_f(void); qboolean ssqc_deprecated_warned; int pr_teamfield; @@ -859,11 +860,14 @@ void PR_Deinit(void) sv.world.progs = NULL; svprogfuncs=NULL; - for (i = 0; i < MAX_LIGHTSTYLES; i++) + for (i = 0; i < sv.maxlightstyles; i++) { - BZ_Free((void*)sv.strings.lightstyles[i]); - sv.strings.lightstyles[i] = NULL; + BZ_Free((void*)sv.lightstyles[i].str); + sv.lightstyles[i].str = NULL; } + BZ_Free(sv.lightstyles); + sv.lightstyles = NULL; + sv.maxlightstyles = 0; } World_Destroy(&sv.world); @@ -1547,6 +1551,8 @@ void PR_Init(void) Cmd_AddCommand ("extensionlist_ssqc", PR_SVExtensionList_f); Cmd_AddCommand ("pr_dumpplatform", PR_DumpPlatform_f); + Cmd_AddCommand ("sv_lightstyle", PR_Lightstyle_f); + /* #ifdef _DEBUG Cmd_AddCommand ("svtestprogs", QCLibTest); @@ -4649,7 +4655,7 @@ void QCBUILTIN PF_applylightstyle(int style, const char *val, vec3_t rgb) client_t *client; int j; - if (style < 0 || style >= MAX_LIGHTSTYLES) + if (style < 0 || style >= MAX_NET_LIGHTSTYLES) { Con_Printf("WARNING: Bad lightstyle %i.\n", style); return; @@ -4657,14 +4663,16 @@ void QCBUILTIN PF_applylightstyle(int style, const char *val, vec3_t rgb) if (strlen(val) >= 64) Con_Printf("WARNING: Style string is longer than standard (%i). Some clients could crash.\n", 63); + if (style+1 > sv.maxlightstyles) + Z_ReallocElements((void**)&sv.lightstyles, &sv.maxlightstyles, style+1, sizeof(*sv.lightstyles)); // change the string in sv - if (sv.strings.lightstyles[style]) - BZ_Free((void*)sv.strings.lightstyles[style]); - sv.strings.lightstyles[style] = Z_StrDup(val); + if (sv.lightstyles[style].str) + BZ_Free((void*)sv.lightstyles[style].str); + sv.lightstyles[style].str = Z_StrDup(val); #ifdef PEXT_LIGHTSTYLECOL - VectorCopy(rgb, sv.lightstylecolours[style]); + VectorCopy(rgb, sv.lightstyles[style].colours); #endif // send message to all clients on this server @@ -4675,58 +4683,13 @@ void QCBUILTIN PF_applylightstyle(int style, const char *val, vec3_t rgb) { if (client->controller) continue; - if ( client->state == cs_spawned ) - { - if (style >= MAX_STANDARDLIGHTSTYLES) //only bug out clients if the styles are needed - if (!*val) - continue; -#ifdef PEXT_LIGHTSTYLECOL - if ((client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (rgb[0] != 1 || rgb[1] != 1 || rgb[2] != 1)) - { - ClientReliableWrite_Begin (client, svcfte_lightstylecol, 3+6+strlen(val)+1); - ClientReliableWrite_Byte (client, style); - ClientReliableWrite_Char (client, 0x87); - ClientReliableWrite_Short (client, rgb[0]*1024); - ClientReliableWrite_Short (client, rgb[1]*1024); - ClientReliableWrite_Short (client, rgb[2]*1024); - ClientReliableWrite_String (client, val); - } - else -#endif - { - ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3); - ClientReliableWrite_Byte (client, style); - ClientReliableWrite_String (client, val); - } - } + if (client->state == cs_spawned) + SV_SendLightstyle(client, NULL, style, false); } #ifdef MVD_RECORDING if (sv.mvdrecording) - { - if (style < MAX_STANDARDLIGHTSTYLES || *val) - { - sizebuf_t *msg = MVDWrite_Begin(dem_all, 0, 3+6+strlen(val)+1); -#ifdef PEXT_LIGHTSTYLECOL - if ((demo.recorder.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (rgb[0] != 1 || rgb[1] != 1 || rgb[2] != 1)) - { - MSG_WriteByte (msg, svcfte_lightstylecol); - MSG_WriteByte (msg, style); - MSG_WriteChar (msg, 0x87); - MSG_WriteShort (msg, rgb[0]*1024); - MSG_WriteShort (msg, rgb[1]*1024); - MSG_WriteShort (msg, rgb[2]*1024); - MSG_WriteString (msg, val); - } - else -#endif - { - MSG_WriteByte (msg, svc_lightstyle); - MSG_WriteByte (msg, style); - MSG_WriteString (msg, val); - } - } - } + SV_SendLightstyle(&demo.recorder, NULL, style, true); #endif } @@ -4754,35 +4717,65 @@ static void QCBUILTIN PF_lightstyle (pubprogfuncs_t *prinst, struct globalvars_s PF_applylightstyle(style, val, rgb); } +static void PR_Lightstyle_f(void) +{ + int style = atoi(Cmd_Argv(1)); + if (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM) + Con_TPrintf ("not supported in the current game mode.\n"); + else if (!SV_MayCheat()) + Con_TPrintf ("Please set sv_cheats 1 and restart the map first.\n"); + else if (Cmd_Argc() <= 2) + { + if (style >= 0 && style < sv.maxlightstyles && Cmd_Argc() >= 2) + Con_Printf("Style %i: %s %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]); + else for (style = 0; style < sv.maxlightstyles; style++) + if (sv.lightstyles[style].str) + Con_Printf("Style %i: %s %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]); + } + else + { + vec3_t rgb = {1,1,1}; + if (Cmd_Argc() > 5) + { + rgb[0] = atof(Cmd_Argv(3)); + rgb[1] = atof(Cmd_Argv(4)); + rgb[2] = atof(Cmd_Argv(5)); + } + else if (Cmd_Argc() > 3) + rgb[0] = rgb[1] = rgb[2] = atof(Cmd_Argv(3)); + PF_applylightstyle(style, Cmd_Argv(2), rgb); + } +} + static void QCBUILTIN PF_getlightstyle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { unsigned int style = G_FLOAT(OFS_PARM0); - if (style >= countof(sv.strings.lightstyles)) + if (style >= sv.maxlightstyles) { VectorSet(G_VECTOR(OFS_PARM1), 0, 0, 0); G_INT(OFS_RETURN) = 0; } else { - VectorCopy(sv.lightstylecolours[style], G_VECTOR(OFS_PARM1)); - if (!sv.strings.lightstyles[style]) + VectorCopy(sv.lightstyles[style].colours, G_VECTOR(OFS_PARM1)); + if (!sv.lightstyles[style].str) G_INT(OFS_RETURN) = 0; else - RETURN_TSTRING(sv.strings.lightstyles[style]); + RETURN_TSTRING(sv.lightstyles[style].str); } } static void QCBUILTIN PF_getlightstylergb (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { unsigned int style = G_FLOAT(OFS_PARM0); int value; - if (!sv.strings.lightstyles[style]) + if (style >= sv.maxlightstyles || !sv.lightstyles[style].str) value = ('m'-'a')*22; - else if (sv.strings.lightstyles[style][0] == '=') - value = atof(sv.strings.lightstyles[style]+1)*256; + else if (sv.lightstyles[style].str[0] == '=') + value = atof(sv.lightstyles[style].str+1)*256; else - value = sv.strings.lightstyles[style][max(0,(int)(sv.time*10)) % strlen(sv.strings.lightstyles[style])] - 'a'; - VectorScale(sv.lightstylecolours[style], value*(1.0/256), G_VECTOR(OFS_RETURN)); + value = sv.lightstyles[style].str[max(0,(int)(sv.time*10)) % strlen(sv.lightstyles[style].str)] - 'a'; + VectorScale(sv.lightstyles[style].colours, value*(1.0/256), G_VECTOR(OFS_RETURN)); } #ifdef HEXEN2 @@ -4790,12 +4783,12 @@ static void QCBUILTIN PF_lightstylevalue (pubprogfuncs_t *prinst, struct globalv { int style; style = G_FLOAT(OFS_PARM0); - if(style < 0 || style >= MAX_LIGHTSTYLES || !sv.strings.lightstyles[style]) + if(style < 0 || style >= sv.maxlightstyles || !sv.lightstyles[style].str || !*sv.lightstyles[style].str) { G_FLOAT(OFS_RETURN) = 0; return; } - G_FLOAT(OFS_RETURN) = *sv.strings.lightstyles[style] - 'a'; + G_FLOAT(OFS_RETURN) = *sv.lightstyles[style].str - 'a'; } static void QCBUILTIN PF_lightstylestatic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index 65b1c506..57fbf8f8 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -253,8 +253,8 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldentity(tag_entity,NULL)\ comfieldfloat(tag_index,NULL)\ comfieldfloat(skeletonindex,"This object serves as a container for the skeletal bone states used to override the animation data.") /*FTE_CSQC_SKELETONOBJECTS*/\ - comfieldvector(colormod,"Provides a colour tint for the entity.")\ - comfieldvector(glowmod,NULL)\ + comfieldvector(colormod,"Provides a colour tint for the entity (does not affect fullbrights).")\ + comfieldvector(glowmod,"Scaler for an entity's fullbright textures.")\ comfieldvector(gravitydir,"Specifies the direction in which gravity acts. Must be normalised. '0 0 0' also means down. Use '0 0 1' if you want the player to be able to run on ceilings.")\ comfieldfunction(camera_transform,".vector(vector org, vector ang)", "Provides portal transform information for portal surfaces attached to this entity. Also used to open up pvs in ssqc.")\ comfieldfloat(pmove_flags,NULL)/*EXT_CSQC_1*/\ @@ -294,9 +294,9 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldentity(viewmodelforclient,"This entity will be sent only to the player named by this field, and this entity will be attached to the player's view as an additional weapon model.")/*DP_ENT_VIEWMODEL*/\ comfieldentity(exteriormodeltoclient,"This entity will be invisible to the player named by this field, except in mirrors or mirror-like surfaces, where it will be visible as normal. It may still cast shadows as normal, and generate lights+particles, depending on client settings. Does not affect how other players see the entity.")\ svextqcfield_clientcamera\ - comfieldfloat(glow_size,NULL)\ - comfieldfloat(glow_color,NULL)\ - comfieldfloat(glow_trail,NULL)\ + comfieldfloat(glow_size,"Some outdated particle trail thing.")\ + comfieldfloat(glow_color,"Some outdated particle trail thing.")\ + comfieldfloat(glow_trail,"Some outdated particle trail thing.")\ comfieldfloat(traileffectnum,"This should be set to the result of particleeffectnum, in order to attach a custom trail effect to an entity as it moves.")/*DP_ENT_TRAILEFFECTNUM*/\ comfieldfloat(emiteffectnum,"This should be set to the result of particleeffectnum, in order to continually spawn particles in the direction that this entity faces.")/*DP_ENT_TRAILEFFECTNUM*/\ /*comfieldfloat(baseframe,"Specifies the current frame(group) to use for the lower (numerically) bones of a skeletal model. The basebone field specifies the bone where the regular frame field takes over.")*/ /*FTESS_QC_BASEFRAME*/\ @@ -350,9 +350,9 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(entnum,"This is the number of the entity that the ssqc is using.") \ comfieldfloat(frame2,"This is typically the old frame of the entity. if lerpfrac is 1, .frame will be ignored and .frame2 will be used solely. lerpfrac 0.5 will give an even 50/50 blend.") /*EXT_CSQC_1*/\ comfieldfloat(frame2time,".frame2 equivelent of frame1time.") /*EXT_CSQC_1*/\ - comfieldfloat(lerpfrac,"The weight of .frame2. A value of 0 means the entity will animate using only .frame, while 1 would exclusively be .frame2. As this value is incremented, more of frame2 will be used. If you wish to use .frame2 as the 'old' frame, it is generally recommended to start this field with the value 1, to decrement it by frametime, and when it drops below 0 add 1 to it and update .frame2 and .frame to lerp into the new frame.") /*EXT_CSQC_1*/\ + comfieldfloat(lerpfrac,"The weight of .frame2 (with the weight of .frame being inferred). A value of 0 normally means the entity will animate using only .frame, while 1 would exclusively be .frame2. As this value is incremented, more of frame2 will be used. If you wish to use .frame2 as the 'old' frame, it is generally recommended to start this field with the value 1, to decrement it by frametime, and when it drops below 0 add 1 to it and update .frame2 and .frame to lerp into the new frame.") /*EXT_CSQC_1*/\ frame34fields \ - comfieldfloat(renderflags,NULL)\ + comfieldfloat(renderflags,"Matches to the RF_* flags, read during addentity/addentities.")\ comfieldfloat(forceshader,"Contains a shader handle used to replace all surfaces upon the entity.")/*FTE_CSQC_SHADERS*/\ \ comfieldfloat(baseframe2,"See basebone") /*FTE_CSQC_BASEFRAME*/\ diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 592d6c0a..82093226 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -97,20 +97,24 @@ pbool PDECL SV_ExtendedSaveData(pubprogfuncs_t *progfuncs, void *loadctx, const { //lightstyle N "STYLESTRING" 1 1 1 l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false; idx = atoi(token); - if (idx >= countof(sv.strings.lightstyles)) - return false; //unsupported index. + if (idx >= sv.maxlightstyles) + { + if (idx >= MAX_NET_LIGHTSTYLES) + return false; //unsupported index. + Z_ReallocElements((void**)&sv.lightstyles, &sv.maxlightstyles, idx+1, sizeof(*sv.lightstyles)); + } l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false; - if (sv.strings.lightstyles[idx]) - Z_Free((char*)sv.strings.lightstyles[idx]); - sv.strings.lightstyles[idx] = Z_StrDup(token); - sv.lightstylecolours[idx][0] = sv.lightstylecolours[idx][1] = sv.lightstylecolours[idx][2] = 1.0; + if (sv.lightstyles[idx].str) + Z_Free((char*)sv.lightstyles[idx].str); + sv.lightstyles[idx].str = Z_StrDup(token); + sv.lightstyles[idx].colours[0] = sv.lightstyles[idx].colours[1] = sv.lightstyles[idx].colours[2] = 1.0; l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false; - sv.lightstylecolours[idx][0] = atof(token); + sv.lightstyles[idx].colours[0] = atof(token); l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false; - sv.lightstylecolours[idx][1] = atof(token); + sv.lightstyles[idx].colours[1] = atof(token); l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false; - sv.lightstylecolours[idx][2] = atof(token); + sv.lightstyles[idx].colours[2] = atof(token); } else if (!strcmp(token, "model_precache") || !strcmp(token, "model")) { //model_precache N "MODELNAME" @@ -352,18 +356,21 @@ static qboolean SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version) // load the light styles lstyles = 64; + if (lstyles > sv.maxlightstyles) + Z_ReallocElements((void**)&sv.lightstyles, &sv.maxlightstyles, lstyles, sizeof(*sv.lightstyles)); for (i=0 ; i MAX_LIGHTSTYLES) + if (numstyles > MAX_NET_LIGHTSTYLES) { VFS_CLOSE (f); Con_Printf ("load failed - invalid number of lightstyles\n"); return false; } - for (i = 0; i= CACHEGAME_VERSION_VERBOSE) { char buf[8192]; - for (i=0 ; i= MAX_STANDARDLIGHTSTYLES) - if (!sv.strings.lightstyles[i]) - continue; -#ifdef PEXT_LIGHTSTYLECOL - if ((demo.recorder.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (sv.lightstylecolours[i][0]!=1||sv.lightstylecolours[i][1]!=1||sv.lightstylecolours[i][2]!=1) && sv.strings.lightstyles[i]) - { - MSG_WriteByte (&buf, svcfte_lightstylecol); - MSG_WriteByte (&buf, (unsigned char)i); - MSG_WriteByte (&buf, 0x87); - MSG_WriteShort(&buf, sv.lightstylecolours[i][0]*1024); - MSG_WriteShort(&buf, sv.lightstylecolours[i][1]*1024); - MSG_WriteShort(&buf, sv.lightstylecolours[i][2]*1024); - MSG_WriteString (&buf, sv.strings.lightstyles[i]); - } - else -#endif - { - MSG_WriteByte (&buf, svc_lightstyle); - MSG_WriteByte (&buf, (unsigned char)i); - MSG_WriteString (&buf, sv.strings.lightstyles[i]); - } - } + for (i=0 ; ixv->dimension_seen, channel, sample, volume, attenuation, pitchadj, timeofs, chflags); } + + +void SV_SendLightstyle(client_t *cl, sizebuf_t *forcemsg, int style, qboolean initial) +{ + sizebuf_t *msg; + const char *stylestring = (style < sv.maxlightstyles)?sv.lightstyles[style].str:NULL; + float *stylecolor = (style < sv.maxlightstyles)?sv.lightstyles[style].colours:vec3_origin; + int flags = 0; + int sz; + + //don't crash old clients unless there's a good reason to do so. + //new clients are expected to reinitialise their styles to empty on map changes. + if (style >= MAX_STANDARDLIGHTSTYLES && initial && !stylestring) + return; + + if (style > 255) + flags |= 0x40; + if (stylestring && (stylecolor[0]!=1||stylecolor[1]!=1||stylecolor[2]!=1)) + { + if (stylecolor[0]!=0) + { + flags |= 1; + if (stylecolor[0]!=1) + flags |= 0x80|7; + } + if (stylecolor[1]!=0) + { + flags |= 2; + if (stylecolor[1]!=1) + flags |= 0x80|7; + } + if (stylecolor[2]!=0) + { + flags |= 4; + if (stylecolor[2]!=1) + flags |= 0x80|7; + } + } + else + flags |= 7; + //flags |= 0x08; + //flags |= 0x10; + //flags |= 0x20; + + if (!(cl->fteprotocolextensions & PEXT_LIGHTSTYLECOL)) + { //if they don't support it then just drop the extra colours, so long as it still makes sense. + if ((flags & ~0x87u) || (ISNQCLIENT(cl) && !ISDPCLIENT(cl) && !cl->fteprotocolextensions2)) + { + char *text = va("//ls %i \"%s\" %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]); + if (forcemsg) + msg = forcemsg; + else + msg = ClientReliable_StartWrite(cl, 2+strlen(text)); + MSG_WriteByte (msg, svc_stufftext); + MSG_WriteString (msg, text); + if (!forcemsg) + ClientReliable_FinishWrite(cl); + return; //erk, can't handle this! + } + flags = 7; + } + + if (forcemsg) + msg = forcemsg; + else + { + sz = 2; + if (flags != 7) + sz+=1; + if (flags & 0x40) + sz+=1; + if (flags & 0x80u) + sz+=3*2; //rough overestimate + sz += (stylestring?strlen(stylestring):0) + 1; + msg = ClientReliable_StartWrite(cl, sz); + } + + MSG_WriteByte(msg, (flags != 7)?svcfte_lightstylecol:svc_lightstyle); + MSG_WriteByte (msg, style&0xffu); + if (flags != 7) + MSG_WriteByte(msg, flags); + if (flags & 0x40) //16bit style indexes + MSG_WriteByte (msg, style>>8); + if (flags & 0x80u) + { //rich style tints + if (flags & 1) + MSG_WriteShort (msg, bound(-0x7fff, stylecolor[0]*1024, 0x7fff)); + if (flags & 2) + MSG_WriteShort (msg, bound(-0x7fff, stylecolor[1]*1024, 0x7fff)); + if (flags & 4) + MSG_WriteShort (msg, bound(-0x7fff, stylecolor[2]*1024, 0x7fff)); + } + MSG_WriteString (msg, stylestring); + + if (!forcemsg) + ClientReliable_FinishWrite(cl); +} + /* =============================================================================== diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 8ae0aa5e..d6ace095 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -38,7 +38,7 @@ void QDECL SV_NQPhysicsUpdate(cvar_t *var, char *oldvalue) { if (!strcmp(var->string, "auto") || !strcmp(var->string, "")) { //prediction requires nq physics, so use it by default in multiplayer. - if (progstype == PROG_QW || (!isDedicated && sv.allocated_client_slots > 1)) + if (progstype <= PROG_QW || (!isDedicated && sv.allocated_client_slots > 1)) var->ival = 0; else var->ival = 1; @@ -1855,7 +1855,7 @@ void SVQW_Spawn_f (void) #endif // send all current light styles - for (i=0 ; i= MAX_STANDARDLIGHTSTYLES) - if (!sv.strings.lightstyles[i]) - continue; -#ifdef PEXT_LIGHTSTYLECOL - if ((host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (sv.lightstylecolours[i][0]!=1||sv.lightstylecolours[i][1]!=1||sv.lightstylecolours[i][2]!=1) && sv.strings.lightstyles[i]) - { - ClientReliableWrite_Begin (host_client, svcfte_lightstylecol, - 10 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1)); - ClientReliableWrite_Byte (host_client, (char)i); - ClientReliableWrite_Char (host_client, 0x87); - ClientReliableWrite_Short (host_client, sv.lightstylecolours[i][0]*1024); - ClientReliableWrite_Short (host_client, sv.lightstylecolours[i][1]*1024); - ClientReliableWrite_Short (host_client, sv.lightstylecolours[i][2]*1024); - ClientReliableWrite_String (host_client, sv.strings.lightstyles[i]); - } - else -#endif - { - ClientReliableWrite_Begin (host_client, svc_lightstyle, - 3 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1)); - ClientReliableWrite_Byte (host_client, (char)i); - ClientReliableWrite_String (host_client, sv.strings.lightstyles[i]); - } - } + SV_SendLightstyle(host_client, NULL, i, true); } #ifdef HLSERVER @@ -5683,16 +5659,8 @@ static void SVNQ_Spawn_f (void) #endif // send all current light styles - for (i=0 ; i= MAX_STANDARDLIGHTSTYLES && host_client->protocol != SCP_DARKPLACES7) - break; //dp7 clients support more lightstyles. - - ClientReliableWrite_Begin (host_client, svc_lightstyle, - 3 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1)); - ClientReliableWrite_Byte (host_client, (char)i); - ClientReliableWrite_String (host_client, sv.strings.lightstyles[i]); - } + for (i=0 ; iedict; diff --git a/engine/web/gl_vidweb.c b/engine/web/gl_vidweb.c index 3077a8cf..10abcc50 100644 --- a/engine/web/gl_vidweb.c +++ b/engine/web/gl_vidweb.c @@ -262,7 +262,7 @@ int VID_ShouldSwitchToFullscreen(void) //this is confounded by escape bringing up the menu. GRR IT CHANGED MODE!WTF IT CHANGED AGAIN FUCKING PIECE OF SHIT!. //annoying, but that's web browsers for you. the best thing we can do is to not regrab until they next click while actually back in the game. extern cvar_t vid_fullscreen; - return !!vid_fullscreen.value && (!Key_Dest_Has(kdm_console | kdm_cwindows | kdm_emenu) || !Key_MouseShouldBeFree()); + return !!vid_fullscreen.value && !Key_MouseShouldBeFree(); } qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) { diff --git a/plugins/bullet/bulletplug.cpp b/plugins/bullet/bulletplug.cpp index e0a47a97..ae3f475d 100644 --- a/plugins/bullet/bulletplug.cpp +++ b/plugins/bullet/bulletplug.cpp @@ -77,14 +77,12 @@ static rbeplugfuncs_t *rbefuncs; static void World_Bullet_RunCmd(world_t *world, rbecommandqueue_t *cmd); -static cvar_t *physics_bullet_enable; static cvar_t *physics_bullet_maxiterationsperframe; static cvar_t *physics_bullet_framerate; static cvar_t *pr_meshpitch; void World_Bullet_Init(void) { - physics_bullet_enable = cvarfuncs->GetNVFDG("physics_bullet_enable", "1", 0, "", "Bullet"); physics_bullet_maxiterationsperframe = cvarfuncs->GetNVFDG("physics_bullet_maxiterationsperframe", "10", 0, "FIXME: should be 1 when CCD is working properly.", "Bullet"); physics_bullet_framerate = cvarfuncs->GetNVFDG("physics_bullet_framerate", "60", 0, "Bullet physics run at a fixed framerate in order to preserve numerical stability (interpolation is used to smooth out the result). Higher framerates are of course more demanding.", "Bullet"); pr_meshpitch = cvarfuncs->GetNVFDG("r_meshpitch", "-1", 0, "", "Bullet"); @@ -1713,9 +1711,6 @@ static void QDECL World_Bullet_Start(world_t *world) if (world->rbe) return; //no thanks, we already have one. somehow. - if (!physics_bullet_enable->value) - return; - ctx = reinterpret_cast(BZ_Malloc(sizeof(*ctx))); memset(ctx, 0, sizeof(*ctx)); ctx->gworld = world; diff --git a/specs/bspx.txt b/specs/bspx.txt index 968c6342..97d5ee23 100644 --- a/specs/bspx.txt +++ b/specs/bspx.txt @@ -28,7 +28,7 @@ This is equivelent to the information stored in a .lit file (sans header), and m Presence of this lump permits omitting the regular mono lightmap to save space, but doing so will harm compatibility. LIGHTING_E5BGR9: -(applies to fte) +(applies to fte, parsed by qss only as a fallback) This is a more advanced alternative to RGBLIGHTING. Each luxel is a E5BGR9 int32 packed value (ie: on little-endian machines, the exponent is the high 5 bits), resulting in what is effectively a memory-efficient floating point rgb value. This lightmap format virtually removes all oversaturation limits, and promises greater precision in dark areas too. @@ -38,7 +38,7 @@ Lighting values are always assumed to be linear. LIGHTINGDIR: (applies to fte) -This lump contains surface-space light directions (read: deluxemap), equivelent to fte's .lux file, or dp's .dlit files (sans header). +This lump contains averaged surface-space light directions (read: deluxemap), equivelent to fte's .lux file, or dp's .dlit files (sans header). (as unorm values, these need to be biased before use). If bumpmaps or specular maps are not available then the effects of this may not be significant/noticable. @@ -55,7 +55,13 @@ This allows a bsp to contain both scaled surfaces and unscaled ones, without loo LMSTYLE: (applies to fte, qss) -This replaces the four lightstyle indexes of each surface lump entry. Should only be used in conjunction with LMSHIFT. +This replaces the four lightstyle indexes of each surface lump entry. Normally only makes sense when used in conjunction with LMSHIFT. + +LMSTYLE16: +(applies to fte, qss) +An upgrade for the LMSTYLE lump, potentially giving up to 65k lightstyles. +Additionally, the number of styles per face is variable, and must be inferred by the lump size vs surface count. +Both of these tweeks make it useful even without LMSHIFT. VERTEXNORMALS: (applies to fte)