From fa62b206033ab52feae2d8645ef21726c635fc08 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Wed, 9 Oct 2019 02:12:04 -0600 Subject: [PATCH] light: add a limited version of Lunaran's "_dome" light feature that only supports domes oriented up/down like sunlight2/3 --- include/light/entities.hh | 3 ++ light/entities.cc | 71 ++++++++++++++++++++++++++++++--------- man/light.1 | 8 +++++ 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/include/light/entities.hh b/include/light/entities.hh index 0dd63ec6..596bd26b 100644 --- a/include/light/entities.hh +++ b/include/light/entities.hh @@ -76,6 +76,7 @@ public: lockable_vec_t dirtscale, dirtgain, dirt, deviance, samples, projfov, bouncescale; lockable_vec_t dirt_off_radius, dirt_on_radius; lockable_vec_t sun; //mxd + lockable_vec_t dome; lockable_vec_t falloff; //mxd lockable_bool_t bleed; lockable_vec3_t origin, color, mangle, projangle; @@ -115,6 +116,7 @@ public: dirt_off_radius { "dirt_off_radius", 0.0f }, dirt_on_radius { "dirt_on_radius", 0.0f }, sun { "sun", 0 }, //mxd + dome { "dome", 0 }, falloff{ "falloff", 0.0f }, //mxd bleed { "bleed", false }, origin { "origin", 0, 0, 0 }, @@ -137,6 +139,7 @@ public: &dirtscale, &dirtgain, &dirt, &deviance, &samples, &projfov, &bouncescale, &dirt_off_radius, &dirt_on_radius, &sun, //mxd + &dome, &falloff, //mxd &origin, &color, &mangle, &projangle, &project_texture, &suntexture }}; diff --git a/light/entities.cc b/light/entities.cc index d5979436..108369ab 100644 --- a/light/entities.cc +++ b/light/entities.cc @@ -537,10 +537,13 @@ SetupSuns(const globalconfig_t &cfg) * Setup a dome of suns for the "_sunlight2" worldspawn key. * * From q3map2 + * + * FIXME: this is becoming a mess * ============= */ static void -SetupSkyDome(const globalconfig_t &cfg) +SetupSkyDome(const globalconfig_t &cfg, float upperLight, const vec3_t upperColor, const int upperDirt, const float upperAnglescale, const int upperStyle, const std::string& upperSuntexture, + float lowerLight, const vec3_t lowerColor, const int lowerDirt, const float lowerAnglescale, const int lowerStyle, const std::string& lowerSuntexture) { int i, j, numSuns; int angleSteps, elevationSteps; @@ -554,7 +557,7 @@ SetupSkyDome(const globalconfig_t &cfg) iterations = qmax(iterations, 2); /* dummy check */ - if ( cfg.sunlight2.floatValue() <= 0.0f && cfg.sunlight3.floatValue() <= 0.0f ) { + if ( upperLight <= 0.0f && lowerLight <= 0.0f ) { return; } @@ -567,15 +570,9 @@ SetupSkyDome(const globalconfig_t &cfg) /* calc individual sun brightness */ numSuns = angleSteps * elevationSteps + 1; - if (cfg.sunlight2.floatValue() > 0) { - logprint("using %d suns for _sunlight2. total light: %f color: %f %f %f\n", numSuns, cfg.sunlight2.floatValue(), (*cfg.sunlight2_color.vec3Value())[0], (*cfg.sunlight2_color.vec3Value())[1], (*cfg.sunlight2_color.vec3Value())[2]); - } - if (cfg.sunlight3.floatValue() > 0) { - logprint("using %d suns for _sunlight3. total light: %f color: %f %f %f\n", numSuns, cfg.sunlight3.floatValue(), (*cfg.sunlight3_color.vec3Value())[0], (*cfg.sunlight3_color.vec3Value())[1], (*cfg.sunlight3_color.vec3Value())[2]); - } - const float sunlight2value = cfg.sunlight2.floatValue() / numSuns; - const float sunlight3value = cfg.sunlight3.floatValue() / numSuns; + const float sunlight2value = upperLight / numSuns; + const float sunlight3value = lowerLight / numSuns; /* iterate elevation */ elevation = elevationStep * 0.5f; @@ -592,14 +589,14 @@ SetupSkyDome(const globalconfig_t &cfg) /* insert top hemisphere light */ if (sunlight2value > 0) { - AddSun(cfg, direction, sunlight2value, *cfg.sunlight2_color.vec3Value(), cfg.sunlight2_dirt.intValue(), cfg.global_anglescale.floatValue(), 0, ""); + AddSun(cfg, direction, sunlight2value, upperColor, upperDirt, upperAnglescale, upperStyle, upperSuntexture); } direction[ 2 ] = -direction[ 2 ]; /* insert bottom hemisphere light */ if (sunlight3value > 0) { - AddSun(cfg, direction, sunlight3value, *cfg.sunlight3_color.vec3Value(), cfg.sunlight2_dirt.intValue(), cfg.global_anglescale.floatValue(), 0, ""); + AddSun(cfg, direction, sunlight3value, lowerColor, lowerDirt, lowerAnglescale, lowerStyle, lowerSuntexture); } /* move */ @@ -615,16 +612,60 @@ SetupSkyDome(const globalconfig_t &cfg) VectorSet( direction, 0.0f, 0.0f, -1.0f ); if (sunlight2value > 0) { - AddSun(cfg, direction, sunlight2value, *cfg.sunlight2_color.vec3Value(), cfg.sunlight2_dirt.intValue(), cfg.global_anglescale.floatValue(), 0, ""); + AddSun(cfg, direction, sunlight2value, upperColor, upperDirt, upperAnglescale, upperStyle, upperSuntexture); } VectorSet( direction, 0.0f, 0.0f, 1.0f ); if (sunlight3value > 0) { - AddSun(cfg, direction, sunlight3value, *cfg.sunlight3_color.vec3Value(), cfg.sunlight2_dirt.intValue(), cfg.global_anglescale.floatValue(), 0, ""); + AddSun(cfg, direction, sunlight3value, lowerColor, lowerDirt, lowerAnglescale, lowerStyle, lowerSuntexture); } } +static void +SetupSkyDomes(const globalconfig_t &cfg) +{ + // worldspawn "legacy" skydomes + SetupSkyDome(cfg, cfg.sunlight2.floatValue(), *cfg.sunlight2_color.vec3Value(), cfg.sunlight2_dirt.intValue(), cfg.global_anglescale.floatValue(), 0, "", + cfg.sunlight3.floatValue(), *cfg.sunlight3_color.vec3Value(), cfg.sunlight2_dirt.intValue(), cfg.global_anglescale.floatValue(), 0, ""); + + // new "_dome" entities + for (light_t &entity : all_lights) { + if (entity.dome.intValue() == 1 && entity.light.intValue() > 0) { + // Set direction to dome center + vec3_t dirToDomeCenter; + if (entity.targetent) { + vec3_t target_pos; + EntDict_VectorForKey(*entity.targetent, "origin", target_pos); + VectorSubtract(target_pos, *entity.origin.vec3Value(), dirToDomeCenter); + } else if (VectorLengthSq(*entity.mangle.vec3Value()) > 0) { + glm_to_vec3_t(vec_from_mangle(vec3_t_to_glm(*entity.mangle.vec3Value())), dirToDomeCenter); + } else { + logprint("WARNING: dome light at (%s) missing direction. assuming dome center is downwards.\n", entity.origin.stringValue().c_str()); + VectorSet(dirToDomeCenter, 0, 0, -1); + } + + const vec3_t up {0, 0, 1}; + const vec3_t down {0, 0, -1}; + + if (VectorCompare(dirToDomeCenter, down, EQUAL_EPSILON)) { + // Add the upper dome, like sunlight2 (pointing down) + SetupSkyDome(cfg, entity.light.floatValue(), *entity.color.vec3Value(), entity.dirt.intValue(), entity.anglescale.floatValue(), entity.style.intValue(), entity.suntexture.stringValue(), + 0, vec3_origin, 0, 0, 0, ""); + } else if (VectorCompare(dirToDomeCenter, up, EQUAL_EPSILON)) { + // Add the lower dome, like sunlight3 (pointing up) + SetupSkyDome(cfg, 0, vec3_origin, 0, 0, 0, "", + entity.light.floatValue(), *entity.color.vec3Value(), entity.dirt.intValue(), entity.anglescale.floatValue(), entity.style.intValue(), entity.suntexture.stringValue()); + } else { + logprint("WARNING: dome lights only support up or down currently, ignoring entity at (%s).\n", entity.origin.stringValue().c_str()); + } + + // Disable the light itself... + entity.light.setFloatValue(0.0f); + } + } +} + /* * ============= * DuplicateEntity @@ -1311,7 +1352,7 @@ SetupLights(const globalconfig_t &cfg, const mbsp_t *bsp) MatchTargets(); SetupSpotlights(cfg); SetupSuns(cfg); - SetupSkyDome(cfg); + SetupSkyDomes(cfg); FixLightsOnFaces(bsp); EstimateLightVisibility(); diff --git a/man/light.1 b/man/light.1 index 9102fc51..7d8cf4ae 100644 --- a/man/light.1 +++ b/man/light.1 @@ -436,6 +436,14 @@ The following light properties correspond to these sunlight settings: _suntexture => this sunlight is only emitted from faces with this texture name .fi +.IP "\fB""_dome"" ""n""\fP" +Set to 1 to make this entity a dome light, as an alternative to using the sunlight2 and sunlight3 worldspawn keys. Acts as an area light at infinite distance that emits from sky surfaces. +The light itself is disabled, so it can be placed anywhere in the map. + +Set the incoming direction of the center of the dome with "mangle". For comparison, sunlight2 is straight down (0 -90 0) and sunlight3 is straight up (0 90 0). If the light targets an info_null entity, the direction towards that entity sets the direction of the center of the dome. + +"targetname", "style", "_color", "_anglescale"/"_anglesense", "_suntexture", and dirt parameters are all supported. + .SH "OTHER INFORMATION" The "\\b" escape sequence toggles red text on/off, you can use this in any strings in the map file. e.g. "message" "Here is \\bsome red text\\b..."