diff --git a/build.gradle b/build.gradle index e6ca87806..48235fc58 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ project.buildnumber = System.getenv('BUILD_NUMBER') != null ? System.getenv('BUI version = "${mc_update_version}-${mod_version}" + (dev ? ".${buildnumber}" : '') group = 'com.jozufozu.flywheel' -archivesBaseName = 'flywheel' +archivesBaseName = 'flywheel-fabric' sourceCompatibility = JavaVersion.VERSION_16 targetCompatibility = JavaVersion.VERSION_16 diff --git a/gradle.properties b/gradle.properties index f4921ab8a..28ca8d50f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ mod_version = 0.3.0 mc_update_version = 1.17 minecraft_version = 1.17.1 loader_version = 0.12.5 -fabric_version = 0.42.1+1.17 +fabric_version = 0.43.0+1.17 # build dependency versions loom_version = 0.10-SNAPSHOT diff --git a/src/main/java/com/jozufozu/flywheel/FlywheelClient.java b/src/main/java/com/jozufozu/flywheel/FlywheelClient.java index a65bc5ec7..00707df63 100644 --- a/src/main/java/com/jozufozu/flywheel/FlywheelClient.java +++ b/src/main/java/com/jozufozu/flywheel/FlywheelClient.java @@ -5,7 +5,6 @@ import com.jozufozu.flywheel.backend.Loader; import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.config.FlwConfig; -import com.jozufozu.flywheel.core.AtlasStitcher; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.PartialModel; @@ -21,10 +20,8 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; -import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.minecraft.server.packs.PackType; -import net.minecraft.world.inventory.InventoryMenu; public class FlywheelClient implements ClientModInitializer { @@ -33,8 +30,6 @@ public class FlywheelClient implements ClientModInitializer { Backend.init(); - ClientSpriteRegistryCallback.event(InventoryMenu.BLOCK_ATLAS).register(AtlasStitcher.getInstance()::onTextureStitch); - FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit); FlywheelEvents.GATHER_CONTEXT.register(Materials::flwInit); ModelLoadingRegistry.INSTANCE.registerModelProvider(PartialModel::onModelRegistry); diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 9228aebea..fe4dc0322 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -40,7 +40,6 @@ public class Backend { private boolean instancedArrays; private boolean enabled; - public boolean chunkCachingEnabled; private final List> contexts = new ArrayList<>(); private final Map> materialRegistry = new HashMap<>(); @@ -138,8 +137,6 @@ public class Backend { enabled = FlwConfig.get() .enabled() && !OptifineHandler.usingShaders(); - chunkCachingEnabled = FlwConfig.get() - .chunkCaching(); } public boolean canUseInstancing(@Nullable Level world) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 474d03de8..b7c65f323 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -22,7 +22,8 @@ public class InstancedRenderDispatcher { * @param te The tile whose instance you want to update. */ public static void enqueueUpdate(BlockEntity te) { - getTiles(te.getLevel()).queueUpdate(te); + if (te.hasLevel() && te.getLevel() instanceof ClientLevel) + getTiles(te.getLevel()).queueUpdate(te); } /** diff --git a/src/main/java/com/jozufozu/flywheel/config/ConfigCommands.java b/src/main/java/com/jozufozu/flywheel/config/ConfigCommands.java index e1921933c..f9b9671da 100644 --- a/src/main/java/com/jozufozu/flywheel/config/ConfigCommands.java +++ b/src/main/java/com/jozufozu/flywheel/config/ConfigCommands.java @@ -46,18 +46,6 @@ public final class ConfigCommands { } )); - commandBuilder.addOption(config.chunkCaching, (builder, option) -> booleanOptionCommand(builder, config, option, - (source, value) -> { - Component text = new TextComponent("Chunk caching is currently: ").append(boolToText(value)); - source.sendFeedback(text); - }, - (source, value) -> { - Component text = boolToText(value).append(new TextComponent(" chunk caching").withStyle(ChatFormatting.WHITE)); - source.sendFeedback(text); - Backend.reloadWorldRenderers(); - } - )); - commandBuilder.build(); } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java index 6b6308517..1c16d87ea 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java @@ -38,8 +38,6 @@ public class FlwConfig { public final BooleanOption enabled = addOption(new BooleanOption("enabled", true)); /** Enable or disable a debug overlay that colors pixels by their normal */ public final BooleanOption debugNormals = addOption(new BooleanOption("debugNormals", false)); - /** Cache chunk lookups to improve performance. */ - public final BooleanOption chunkCaching = addOption(new BooleanOption("chunkCaching", true)); public FlwConfig(File file) { this.file = file; @@ -62,10 +60,6 @@ public class FlwConfig { return debugNormals.get(); } - public boolean chunkCaching() { - return chunkCaching.get(); - } - public void load() { if (file.exists()) { try (FileReader reader = new FileReader(file)) { diff --git a/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java b/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java deleted file mode 100644 index aff5a97e4..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.jozufozu.flywheel.core; - -import java.util.ArrayList; -import java.util.List; - -import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback.Registry; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.resources.ResourceLocation; - -/** - * This is primarily for hacking entity textures into the block atlas. - */ -public class AtlasStitcher { - protected static final AtlasStitcher INSTANCE = new AtlasStitcher(); - - public static AtlasStitcher getInstance() { - return INSTANCE; - } - - private final List sprites = new ArrayList<>(); - - public StitchedSprite get(ResourceLocation loc) { - StitchedSprite sprite = new StitchedSprite(loc); - - sprites.add(sprite); - - return sprite; - } - - public void onTextureStitch(TextureAtlas atlasTexture, Registry registry) { - sprites.forEach(StitchedSprite::reset); - sprites.stream() - .map(StitchedSprite::getLoc) - .forEach(registry::register); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/StitchedSprite.java b/src/main/java/com/jozufozu/flywheel/core/StitchedSprite.java index c43f045a6..a06f22d8a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/StitchedSprite.java +++ b/src/main/java/com/jozufozu/flywheel/core/StitchedSprite.java @@ -1,35 +1,81 @@ package com.jozufozu.flywheel.core; -import net.minecraft.client.Minecraft; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.InventoryMenu; public class StitchedSprite { + private static final Map ALL = new HashMap<>(); - private final ResourceLocation loc; + protected final ResourceLocation atlasLocation; + protected final ResourceLocation location; + protected TextureAtlasSprite sprite; - TextureAtlasSprite sprite; - - StitchedSprite(ResourceLocation loc) { - this.loc = loc; + public StitchedSprite(ResourceLocation atlas, ResourceLocation location) { + atlasLocation = atlas; + this.location = location; + ALL.computeIfAbsent(atlasLocation, SingleAtlasSpriteHolder::new).add(this); } - public ResourceLocation getLoc() { - return loc; + public StitchedSprite(ResourceLocation location) { + this(InventoryMenu.BLOCK_ATLAS, location); } - public TextureAtlasSprite getSprite() { - if (sprite == null) { - sprite = Minecraft.getInstance() - .getTextureAtlas(InventoryMenu.BLOCK_ATLAS) - .apply(loc); + public static void onTextureStitchPost(TextureAtlas atlas) { + ResourceLocation atlasLocation = atlas.location(); + SingleAtlasSpriteHolder holder = ALL.get(atlasLocation); + if (holder != null) { + holder.loadSprites(atlas); } + } + protected void loadSprite(TextureAtlas atlas) { + sprite = atlas.getSprite(location); + } + + public ResourceLocation getAtlasLocation() { + return atlasLocation; + } + + public ResourceLocation getLocation() { + return location; + } + + public TextureAtlasSprite get() { return sprite; } - void reset() { - sprite = null; + private static class SingleAtlasSpriteHolder implements ClientSpriteRegistryCallback { + private final ResourceLocation atlasLocation; + private final List sprites = new ArrayList<>(); + + private SingleAtlasSpriteHolder(ResourceLocation atlasLocation) { + this.atlasLocation = atlasLocation; + ClientSpriteRegistryCallback.event(this.atlasLocation).register(this); + } + + public void add(StitchedSprite sprite) { + sprites.add(sprite); + } + + @Override + public void registerSprites(TextureAtlas atlas, Registry registry) { + for (StitchedSprite sprite : sprites) { + registry.register(sprite.getLocation()); + } + } + + public void loadSprites(TextureAtlas atlas) { + for (StitchedSprite sprite : sprites) { + sprite.loadSprite(atlas); + } + } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelData.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelData.java index 2d437a1d2..7f53555ba 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelData.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelData.java @@ -1,24 +1,27 @@ package com.jozufozu.flywheel.core.materials.model; -import java.nio.FloatBuffer; - import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.core.materials.BasicData; -import com.jozufozu.flywheel.util.Attribute; +import com.jozufozu.flywheel.util.WriteSafe; +import com.jozufozu.flywheel.util.transform.Rotate; +import com.jozufozu.flywheel.util.transform.Scale; +import com.jozufozu.flywheel.util.transform.Translate; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import com.mojang.math.Quaternion; -public class ModelData extends BasicData { - private static final float[] empty = new float[25]; +import net.minecraft.util.Mth; - public final float[] matrices = empty.clone(); - private final FloatBuffer wrap = FloatBuffer.wrap(matrices); +public class ModelData extends BasicData implements Translate, Rotate, Scale { + public final Matrix4f model = new Matrix4f(); + public final Matrix3f normal = new Matrix3f(); public ModelData setTransform(PoseStack stack) { - this.wrap.position(0); - - ((Attribute)(Object) stack.last().pose()).append(this.wrap); - ((Attribute)(Object) stack.last().normal()).append(this.wrap); markDirty(); + + this.model.load(stack.last().pose()); + this.normal.load(stack.last().normal()); return this; } @@ -30,15 +33,63 @@ public class ModelData extends BasicData { *

*/ public ModelData setEmptyTransform() { - this.wrap.position(0) - .put(empty); markDirty(); + + this.model.load(new Matrix4f()); + this.normal.load(new Matrix3f()); + return this; + } + + public ModelData loadIdentity() { + markDirty(); + + this.model.setIdentity(); + this.normal.setIdentity(); return this; } @Override public void write(VecBuffer buf) { super.write(buf); - buf.putFloatArray(matrices); + ((WriteSafe) (Object) model).write(buf); + ((WriteSafe) (Object) normal).write(buf); + } + + @Override + public ModelData multiply(Quaternion quaternion) { + markDirty(); + + model.multiply(quaternion); + normal.mul(quaternion); + return this; + } + + @Override + public ModelData scale(float pX, float pY, float pZ) { + markDirty(); + + model.multiply(Matrix4f.createScaleMatrix(pX, pY, pZ)); + if (pX == pY && pY == pZ) { + if (pX > 0.0F) { + return this; + } + + normal.mul(-1.0F); + } + + float f = 1.0F / pX; + float f1 = 1.0F / pY; + float f2 = 1.0F / pZ; + float f3 = Mth.fastInvCubeRoot(f * f1 * f2); + normal.mul(Matrix3f.createScaleMatrix(f3 * f, f3 * f1, f3 * f2)); + return this; + } + + @Override + public ModelData translate(double x, double y, double z) { + markDirty(); + + model.multiplyWithTranslation((float) x, (float) y, (float) z); + return this; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java index 2b07cebf0..090070cc2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java @@ -6,6 +6,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.struct.StructType; import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter; import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.jozufozu.flywheel.util.WriteUnsafe; public class UnsafeModelWriter extends UnsafeBufferWriter { @@ -25,10 +26,9 @@ public class UnsafeModelWriter extends UnsafeBufferWriter { addr += 6; - float[] matrices = d.matrices; - for (int i = 0; i < matrices.length; i++) { - MemoryUtil.memPutFloat(addr + i * 4L, matrices[i]); - } + ((WriteUnsafe) (Object) d.model).writeUnsafe(addr); + addr += 4 * 16; + ((WriteUnsafe) (Object) d.normal).writeUnsafe(addr); advance(); } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedData.java b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedData.java index b43711cf9..850b426a3 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedData.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedData.java @@ -83,6 +83,15 @@ public class OrientedData extends BasicData { return this; } + public OrientedData resetRotation() { + this.qX = 0; + this.qY = 0; + this.qZ = 0; + this.qW = 1; + markDirty(); + return this; + } + @Override public void write(VecBuffer buf) { super.write(buf); diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 486499540..7a10218c4 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -6,6 +6,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.util.ChunkIter; +import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -33,6 +34,7 @@ public class ForgeEvents { public static void unloadWorld(ClientLevel world) { ChunkIter._unload(world); + WorldAttached.invalidateWorld(world); } public static void tickLight(Minecraft mc) { diff --git a/src/main/java/com/jozufozu/flywheel/mixin/fabric/TextureAtlasMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/fabric/TextureAtlasMixin.java new file mode 100644 index 000000000..ad11b74ea --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/fabric/TextureAtlasMixin.java @@ -0,0 +1,19 @@ +package com.jozufozu.flywheel.mixin.fabric; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.jozufozu.flywheel.core.StitchedSprite; + +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlas.Preparations; + +@Mixin(TextureAtlas.class) +public class TextureAtlasMixin { + @Inject(method = "reload(Lnet/minecraft/client/renderer/texture/TextureAtlas$Preparations;)V", at = @At("TAIL")) + private void onTailReload(Preparations preparations, CallbackInfo ci) { + StitchedSprite.onTextureStitchPost((TextureAtlas) (Object) this); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java index cf122e746..42a2e6023 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java @@ -1,15 +1,16 @@ package com.jozufozu.flywheel.mixin.matrix; -import java.nio.FloatBuffer; - +import org.lwjgl.system.MemoryUtil; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import com.jozufozu.flywheel.util.Attribute; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.util.WriteSafe; +import com.jozufozu.flywheel.util.WriteUnsafe; import com.mojang.math.Matrix3f; @Mixin(Matrix3f.class) -public abstract class Matrix3fMixin implements Attribute { +public abstract class Matrix3fMixin implements WriteUnsafe, WriteSafe { @Shadow protected float m00; @Shadow protected float m01; @@ -22,15 +23,28 @@ public abstract class Matrix3fMixin implements Attribute { @Shadow protected float m22; @Override - public void append(FloatBuffer buffer) { - buffer.put(m00); - buffer.put(m10); - buffer.put(m20); - buffer.put(m01); - buffer.put(m11); - buffer.put(m21); - buffer.put(m02); - buffer.put(m12); - buffer.put(m22); + public void writeUnsafe(long addr) { + MemoryUtil.memPutFloat(addr, m00); + MemoryUtil.memPutFloat(addr += 4L, m10); + MemoryUtil.memPutFloat(addr += 4L, m20); + MemoryUtil.memPutFloat(addr += 4L, m01); + MemoryUtil.memPutFloat(addr += 4L, m11); + MemoryUtil.memPutFloat(addr += 4L, m21); + MemoryUtil.memPutFloat(addr += 4L, m02); + MemoryUtil.memPutFloat(addr += 4L, m12); + MemoryUtil.memPutFloat(addr += 4L, m22); + } + + @Override + public void write(VecBuffer buffer) { + buffer.putFloat(m00); + buffer.putFloat(m10); + buffer.putFloat(m20); + buffer.putFloat(m01); + buffer.putFloat(m11); + buffer.putFloat(m21); + buffer.putFloat(m02); + buffer.putFloat(m12); + buffer.putFloat(m22); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java index 224c6104f..3650880f9 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java @@ -1,15 +1,16 @@ package com.jozufozu.flywheel.mixin.matrix; -import java.nio.FloatBuffer; - +import org.lwjgl.system.MemoryUtil; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import com.jozufozu.flywheel.util.Attribute; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.util.WriteSafe; +import com.jozufozu.flywheel.util.WriteUnsafe; import com.mojang.math.Matrix4f; @Mixin(Matrix4f.class) -public abstract class Matrix4fMixin implements Attribute { +public abstract class Matrix4fMixin implements WriteUnsafe, WriteSafe { @Shadow protected float m00; @Shadow protected float m01; @@ -29,22 +30,42 @@ public abstract class Matrix4fMixin implements Attribute { @Shadow protected float m33; @Override - public void append(FloatBuffer buffer) { - buffer.put(m00); - buffer.put(m10); - buffer.put(m20); - buffer.put(m30); - buffer.put(m01); - buffer.put(m11); - buffer.put(m21); - buffer.put(m31); - buffer.put(m02); - buffer.put(m12); - buffer.put(m22); - buffer.put(m32); - buffer.put(m03); - buffer.put(m13); - buffer.put(m23); - buffer.put(m33); + public void writeUnsafe(long addr) { + MemoryUtil.memPutFloat(addr, m00); + MemoryUtil.memPutFloat(addr += 4L, m10); + MemoryUtil.memPutFloat(addr += 4L, m20); + MemoryUtil.memPutFloat(addr += 4L, m30); + MemoryUtil.memPutFloat(addr += 4L, m01); + MemoryUtil.memPutFloat(addr += 4L, m11); + MemoryUtil.memPutFloat(addr += 4L, m21); + MemoryUtil.memPutFloat(addr += 4L, m31); + MemoryUtil.memPutFloat(addr += 4L, m02); + MemoryUtil.memPutFloat(addr += 4L, m12); + MemoryUtil.memPutFloat(addr += 4L, m22); + MemoryUtil.memPutFloat(addr += 4L, m32); + MemoryUtil.memPutFloat(addr += 4L, m03); + MemoryUtil.memPutFloat(addr += 4L, m13); + MemoryUtil.memPutFloat(addr += 4L, m23); + MemoryUtil.memPutFloat(addr += 4L, m33); + } + + @Override + public void write(VecBuffer buf) { + buf.putFloat(m00); + buf.putFloat(m10); + buf.putFloat(m20); + buf.putFloat(m30); + buf.putFloat(m01); + buf.putFloat(m11); + buf.putFloat(m21); + buf.putFloat(m31); + buf.putFloat(m02); + buf.putFloat(m12); + buf.putFloat(m22); + buf.putFloat(m32); + buf.putFloat(m03); + buf.putFloat(m13); + buf.putFloat(m23); + buf.putFloat(m33); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/matrix/PoseStackMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/matrix/PoseStackMixin.java new file mode 100644 index 000000000..8588b9546 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/matrix/PoseStackMixin.java @@ -0,0 +1,56 @@ +package com.jozufozu.flywheel.mixin.matrix; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Quaternion; + +@Mixin(PoseStack.class) +public abstract class PoseStackMixin implements TransformStack { + @Shadow + public abstract void mulPose(Quaternion pQuaternion); + + @Shadow + public abstract void shadow$scale(float factorX, float factorY, float factorZ); + + @Shadow + public abstract void shadow$pushPose(); + + @Shadow + public abstract void shadow$popPose(); + + @Shadow + public abstract void shadow$translate(double x, double y, double z); + + @Override + public TransformStack multiply(Quaternion quaternion) { + mulPose(quaternion); + return this; + } + + @Override + public TransformStack scale(float factorX, float factorY, float factorZ) { + shadow$scale(factorX, factorY, factorZ); + return this; + } + + @Override + public TransformStack pushPose() { + shadow$pushPose(); + return this; + } + + @Override + public TransformStack popPose() { + shadow$popPose(); + return this; + } + + @Override + public TransformStack translate(double x, double y, double z) { + shadow$translate(x, y, z); + return this; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/AngleHelper.java b/src/main/java/com/jozufozu/flywheel/util/AngleHelper.java index 7dbddb193..a89f8bf87 100644 --- a/src/main/java/com/jozufozu/flywheel/util/AngleHelper.java +++ b/src/main/java/com/jozufozu/flywheel/util/AngleHelper.java @@ -5,19 +5,7 @@ import net.minecraft.core.Direction.Axis; public class AngleHelper { - /** - * Legacy method. See {@link #horizontalAngleNew(Direction)} for new method. - */ public static float horizontalAngle(Direction facing) { - float angle = facing.toYRot(); - if (facing.getAxis() == Axis.X) angle = -angle; - return angle; - } - - /** - * Same as {@link #horizontalAngle(Direction)}, but returns 0 instead of -90 for vertical directions. - */ - public static float horizontalAngleNew(Direction facing) { if (facing.getAxis() .isVertical()) { return 0; diff --git a/src/main/java/com/jozufozu/flywheel/util/Attribute.java b/src/main/java/com/jozufozu/flywheel/util/Attribute.java deleted file mode 100644 index 75739b500..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/Attribute.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.jozufozu.flywheel.util; - -import java.nio.FloatBuffer; - -public interface Attribute { - - /** - * Append the contents of this object to the given FloatBuffer. - */ - void append(FloatBuffer buffer); -} diff --git a/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java b/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java index 666658a2c..da296f4ca 100644 --- a/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java +++ b/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java @@ -31,7 +31,7 @@ public class ChunkIter { } } - // INTERNAL MAINTENENCE METHODS BELOW + // INTERNAL MAINTENANCE METHODS BELOW public static void _putStorageReference(BlockGetter level, AtomicReferenceArray storage) { storages.put(level, storage); diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index 002ad3d86..408b54e51 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -1,6 +1,10 @@ package com.jozufozu.flywheel.util; +import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -12,12 +16,30 @@ import net.minecraft.world.level.LevelAccessor; public class WorldAttached { + // weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime + static List>> allMaps = new ArrayList<>(); private final Map attached; private final Function factory; public WorldAttached(Function factory) { this.factory = factory; attached = new HashMap<>(); + allMaps.add(new WeakReference<>(attached)); + } + + public static void invalidateWorld(LevelAccessor world) { + Iterator>> i = allMaps.iterator(); + while (i.hasNext()) { + Map map = i.next() + .get(); + if (map == null) { + // If the map has been GC'd, remove the weak reference + i.remove(); + } else { + // Prevent leaks + map.remove(world); + } + } } @Nonnull diff --git a/src/main/java/com/jozufozu/flywheel/util/WriteSafe.java b/src/main/java/com/jozufozu/flywheel/util/WriteSafe.java new file mode 100644 index 000000000..0fdc7f128 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/WriteSafe.java @@ -0,0 +1,7 @@ +package com.jozufozu.flywheel.util; + +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; + +public interface WriteSafe { + void write(VecBuffer buf); +} diff --git a/src/main/java/com/jozufozu/flywheel/util/WriteUnsafe.java b/src/main/java/com/jozufozu/flywheel/util/WriteUnsafe.java new file mode 100644 index 000000000..7d963ee5c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/WriteUnsafe.java @@ -0,0 +1,9 @@ +package com.jozufozu.flywheel.util; + +public interface WriteUnsafe { + + /** + * Write the contents of this object into sequential memory starting at the given address. + */ + void writeUnsafe(long addr); +} diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java index 5f8604b9e..2fa562ffa 100644 --- a/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java +++ b/src/main/java/com/jozufozu/flywheel/util/transform/MatrixTransformStack.java @@ -15,10 +15,6 @@ public class MatrixTransformStack implements TransformStack { this.internal = internal; } - public static MatrixTransformStack of(PoseStack ms) { - return new MatrixTransformStack(ms); - } - public PoseStack unwrap() { return internal; } @@ -58,13 +54,13 @@ public class MatrixTransformStack implements TransformStack { } @Override - public TransformStack push() { + public TransformStack pushPose() { internal.pushPose(); return this; } @Override - public TransformStack pop() { + public TransformStack popPose() { internal.popPose(); return this; } diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/Rotate.java b/src/main/java/com/jozufozu/flywheel/util/transform/Rotate.java new file mode 100644 index 000000000..68814740c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/transform/Rotate.java @@ -0,0 +1,72 @@ +package com.jozufozu.flywheel.util.transform; + +import com.mojang.math.Quaternion; +import com.mojang.math.Vector3f; + +import net.minecraft.core.Direction; + +public interface Rotate { + + Self multiply(Quaternion quaternion); + + default Self rotate(Direction axis, float radians) { + if (radians == 0) + return (Self) this; + return multiply(axis.step() + .rotation(radians)); + } + + default Self rotate(double angle, Direction.Axis axis) { + Vector3f vec = + axis == Direction.Axis.X ? Vector3f.XP : axis == Direction.Axis.Y ? Vector3f.YP : Vector3f.ZP; + return multiply(vec, angle); + } + + default Self rotateX(double angle) { + return multiply(Vector3f.XP, angle); + } + + default Self rotateY(double angle) { + return multiply(Vector3f.YP, angle); + } + + default Self rotateZ(double angle) { + return multiply(Vector3f.ZP, angle); + } + + default Self rotateXRadians(double angle) { + return multiplyRadians(Vector3f.XP, angle); + } + + default Self rotateYRadians(double angle) { + return multiplyRadians(Vector3f.YP, angle); + } + + default Self rotateZRadians(double angle) { + return multiplyRadians(Vector3f.ZP, angle); + } + + default Self multiply(Vector3f axis, double angle) { + if (angle == 0) + return (Self) this; + return multiply(axis.rotationDegrees((float) angle)); + } + + default Self multiplyRadians(Vector3f axis, double angle) { + if (angle == 0) + return (Self) this; + return multiply(axis.rotation((float) angle)); + } + + default Self rotateToFace(Direction facing) { + switch (facing) { + case SOUTH -> multiply(Vector3f.YP.rotationDegrees(180)); + case WEST -> multiply(Vector3f.YP.rotationDegrees(90)); + case NORTH -> multiply(Vector3f.YP.rotationDegrees(0)); + case EAST -> multiply(Vector3f.YP.rotationDegrees(270)); + case UP -> multiply(Vector3f.XP.rotationDegrees(90)); + case DOWN -> multiply(Vector3f.XN.rotationDegrees(90)); + } + return (Self) this; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/Scale.java b/src/main/java/com/jozufozu/flywheel/util/transform/Scale.java new file mode 100644 index 000000000..8fd7e7ab7 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/transform/Scale.java @@ -0,0 +1,9 @@ +package com.jozufozu.flywheel.util.transform; + +public interface Scale { + Self scale(float factorX, float factorY, float factorZ); + + default Self scale(float factor) { + return scale(factor, factor, factor); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/TStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/TStack.java new file mode 100644 index 000000000..1502fd750 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/transform/TStack.java @@ -0,0 +1,7 @@ +package com.jozufozu.flywheel.util.transform; + +public interface TStack { + Self pushPose(); + + Self popPose(); +} diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java b/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java index f6cdf2ade..da521b69b 100644 --- a/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java +++ b/src/main/java/com/jozufozu/flywheel/util/transform/TransformStack.java @@ -1,152 +1,9 @@ package com.jozufozu.flywheel.util.transform; -import com.mojang.math.Quaternion; -import com.mojang.math.Vector3f; +import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.world.phys.Vec3; - -public interface TransformStack { - Vec3 CENTER = new Vec3(0.5, 0.5, 0.5); - - TransformStack translate(double x, double y, double z); - - TransformStack multiply(Quaternion quaternion); - - TransformStack scale(float factorX, float factorY, float factorZ); - - TransformStack push(); - - TransformStack pop(); - - default TransformStack scale(float factor) { - return scale(factor, factor, factor); - } - - default TransformStack rotate(Direction axis, float radians) { - if (radians == 0) - return this; - return multiply(axis.step() - .rotation(radians)); - } - - default TransformStack rotate(double angle, Direction.Axis axis) { - Vector3f vec = - axis == Direction.Axis.X ? Vector3f.XP : axis == Direction.Axis.Y ? Vector3f.YP : Vector3f.ZP; - return multiply(vec, angle); - } - - default TransformStack rotateX(double angle) { - return multiply(Vector3f.XP, angle); - } - - default TransformStack rotateY(double angle) { - return multiply(Vector3f.YP, angle); - } - - default TransformStack rotateZ(double angle) { - return multiply(Vector3f.ZP, angle); - } - - default TransformStack rotateXRadians(double angle) { - return multiplyRadians(Vector3f.XP, angle); - } - - default TransformStack rotateYRadians(double angle) { - return multiplyRadians(Vector3f.YP, angle); - } - - default TransformStack rotateZRadians(double angle) { - return multiplyRadians(Vector3f.ZP, angle); - } - - default TransformStack centre() { - return translateAll(0.5); - } - - default TransformStack unCentre() { - return translateAll(-0.5); - } - - default TransformStack translateAll(double v) { - return translate(v, v, v); - } - - default TransformStack translateX(double x) { - return translate(x, 0, 0); - } - - default TransformStack translateY(double y) { - return translate(0, y, 0); - } - - default TransformStack translateZ(double z) { - return translate(0, 0, z); - } - - default TransformStack translate(Vec3i vec) { - return translate(vec.getX(), vec.getY(), vec.getZ()); - } - - default TransformStack translate(Vec3 vec) { - return translate(vec.x, vec.y, vec.z); - } - - default TransformStack translate(Vector3f vec) { - return translate(vec.x(), vec.y(), vec.z()); - } - - default TransformStack translateBack(Vec3 vec) { - return translate(-vec.x, -vec.y, -vec.z); - } - - default TransformStack translateBack(Vec3i vec) { - return translate(-vec.getX(), -vec.getY(), -vec.getZ()); - } - - default TransformStack nudge(int id) { - long randomBits = (long) id * 31L * 493286711L; - randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; - float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - return translate(xNudge, yNudge, zNudge); - } - - default TransformStack multiply(Vector3f axis, double angle) { - if (angle == 0) - return this; - return multiply(axis.rotationDegrees((float) angle)); - } - - default TransformStack multiplyRadians(Vector3f axis, double angle) { - if (angle == 0) - return this; - return multiply(axis.rotation((float) angle)); - } - - default TransformStack rotateToFace(Direction facing) { - switch (facing) { - case SOUTH: - multiply(Vector3f.YP.rotationDegrees(180)); - break; - case WEST: - multiply(Vector3f.YP.rotationDegrees(90)); - break; - case NORTH: - multiply(Vector3f.YP.rotationDegrees(0)); - break; - case EAST: - multiply(Vector3f.YP.rotationDegrees(270)); - break; - case UP: - multiply(Vector3f.XP.rotationDegrees(90)); - break; - case DOWN: - multiply(Vector3f.XN.rotationDegrees(90)); - break; - } - return this; +public interface TransformStack extends Scale, Translate, Rotate, TStack { + static TransformStack cast(PoseStack stack) { + return (TransformStack) stack; } } diff --git a/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java b/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java new file mode 100644 index 000000000..2e3da5a32 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/transform/Translate.java @@ -0,0 +1,67 @@ +package com.jozufozu.flywheel.util.transform; + +import com.mojang.math.Vector3f; + +import net.minecraft.core.Vec3i; +import net.minecraft.world.phys.Vec3; + +public interface Translate { + Self translate(double x, double y, double z); + + default Self centre() { + return translateAll(0.5); + } + + default Self unCentre() { + return translateAll(-0.5); + } + + default Self translateAll(double v) { + return translate(v, v, v); + } + + default Self translateX(double x) { + return translate(x, 0, 0); + } + + default Self translateY(double y) { + return translate(0, y, 0); + } + + default Self translateZ(double z) { + return translate(0, 0, z); + } + + default Self translate(Vec3i vec) { + return translate(vec.getX(), vec.getY(), vec.getZ()); + } + + default Self translate(Vec3 vec) { + return translate(vec.x, vec.y, vec.z); + } + + default Self translate(Vector3f vec) { + return translate(vec.x(), vec.y(), vec.z()); + } + + default Self translateBack(Vec3 vec) { + return translate(-vec.x, -vec.y, -vec.z); + } + + default Self translateBack(double x, double y, double z) { + return translate(-x, -y, -z); + } + + default Self translateBack(Vec3i vec) { + return translate(-vec.getX(), -vec.getY(), -vec.getZ()); + } + + default Self nudge(int id) { + long randomBits = (long) id * 31L * 493286711L; + randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; + float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + return translate(xNudge, yNudge, zNudge); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index 3ed6547ec..a11867494 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -13,7 +13,6 @@ import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.jozufozu.flywheel.core.model.ModelPart; import com.jozufozu.flywheel.util.AnimationTickHolder; -import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; @@ -31,7 +30,6 @@ import net.minecraft.world.level.block.state.properties.ChestType; public class ChestInstance extends TileEntityInstance implements IDynamicInstance { - private final MatrixTransformStack stack = new MatrixTransformStack(); private final OrientedData body; private final ModelData lid; @@ -57,9 +55,6 @@ public class ChestInstance extends TileE if (block instanceof AbstractChestBlock) { -// MatrixStack stack = new MatrixStack(); -// -// stack.push(); float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot(); baseRotation = Vector3f.YP.rotationDegrees(-horizontalAngle); @@ -92,7 +87,7 @@ public class ChestInstance extends TileE float angleX = -(progress * ((float) Math.PI / 2F)); - stack.setIdentity() + lid.loadIdentity() .translate(getInstancePosition()) .translate(0, 9f/16f, 0) .centre() @@ -101,9 +96,6 @@ public class ChestInstance extends TileE .translate(0, 0, 1f / 16f) .multiply(Vector3f.XP.rotation(angleX)) .translate(0, 0, -1f / 16f); - - lid.setTransform(stack.unwrap()); - } @Override diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java index 021c5f069..a7e2ff9ae 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java @@ -111,12 +111,12 @@ public class MinecartInstance extends EntityInstance int j = entity.getDisplayOffset(); if (contents != null) { - stack.push(); + stack.pushPose(); stack.scale(0.75F); stack.translate(-0.5D, (float)(j - 8) / 16, 0.5D); stack.multiply(Vector3f.YP.rotationDegrees(90)); contents.setTransform(stack.unwrap()); - stack.pop(); + stack.popPose(); } body.setTransform(stack.unwrap()); diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java index a77affd6b..5da600a83 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java @@ -24,7 +24,7 @@ public class ShulkerBoxInstance extends TileEntityInstance