Add ZDRay light intensity support
This commit is contained in:
parent
f360457899
commit
c05ef67679
4 changed files with 133 additions and 64 deletions
|
|
@ -174,19 +174,138 @@ void DoomLevelMesh::CreatePortals()
|
|||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::UpdateLightLists()
|
||||
void DoomLevelMesh::PropagateLight(const LevelMeshLight* light, std::set<LevelMeshPortal, RecursivePortalComparator>& touchedPortals, int lightPropagationRecursiveDepth)
|
||||
{
|
||||
for (auto& surface : Surfaces)
|
||||
if (++lightPropagationRecursiveDepth > 32) // TODO is this too much?
|
||||
{
|
||||
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
|
||||
return;
|
||||
}
|
||||
|
||||
SphereShape sphere;
|
||||
sphere.center = FVector3(light->RelativeOrigin);
|
||||
sphere.radius = light->Radius;
|
||||
std::set<LevelMeshPortal, RecursivePortalComparator> portalsToErase;
|
||||
for (int triangleIndex : TriangleMeshShape::find_all_hits(Collision.get(), &sphere))
|
||||
{
|
||||
auto& surface = Surfaces[MeshSurfaceIndexes[triangleIndex]];
|
||||
|
||||
// TODO skip any surface which isn't physically connected to the sector group in which the light resides
|
||||
//if (light-> == surface.sectorGroup)
|
||||
{
|
||||
CreateLightList(&surface, surface.Subsector->section->lighthead, surface.Subsector->sector->PortalGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateLightList(&surface, surface.Side->lighthead, surface.Side->sector->PortalGroup);
|
||||
if (surface.portalIndex >= 0)
|
||||
{
|
||||
auto& portal = Portals[surface.portalIndex];
|
||||
|
||||
if (touchedPortals.insert(portal).second)
|
||||
{
|
||||
auto newLight = std::make_unique<LevelMeshLight>(*light);
|
||||
auto fakeLight = newLight.get();
|
||||
Lights.push_back(std::move(newLight));
|
||||
|
||||
fakeLight->RelativeOrigin = portal.TransformPosition(light->RelativeOrigin);
|
||||
//fakeLight->sectorGroup = portal->targetSectorGroup;
|
||||
|
||||
PropagateLight(fakeLight, touchedPortals, lightPropagationRecursiveDepth);
|
||||
portalsToErase.insert(portal);
|
||||
}
|
||||
}
|
||||
|
||||
// Add light to the list if it isn't already there
|
||||
// TODO in order for this to work the light list be fed from global light buffer? Or just somehow de-duplicate portals?
|
||||
bool found = false;
|
||||
for (const LevelMeshLight* light2 : surface.LightList)
|
||||
{
|
||||
if (light2 == light)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
surface.LightList.push_back(light);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& portal : portalsToErase)
|
||||
{
|
||||
touchedPortals.erase(portal); // Dear me: I wonder what was the reason for all of this.
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateLightList()
|
||||
{
|
||||
std::set<FDynamicLight*> lightList; // bit silly ain't it?
|
||||
|
||||
Lights.clear();
|
||||
for (auto& surface : Surfaces)
|
||||
{
|
||||
surface.LightList.clear();
|
||||
|
||||
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
|
||||
{
|
||||
auto node = surface.Subsector->section->lighthead;
|
||||
|
||||
while (node)
|
||||
{
|
||||
FDynamicLight* light = node->lightsource;
|
||||
|
||||
if (light->Trace())
|
||||
{
|
||||
if (lightList.insert(light).second)
|
||||
{
|
||||
DVector3 pos = light->Pos; //light->PosRelative(portalgroup);
|
||||
|
||||
LevelMeshLight meshlight;
|
||||
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
||||
meshlight.RelativeOrigin = meshlight.Origin;
|
||||
meshlight.Radius = (float)light->GetRadius();
|
||||
meshlight.Intensity = light->target->Alpha;
|
||||
if (light->IsSpot())
|
||||
{
|
||||
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
|
||||
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
|
||||
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xzLen = negPitch.Cos();
|
||||
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
|
||||
meshlight.SpotDir.Y = float(-negPitch.Sin());
|
||||
meshlight.SpotDir.Z = float(-Angle.Sin() * xzLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
meshlight.InnerAngleCos = -1.0f;
|
||||
meshlight.OuterAngleCos = -1.0f;
|
||||
meshlight.SpotDir.X = 0.0f;
|
||||
meshlight.SpotDir.Y = 0.0f;
|
||||
meshlight.SpotDir.Z = 0.0f;
|
||||
}
|
||||
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
|
||||
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
|
||||
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
|
||||
|
||||
Lights.push_back(std::make_unique<LevelMeshLight>(meshlight));
|
||||
}
|
||||
}
|
||||
|
||||
node = node->nextLight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::set<LevelMeshPortal, RecursivePortalComparator> touchedPortals;
|
||||
touchedPortals.insert(Portals[0]);
|
||||
|
||||
for (int i = 0, count = Lights.size(); i < count; ++i) // The array expands as the lights are duplicated/propagated
|
||||
{
|
||||
PropagateLight(Lights[i].get(), touchedPortals, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::UpdateLightLists()
|
||||
{
|
||||
CreateLightList(); // full recreation
|
||||
}
|
||||
|
||||
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
|
||||
|
|
@ -296,58 +415,6 @@ void DoomLevelMesh::SetSideLightmap(DoomLevelMeshSurface* surface)
|
|||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateLightList(DoomLevelMeshSurface* surface, FLightNode* node, int portalgroup)
|
||||
{
|
||||
surface->LightListBuffer.clear();
|
||||
surface->LightList.clear();
|
||||
|
||||
while (node)
|
||||
{
|
||||
FDynamicLight* light = node->lightsource;
|
||||
|
||||
if (light->Trace())
|
||||
{
|
||||
DVector3 pos = light->PosRelative(portalgroup);
|
||||
|
||||
LevelMeshLight meshlight;
|
||||
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
||||
meshlight.RelativeOrigin = meshlight.Origin; // ?? what is the difference between this and Origin?
|
||||
meshlight.Radius = (float)light->GetRadius();
|
||||
meshlight.Intensity = light->target->Alpha;
|
||||
if (light->IsSpot())
|
||||
{
|
||||
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
|
||||
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
|
||||
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xzLen = negPitch.Cos();
|
||||
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
|
||||
meshlight.SpotDir.Y = float(-negPitch.Sin());
|
||||
meshlight.SpotDir.Z = float(-Angle.Sin() * xzLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
meshlight.InnerAngleCos = -1.0f;
|
||||
meshlight.OuterAngleCos = -1.0f;
|
||||
meshlight.SpotDir.X = 0.0f;
|
||||
meshlight.SpotDir.Y = 0.0f;
|
||||
meshlight.SpotDir.Z = 0.0f;
|
||||
}
|
||||
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
|
||||
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
|
||||
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
|
||||
|
||||
surface->LightListBuffer.push_back(meshlight);
|
||||
}
|
||||
|
||||
node = node->nextLight;
|
||||
}
|
||||
|
||||
for (auto& silly : surface->LightListBuffer)
|
||||
surface->LightList.push_back(&silly);
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side)
|
||||
{
|
||||
sector_t *front;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue