From 7fbcbd7fb6da17f90709d01772f402dfc9d94398 Mon Sep 17 00:00:00 2001 From: wootguy Date: Sun, 8 Sep 2024 12:42:14 -0700 Subject: [PATCH] allow downscaling wad textures only updates the texture info and coordinates. The texture in the WAD still needs to be updated separately. --- src/bsp/Bsp.cpp | 109 ++++++++++++++++++++++++++------------------- src/bsp/Bsp.h | 8 +++- src/editor/Gui.cpp | 2 +- 3 files changed, 71 insertions(+), 48 deletions(-) diff --git a/src/bsp/Bsp.cpp b/src/bsp/Bsp.cpp index 4800e30f..84f52d2f 100644 --- a/src/bsp/Bsp.cpp +++ b/src/bsp/Bsp.cpp @@ -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--; @@ -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; @@ -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; @@ -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; diff --git a/src/bsp/Bsp.h b/src/bsp/Bsp.h index fc92f168..baeda720 100644 --- a/src/bsp/Bsp.h +++ b/src/bsp/Bsp.h @@ -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 diff --git a/src/editor/Gui.cpp b/src/editor/Gui.cpp index 3a2749ed..5555fdcb 100644 --- a/src/editor/Gui.cpp +++ b/src/editor/Gui.cpp @@ -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();