mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-01-24 08:41:06 +00:00
- split map loading code from surface mesh code
This commit is contained in:
parent
73724c111c
commit
9a84d487dc
9 changed files with 438 additions and 383 deletions
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "framework/tarray.h"
|
||||
#include "math/mathlib.h"
|
||||
#include "lightmap/collision.h"
|
||||
#include <memory>
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
|
@ -52,6 +51,7 @@ struct IntSideDef
|
|||
char midtexture[8];
|
||||
|
||||
int sector;
|
||||
int lightdef;
|
||||
|
||||
IntLineDef *line;
|
||||
|
||||
|
@ -112,8 +112,12 @@ struct IntSector
|
|||
kexPlane ceilingplane;
|
||||
kexPlane floorplane;
|
||||
|
||||
int floorlightdef;
|
||||
int ceilinglightdef;
|
||||
|
||||
bool controlsector;
|
||||
TArray<IntSector*> x3dfloors;
|
||||
bool skySector;
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
};
|
||||
|
@ -305,17 +309,6 @@ enum mapFlags_t
|
|||
#define NO_SIDE_INDEX -1
|
||||
#define NO_LINE_INDEX 0xffffffff
|
||||
|
||||
struct LevelTraceHit
|
||||
{
|
||||
kexVec3 start;
|
||||
kexVec3 end;
|
||||
float fraction;
|
||||
|
||||
surface_t *hitSurface;
|
||||
int indices[3];
|
||||
float b, c;
|
||||
};
|
||||
|
||||
struct FLevel
|
||||
{
|
||||
FLevel ();
|
||||
|
@ -359,23 +352,12 @@ struct FLevel
|
|||
|
||||
// Dlight helpers
|
||||
|
||||
TArray<kexVec3> MeshVertices;
|
||||
TArray<int> MeshUVIndex;
|
||||
TArray<unsigned int> MeshElements;
|
||||
TArray<int> MeshSurfaces;
|
||||
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
||||
|
||||
std::vector<bool> bSkySectors;
|
||||
|
||||
std::vector<std::unique_ptr<thingLight_t>> thingLights;
|
||||
std::vector<std::unique_ptr<kexLightSurface>> lightSurfaces;
|
||||
TArray<thingLight_t> ThingLights;
|
||||
TArray<surfaceLightDef> SurfaceLights;
|
||||
|
||||
void SetupDlight();
|
||||
void CreateLights();
|
||||
|
||||
LevelTraceHit Trace(const kexVec3 &startVec, const kexVec3 &endVec);
|
||||
bool TraceAnyHit(const kexVec3 &startVec, const kexVec3 &endVec);
|
||||
|
||||
const kexVec3 &GetSunColor() const;
|
||||
const kexVec3 &GetSunDirection() const;
|
||||
IntSector *GetFrontSector(const IntSideDef *side);
|
||||
|
|
|
@ -622,7 +622,6 @@ void FProcessor::BuildLightmaps()
|
|||
LMBuilder.textureHeight = LMDims;
|
||||
|
||||
Level.SetupDlight();
|
||||
CreateSurfaces(Level);
|
||||
Level.CreateLights();
|
||||
|
||||
LMBuilder.CreateLightmaps(Level);
|
||||
|
|
|
@ -47,14 +47,47 @@ static const kexVec3 defaultSunDirection(0.45f, 0.3f, 0.9f);
|
|||
void FLevel::SetupDlight()
|
||||
{
|
||||
CheckSkySectors();
|
||||
|
||||
for (unsigned int i = 0; i < Sectors.Size(); i++)
|
||||
Sectors[i].controlsector = false;
|
||||
|
||||
for (unsigned int i = 0; i < Sides.Size(); i++)
|
||||
Sides[i].line = nullptr;
|
||||
|
||||
for (unsigned int i = 0; i < Lines.Size(); i++)
|
||||
{
|
||||
IntLineDef *line = &Lines[i];
|
||||
|
||||
// Link sides to lines
|
||||
if (line->sidenum[0] < Sides.Size())
|
||||
Sides[line->sidenum[0]].line = line;
|
||||
if (line->sidenum[1] < Sides.Size())
|
||||
Sides[line->sidenum[1]].line = line;
|
||||
|
||||
if (line->special == 160) // Sector_Set3dFloor
|
||||
{
|
||||
int sectorTag = line->args[0];
|
||||
int type = line->args[1];
|
||||
//int opacity = line.args[3];
|
||||
|
||||
IntSector *controlsector = &Sectors[Sides[Lines[i].sidenum[0]].sector];
|
||||
controlsector->controlsector = true;
|
||||
|
||||
for (unsigned int j = 0; j < Sectors.Size(); j++)
|
||||
{
|
||||
if (Sectors[j].data.tag == sectorTag)
|
||||
{
|
||||
Sectors[j].x3dfloors.Push(controlsector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FLevel::CheckSkySectors()
|
||||
{
|
||||
char name[9];
|
||||
|
||||
bSkySectors = std::vector<bool>(Sectors.Size()); // Most retarded way to resize ever, but Microsoft apparently broke std::vector<bool> in the latest update..
|
||||
|
||||
for (int i = 0; i < (int)Sectors.Size(); ++i)
|
||||
{
|
||||
//if (mapDef && mapDef->sunIgnoreTag != 0 && Sectors[i].data.tag == mapDef->sunIgnoreTag)
|
||||
|
@ -65,7 +98,11 @@ void FLevel::CheckSkySectors()
|
|||
|
||||
if (!strncmp(name, "F_SKY001", 8) || !strncmp(name, "F_SKY1", 8) || !strncmp(name, "F_SKY", 8))
|
||||
{
|
||||
bSkySectors[i] = true;
|
||||
Sectors[i].skySector = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Sectors[i].skySector = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,175 +249,141 @@ void FLevel::CreateLights()
|
|||
int x = thing->x >> FRACBITS;
|
||||
int y = thing->y >> FRACBITS;
|
||||
|
||||
auto thingLight = std::make_unique<thingLight_t>();
|
||||
thingLight_t thingLight;
|
||||
thingLight.mapThing = thing;
|
||||
thingLight.rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
thingLight.rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
thingLight.rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
thingLight.intensity = lightintensity;
|
||||
thingLight.innerAngleCos = std::max(innerAngleCos, outerAngleCos);
|
||||
thingLight.outerAngleCos = outerAngleCos;
|
||||
thingLight.radius = lightdistance;
|
||||
thingLight.height = thing->height;
|
||||
thingLight.bCeiling = false;
|
||||
thingLight.ssect = PointInSubSector(x, y);
|
||||
thingLight.sector = GetSectorFromSubSector(thingLight.ssect);
|
||||
thingLight.origin.Set(x, y);
|
||||
|
||||
thingLight->mapThing = thing;
|
||||
thingLight->rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
thingLight->rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
thingLight->rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
thingLight->intensity = lightintensity;
|
||||
thingLight->innerAngleCos = std::max(innerAngleCos, outerAngleCos);
|
||||
thingLight->outerAngleCos = outerAngleCos;
|
||||
thingLight->radius = lightdistance;
|
||||
thingLight->height = thing->height;
|
||||
thingLight->bCeiling = false;
|
||||
thingLight->ssect = PointInSubSector(x, y);
|
||||
thingLight->sector = GetSectorFromSubSector(thingLight->ssect);
|
||||
|
||||
thingLight->origin.Set(x, y);
|
||||
thingLights.push_back(std::move(thingLight));
|
||||
ThingLights.Push(thingLight);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Thing lights: %i\n", (int)thingLights.size());
|
||||
printf("Thing lights: %i\n", (int)ThingLights.Size());
|
||||
|
||||
// add surface lights
|
||||
int numSurfLights = 0;
|
||||
for (size_t j = 0; j < surfaces.size(); ++j)
|
||||
for (unsigned int i = 0; i < Sides.Size(); i++)
|
||||
{
|
||||
surface_t *surface = surfaces[j].get();
|
||||
IntSideDef *side = &Sides[i];
|
||||
side->lightdef = -1;
|
||||
|
||||
if (surface->type >= ST_MIDDLESIDE && surface->type <= ST_LOWERSIDE)
|
||||
IntLineDef *line = side->line;
|
||||
if (line)
|
||||
{
|
||||
IntLineDef *line = Sides[surface->typeIndex].line;
|
||||
if (line)
|
||||
uint32_t lightcolor = 0xffffff;
|
||||
float lightintensity = 1.0f;
|
||||
float lightdistance = 0.0f;
|
||||
|
||||
for (unsigned int propIndex = 0; propIndex < line->props.Size(); propIndex++)
|
||||
{
|
||||
uint32_t lightcolor = 0xffffff;
|
||||
float lightintensity = 1.0f;
|
||||
float lightdistance = 0.0f;
|
||||
|
||||
for (unsigned int propIndex = 0; propIndex < line->props.Size(); propIndex++)
|
||||
const UDMFKey &key = line->props[propIndex];
|
||||
if (!stricmp(key.key, "lightcolor"))
|
||||
{
|
||||
const UDMFKey &key = line->props[propIndex];
|
||||
if (!stricmp(key.key, "lightcolor"))
|
||||
{
|
||||
lightcolor = atoi(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightintensity"))
|
||||
{
|
||||
lightintensity = atof(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightdistance"))
|
||||
{
|
||||
lightdistance = atof(key.value);
|
||||
}
|
||||
lightcolor = atoi(key.value);
|
||||
}
|
||||
|
||||
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
||||
else if (!stricmp(key.key, "lightintensity"))
|
||||
{
|
||||
surfaceLightDef desc;
|
||||
desc.intensity = lightintensity;
|
||||
desc.distance = lightdistance;
|
||||
desc.rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
desc.rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
desc.rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
|
||||
auto lightSurface = std::make_unique<kexLightSurface>(desc, surface);
|
||||
lightSurface->Subdivide(16);
|
||||
//lightSurface->CreateCenterOrigin();
|
||||
lightSurfaces.push_back(std::move(lightSurface));
|
||||
numSurfLights++;
|
||||
lightintensity = atof(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightdistance"))
|
||||
{
|
||||
lightdistance = atof(key.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
||||
{
|
||||
MapSubsectorEx *sub = &GLSubsectors[surface->typeIndex];
|
||||
IntSector *sector = GetSectorFromSubSector(sub);
|
||||
|
||||
if (sector && surface->numVerts > 0)
|
||||
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
||||
{
|
||||
uint32_t lightcolor = 0xffffff;
|
||||
float lightintensity = 1.0f;
|
||||
float lightdistance = 0.0f;
|
||||
|
||||
for (unsigned int propIndex = 0; propIndex < sector->props.Size(); propIndex++)
|
||||
{
|
||||
const UDMFKey &key = sector->props[propIndex];
|
||||
if (surface->type == ST_FLOOR)
|
||||
{
|
||||
if (!stricmp(key.key, "lightcolorfloor"))
|
||||
{
|
||||
lightcolor = atoi(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightintensityfloor"))
|
||||
{
|
||||
lightintensity = atof(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightdistancefloor"))
|
||||
{
|
||||
lightdistance = atof(key.value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!stricmp(key.key, "lightcolorceiling"))
|
||||
{
|
||||
lightcolor = atoi(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightintensityceiling"))
|
||||
{
|
||||
lightintensity = atof(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightdistanceceiling"))
|
||||
{
|
||||
lightdistance = atof(key.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
||||
{
|
||||
surfaceLightDef desc;
|
||||
desc.intensity = lightintensity;
|
||||
desc.distance = lightdistance;
|
||||
desc.rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
desc.rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
desc.rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
|
||||
auto lightSurface = std::make_unique<kexLightSurface>(desc, surface);
|
||||
lightSurface->Subdivide(16);
|
||||
lightSurfaces.push_back(std::move(lightSurface));
|
||||
numSurfLights++;
|
||||
}
|
||||
surfaceLightDef desc;
|
||||
desc.intensity = lightintensity;
|
||||
desc.distance = lightdistance;
|
||||
desc.rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
desc.rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
desc.rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
side->lightdef = SurfaceLights.Push(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Surface lights: %i\n", numSurfLights);
|
||||
}
|
||||
|
||||
LevelTraceHit FLevel::Trace(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||
{
|
||||
TraceHit hit = TriangleMeshShape::find_first_hit(CollisionMesh.get(), startVec, endVec);
|
||||
|
||||
LevelTraceHit trace;
|
||||
trace.start = startVec;
|
||||
trace.end = endVec;
|
||||
trace.fraction = hit.fraction;
|
||||
if (trace.fraction < 1.0f)
|
||||
for (unsigned int i = 0; i < Sectors.Size(); i++)
|
||||
{
|
||||
int elementIdx = hit.triangle * 3;
|
||||
trace.hitSurface = surfaces[MeshSurfaces[hit.triangle]].get();
|
||||
trace.indices[0] = MeshUVIndex[MeshElements[elementIdx]];
|
||||
trace.indices[1] = MeshUVIndex[MeshElements[elementIdx + 1]];
|
||||
trace.indices[2] = MeshUVIndex[MeshElements[elementIdx + 2]];
|
||||
trace.b = hit.b;
|
||||
trace.c = hit.c;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace.hitSurface = nullptr;
|
||||
trace.indices[0] = 0;
|
||||
trace.indices[1] = 0;
|
||||
trace.indices[2] = 0;
|
||||
trace.b = 0.0f;
|
||||
trace.c = 0.0f;
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
IntSector *sector = &Sectors[i];
|
||||
|
||||
bool FLevel::TraceAnyHit(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||
{
|
||||
return TriangleMeshShape::find_any_hit(CollisionMesh.get(), startVec, endVec);
|
||||
sector->floorlightdef = -1;
|
||||
sector->ceilinglightdef = -1;
|
||||
|
||||
uint32_t lightcolor = 0xffffff;
|
||||
float lightintensity = 1.0f;
|
||||
float lightdistance = 0.0f;
|
||||
|
||||
for (unsigned int propIndex = 0; propIndex < sector->props.Size(); propIndex++)
|
||||
{
|
||||
const UDMFKey &key = sector->props[propIndex];
|
||||
if (!stricmp(key.key, "lightcolorfloor"))
|
||||
{
|
||||
lightcolor = atoi(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightintensityfloor"))
|
||||
{
|
||||
lightintensity = atof(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightdistancefloor"))
|
||||
{
|
||||
lightdistance = atof(key.value);
|
||||
}
|
||||
}
|
||||
|
||||
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
||||
{
|
||||
surfaceLightDef desc;
|
||||
desc.intensity = lightintensity;
|
||||
desc.distance = lightdistance;
|
||||
desc.rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
desc.rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
desc.rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
sector->floorlightdef = SurfaceLights.Push(desc);
|
||||
}
|
||||
|
||||
lightcolor = 0xffffff;
|
||||
lightintensity = 1.0f;
|
||||
lightdistance = 0.0f;
|
||||
|
||||
for (unsigned int propIndex = 0; propIndex < sector->props.Size(); propIndex++)
|
||||
{
|
||||
const UDMFKey &key = sector->props[propIndex];
|
||||
if (!stricmp(key.key, "lightcolorceiling"))
|
||||
{
|
||||
lightcolor = atoi(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightintensityceiling"))
|
||||
{
|
||||
lightintensity = atof(key.value);
|
||||
}
|
||||
else if (!stricmp(key.key, "lightdistanceceiling"))
|
||||
{
|
||||
lightdistance = atof(key.value);
|
||||
}
|
||||
}
|
||||
|
||||
if (lightdistance > 0.0f && lightintensity > 0.0f && lightcolor != 0)
|
||||
{
|
||||
surfaceLightDef desc;
|
||||
desc.intensity = lightintensity;
|
||||
desc.distance = lightdistance;
|
||||
desc.rgb.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||
desc.rgb.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||
desc.rgb.z = (lightcolor & 0xff) / 255.0f;
|
||||
sector->ceilinglightdef = SurfaceLights.Push(desc);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Surface lights: %i\n", (int)SurfaceLights.Size());
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ bool kexLightmapBuilder::EmitFromCeiling(const surface_t *surface, const kexVec3
|
|||
return false;
|
||||
}
|
||||
|
||||
LevelTraceHit trace = map->Trace(origin, origin + (map->GetSunDirection() * 32768.0f));
|
||||
LevelTraceHit trace = mesh->Trace(origin, origin + (map->GetSunDirection() * 32768.0f));
|
||||
|
||||
if (trace.fraction == 1.0f)
|
||||
{
|
||||
|
@ -216,9 +216,9 @@ kexVec3 kexLightmapBuilder::LightTexelSample(const kexVec3 &origin, surface_t *s
|
|||
kexVec3 color(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// check all thing lights
|
||||
for (size_t i = 0; i < map->thingLights.size(); i++)
|
||||
for (unsigned int i = 0; i < map->ThingLights.Size(); i++)
|
||||
{
|
||||
thingLight_t *tl = map->thingLights[i].get();
|
||||
thingLight_t *tl = &map->ThingLights[i];
|
||||
|
||||
float originZ;
|
||||
if (!tl->bCeiling)
|
||||
|
@ -265,7 +265,7 @@ kexVec3 kexLightmapBuilder::LightTexelSample(const kexVec3 &origin, surface_t *s
|
|||
}
|
||||
}
|
||||
|
||||
if (map->TraceAnyHit(lightOrigin, origin))
|
||||
if (mesh->TraceAnyHit(lightOrigin, origin))
|
||||
{
|
||||
// this light is occluded by something
|
||||
continue;
|
||||
|
@ -291,11 +291,11 @@ kexVec3 kexLightmapBuilder::LightTexelSample(const kexVec3 &origin, surface_t *s
|
|||
}
|
||||
|
||||
// trace against surface lights
|
||||
for (size_t i = 0; i < map->lightSurfaces.size(); ++i)
|
||||
for (size_t i = 0; i < lightSurfaces.size(); ++i)
|
||||
{
|
||||
kexLightSurface *surfaceLight = map->lightSurfaces[i].get();
|
||||
kexLightSurface *surfaceLight = lightSurfaces[i].get();
|
||||
|
||||
float attenuation = surfaceLight->TraceSurface(map, surface, origin);
|
||||
float attenuation = surfaceLight->TraceSurface(mesh.get(), surface, origin);
|
||||
if (attenuation > 0.0f)
|
||||
{
|
||||
color += surfaceLight->GetRGB() * surfaceLight->Intensity() * attenuation;
|
||||
|
@ -601,7 +601,7 @@ void kexLightmapBuilder::TraceIndirectLight(surface_t *surface)
|
|||
if (NdotL > 0.0f)
|
||||
{
|
||||
tracedTexels++;
|
||||
LevelTraceHit hit = map->Trace(pos, pos + L * 1000.0f);
|
||||
LevelTraceHit hit = mesh->Trace(pos, pos + L * 1000.0f);
|
||||
if (hit.fraction < 1.0f)
|
||||
{
|
||||
kexVec3 surfaceLight;
|
||||
|
@ -653,12 +653,12 @@ void kexLightmapBuilder::TraceIndirectLight(surface_t *surface)
|
|||
|
||||
void kexLightmapBuilder::LightSurface(const int surfid)
|
||||
{
|
||||
BuildSurfaceParams(surfaces[surfid].get());
|
||||
TraceSurface(surfaces[surfid].get());
|
||||
BuildSurfaceParams(mesh->surfaces[surfid].get());
|
||||
TraceSurface(mesh->surfaces[surfid].get());
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
int numsurfs = surfaces.size();
|
||||
int numsurfs = mesh->surfaces.size();
|
||||
int lastproc = processed * 100 / numsurfs;
|
||||
processed++;
|
||||
int curproc = processed * 100 / numsurfs;
|
||||
|
@ -671,9 +671,9 @@ void kexLightmapBuilder::LightSurface(const int surfid)
|
|||
|
||||
void kexLightmapBuilder::LightIndirect(const int surfid)
|
||||
{
|
||||
TraceIndirectLight(surfaces[surfid].get());
|
||||
TraceIndirectLight(mesh->surfaces[surfid].get());
|
||||
|
||||
int numsurfs = surfaces.size();
|
||||
int numsurfs = mesh->surfaces.size();
|
||||
int lastproc = processed * 100 / numsurfs;
|
||||
processed++;
|
||||
int curproc = processed * 100 / numsurfs;
|
||||
|
@ -684,9 +684,52 @@ void kexLightmapBuilder::LightIndirect(const int surfid)
|
|||
}
|
||||
}
|
||||
|
||||
void kexLightmapBuilder::CreateLightSurfaces()
|
||||
{
|
||||
for (size_t j = 0; j < mesh->surfaces.size(); ++j)
|
||||
{
|
||||
surface_t *surface = mesh->surfaces[j].get();
|
||||
|
||||
if (surface->type >= ST_MIDDLESIDE && surface->type <= ST_LOWERSIDE)
|
||||
{
|
||||
int lightdefidx = map->Sides[surface->typeIndex].lightdef;
|
||||
if (lightdefidx != -1)
|
||||
{
|
||||
auto lightSurface = std::make_unique<kexLightSurface>(map->SurfaceLights[lightdefidx], surface);
|
||||
lightSurface->Subdivide(16);
|
||||
lightSurfaces.push_back(std::move(lightSurface));
|
||||
}
|
||||
}
|
||||
else if (surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
||||
{
|
||||
MapSubsectorEx *sub = &map->GLSubsectors[surface->typeIndex];
|
||||
IntSector *sector = map->GetSectorFromSubSector(sub);
|
||||
|
||||
if (sector && surface->numVerts > 0)
|
||||
{
|
||||
if (sector->floorlightdef != -1 && surface->type == ST_FLOOR)
|
||||
{
|
||||
auto lightSurface = std::make_unique<kexLightSurface>(map->SurfaceLights[sector->floorlightdef], surface);
|
||||
lightSurface->Subdivide(16);
|
||||
lightSurfaces.push_back(std::move(lightSurface));
|
||||
}
|
||||
else if (sector->ceilinglightdef != -1 && surface->type == ST_CEILING)
|
||||
{
|
||||
auto lightSurface = std::make_unique<kexLightSurface>(map->SurfaceLights[sector->ceilinglightdef], surface);
|
||||
lightSurface->Subdivide(16);
|
||||
lightSurfaces.push_back(std::move(lightSurface));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
||||
{
|
||||
map = &doomMap;
|
||||
mesh = std::make_unique<LevelMesh>(doomMap);
|
||||
|
||||
CreateLightSurfaces();
|
||||
|
||||
printf("-------------- Tracing cells ---------------\n");
|
||||
|
||||
|
@ -704,7 +747,7 @@ void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
|||
|
||||
tracedTexels = 0;
|
||||
processed = 0;
|
||||
kexWorker::RunJob(surfaces.size(), [=](int id) {
|
||||
kexWorker::RunJob(mesh->surfaces.size(), [=](int id) {
|
||||
LightSurface(id);
|
||||
});
|
||||
|
||||
|
@ -716,7 +759,7 @@ void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
|||
|
||||
tracedTexels = 0;
|
||||
processed = 0;
|
||||
kexWorker::RunJob(surfaces.size(), [=](int id) {
|
||||
kexWorker::RunJob(mesh->surfaces.size(), [=](int id) {
|
||||
LightIndirect(id);
|
||||
});
|
||||
|
||||
|
@ -736,7 +779,7 @@ void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
|||
|
||||
void kexLightmapBuilder::SetupLightCellGrid()
|
||||
{
|
||||
kexBBox worldBBox = map->CollisionMesh->get_bbox();
|
||||
kexBBox worldBBox = mesh->CollisionMesh->get_bbox();
|
||||
float blockWorldSize = LIGHTCELL_BLOCK_SIZE * LIGHTCELL_SIZE;
|
||||
grid.x = static_cast<int>(std::floor(worldBBox.min.x / blockWorldSize));
|
||||
grid.y = static_cast<int>(std::floor(worldBBox.min.y / blockWorldSize));
|
||||
|
@ -845,15 +888,16 @@ void kexLightmapBuilder::LightBlock(int id)
|
|||
float remaining = (float)processed / (float)numblocks;
|
||||
printf("%i%c cells done\r", (int)(remaining * 100.0f), '%');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void kexLightmapBuilder::AddLightmapLump(FWadWriter &wadFile)
|
||||
{
|
||||
const auto &surfaces = mesh->surfaces;
|
||||
|
||||
// Calculate size of lump
|
||||
int numTexCoords = 0;
|
||||
int numSurfaces = 0;
|
||||
for (size_t i = 0; i < surfaces.size(); i++)
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
if (surfaces[i]->lightmapNum != -1)
|
||||
{
|
||||
|
@ -1018,78 +1062,3 @@ void kexLightmapBuilder::WriteTexturesToTGA()
|
|||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void kexLightmapBuilder::WriteMeshToOBJ()
|
||||
{
|
||||
FILE *f = fopen("mesh.obj", "w");
|
||||
|
||||
std::map<int, std::vector<surface_t*>> sortedSurfs;
|
||||
|
||||
for (unsigned int i = 0; i < surfaces.size(); i++)
|
||||
sortedSurfs[surfaces[i]->lightmapNum].push_back(surfaces[i].get());
|
||||
|
||||
for (const auto &it : sortedSurfs)
|
||||
{
|
||||
for (const auto &s : it.second)
|
||||
{
|
||||
for (int j = 0; j < s->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "v %f %f %f\n", s->verts[j].x, s->verts[j].z + 100.0f, s->verts[j].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &it : sortedSurfs)
|
||||
{
|
||||
for (const auto &s : it.second)
|
||||
{
|
||||
for (int j = 0; j < s->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "vt %f %f\n", s->lightmapCoords[j * 2], s->lightmapCoords[j * 2 + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int voffset = 1;
|
||||
for (const auto &it : sortedSurfs)
|
||||
{
|
||||
int lightmapNum = it.first;
|
||||
|
||||
if (lightmapNum != -1)
|
||||
fprintf(f, "usemtl lightmap_%02d\n", lightmapNum);
|
||||
else
|
||||
fprintf(f, "usemtl black\n");
|
||||
|
||||
for (const auto &s : it.second)
|
||||
{
|
||||
switch (s->type)
|
||||
{
|
||||
case ST_FLOOR:
|
||||
for (int j = 2; j < s->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset + j, voffset + j, voffset + j - 1, voffset + j - 1, voffset, voffset);
|
||||
}
|
||||
break;
|
||||
case ST_CEILING:
|
||||
for (int j = 2; j < s->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset, voffset, voffset + j - 1, voffset + j - 1, voffset + j, voffset + j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (int j = 2; j < s->numVerts; j++)
|
||||
{
|
||||
if (j % 2 == 0)
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset + j - 2, voffset + j - 2, voffset + j - 1, voffset + j - 1, voffset + j, voffset + j);
|
||||
else
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset + j, voffset + j, voffset + j - 1, voffset + j - 1, voffset + j - 2, voffset + j - 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
voffset += s->numVerts;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define LIGHTCELL_BLOCK_SIZE 16
|
||||
|
||||
class FWadWriter;
|
||||
class kexLightSurface;
|
||||
|
||||
class LightCellBlock
|
||||
{
|
||||
|
@ -62,7 +63,6 @@ public:
|
|||
|
||||
void CreateLightmaps(FLevel &doomMap);
|
||||
//void WriteTexturesToTGA();
|
||||
void WriteMeshToOBJ();
|
||||
void AddLightmapLump(FWadWriter &wadFile);
|
||||
|
||||
int samples = 16;
|
||||
|
@ -85,7 +85,11 @@ private:
|
|||
void LightSurface(const int surfid);
|
||||
void LightIndirect(const int surfid);
|
||||
|
||||
void CreateLightSurfaces();
|
||||
|
||||
std::unique_ptr<LevelMesh> mesh;
|
||||
FLevel *map;
|
||||
std::vector<std::unique_ptr<kexLightSurface>> lightSurfaces;
|
||||
std::vector<std::vector<uint16_t>> textures;
|
||||
std::vector<uint16_t> indirectoutput;
|
||||
std::vector<std::vector<int>> allocBlocks;
|
||||
|
|
|
@ -241,7 +241,7 @@ void kexLightSurface::Subdivide(const float divide)
|
|||
}
|
||||
}
|
||||
|
||||
float kexLightSurface::TraceSurface(FLevel *map, const surface_t *fragmentSurface, const kexVec3 &fragmentPos)
|
||||
float kexLightSurface::TraceSurface(LevelMesh *mesh, const surface_t *fragmentSurface, const kexVec3 &fragmentPos)
|
||||
{
|
||||
if (fragmentSurface == surface)
|
||||
return 1.0f; // light surface will always be fullbright
|
||||
|
@ -286,7 +286,7 @@ float kexLightSurface::TraceSurface(FLevel *map, const surface_t *fragmentSurfac
|
|||
|
||||
// trace the origin to the center of the light surface. nudge by the normals in
|
||||
// case the start/end points are directly on or inside the surface
|
||||
if (map->TraceAnyHit(lightPos + lightSurfaceNormal, fragmentPos + fragmentNormal))
|
||||
if (mesh->TraceAnyHit(lightPos + lightSurfaceNormal, fragmentPos + fragmentNormal))
|
||||
continue; // something is obstructing it
|
||||
|
||||
if (d < closestDistance)
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
~kexLightSurface();
|
||||
|
||||
void Subdivide(const float divide);
|
||||
float TraceSurface(FLevel *doomMap, const surface_t *surface, const kexVec3 &origin);
|
||||
float TraceSurface(LevelMesh *map, const surface_t *surface, const kexVec3 &origin);
|
||||
|
||||
const float Distance() const { return distance; }
|
||||
const float Intensity() const { return intensity; }
|
||||
|
|
|
@ -24,24 +24,83 @@
|
|||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Prepares geometry from map structures
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "math/mathlib.h"
|
||||
#include "level/level.h"
|
||||
#include "surfaces.h"
|
||||
#include <map>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4267) // warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
|
||||
#pragma warning(disable: 4244) // warning C4244: '=': conversion from '__int64' to 'int', possible loss of data
|
||||
#endif
|
||||
|
||||
std::vector<std::unique_ptr<surface_t>> surfaces;
|
||||
LevelMesh::LevelMesh(FLevel &doomMap)
|
||||
{
|
||||
printf("------------- Building side surfaces -------------\n");
|
||||
|
||||
static void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
|
||||
for (unsigned int i = 0; i < doomMap.Sides.Size(); i++)
|
||||
{
|
||||
CreateSideSurfaces(doomMap, &doomMap.Sides[i]);
|
||||
printf("sides: %i / %i\r", i + 1, doomMap.Sides.Size());
|
||||
}
|
||||
|
||||
printf("\nSide surfaces: %i\n", (int)surfaces.size());
|
||||
|
||||
CreateSubsectorSurfaces(doomMap);
|
||||
|
||||
printf("Surfaces total: %i\n\n", (int)surfaces.size());
|
||||
|
||||
printf("Building collision mesh..\n\n");
|
||||
|
||||
for (size_t i = 0; i < surfaces.size(); i++)
|
||||
{
|
||||
const auto &s = surfaces[i];
|
||||
int numVerts = s->numVerts;
|
||||
unsigned int pos = MeshVertices.Size();
|
||||
|
||||
for (int j = 0; j < numVerts; j++)
|
||||
{
|
||||
MeshVertices.Push(s->verts[j]);
|
||||
MeshUVIndex.Push(j);
|
||||
}
|
||||
|
||||
if (s->type == ST_FLOOR || s->type == ST_CEILING)
|
||||
{
|
||||
for (int j = 2; j < numVerts; j++)
|
||||
{
|
||||
if (!IsDegenerate(s->verts[0], s->verts[j - 1], s->verts[j]))
|
||||
{
|
||||
MeshElements.Push(pos);
|
||||
MeshElements.Push(pos + j - 1);
|
||||
MeshElements.Push(pos + j);
|
||||
MeshSurfaces.Push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s->type == ST_MIDDLESIDE || s->type == ST_UPPERSIDE || s->type == ST_LOWERSIDE)
|
||||
{
|
||||
if (!IsDegenerate(s->verts[0], s->verts[1], s->verts[2]))
|
||||
{
|
||||
MeshElements.Push(pos + 0);
|
||||
MeshElements.Push(pos + 1);
|
||||
MeshElements.Push(pos + 2);
|
||||
MeshSurfaces.Push(i);
|
||||
}
|
||||
if (!IsDegenerate(s->verts[1], s->verts[2], s->verts[3]))
|
||||
{
|
||||
MeshElements.Push(pos + 1);
|
||||
MeshElements.Push(pos + 2);
|
||||
MeshElements.Push(pos + 3);
|
||||
MeshSurfaces.Push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CollisionMesh = std::make_unique<TriangleMeshShape>(&MeshVertices[0], MeshVertices.Size(), &MeshElements[0], MeshElements.Size());
|
||||
}
|
||||
|
||||
void LevelMesh::CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
|
||||
{
|
||||
IntSector *front;
|
||||
IntSector *back;
|
||||
|
@ -151,10 +210,8 @@ static void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
|
|||
if (v1Top > v1TopBack || v2Top > v2TopBack)
|
||||
{
|
||||
bool bSky = false;
|
||||
int frontidx = front - &doomMap.Sectors[0];
|
||||
int backidx = back - &doomMap.Sectors[0];
|
||||
|
||||
if (doomMap.bSkySectors[frontidx] && doomMap.bSkySectors[backidx])
|
||||
if (front->skySector && back->skySector)
|
||||
{
|
||||
if (front->data.ceilingheight != back->data.ceilingheight && side->toptexture[0] == '-')
|
||||
{
|
||||
|
@ -218,7 +275,7 @@ static void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
|
|||
}
|
||||
}
|
||||
|
||||
static void CreateFloorSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor)
|
||||
void LevelMesh::CreateFloorSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor)
|
||||
{
|
||||
auto surf = std::make_unique<surface_t>();
|
||||
surf->numVerts = sub->numlines;
|
||||
|
@ -250,16 +307,12 @@ static void CreateFloorSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *
|
|||
surfaces.push_back(std::move(surf));
|
||||
}
|
||||
|
||||
static void CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor)
|
||||
void LevelMesh::CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor)
|
||||
{
|
||||
auto surf = std::make_unique<surface_t>();
|
||||
surf->numVerts = sub->numlines;
|
||||
surf->verts.resize(surf->numVerts);
|
||||
|
||||
if (doomMap.bSkySectors[sector - &doomMap.Sectors[0]])
|
||||
{
|
||||
surf->bSky = true;
|
||||
}
|
||||
surf->bSky = sector->skySector;
|
||||
|
||||
if (!is3DFloor)
|
||||
{
|
||||
|
@ -287,7 +340,7 @@ static void CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector
|
|||
surfaces.push_back(std::move(surf));
|
||||
}
|
||||
|
||||
static void CreateSubsectorSurfaces(FLevel &doomMap)
|
||||
void LevelMesh::CreateSubsectorSurfaces(FLevel &doomMap)
|
||||
{
|
||||
printf("------------- Building subsector surfaces -------------\n");
|
||||
|
||||
|
@ -319,7 +372,42 @@ static void CreateSubsectorSurfaces(FLevel &doomMap)
|
|||
printf("\nLeaf surfaces: %i\n", (int)surfaces.size() - doomMap.NumGLSubsectors);
|
||||
}
|
||||
|
||||
static bool IsDegenerate(const kexVec3 &v0, const kexVec3 &v1, const kexVec3 &v2)
|
||||
LevelTraceHit LevelMesh::Trace(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||
{
|
||||
TraceHit hit = TriangleMeshShape::find_first_hit(CollisionMesh.get(), startVec, endVec);
|
||||
|
||||
LevelTraceHit trace;
|
||||
trace.start = startVec;
|
||||
trace.end = endVec;
|
||||
trace.fraction = hit.fraction;
|
||||
if (trace.fraction < 1.0f)
|
||||
{
|
||||
int elementIdx = hit.triangle * 3;
|
||||
trace.hitSurface = surfaces[MeshSurfaces[hit.triangle]].get();
|
||||
trace.indices[0] = MeshUVIndex[MeshElements[elementIdx]];
|
||||
trace.indices[1] = MeshUVIndex[MeshElements[elementIdx + 1]];
|
||||
trace.indices[2] = MeshUVIndex[MeshElements[elementIdx + 2]];
|
||||
trace.b = hit.b;
|
||||
trace.c = hit.c;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace.hitSurface = nullptr;
|
||||
trace.indices[0] = 0;
|
||||
trace.indices[1] = 0;
|
||||
trace.indices[2] = 0;
|
||||
trace.b = 0.0f;
|
||||
trace.c = 0.0f;
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
bool LevelMesh::TraceAnyHit(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||
{
|
||||
return TriangleMeshShape::find_any_hit(CollisionMesh.get(), startVec, endVec);
|
||||
}
|
||||
|
||||
bool LevelMesh::IsDegenerate(const kexVec3 &v0, const kexVec3 &v1, const kexVec3 &v2)
|
||||
{
|
||||
// A degenerate triangle has a zero cross product for two of its sides.
|
||||
float ax = v1.x - v0.x;
|
||||
|
@ -335,104 +423,77 @@ static bool IsDegenerate(const kexVec3 &v0, const kexVec3 &v1, const kexVec3 &v2
|
|||
return crosslengthsqr <= 1.e-6f;
|
||||
}
|
||||
|
||||
void CreateSurfaces(FLevel &doomMap)
|
||||
void LevelMesh::WriteMeshToOBJ()
|
||||
{
|
||||
surfaces.clear();
|
||||
FILE *f = fopen("mesh.obj", "w");
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.Sectors.Size(); i++)
|
||||
doomMap.Sectors[i].controlsector = false;
|
||||
std::map<int, std::vector<surface_t*>> sortedSurfs;
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.Sides.Size(); i++)
|
||||
doomMap.Sides[i].line = nullptr;
|
||||
for (unsigned int i = 0; i < surfaces.size(); i++)
|
||||
sortedSurfs[surfaces[i]->lightmapNum].push_back(surfaces[i].get());
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.Lines.Size(); i++)
|
||||
for (const auto &it : sortedSurfs)
|
||||
{
|
||||
IntLineDef *line = &doomMap.Lines[i];
|
||||
|
||||
// Link sides to lines
|
||||
if (line->sidenum[0] < doomMap.Sides.Size())
|
||||
doomMap.Sides[line->sidenum[0]].line = line;
|
||||
if (line->sidenum[1] < doomMap.Sides.Size())
|
||||
doomMap.Sides[line->sidenum[1]].line = line;
|
||||
|
||||
if (line->special == 160) // Sector_Set3dFloor
|
||||
for (const auto &s : it.second)
|
||||
{
|
||||
int sectorTag = line->args[0];
|
||||
int type = line->args[1];
|
||||
//int opacity = line.args[3];
|
||||
|
||||
IntSector *controlsector = &doomMap.Sectors[doomMap.Sides[doomMap.Lines[i].sidenum[0]].sector];
|
||||
controlsector->controlsector = true;
|
||||
|
||||
for (unsigned int j = 0; j < doomMap.Sectors.Size(); j++)
|
||||
for (int j = 0; j < s->numVerts; j++)
|
||||
{
|
||||
if (doomMap.Sectors[j].data.tag == sectorTag)
|
||||
fprintf(f, "v %f %f %f\n", s->verts[j].x, s->verts[j].z + 100.0f, s->verts[j].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &it : sortedSurfs)
|
||||
{
|
||||
for (const auto &s : it.second)
|
||||
{
|
||||
for (int j = 0; j < s->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "vt %f %f\n", s->lightmapCoords[j * 2], s->lightmapCoords[j * 2 + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int voffset = 1;
|
||||
for (const auto &it : sortedSurfs)
|
||||
{
|
||||
int lightmapNum = it.first;
|
||||
|
||||
if (lightmapNum != -1)
|
||||
fprintf(f, "usemtl lightmap_%02d\n", lightmapNum);
|
||||
else
|
||||
fprintf(f, "usemtl black\n");
|
||||
|
||||
for (const auto &s : it.second)
|
||||
{
|
||||
switch (s->type)
|
||||
{
|
||||
case ST_FLOOR:
|
||||
for (int j = 2; j < s->numVerts; j++)
|
||||
{
|
||||
doomMap.Sectors[j].x3dfloors.Push(controlsector);
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset + j, voffset + j, voffset + j - 1, voffset + j - 1, voffset, voffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("------------- Building side surfaces -------------\n");
|
||||
|
||||
for (unsigned int i = 0; i < doomMap.Sides.Size(); i++)
|
||||
{
|
||||
CreateSideSurfaces(doomMap, &doomMap.Sides[i]);
|
||||
printf("sides: %i / %i\r", i + 1, doomMap.Sides.Size());
|
||||
}
|
||||
|
||||
printf("\nSide surfaces: %i\n", (int)surfaces.size());
|
||||
|
||||
CreateSubsectorSurfaces(doomMap);
|
||||
|
||||
printf("Surfaces total: %i\n\n", (int)surfaces.size());
|
||||
|
||||
printf("Building collision mesh..\n\n");
|
||||
|
||||
for (size_t i = 0; i < surfaces.size(); i++)
|
||||
{
|
||||
const auto &s = surfaces[i];
|
||||
int numVerts = s->numVerts;
|
||||
unsigned int pos = doomMap.MeshVertices.Size();
|
||||
|
||||
for (int j = 0; j < numVerts; j++)
|
||||
{
|
||||
doomMap.MeshVertices.Push(s->verts[j]);
|
||||
doomMap.MeshUVIndex.Push(j);
|
||||
}
|
||||
|
||||
if (s->type == ST_FLOOR || s->type == ST_CEILING)
|
||||
{
|
||||
for (int j = 2; j < numVerts; j++)
|
||||
{
|
||||
if (!IsDegenerate(s->verts[0], s->verts[j - 1], s->verts[j]))
|
||||
break;
|
||||
case ST_CEILING:
|
||||
for (int j = 2; j < s->numVerts; j++)
|
||||
{
|
||||
doomMap.MeshElements.Push(pos);
|
||||
doomMap.MeshElements.Push(pos + j - 1);
|
||||
doomMap.MeshElements.Push(pos + j);
|
||||
doomMap.MeshSurfaces.Push(i);
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset, voffset, voffset + j - 1, voffset + j - 1, voffset + j, voffset + j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (int j = 2; j < s->numVerts; j++)
|
||||
{
|
||||
if (j % 2 == 0)
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset + j - 2, voffset + j - 2, voffset + j - 1, voffset + j - 1, voffset + j, voffset + j);
|
||||
else
|
||||
fprintf(f, "f %d/%d %d/%d %d/%d\n", voffset + j, voffset + j, voffset + j - 1, voffset + j - 1, voffset + j - 2, voffset + j - 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (s->type == ST_MIDDLESIDE || s->type == ST_UPPERSIDE || s->type == ST_LOWERSIDE)
|
||||
{
|
||||
if (!IsDegenerate(s->verts[0], s->verts[1], s->verts[2]))
|
||||
{
|
||||
doomMap.MeshElements.Push(pos + 0);
|
||||
doomMap.MeshElements.Push(pos + 1);
|
||||
doomMap.MeshElements.Push(pos + 2);
|
||||
doomMap.MeshSurfaces.Push(i);
|
||||
}
|
||||
if (!IsDegenerate(s->verts[1], s->verts[2], s->verts[3]))
|
||||
{
|
||||
doomMap.MeshElements.Push(pos + 1);
|
||||
doomMap.MeshElements.Push(pos + 2);
|
||||
doomMap.MeshElements.Push(pos + 3);
|
||||
doomMap.MeshSurfaces.Push(i);
|
||||
}
|
||||
|
||||
voffset += s->numVerts;
|
||||
}
|
||||
}
|
||||
|
||||
doomMap.CollisionMesh = std::make_unique<TriangleMeshShape>(&doomMap.MeshVertices[0], doomMap.MeshVertices.Size(), &doomMap.MeshElements[0], doomMap.MeshElements.Size());
|
||||
fclose(f);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,13 @@
|
|||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "framework/tarray.h"
|
||||
#include "lightmap/collision.h"
|
||||
|
||||
struct MapSubsectorEx;
|
||||
struct IntSector;
|
||||
struct IntSideDef;
|
||||
struct FLevel;
|
||||
|
||||
enum surfaceType_t
|
||||
{
|
||||
|
@ -45,8 +51,6 @@ enum surfaceType_t
|
|||
// convert from fixed point(FRACUNIT) to floating point
|
||||
#define F(x) (((float)(x))/65536.0f)
|
||||
|
||||
struct IntSector;
|
||||
|
||||
struct surface_t
|
||||
{
|
||||
kexPlane plane;
|
||||
|
@ -66,8 +70,41 @@ struct surface_t
|
|||
bool bSky;
|
||||
};
|
||||
|
||||
extern std::vector<std::unique_ptr<surface_t>> surfaces;
|
||||
struct LevelTraceHit
|
||||
{
|
||||
kexVec3 start;
|
||||
kexVec3 end;
|
||||
float fraction;
|
||||
|
||||
struct FLevel;
|
||||
surface_t *hitSurface;
|
||||
int indices[3];
|
||||
float b, c;
|
||||
};
|
||||
|
||||
void CreateSurfaces(FLevel &doomMap);
|
||||
class LevelMesh
|
||||
{
|
||||
public:
|
||||
LevelMesh(FLevel &doomMap);
|
||||
|
||||
LevelTraceHit Trace(const kexVec3 &startVec, const kexVec3 &endVec);
|
||||
bool TraceAnyHit(const kexVec3 &startVec, const kexVec3 &endVec);
|
||||
|
||||
void WriteMeshToOBJ();
|
||||
|
||||
std::vector<std::unique_ptr<surface_t>> surfaces;
|
||||
|
||||
TArray<kexVec3> MeshVertices;
|
||||
TArray<int> MeshUVIndex;
|
||||
TArray<unsigned int> MeshElements;
|
||||
TArray<int> MeshSurfaces;
|
||||
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
||||
|
||||
private:
|
||||
void CreateSubsectorSurfaces(FLevel &doomMap);
|
||||
void CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor);
|
||||
void CreateFloorSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor);
|
||||
|
||||
void CreateSideSurfaces(FLevel &doomMap, IntSideDef *side);
|
||||
|
||||
static bool IsDegenerate(const kexVec3 &v0, const kexVec3 &v1, const kexVec3 &v2);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue