|
|
|
@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|