From 0c0f0789c296bed8c00e3541c60a3880d159f254 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 25 Jul 2017 23:00:09 +0200 Subject: [PATCH 1/6] - Improved dynamic lights on models --- src/gl/dynlights/gl_dynlight.h | 2 +- src/gl/dynlights/gl_dynlight1.cpp | 22 ++++++++++++---------- src/gl/models/gl_models_md2.cpp | 3 +++ src/gl/models/gl_models_md3.cpp | 3 +++ src/gl/models/gl_voxels.cpp | 2 ++ src/gl/scene/gl_sprite.cpp | 5 ++++- src/gl/scene/gl_spritelight.cpp | 27 +++++++++++++++++++++++++++ src/gl/scene/gl_wall.h | 1 + 8 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index 74e49baba..2796f093e 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -58,7 +58,7 @@ struct FDynLightData -bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data); +bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data, bool planecheck = true); void gl_UploadLights(FDynLightData &data); diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index 4000554c8..db1eebc43 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -63,22 +63,24 @@ CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option. // Sets up the parameters to render one dynamic light onto one plane // //========================================================================== -bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata) +bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata, bool planecheck) { int i = 0; DVector3 pos = light->PosRelative(group); - - float dist = fabsf(p.DistToPoint(pos.X, pos.Z, pos.Y)); float radius = (light->GetRadius()); - - if (radius <= 0.f) return false; - if (dist > radius) return false; - if (checkside && gl_lights_checkside && p.PointOnSide(pos.X, pos.Z, pos.Y)) - { - return false; - } + if (planecheck) + { + float dist = fabsf(p.DistToPoint(pos.X, pos.Z, pos.Y)); + + if (radius <= 0.f) return false; + if (dist > radius) return false; + if (checkside && gl_lights_checkside && p.PointOnSide(pos.X, pos.Z, pos.Y)) + { + return false; + } + } float cs; if (light->IsAdditive()) diff --git a/src/gl/models/gl_models_md2.cpp b/src/gl/models/gl_models_md2.cpp index 507e5977a..7f7930ac9 100644 --- a/src/gl/models/gl_models_md2.cpp +++ b/src/gl/models/gl_models_md2.cpp @@ -40,6 +40,8 @@ #include "gl/shaders/gl_shader.h" #include "gl/data/gl_vertexbuffer.h" +extern int modellightindex; + static float avertexnormals[NUMVERTEXNORMALS][3] = { #include "tab_anorms.h" }; @@ -379,6 +381,7 @@ void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double i gl_RenderState.SetInterpolationFactor((float)inter); gl_RenderState.Apply(); + if (modellightindex != -1) gl_RenderState.ApplyLightIndex(modellightindex); mVBuf->SetupFrame(frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3); glDrawArrays(GL_TRIANGLES, 0, lodInfo[0].numTriangles * 3); gl_RenderState.SetInterpolationFactor(0.f); diff --git a/src/gl/models/gl_models_md3.cpp b/src/gl/models/gl_models_md3.cpp index 6336ce277..9573b83c1 100644 --- a/src/gl/models/gl_models_md3.cpp +++ b/src/gl/models/gl_models_md3.cpp @@ -35,6 +35,8 @@ #define MAX_QPATH 64 +extern int modellightindex; + //=========================================================================== // // decode the lat/lng normal to a 3 float normal @@ -372,6 +374,7 @@ void FMD3Model::RenderFrame(FTexture * skin, int frameno, int frameno2, double i gl_RenderState.SetMaterial(tex, CLAMP_NONE, translation, -1, false); gl_RenderState.Apply(); + if (modellightindex != -1) gl_RenderState.ApplyLightIndex(modellightindex); mVBuf->SetupFrame(surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices); glDrawElements(GL_TRIANGLES, surf->numTriangles * 3, GL_UNSIGNED_INT, (void*)(intptr_t)(surf->iindex * sizeof(unsigned int))); } diff --git a/src/gl/models/gl_voxels.cpp b/src/gl/models/gl_voxels.cpp index 48b6da442..0b97e87f8 100644 --- a/src/gl/models/gl_voxels.cpp +++ b/src/gl/models/gl_voxels.cpp @@ -50,6 +50,7 @@ #include "gl/utility/gl_convert.h" #include "gl/renderer/gl_renderstate.h" +extern int modellightindex; //=========================================================================== // @@ -445,6 +446,7 @@ void FVoxelModel::RenderFrame(FTexture * skin, int frame, int frame2, double int gl_RenderState.SetMaterial(tex, CLAMP_NOFILTER, translation, -1, false); gl_RenderState.Apply(); + if (modellightindex != -1) gl_RenderState.ApplyLightIndex(modellightindex); mVBuf->SetupFrame(0, 0, 0); glDrawElements(GL_TRIANGLES, mNumIndices, GL_UNSIGNED_INT, (void*)(intptr_t)0); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index bc8275ddd..d42eea5ee 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -326,7 +326,10 @@ void GLSprite::Draw(int pass) { if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) { - gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); + if (modelframe && !particle) + gl_SetDynModelLight(gl_light_sprites ? actor : NULL, actor->X(), actor->Y(), actor->Center(), actor->subsector); + else + gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); } sector_t *cursec = actor ? actor->Sector : particle ? particle->subsector->sector : nullptr; if (cursec != nullptr) diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index bb9de17b3..58b31f67d 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -42,7 +42,10 @@ #include "gl/scene/gl_portal.h" #include "gl/shaders/gl_shader.h" #include "gl/textures/gl_material.h" +#include "gl/dynlights/gl_lightbuffer.h" +FDynLightData modellightdata; +int modellightindex = -1; //========================================================================== // @@ -114,6 +117,7 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * node = node->nextLight; } gl_RenderState.SetDynLight(out[0], out[1], out[2]); + modellightindex = -1; } void gl_SetDynSpriteLight(AActor *thing, particle_t *particle) @@ -127,3 +131,26 @@ void gl_SetDynSpriteLight(AActor *thing, particle_t *particle) gl_SetDynSpriteLight(NULL, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector); } } + +void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec) +{ + Plane p; + p.Set(subsec->sector->ceilingplane); // Is this correct? + + modellightdata.Clear(); + + // Go through both light lists + FLightNode * node = subsec->lighthead; + while (node) + { + ADynamicLight *light = node->lightsource; + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS)) + { + gl_GetLight(subsec->sector->PortalGroup, p, node->lightsource, false, modellightdata, false); + } + node = node->nextLight; + } + + gl_RenderState.SetDynLight(0, 0, 0); + modellightindex = GLRenderer->mLights->UploadLights(modellightdata); +} diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 1c52e3c30..2f3fb6638 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -422,5 +422,6 @@ inline float Dist2(float x1,float y1,float x2,float y2) void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); +void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec); #endif From cbda6e942790b207e8f58003cbe911125c9d75fb Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 26 Jul 2017 09:18:05 +0200 Subject: [PATCH 2/6] - Improve dynamic lights for the HUD model --- src/gl/dynlights/gl_dynlight.h | 2 +- src/gl/dynlights/gl_dynlight1.cpp | 27 ++++++++++++++++++++++++++- src/gl/models/gl_models.cpp | 3 +++ src/gl/scene/gl_spritelight.cpp | 4 ++-- src/gl/scene/gl_wall.h | 2 +- src/gl/scene/gl_weapon.cpp | 6 +++++- 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index 2796f093e..3eb19ee39 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -58,7 +58,7 @@ struct FDynLightData -bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data, bool planecheck = true); +bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data, bool planecheck = true, bool hudmodel = false); void gl_UploadLights(FDynLightData &data); diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index db1eebc43..13443c26a 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -63,7 +63,7 @@ CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option. // Sets up the parameters to render one dynamic light onto one plane // //========================================================================== -bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata, bool planecheck) +bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata, bool planecheck, bool hudmodel) { int i = 0; @@ -82,6 +82,31 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD } } + if (hudmodel) + { + // HUD model is already translated and rotated. We must rotate the lights into that view space. + + DVector3 rotation; + DVector3 localpos = pos - r_viewpoint.Pos; + + rotation.X = localpos.X * r_viewpoint.Angles.Yaw.Sin() - localpos.Y * r_viewpoint.Angles.Yaw.Cos(); + rotation.Y = localpos.X * r_viewpoint.Angles.Yaw.Cos() + localpos.Y * r_viewpoint.Angles.Yaw.Sin(); + rotation.Z = localpos.Z; + localpos = rotation; + + rotation.X = localpos.X; + rotation.Y = localpos.Y * r_viewpoint.Angles.Pitch.Sin() - localpos.Z * r_viewpoint.Angles.Pitch.Cos(); + rotation.Z = localpos.Y * r_viewpoint.Angles.Pitch.Cos() + localpos.Z * r_viewpoint.Angles.Pitch.Sin(); + localpos = rotation; + + rotation.Y = localpos.Y; + rotation.Z = localpos.Z * r_viewpoint.Angles.Roll.Sin() - localpos.X * r_viewpoint.Angles.Roll.Cos(); + rotation.X = localpos.Z * r_viewpoint.Angles.Roll.Cos() + localpos.X * r_viewpoint.Angles.Roll.Sin(); + localpos = rotation; + + pos = localpos; + } + float cs; if (light->IsAdditive()) { diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index a118e20f2..45b955b56 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -1099,6 +1099,9 @@ void gl_RenderHUDModel(DPSprite *psp, float ofsX, float ofsY) // so we have to reset the view matrix. gl_RenderState.mViewMatrix.loadIdentity(); + // Need to reset the normal matrix too + gl_RenderState.mNormalViewMatrix.loadIdentity(); + // Scaling model (y scale for a sprite means height, i.e. z in the world!). gl_RenderState.mViewMatrix.scale(smf->xscale, smf->zscale, smf->yscale); diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 58b31f67d..7a30015f8 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -132,7 +132,7 @@ void gl_SetDynSpriteLight(AActor *thing, particle_t *particle) } } -void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec) +void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec, bool hudmodel) { Plane p; p.Set(subsec->sector->ceilingplane); // Is this correct? @@ -146,7 +146,7 @@ void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * ADynamicLight *light = node->lightsource; if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS)) { - gl_GetLight(subsec->sector->PortalGroup, p, node->lightsource, false, modellightdata, false); + gl_GetLight(subsec->sector->PortalGroup, p, node->lightsource, false, modellightdata, false, hudmodel); } node = node->nextLight; } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 2f3fb6638..9298a4703 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -422,6 +422,6 @@ inline float Dist2(float x1,float y1,float x2,float y2) void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); -void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec); +void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec, bool hudmodel = false); #endif diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index ff2321da5..36990944e 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -420,7 +420,11 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { if (gl_lights && GLRenderer->mLightCount && FixedColormap == CM_DEFAULT && gl_light_sprites) { - gl_SetDynSpriteLight(playermo, NULL); + FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false); + if (smf) + gl_SetDynModelLight(playermo, playermo->X(), playermo->Y(), playermo->Center(), playermo->subsector, true); + else + gl_SetDynSpriteLight(playermo, NULL); } SetColor(ll, 0, cmc, trans, true); } From 65d5f4ae18a507ef0509f1fa370307c257188811 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 27 Jul 2017 22:31:57 +0200 Subject: [PATCH 3/6] - Fix normal normalize --- wadsrc/static/shaders/glsl/main.vp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 9901fba3f..a6055c2b5 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -62,7 +62,7 @@ void main() gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); } - vWorldNormal = NormalModelMatrix * normalize(aNormal); + vWorldNormal = NormalModelMatrix * vec4(normalize(aNormal.xyz), 1.0); vEyeNormal = NormalViewMatrix * vWorldNormal; #endif From aaa00cbcb9c493d62500df5a8652929fc2c58942 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 1 Aug 2017 00:43:58 +0200 Subject: [PATCH 4/6] - Include all lights touching a model actor's render radius --- src/gl/dynlights/gl_dynlight.h | 3 +- src/gl/dynlights/gl_dynlight1.cpp | 40 +++++++++----- src/gl/scene/gl_sprite.cpp | 2 +- src/gl/scene/gl_spritelight.cpp | 91 +++++++++++++++++++++++++++---- src/gl/scene/gl_wall.h | 2 +- src/gl/scene/gl_weapon.cpp | 2 +- 6 files changed, 110 insertions(+), 30 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index 3eb19ee39..a85814b6b 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -58,7 +58,8 @@ struct FDynLightData -bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data, bool planecheck = true, bool hudmodel = false); +bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data); +void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata, bool hudmodel); void gl_UploadLights(FDynLightData &data); diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index 13443c26a..92a503c8d 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -63,24 +63,35 @@ CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option. // Sets up the parameters to render one dynamic light onto one plane // //========================================================================== -bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata, bool planecheck, bool hudmodel) +bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata) +{ + DVector3 pos = light->PosRelative(group); + float radius = (light->GetRadius()); + + float dist = fabsf(p.DistToPoint(pos.X, pos.Z, pos.Y)); + + if (radius <= 0.f) return false; + if (dist > radius) return false; + if (checkside && gl_lights_checkside && p.PointOnSide(pos.X, pos.Z, pos.Y)) + { + return false; + } + + gl_AddLightToList(group, light, ldata, false); + return true; +} + +//========================================================================== +// +// Add one dynamic light to the light data list +// +//========================================================================== +void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata, bool hudmodel) { int i = 0; DVector3 pos = light->PosRelative(group); - float radius = (light->GetRadius()); - - if (planecheck) - { - float dist = fabsf(p.DistToPoint(pos.X, pos.Z, pos.Y)); - - if (radius <= 0.f) return false; - if (dist > radius) return false; - if (checkside && gl_lights_checkside && p.PointOnSide(pos.X, pos.Z, pos.Y)) - { - return false; - } - } + float radius = light->GetRadius(); if (hudmodel) { @@ -151,6 +162,5 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD data[5] = g; data[6] = b; data[7] = shadowIndex; - return true; } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index d42eea5ee..e7e82a569 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -327,7 +327,7 @@ void GLSprite::Draw(int pass) if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) { if (modelframe && !particle) - gl_SetDynModelLight(gl_light_sprites ? actor : NULL, actor->X(), actor->Y(), actor->Center(), actor->subsector); + gl_SetDynModelLight(gl_light_sprites ? actor : NULL, false); else gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); } diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 7a30015f8..fa4318535 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -32,6 +32,7 @@ #include "vectors.h" #include "gl/gl_functions.h" #include "g_level.h" +#include "g_levellocals.h" #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderer.h" @@ -132,23 +133,91 @@ void gl_SetDynSpriteLight(AActor *thing, particle_t *particle) } } -void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec, bool hudmodel) +// Check if circle potentially intersects with node AABB +static bool CheckBBoxCircle(float *bbox, float x, float y, float radiusSquared) { - Plane p; - p.Set(subsec->sector->ceilingplane); // Is this correct? + float centerX = (bbox[BOXRIGHT] + bbox[BOXLEFT]) * 0.5f; + float centerY = (bbox[BOXBOTTOM] + bbox[BOXTOP]) * 0.5f; + float extentX = (bbox[BOXRIGHT] - bbox[BOXLEFT]) * 0.5f; + float extentY = (bbox[BOXBOTTOM] - bbox[BOXTOP]) * 0.5f; + float aabbRadiusSquared = extentX * extentX + extentY * extentY; + x -= centerX; + y -= centerY; + float dist = x * x + y * y; + return dist <= radiusSquared + aabbRadiusSquared; +} +template +void BSPNodeWalkCircle(void *node, float x, float y, float radiusSquared, Callback &callback) +{ + while (!((size_t)node & 1)) + { + node_t *bsp = (node_t *)node; + + if (CheckBBoxCircle(bsp->bbox[0], x, y, radiusSquared)) + BSPNodeWalkCircle(bsp->children[0], x, y, radiusSquared, callback); + + if (!CheckBBoxCircle(bsp->bbox[1], x, y, radiusSquared)) + return; + + node = bsp->children[1]; + } + + subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); + callback(sub); +} + +template +void BSPWalkCircle(float x, float y, float radiusSquared, Callback &callback) +{ + if (level.nodes.Size() == 0) + callback(&level.subsectors[0]); + else + BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback); +} + +void gl_SetDynModelLight(AActor *self, bool hudmodel) +{ modellightdata.Clear(); - // Go through both light lists - FLightNode * node = subsec->lighthead; - while (node) + if (self) { - ADynamicLight *light = node->lightsource; - if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS)) + static std::vector addedLights; // static so that we build up a reserve (memory allocations stop) + + addedLights.clear(); + + float x = self->X(); + float y = self->Y(); + float z = self->Center(); + float radiusSquared = self->renderradius * self->renderradius; + + BSPWalkCircle(x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor { - gl_GetLight(subsec->sector->PortalGroup, p, node->lightsource, false, modellightdata, false, hudmodel); - } - node = node->nextLight; + FLightNode * node = subsector->lighthead; + while (node) // check all lights touching a subsector + { + ADynamicLight *light = node->lightsource; + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS)) + { + int group = subsector->sector->PortalGroup; + DVector3 pos = light->PosRelative(group); + float radius = light->GetRadius(); + double dx = pos.X - x; + double dy = pos.Y - y; + double dz = pos.Z - z; + double distSquared = dx * dx + dy * dy + dz * dz; + if (distSquared < radiusSquared + radius * radius) // Light and actor touches + { + if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector + { + gl_AddLightToList(group, light, modellightdata, hudmodel); + addedLights.push_back(light); + } + } + } + node = node->nextLight; + } + }); } gl_RenderState.SetDynLight(0, 0, 0); diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 9298a4703..47cf5654c 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -422,6 +422,6 @@ inline float Dist2(float x1,float y1,float x2,float y2) void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec); void gl_SetDynSpriteLight(AActor *actor, particle_t *particle); -void gl_SetDynModelLight(AActor *self, float x, float y, float z, subsector_t * subsec, bool hudmodel = false); +void gl_SetDynModelLight(AActor *self, bool hudmodel); #endif diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 36990944e..548078bed 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -422,7 +422,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false); if (smf) - gl_SetDynModelLight(playermo, playermo->X(), playermo->Y(), playermo->Center(), playermo->subsector, true); + gl_SetDynModelLight(playermo, true); else gl_SetDynSpriteLight(playermo, NULL); } From 801fbddd475b7c620fd9d3fd4221629da2b7047a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 2 Aug 2017 01:41:48 +0200 Subject: [PATCH 5/6] - Fix gcc compile error - Fix weapon null pointer crash --- src/gl/scene/gl_spritelight.cpp | 4 ++-- src/gl/scene/gl_weapon.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index fa4318535..0eba9249b 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -148,7 +148,7 @@ static bool CheckBBoxCircle(float *bbox, float x, float y, float radiusSquared) } template -void BSPNodeWalkCircle(void *node, float x, float y, float radiusSquared, Callback &callback) +void BSPNodeWalkCircle(void *node, float x, float y, float radiusSquared, const Callback &callback) { while (!((size_t)node & 1)) { @@ -168,7 +168,7 @@ void BSPNodeWalkCircle(void *node, float x, float y, float radiusSquared, Callba } template -void BSPWalkCircle(float x, float y, float radiusSquared, Callback &callback) +void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callback) { if (level.nodes.Size() == 0) callback(&level.subsectors[0]); diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 548078bed..551f34cbd 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -420,7 +420,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { if (gl_lights && GLRenderer->mLightCount && FixedColormap == CM_DEFAULT && gl_light_sprites) { - FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false); + FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; if (smf) gl_SetDynModelLight(playermo, true); else From 507122b778e9f84e928d334e5c74d2215fe7f31b Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Fri, 4 Aug 2017 09:13:20 -0400 Subject: [PATCH 6/6] - put in actorinlines include as suggested by dpjudas here, to fix compile: https://forum.zdoom.org/viewtopic.php?f=2&t=57484 --- src/gl/scene/gl_spritelight.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 0eba9249b..4bc2588e8 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -33,6 +33,7 @@ #include "gl/gl_functions.h" #include "g_level.h" #include "g_levellocals.h" +#include "actorinlines.h" #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderer.h"