diff --git a/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 5cd84e82..be6c50c0 100644 --- a/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -43,7 +43,7 @@ public class ModernFixEarlyConfig { this.addMixinRule("perf.faster_baking", true); this.addMixinRule("perf.cache_model_materials", true); this.addMixinRule("perf.datapack_reload_exceptions", true); - this.addMixinRule("perf.faster_texture_stitching", false); + this.addMixinRule("perf.faster_texture_stitching", true); /* off by default in 1.18 because it doesn't work as well */ this.addMixinRule("perf.faster_singleplayer_load", false); /* Keep this off if JEI/REI isn't installed to prevent breaking vanilla gameplay */ diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/parallelize_model_loading/BlockModelShaperMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/parallelize_model_loading/BlockModelShaperMixin.java new file mode 100644 index 00000000..9da0fed8 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/parallelize_model_loading/BlockModelShaperMixin.java @@ -0,0 +1,26 @@ +package org.embeddedt.modernfix.mixin.perf.parallelize_model_loading; + +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import net.minecraft.client.renderer.block.BlockModelShaper; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Mixin(BlockModelShaper.class) +public class BlockModelShaperMixin { + private static Map stateToPropertiesCache = new ConcurrentHashMap<>(); + + @Redirect(method = "stateToModelLocation(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/resources/model/ModelResourceLocation;", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;statePropertiesToString(Ljava/util/Map;)Ljava/lang/String;")) + private static String getCachedProperty(Map, Comparable> values, ResourceLocation location, BlockState state) { + /* We intentionally don't use the values parameter inside the lambda to avoid an allocation */ + return stateToPropertiesCache.computeIfAbsent(state, s -> BlockModelShaper.statePropertiesToString(s.getValues())); + } +} diff --git a/src/main/java/org/embeddedt/modernfix/textures/StbStitcher.java b/src/main/java/org/embeddedt/modernfix/textures/StbStitcher.java index d2fbb230..7f872371 100644 --- a/src/main/java/org/embeddedt/modernfix/textures/StbStitcher.java +++ b/src/main/java/org/embeddedt/modernfix/textures/StbStitcher.java @@ -135,7 +135,8 @@ public class StbStitcher { // Initialize the rectangles that we'll be using in the calculation // While that's happening, sum up the area needed to fit all of the images - int sqSize = 0; + int totalArea = 0; + int longestWidth = 0, longestHeight = 0; for (int j = 0; j < holderSize; ++j) { Stitcher.Holder holder = holders[j]; @@ -147,17 +148,29 @@ public class StbStitcher { setWrapper(rect, j, width, height, 0, 0, false); - sqSize += (width * height); + totalArea += (width * height); + longestWidth = Math.max(longestWidth, width); + longestHeight = Math.max(longestHeight, height); } - int size = Mth.smallestEncompassingPowerOfTwo((int) Math.sqrt(sqSize)); - int width = size * 2; // needed to fix weirdness in 1.16 - int height = size; + longestWidth = Mth.smallestEncompassingPowerOfTwo(longestWidth); + longestHeight = Mth.smallestEncompassingPowerOfTwo(longestHeight); + + /* + * The atlas needs to be at least this wide and tall to accomodate oddly shaped sprites. If this is + * not enough, keep doubling the smaller of the two values until its big enough. + */ + while((longestWidth*longestHeight) < totalArea) { + if(longestWidth <= longestHeight) + longestWidth *= 2; + else + longestHeight *= 2; + } // Internal node structure needed for STB - try (STBRPNode.Buffer nodes = STBRPNode.malloc(width + 10)) { + try (STBRPNode.Buffer nodes = STBRPNode.malloc(longestWidth + 10)) { // Initialize the rect packer - STBRectPack.stbrp_init_target(ctx, width, height, nodes); + STBRectPack.stbrp_init_target(ctx, longestWidth, longestHeight, nodes); // Perform rectangle packing STBRectPack.stbrp_pack_rects(ctx, rectBuf); @@ -172,11 +185,11 @@ public class StbStitcher { } // Initialize the sprite now with the position and size that we've calculated so far - infoList.add(new LoadableSpriteInfo(holder.spriteInfo, width, height, getX(rect), getY(rect))); + infoList.add(new LoadableSpriteInfo(holder.spriteInfo, longestWidth, longestHeight, getX(rect), getY(rect))); //holder.spriteInfo.initSprite(size, size, rect.x(), rect.y(), false); } - return Pair.of(Pair.of(width, height), infoList); + return Pair.of(Pair.of(longestWidth, longestHeight), infoList); } } } diff --git a/src/main/resources/modernfix.mixins.json b/src/main/resources/modernfix.mixins.json index 0a7c3345..f3ea0e41 100644 --- a/src/main/resources/modernfix.mixins.json +++ b/src/main/resources/modernfix.mixins.json @@ -38,6 +38,7 @@ "feature.measure_time.MinecraftMixin", "feature.reduce_loading_screen_freezes.ModelBakeryMixin", "bugfix.concurrency.MinecraftMixin", + "perf.parallelize_model_loading.BlockModelShaperMixin", "perf.parallelize_model_loading.ModelBakeryMixin", "perf.parallelize_model_loading.OBJLoaderMixin", "perf.parallelize_model_loading.multipart.MultipartMixin",