mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-10 14:51:40 +00:00
Implement basic linedef sunlight portal support
This commit is contained in:
parent
1427ca5f35
commit
38916e7f75
7 changed files with 254 additions and 42 deletions
|
@ -445,6 +445,7 @@ struct FLevel
|
||||||
FloatVertex GetSegVertex(int index);
|
FloatVertex GetSegVertex(int index);
|
||||||
|
|
||||||
int FindFirstSectorFromTag(int tag);
|
int FindFirstSectorFromTag(int tag);
|
||||||
|
unsigned FindFirstLineId(int lineId);
|
||||||
|
|
||||||
inline IntSector* PointInSector(const dvec2& pos) { return GetSectorFromSubSector(PointInSubSector(int(pos.x), int(pos.y))); }
|
inline IntSector* PointInSector(const dvec2& pos) { return GetSectorFromSubSector(PointInSubSector(int(pos.x), int(pos.y))); }
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -551,6 +551,19 @@ int FLevel::FindFirstSectorFromTag(int tag)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned FLevel::FindFirstLineId(int lineId)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < Lines.Size(); ++i)
|
||||||
|
{
|
||||||
|
for (const auto& e : Lines[i].ids)
|
||||||
|
{
|
||||||
|
if (e == lineId)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void FProcessor::GetPolySpots ()
|
void FProcessor::GetPolySpots ()
|
||||||
{
|
{
|
||||||
if (Extended && CheckPolyobjs)
|
if (Extended && CheckPolyobjs)
|
||||||
|
|
|
@ -39,7 +39,13 @@ struct SurfaceInfo
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
float Sky;
|
float Sky;
|
||||||
float SamplingDistance;
|
float SamplingDistance;
|
||||||
float Padding1, Padding2, Padding3;
|
uint PortalIndex;
|
||||||
|
float Padding1, Padding2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PortalInfo
|
||||||
|
{
|
||||||
|
mat4 Transformation;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LightInfo
|
struct LightInfo
|
||||||
|
@ -59,6 +65,7 @@ struct LightInfo
|
||||||
layout(set = 0, binding = 1) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
|
layout(set = 0, binding = 1) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
|
||||||
layout(set = 0, binding = 2) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
layout(set = 0, binding = 2) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
layout(set = 0, binding = 3) buffer LightBuffer { LightInfo lights[]; };
|
layout(set = 0, binding = 3) buffer LightBuffer { LightInfo lights[]; };
|
||||||
|
layout(set = 0, binding = 4) buffer PortalBuffer { PortalInfo portals[]; };
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants
|
layout(push_constant) uniform PushConstants
|
||||||
{
|
{
|
||||||
|
@ -209,38 +216,7 @@ float RadicalInverse_VdC(uint bits)
|
||||||
|
|
||||||
#if defined(USE_RAYQUERY)
|
#if defined(USE_RAYQUERY)
|
||||||
|
|
||||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
||||||
{
|
|
||||||
rayQueryEXT rayQuery;
|
|
||||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
|
||||||
while(rayQueryProceedEXT(rayQuery)) { }
|
|
||||||
return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
|
||||||
{
|
|
||||||
rayQueryEXT rayQuery;
|
|
||||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
|
||||||
|
|
||||||
while(rayQueryProceedEXT(rayQuery))
|
|
||||||
{
|
|
||||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
|
||||||
{
|
|
||||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
|
||||||
{
|
|
||||||
return rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
|
||||||
{
|
{
|
||||||
rayQueryEXT rayQuery;
|
rayQueryEXT rayQuery;
|
||||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
||||||
|
@ -264,6 +240,16 @@ int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out fl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||||
|
{
|
||||||
|
rayQueryEXT rayQuery;
|
||||||
|
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
||||||
|
while(rayQueryProceedEXT(rayQuery)) { }
|
||||||
|
return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct RayBBox
|
struct RayBBox
|
||||||
|
@ -376,6 +362,7 @@ bool is_leaf(int node_index)
|
||||||
return nodes[node_index].element_index != -1;
|
return nodes[node_index].element_index != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||||
{
|
{
|
||||||
if (tmax <= 0.0f)
|
if (tmax <= 0.0f)
|
||||||
|
@ -410,6 +397,7 @@ bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||||
} while (stackIndex > 0);
|
} while (stackIndex > 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
struct TraceHit
|
struct TraceHit
|
||||||
{
|
{
|
||||||
|
@ -457,13 +445,7 @@ TraceHit find_first_hit(RayBBox ray)
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax, out float tparam)
|
||||||
{
|
|
||||||
float t;
|
|
||||||
return TraceFirstHitTriangleT(origin, tmin, dir, tmax, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float hitFraction)
|
|
||||||
{
|
{
|
||||||
// Perform segmented tracing to keep the ray AABB box smaller
|
// Perform segmented tracing to keep the ray AABB box smaller
|
||||||
vec3 ray_start = origin;
|
vec3 ray_start = origin;
|
||||||
|
@ -480,14 +462,54 @@ int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out fl
|
||||||
TraceHit hit = find_first_hit(ray);
|
TraceHit hit = find_first_hit(ray);
|
||||||
if (hit.fraction < 1.0)
|
if (hit.fraction < 1.0)
|
||||||
{
|
{
|
||||||
hit.fraction = segstart * (1.0 - hit.fraction) + segend * hit.fraction;
|
tparam = hit.fraction = segstart * (1.0 - hit.fraction) + segend * hit.fraction;
|
||||||
return hit.triangle;
|
return hit.triangle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
||||||
|
{
|
||||||
|
int primitiveID;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
primitiveID = TraceFirstHitTriangleNoPortal(origin, tmin, dir, tmax, t);
|
||||||
|
|
||||||
|
if(primitiveID < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||||
|
|
||||||
|
if(surface.PortalIndex == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Portal was hit: Apply transformation onto the ray
|
||||||
|
mat4 transformationMatrix = portals[surface.PortalIndex].Transformation;
|
||||||
|
|
||||||
|
origin = (transformationMatrix * vec4(origin + dir * t, 1.0)).xyz;
|
||||||
|
dir = (transformationMatrix * vec4(dir, 0.0)).xyz;
|
||||||
|
tmax -= t;
|
||||||
|
}
|
||||||
|
return primitiveID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||||
|
{
|
||||||
|
float t;
|
||||||
|
return TraceFirstHitTriangleT(origin, tmin, dir, tmax, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||||
|
{
|
||||||
|
return TraceFirstHitTriangle(origin, tmin, dir, tmax) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -489,6 +489,7 @@ void GPURaytracer::FinishCommands()
|
||||||
void GPURaytracer::CreateVertexAndIndexBuffers()
|
void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
{
|
{
|
||||||
std::vector<SurfaceInfo> surfaces = CreateSurfaceInfo();
|
std::vector<SurfaceInfo> surfaces = CreateSurfaceInfo();
|
||||||
|
std::vector<PortalInfo> portals = CreatePortalInfo();
|
||||||
std::vector<CollisionNode> nodes = CreateCollisionNodes();
|
std::vector<CollisionNode> nodes = CreateCollisionNodes();
|
||||||
|
|
||||||
// std430 alignment rules forces us to convert the vec3 to a vec4
|
// std430 alignment rules forces us to convert the vec3 to a vec4
|
||||||
|
@ -536,6 +537,12 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
.DebugName("surfaceBuffer")
|
.DebugName("surfaceBuffer")
|
||||||
.Create(device.get());
|
.Create(device.get());
|
||||||
|
|
||||||
|
portalBuffer = BufferBuilder()
|
||||||
|
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||||
|
.Size(portals.size() * sizeof(PortalInfo))
|
||||||
|
.DebugName("portalBuffer")
|
||||||
|
.Create(device.get());
|
||||||
|
|
||||||
nodesBuffer = BufferBuilder()
|
nodesBuffer = BufferBuilder()
|
||||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||||
.Size(sizeof(CollisionNodeBufferHeader) + nodes.size() * sizeof(CollisionNode))
|
.Size(sizeof(CollisionNodeBufferHeader) + nodes.size() * sizeof(CollisionNode))
|
||||||
|
@ -547,6 +554,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
.AddBuffer(indexBuffer.get(), mesh->MeshElements.Data(), (size_t)mesh->MeshElements.Size() * sizeof(uint32_t))
|
.AddBuffer(indexBuffer.get(), mesh->MeshElements.Data(), (size_t)mesh->MeshElements.Size() * sizeof(uint32_t))
|
||||||
.AddBuffer(surfaceIndexBuffer.get(), mesh->MeshSurfaces.Data(), (size_t)mesh->MeshSurfaces.Size() * sizeof(uint32_t))
|
.AddBuffer(surfaceIndexBuffer.get(), mesh->MeshSurfaces.Data(), (size_t)mesh->MeshSurfaces.Size() * sizeof(uint32_t))
|
||||||
.AddBuffer(surfaceBuffer.get(), surfaces.data(), surfaces.size() * sizeof(SurfaceInfo))
|
.AddBuffer(surfaceBuffer.get(), surfaces.data(), surfaces.size() * sizeof(SurfaceInfo))
|
||||||
|
.AddBuffer(portalBuffer.get(), portals.data(), portals.size() * sizeof(PortalInfo))
|
||||||
.AddBuffer(nodesBuffer.get(), &nodesHeader, sizeof(CollisionNodeBufferHeader), nodes.data(), nodes.size() * sizeof(CollisionNode))
|
.AddBuffer(nodesBuffer.get(), &nodesHeader, sizeof(CollisionNodeBufferHeader), nodes.data(), nodes.size() * sizeof(CollisionNode))
|
||||||
.Execute(device.get(), cmdbuffer.get());
|
.Execute(device.get(), cmdbuffer.get());
|
||||||
|
|
||||||
|
@ -728,6 +736,7 @@ void GPURaytracer::CreateRaytracePipeline()
|
||||||
.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
|
.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
.DebugName("raytrace.descriptorSetLayout0")
|
.DebugName("raytrace.descriptorSetLayout0")
|
||||||
.Create(device.get());
|
.Create(device.get());
|
||||||
|
|
||||||
|
@ -838,6 +847,7 @@ void GPURaytracer::CreateRaytracePipeline()
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get())
|
.AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get())
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get())
|
.AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get())
|
||||||
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, sceneLightBuffer.get())
|
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, sceneLightBuffer.get())
|
||||||
|
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, portalBuffer.get())
|
||||||
.Execute(device.get());
|
.Execute(device.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,6 +987,16 @@ std::vector<SurfaceInfo> GPURaytracer::CreateSurfaceInfo()
|
||||||
info.Sky = surface->bSky ? 1.0f : 0.0f;
|
info.Sky = surface->bSky ? 1.0f : 0.0f;
|
||||||
info.Normal = surface->plane.Normal();
|
info.Normal = surface->plane.Normal();
|
||||||
info.SamplingDistance = float(surface->sampleDimension);
|
info.SamplingDistance = float(surface->sampleDimension);
|
||||||
|
|
||||||
|
if (surface->portalIndex >= 0)
|
||||||
|
{
|
||||||
|
info.PortalIndex = surface->portalIndex + 1; // Index 0 is already occupied. See GPURaytracer::CreatePortalInfo()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.PortalIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
surfaces.push_back(info);
|
surfaces.push_back(info);
|
||||||
}
|
}
|
||||||
if (surfaces.empty()) // vulkan doesn't support zero byte buffers
|
if (surfaces.empty()) // vulkan doesn't support zero byte buffers
|
||||||
|
@ -984,6 +1004,28 @@ std::vector<SurfaceInfo> GPURaytracer::CreateSurfaceInfo()
|
||||||
return surfaces;
|
return surfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<PortalInfo> GPURaytracer::CreatePortalInfo()
|
||||||
|
{
|
||||||
|
std::vector<PortalInfo> portals;
|
||||||
|
{
|
||||||
|
PortalInfo noPortal;
|
||||||
|
noPortal.Transformation = mat4::identity(); // index 0 will always contain identity matrix (for convenience)
|
||||||
|
portals.push_back(noPortal);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& surface : mesh->surfaces)
|
||||||
|
{
|
||||||
|
if (surface->portalDestinationIndex >= 0)
|
||||||
|
{
|
||||||
|
PortalInfo info;
|
||||||
|
info.Transformation = mesh->portals[surface->portalIndex]->transformation;
|
||||||
|
portals.push_back(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return portals;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CollisionNode> GPURaytracer::CreateCollisionNodes()
|
std::vector<CollisionNode> GPURaytracer::CreateCollisionNodes()
|
||||||
{
|
{
|
||||||
std::vector<CollisionNode> nodes;
|
std::vector<CollisionNode> nodes;
|
||||||
|
|
|
@ -33,9 +33,19 @@ struct SurfaceInfo
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
float Sky;
|
float Sky;
|
||||||
float SamplingDistance;
|
float SamplingDistance;
|
||||||
float Padding1, Padding2, Padding3;
|
uint32_t PortalIndex;
|
||||||
|
float Padding1, Padding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(SurfaceInfo) == sizeof(float) * 8);
|
||||||
|
|
||||||
|
struct PortalInfo
|
||||||
|
{
|
||||||
|
mat4 Transformation;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(PortalInfo) == sizeof(float) * 16);
|
||||||
|
|
||||||
struct LightInfo
|
struct LightInfo
|
||||||
{
|
{
|
||||||
vec3 Origin;
|
vec3 Origin;
|
||||||
|
@ -128,6 +138,7 @@ private:
|
||||||
void PrintVulkanInfo();
|
void PrintVulkanInfo();
|
||||||
|
|
||||||
std::vector<SurfaceInfo> CreateSurfaceInfo();
|
std::vector<SurfaceInfo> CreateSurfaceInfo();
|
||||||
|
std::vector<PortalInfo> CreatePortalInfo();
|
||||||
std::vector<CollisionNode> CreateCollisionNodes();
|
std::vector<CollisionNode> CreateCollisionNodes();
|
||||||
|
|
||||||
static vec2 ToUV(const vec3& vert, const Surface* targetSurface);
|
static vec2 ToUV(const vec3& vert, const Surface* targetSurface);
|
||||||
|
@ -158,6 +169,7 @@ private:
|
||||||
std::unique_ptr<VulkanBuffer> transferBuffer;
|
std::unique_ptr<VulkanBuffer> transferBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> surfaceIndexBuffer;
|
std::unique_ptr<VulkanBuffer> surfaceIndexBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> surfaceBuffer;
|
std::unique_ptr<VulkanBuffer> surfaceBuffer;
|
||||||
|
std::unique_ptr<VulkanBuffer> portalBuffer;
|
||||||
std::unique_ptr<VulkanBuffer> nodesBuffer;
|
std::unique_ptr<VulkanBuffer> nodesBuffer;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
||||||
|
|
|
@ -480,6 +480,117 @@ void LevelMesh::CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
|
||||||
vec2 dx(v2.x - v1.x, v2.y - v1.y);
|
vec2 dx(v2.x - v1.x, v2.y - v1.y);
|
||||||
float distance = length(dx);
|
float distance = length(dx);
|
||||||
|
|
||||||
|
// line portal
|
||||||
|
if (side->line->special == Line_SetPortal && side->line->frontsector == front)
|
||||||
|
{
|
||||||
|
const unsigned destLineIndex = doomMap.FindFirstLineId(side->line->args[0]);
|
||||||
|
|
||||||
|
if (destLineIndex < doomMap.Lines.Size())
|
||||||
|
{
|
||||||
|
float texWidth = 128.0f;
|
||||||
|
float texHeight = 128.0f;
|
||||||
|
|
||||||
|
auto surf = std::make_unique<Surface>();
|
||||||
|
surf->material = side->midtexture;
|
||||||
|
surf->verts.resize(4);
|
||||||
|
surf->bSky = false;
|
||||||
|
|
||||||
|
surf->verts[0].x = surf->verts[2].x = v1.x;
|
||||||
|
surf->verts[0].y = surf->verts[2].y = v1.y;
|
||||||
|
surf->verts[1].x = surf->verts[3].x = v2.x;
|
||||||
|
surf->verts[1].y = surf->verts[3].y = v2.y;
|
||||||
|
surf->verts[0].z = v1Bottom;
|
||||||
|
surf->verts[1].z = v2Bottom;
|
||||||
|
surf->verts[2].z = v1Top;
|
||||||
|
surf->verts[3].z = v2Top;
|
||||||
|
|
||||||
|
surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2], surf->verts[3]);
|
||||||
|
surf->plane.SetDistance(surf->verts[0]);
|
||||||
|
surf->type = ST_MIDDLESIDE;
|
||||||
|
surf->typeIndex = typeIndex;
|
||||||
|
surf->controlSector = nullptr;
|
||||||
|
surf->sampleDimension = (surf->sampleDimension = side->GetSampleDistanceMiddle()) ? surf->sampleDimension : defaultSamples;
|
||||||
|
|
||||||
|
float texZ = surf->verts[0].z;
|
||||||
|
|
||||||
|
surf->texUV.resize(4);
|
||||||
|
surf->texUV[0].x = 0.0f;
|
||||||
|
surf->texUV[1].x = distance / texWidth;
|
||||||
|
surf->texUV[2].x = 0.0f;
|
||||||
|
surf->texUV[3].x = distance / texWidth;
|
||||||
|
surf->texUV[0].y = (surf->verts[0].z - texZ) / texHeight;
|
||||||
|
surf->texUV[1].y = (surf->verts[1].z - texZ) / texHeight;
|
||||||
|
surf->texUV[2].y = (surf->verts[2].z - texZ) / texHeight;
|
||||||
|
surf->texUV[3].y = (surf->verts[3].z - texZ) / texHeight;
|
||||||
|
|
||||||
|
surf->portalDestinationIndex = destLineIndex;
|
||||||
|
|
||||||
|
// Portal calculation
|
||||||
|
{
|
||||||
|
auto portal = std::make_unique<Portal>();
|
||||||
|
|
||||||
|
// Calculate portal transformation
|
||||||
|
{
|
||||||
|
auto& destLine = doomMap.Lines[destLineIndex];
|
||||||
|
FloatVertex destV1 = doomMap.GetSegVertex(destLine.v1);
|
||||||
|
FloatVertex destV2 = doomMap.GetSegVertex(destLine.v2);
|
||||||
|
|
||||||
|
int alignment = side->line->args[3];
|
||||||
|
|
||||||
|
double dstAZ = 0;
|
||||||
|
double dstBZ = 0;
|
||||||
|
double srcAZ = 0;
|
||||||
|
double srcBZ = 0;
|
||||||
|
|
||||||
|
const auto* dstFront = doomMap.GetFrontSector(&doomMap.Sides[destLine.sidenum[0]]);
|
||||||
|
|
||||||
|
if (alignment == 1) // floor
|
||||||
|
{
|
||||||
|
srcAZ = front->floorplane.zAt(v1.x, v1.y);
|
||||||
|
srcBZ = front->floorplane.zAt(v2.x, v2.y);
|
||||||
|
dstAZ = dstFront->floorplane.zAt(destV1.x, destV1.y);
|
||||||
|
dstBZ = dstFront->floorplane.zAt(destV2.x, destV2.y);
|
||||||
|
}
|
||||||
|
else if (alignment == 2) // ceiling
|
||||||
|
{
|
||||||
|
srcAZ = front->ceilingplane.zAt(v1.x, v1.y);
|
||||||
|
srcBZ = front->ceilingplane.zAt(v2.x, v2.y);
|
||||||
|
dstAZ = dstFront->ceilingplane.zAt(destV1.x, destV1.y);
|
||||||
|
dstBZ = dstFront->ceilingplane.zAt(destV2.x, destV2.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec3 vecSrcA = vec3(vec2(v1.x, v1.y), srcAZ);
|
||||||
|
const vec3 vecSrcB = vec3(vec2(v2.x, v2.y), srcAZ);
|
||||||
|
const vec3 vecDstA = vec3(vec2(destV1.x, destV1.y), dstAZ);
|
||||||
|
const vec3 vecDstB = vec3(vec2(destV2.x, destV2.y), dstBZ);
|
||||||
|
|
||||||
|
// Translation
|
||||||
|
vec3 originSrc = (vecSrcB + vecSrcA) * 0.5f;
|
||||||
|
vec3 originDst = (vecDstB + vecDstA) * 0.5f;
|
||||||
|
|
||||||
|
vec3 translation = originDst - originSrc;
|
||||||
|
|
||||||
|
// Rotation
|
||||||
|
// TODO :(
|
||||||
|
|
||||||
|
// printf("Portal translation: %.3f %.3f %.3f\n", translation.x, translation.y, translation.z);
|
||||||
|
|
||||||
|
portal->transformation = mat4::translate(translation);
|
||||||
|
}
|
||||||
|
|
||||||
|
surf->portalIndex = portals.size();
|
||||||
|
portals.push_back(std::move(portal));
|
||||||
|
}
|
||||||
|
|
||||||
|
surfaces.push_back(std::move(surf));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Warn about broken portal?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// line_horizont consumes everything
|
// line_horizont consumes everything
|
||||||
if (side->line->special == Line_Horizon && front != back)
|
if (side->line->special == Line_Horizon && front != back)
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,11 @@ enum SurfaceType
|
||||||
ST_FLOOR
|
ST_FLOOR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Portal
|
||||||
|
{
|
||||||
|
mat4 transformation = mat4::identity();
|
||||||
|
};
|
||||||
|
|
||||||
struct Surface
|
struct Surface
|
||||||
{
|
{
|
||||||
// Surface geometry
|
// Surface geometry
|
||||||
|
@ -77,6 +82,10 @@ struct Surface
|
||||||
int sampleDimension = 0;
|
int sampleDimension = 0;
|
||||||
bool bSky = false;
|
bool bSky = false;
|
||||||
|
|
||||||
|
// Portal
|
||||||
|
int portalDestinationIndex = -1; // line or sector index
|
||||||
|
int portalIndex = -1;
|
||||||
|
|
||||||
// Touching light sources
|
// Touching light sources
|
||||||
std::vector<ThingLight*> LightList;
|
std::vector<ThingLight*> LightList;
|
||||||
|
|
||||||
|
@ -124,6 +133,8 @@ public:
|
||||||
|
|
||||||
std::vector<Plane> smoothingGroups;
|
std::vector<Plane> smoothingGroups;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Portal>> portals;
|
||||||
|
|
||||||
int defaultSamples = 16;
|
int defaultSamples = 16;
|
||||||
int textureWidth = 128;
|
int textureWidth = 128;
|
||||||
int textureHeight = 128;
|
int textureHeight = 128;
|
||||||
|
|
Loading…
Reference in a new issue