Skip to content

Commit

Permalink
allow downscaling wad textures
Browse files Browse the repository at this point in the history
only updates the texture info and coordinates. The texture in the WAD still needs to be updated separately.
  • Loading branch information
wootguy committed Sep 8, 2024
1 parent 47d3d66 commit 7fbcbd7
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 48 deletions.
109 changes: 64 additions & 45 deletions src/bsp/Bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2982,7 +2982,7 @@ void Bsp::fix_bad_surface_extents(bool scaleNotSubdivide, bool downscaleOnly, in
continue;
}

if (maxTextureDim > 0 && downscale_texture(info.iMiptex, maxTextureDim)) {
if (maxTextureDim > 0 && downscale_texture(info.iMiptex, maxTextureDim, false)) {
// retry after downscaling
numShrink++;
fa--;
Expand Down Expand Up @@ -3125,44 +3125,7 @@ bool Bsp::downscale_texture(int textureId, int newWidth, int newHeight) {
tex.nOffsets[i] = newOffset[i];
}

// scale up face texture coordinates
float scaleX = tex.nWidth / (float)oldWidth;
float scaleY = tex.nHeight / (float)oldHeight;

for (int i = 0; i < faceCount; i++) {
BSPFACE& face = faces[i];

if (texinfos[face.iTextureInfo].iMiptex != textureId)
continue;

// each affected face should have a unique texinfo because
// the shift amount may be different for every face after scaling
BSPTEXTUREINFO* info = get_unique_texinfo(i);

// get any vert on the face to use a reference point. Why?
// When textures are scaled, the texture relative to the face will depend on how far away its
// vertices are from the world origin. This means faces far away from the world origin shift many
// pixels per scale unit, and faces aligned with the world origin don't shift at all when scaled.
int32_t edgeIdx = surfedges[face.iFirstEdge];
BSPEDGE& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx >= 0 ? edge.iVertex[1] : edge.iVertex[0];
vec3 vert = verts[vertIdx];

vec3 oldvs = info->vS;
vec3 oldvt = info->vT;
info->vS *= scaleX;
info->vT *= scaleY;

// get before/after uv coordinates
float oldu = (dotProduct(oldvs, vert) + info->shiftS) * (1.0f / (float)oldWidth);
float oldv = (dotProduct(oldvt, vert) + info->shiftT) * (1.0f / (float)oldHeight);
float u = dotProduct(info->vS, vert) + info->shiftS;
float v = dotProduct(info->vT, vert) + info->shiftT;

// undo the shift in uv coordinates for this face
info->shiftS += (oldu * tex.nWidth) - u;
info->shiftT += (oldv * tex.nHeight) - v;
}
adjust_downscaled_texture_coordinates(textureId, oldWidth, oldHeight);

// shrink texture lump
int removedBytes = palette - newPalette;
Expand All @@ -3184,15 +3147,10 @@ bool Bsp::downscale_texture(int textureId, int newWidth, int newHeight) {
return true;
}

bool Bsp::downscale_texture(int textureId, int maxDim) {
bool Bsp::downscale_texture(int textureId, int maxDim, bool allowWad) {
int32_t texOffset = ((int32_t*)textures)[textureId + 1];
BSPMIPTEX& tex = *((BSPMIPTEX*)(textures + texOffset));

if (tex.nOffsets[0] == 0) {
logf("Can't downscale WAD texture %s\n", tex.szName);
return false;
}

int oldWidth = tex.nWidth;
int oldHeight = tex.nHeight;
int newWidth = tex.nWidth;
Expand Down Expand Up @@ -3223,9 +3181,70 @@ bool Bsp::downscale_texture(int textureId, int maxDim) {
return false;
}

if (tex.nOffsets[0] == 0) {
if (allowWad) {
tex.nWidth = newWidth;
tex.nHeight = newHeight;
adjust_downscaled_texture_coordinates(textureId, oldWidth, oldHeight);
logf("Texture coords were updated for %s. The WAD texture must be updated separately.\n", tex.szName);
}
else {
logf("Can't downscale WAD texture %s\n", tex.szName);
}

return false;
}

return downscale_texture(textureId, newWidth, newHeight);
}

void Bsp::adjust_downscaled_texture_coordinates(int textureId, int oldWidth, int oldHeight) {
int32_t texOffset = ((int32_t*)textures)[textureId + 1];
BSPMIPTEX& tex = *((BSPMIPTEX*)(textures + texOffset));

int newWidth = tex.nWidth;
int newHeight = tex.nHeight;

// scale up face texture coordinates
float scaleX = newWidth / (float)oldWidth;
float scaleY = newHeight / (float)oldHeight;

for (int i = 0; i < faceCount; i++) {
BSPFACE& face = faces[i];

if (texinfos[face.iTextureInfo].iMiptex != textureId)
continue;

// each affected face should have a unique texinfo because
// the shift amount may be different for every face after scaling
BSPTEXTUREINFO* info = get_unique_texinfo(i);

// get any vert on the face to use a reference point. Why?
// When textures are scaled, the texture relative to the face will depend on how far away its
// vertices are from the world origin. This means faces far away from the world origin shift many
// pixels per scale unit, and faces aligned with the world origin don't shift at all when scaled.
int32_t edgeIdx = surfedges[face.iFirstEdge];
BSPEDGE& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx >= 0 ? edge.iVertex[1] : edge.iVertex[0];
vec3 vert = verts[vertIdx];

vec3 oldvs = info->vS;
vec3 oldvt = info->vT;
info->vS *= scaleX;
info->vT *= scaleY;

// get before/after uv coordinates
float oldu = (dotProduct(oldvs, vert) + info->shiftS) * (1.0f / (float)oldWidth);
float oldv = (dotProduct(oldvt, vert) + info->shiftT) * (1.0f / (float)oldHeight);
float u = dotProduct(info->vS, vert) + info->shiftS;
float v = dotProduct(info->vT, vert) + info->shiftT;

// undo the shift in uv coordinates for this face
info->shiftS += (oldu * newWidth) - u;
info->shiftT += (oldv * newHeight) - v;
}
}

void Bsp::downscale_invalid_textures() {
int count = 0;

Expand Down
8 changes: 6 additions & 2 deletions src/bsp/Bsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,15 @@ class Bsp
void downscale_textures(int maxDim);

// downscales a texture to the maximum specified width/height
// true if was downscaled
bool downscale_texture(int textureId, int maxDim);
// allowWad:true = texture coordinates will be scaled even if the the texture is from a WAD and must be scaled separately
// returns true if was downscaled
bool downscale_texture(int textureId, int maxDim, bool allowWad);

bool downscale_texture(int textureId, int newWidth, int newHeight);

// updates texture coordinates after a texture has been downscaled
void adjust_downscaled_texture_coordinates(int textureId, int oldWidth, int oldHeight);

vec3 get_face_center(int faceIdx);

// scales up texture sizes on models that aren't used by visible entities
Expand Down
2 changes: 1 addition & 1 deletion src/editor/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ void Gui::draw3dContextMenus() {
else if (maxDim > 32) { nextBestDim = 32; }

downscaled.insert(info.iMiptex);
map->downscale_texture(info.iMiptex, nextBestDim);
map->downscale_texture(info.iMiptex, nextBestDim, true);
}

app->deselectFaces();
Expand Down

0 comments on commit 7fbcbd7

Please sign in to comment.