Browse Source

Invent some texture UVs that remain within each face's UV bounds, to prevent tiling and still get some UVs that make at least a bit of sense.

master
Nico de Poel 3 years ago
parent
commit
6c2d61b2dc
  1. 58
      main.cpp

58
main.cpp

@ -112,7 +112,6 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
std::vector<ps1bsp_face_t> outFaces;
std::vector<ps1bsp_facevertex_t> outFaceVertices;
FaceBounds faceBounds;
VertexFaces vertexFaces;
for (int faceIdx = 0; faceIdx < world->numFaces; ++faceIdx)
{
face_t* face = &world->faces[faceIdx];
@ -126,6 +125,9 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
outFace.firstFaceVertex = (unsigned short)outFaceVertices.size();
outFace.textureId = (unsigned char)texinfo->texture_id;
float minS = FLT_MAX, minT = FLT_MAX;
float maxS = FLT_MIN, maxT = FLT_MIN;
// Traverse the list of face edges to collect all of the face's vertices
Vec3 vertexSum;
BoundBox bounds;
@ -140,19 +142,11 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
const vertex_t* vertex = &world->vertices[vertIndex];
Vec3 vertexPoint = vertex->toVec();
ps1bsp_facevertex_t faceVertex = { 0 };
faceVertex.index = vertIndex;
faceVertex.light = 0;
// Calculate texture UVs
// Calculate texture UV bounds
float s = (vertexPoint.dotProduct(texinfo->vectorS) + texinfo->distS) / miptex->width;
float t = (vertexPoint.dotProduct(texinfo->vectorT) + texinfo->distT) / miptex->height;
// Rescale the UVs to the dimensions of the mipmap we've selected for our texture atlas
faceVertex.u = (unsigned char)(fmodf(s * ps1tex.w, ps1tex.w)); // TODO: fmodf is a nasty fudge to deal with the lack of texture tiling on PS1 hardware
faceVertex.v = (unsigned char)(fmodf(t * ps1tex.h, ps1tex.h)); // We'll need to break up the faces and manually tile I guess...
outFaceVertices.push_back(faceVertex);
if (s > maxS) maxS = s; if (s < minS) minS = s;
if (t > maxT) maxT = t; if (t < minT) minT = t;
// Calculate bounding box of this face
if (edgeListIdx == 0)
@ -160,16 +154,39 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
else
bounds.includePoint(vertexPoint);
auto vertexIter = vertexFaces.find(vertex);
if (vertexIter == vertexFaces.end())
vertexFaces[vertex] = std::unordered_set<const face_t*>{ face };
else
vertexIter->second.insert(face);
// Sum all vertices to calculate an average center point
vertexSum = vertexSum + vertexPoint;
}
// Go over the edges again to fudge some UVs for the vertices (this second pass is only necessary because we don't have texture tiling yet)
for (int edgeListIdx = 0; edgeListIdx < face->ledge_num; ++edgeListIdx)
{
int edgeIdx = world->edgeList[face->ledge_id + edgeListIdx];
unsigned short vertIndex = edgeIdx > 0 ?
world->edges[edgeIdx].vertex0 :
world->edges[-edgeIdx].vertex1;
const vertex_t* vertex = &world->vertices[vertIndex];
Vec3 vertexPoint = vertex->toVec();
ps1bsp_facevertex_t faceVertex = { 0 };
faceVertex.index = vertIndex;
faceVertex.light = 0;
// Calculate texture UVs
float s = (vertexPoint.dotProduct(texinfo->vectorS) + texinfo->distS) / miptex->width;
float t = (vertexPoint.dotProduct(texinfo->vectorT) + texinfo->distT) / miptex->height;
s = (s - minS) / (maxS - minS);
t = (t - minT) / (maxT - minT);
// Rescale the UVs to the dimensions of the mipmap we've selected for our texture atlas
faceVertex.u = (unsigned char)(s * ps1tex.w);
faceVertex.v = (unsigned char)(t * ps1tex.h);
outFaceVertices.push_back(faceVertex);
}
faceBounds[face] = bounds;
// For visualizing and debugging lightmaps
@ -183,8 +200,6 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
outFaces.push_back(outFace);
}
SurfaceList surfaces = group_surfaces(world, vertexFaces);
// Iterate over all faces again; now that we know the bounds of each face, we can calculate lighting for all of them
for (int faceIdx = 0; faceIdx < world->numFaces; ++faceIdx)
{
@ -197,6 +212,9 @@ int process_faces(const world_t* world, const std::vector<ps1bsp_texture_t>& tex
ps1bsp_facevertex_t& faceVertex = outFaceVertices[outFace.firstFaceVertex + faceVertIdx];
const vertex_t* vertex = &world->vertices[faceVertex.index];
faceVertex.light = compute_faceVertex_light4(world, face, faceBounds, vertex->toVec());
faceVertex.light <<= 1;
if (faceVertex.light > 255)
faceVertex.light = 255;
}
}

Loading…
Cancel
Save