WIP BuildSurfaceParams from ZDRay

This commit is contained in:
RaveYard 2023-08-31 10:07:19 +02:00 committed by Magnus Norddahl
commit 0fc5f254fc
4 changed files with 339 additions and 4 deletions

View file

@ -463,3 +463,115 @@ void DoomLevelMesh::DumpMesh(const FString& filename) const
fclose(f);
}
void DoomLevelMesh::BuildSurfaceParams(int lightMapTextureWidth, int lightMapTextureHeight, Surface& surface)
{
secplane_t* plane;
BBox bounds;
FVector3 roundedSize;
int i;
PlaneAxis axis;
FVector3 tOrigin;
int width;
int height;
float d;
plane = &surface.plane;
bounds = GetBoundsFromSurface(surface);
//surface->bounds = bounds;
if (surface.sampleDimension <= 0)
{
surface.sampleDimension = 1; // TODO change?
}
surface.sampleDimension = 1;
//surface->sampleDimension = Math::RoundPowerOfTwo(surface->sampleDimension);
// round off dimensions
for (i = 0; i < 3; i++)
{
bounds.min[i] = surface.sampleDimension * (floor(bounds.min[i] / surface.sampleDimension) - 1);
bounds.max[i] = surface.sampleDimension * (ceil(bounds.max[i] / surface.sampleDimension) + 1);
roundedSize[i] = (bounds.max[i] - bounds.min[i]) / surface.sampleDimension;
}
FVector3 tCoords[2] = { FVector3(0.0f, 0.0f, 0.0f), FVector3(0.0f, 0.0f, 0.0f) };
axis = BestAxis(*plane);
switch (axis)
{
case AXIS_YZ:
width = (int)roundedSize.Y;
height = (int)roundedSize.Z;
tCoords[0].Y = 1.0f / surface.sampleDimension;
tCoords[1].Z = 1.0f / surface.sampleDimension;
break;
case AXIS_XZ:
width = (int)roundedSize.X;
height = (int)roundedSize.Z;
tCoords[0].X = 1.0f / surface.sampleDimension;
tCoords[1].Z = 1.0f / surface.sampleDimension;
break;
case AXIS_XY:
width = (int)roundedSize.X;
height = (int)roundedSize.Y;
tCoords[0].X = 1.0f / surface.sampleDimension;
tCoords[1].Y = 1.0f / surface.sampleDimension;
break;
}
// clamp width
if (width > lightMapTextureWidth - 2)
{
tCoords[0] *= ((float)(lightMapTextureWidth - 2) / (float)width);
width = (lightMapTextureWidth - 2);
}
// clamp height
if (height > lightMapTextureHeight - 2)
{
tCoords[1] *= ((float)(lightMapTextureHeight - 2) / (float)height);
height = (lightMapTextureHeight - 2);
}
surface.translateWorldToLocal = bounds.min;
surface.projLocalToU = tCoords[0];
surface.projLocalToV = tCoords[1];
surface.startUvIndex = AllocUvs(surface.numVerts);
auto uv = surface.startUvIndex;
for (i = 0; i < surface.numVerts; i++)
{
FVector3 tDelta = MeshVertices[surface.startVertIndex + i] - surface.translateWorldToLocal;
LightmapUvs[uv++] = (tDelta | surface.projLocalToU);
LightmapUvs[uv++] = (tDelta | surface.projLocalToV);
}
tOrigin = bounds.min;
// project tOrigin and tCoords so they lie on the plane
d = float(((bounds.min | FVector3(plane->Normal())) - plane->D) / plane->Normal()[axis]); //d = (plane->PointToDist(bounds.min)) / plane->Normal()[axis];
tOrigin[axis] -= d;
for (i = 0; i < 2; i++)
{
tCoords[i].MakeUnit();
d = (tCoords[i] | FVector3(plane->Normal())) / plane->Normal()[axis]; //d = dot(tCoords[i], plane->Normal()) / plane->Normal()[axis];
tCoords[i][axis] -= d;
}
surface.texWidth = width;
surface.texHeight = height;
//surface->texPixels.resize(width * height);
surface.worldOrigin = tOrigin;
surface.worldStepX = tCoords[0] * (float)surface.sampleDimension;
surface.worldStepY = tCoords[1] * (float)surface.sampleDimension;
}

View file

@ -5,6 +5,7 @@
#include "tarray.h"
#include "vectors.h"
#include "r_defs.h"
#include "bounds.h"
struct FLevelLocals;
@ -17,6 +18,28 @@ struct Surface
secplane_t plane;
sector_t *controlSector;
bool bSky;
//
// Required for internal lightmapper:
int sampleDimension = 0;
// Lightmap world coordinates for the texture
FVector3 worldOrigin = { 0.f, 0.f, 0.f };
FVector3 worldStepX = { 0.f, 0.f, 0.f };
FVector3 worldStepY = { 0.f, 0.f, 0.f };
// Calculate world coordinates to UV coordinates
FVector3 translateWorldToLocal = { 0.f, 0.f, 0.f };
FVector3 projLocalToU = { 0.f, 0.f, 0.f };
FVector3 projLocalToV = { 0.f, 0.f, 0.f };
// Output lightmap for the surface
int texWidth = 0;
int texHeight = 0;
// UV coordinates for the vertices
int startUvIndex = -666;
};
class DoomLevelMesh : public hwrenderer::LevelMesh
@ -37,6 +60,7 @@ public:
}
TArray<Surface> Surfaces;
TArray<float> LightmapUvs;
void DumpMesh(const FString& filename) const;
@ -66,4 +90,69 @@ private:
static FVector4 ToFVector4(const DVector4& v) { return FVector4((float)v.X, (float)v.Y, (float)v.Z, (float)v.W); }
static bool IsDegenerate(const FVector3 &v0, const FVector3 &v1, const FVector3 &v2);
// WIP internal lightmapper
BBox GetBoundsFromSurface(const Surface& surface) const
{
constexpr float M_INFINITY = 1e30; // TODO cleanup
FVector3 low(M_INFINITY, M_INFINITY, M_INFINITY);
FVector3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
for (int i = int(surface.startVertIndex); i < int(surface.startVertIndex) + surface.numVerts; i++)
{
for (int j = 0; j < 3; j++)
{
if (MeshVertices[i][j] < low[j])
{
low[j] = MeshVertices[i][j];
}
if (MeshVertices[i][j] > hi[j])
{
hi[j] = MeshVertices[i][j];
}
}
}
BBox bounds;
bounds.Clear();
bounds.min = low;
bounds.max = hi;
return bounds;
}
enum PlaneAxis
{
AXIS_YZ = 0,
AXIS_XZ,
AXIS_XY
};
inline static PlaneAxis BestAxis(const secplane_t& p)
{
float na = fabs(float(p.Normal().X));
float nb = fabs(float(p.Normal().Y));
float nc = fabs(float(p.Normal().Z));
// figure out what axis the plane lies on
if (na >= nb && na >= nc)
{
return AXIS_YZ;
}
else if (nb >= na && nb >= nc)
{
return AXIS_XZ;
}
return AXIS_XY;
}
int AllocUvs(int amount)
{
return LightmapUvs.Reserve(amount * 2);
}
public:
void BuildSurfaceParams(int lightMapTextureWidth, int lightMapTextureHeight, Surface& surface);
};