diff --git a/common/src/lib/java/com/jozufozu/flywheel/lib/model/SimpleModel.java b/common/src/lib/java/com/jozufozu/flywheel/lib/model/SimpleModel.java index 3f54484ed..bd5b7bb45 100644 --- a/common/src/lib/java/com/jozufozu/flywheel/lib/model/SimpleModel.java +++ b/common/src/lib/java/com/jozufozu/flywheel/lib/model/SimpleModel.java @@ -4,14 +4,13 @@ import org.joml.Vector4fc; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.model.Model; public class SimpleModel implements Model { - private final ImmutableList meshes; + private final List meshes; private final Vector4fc boundingSphere; - public SimpleModel(ImmutableList meshes) { + public SimpleModel(List meshes) { this.meshes = meshes; this.boundingSphere = ModelUtil.computeBoundingSphere(meshes); } diff --git a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java index 39b9fb9eb..a0eb2302d 100644 --- a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java +++ b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java @@ -23,8 +23,8 @@ import net.minecraft.world.level.material.FluidState; final class BakedModelBufferer { - private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new); - private static final int CHUNK_LAYER_AMOUNT = CHUNK_LAYERS.length; + static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new); + static final int CHUNK_LAYER_AMOUNT = CHUNK_LAYERS.length; private static final ThreadLocal THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new); diff --git a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ChunkLayerSortedListBuilder.java b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ChunkLayerSortedListBuilder.java new file mode 100644 index 000000000..5978d7729 --- /dev/null +++ b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ChunkLayerSortedListBuilder.java @@ -0,0 +1,58 @@ +package com.jozufozu.flywheel.lib.model.baked; + +import java.util.List; + +import com.google.common.collect.ImmutableList; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.minecraft.client.renderer.RenderType; + +class ChunkLayerSortedListBuilder { + private static final ThreadLocal> THREAD_LOCAL = ThreadLocal.withInitial(ChunkLayerSortedListBuilder::new); + + @SuppressWarnings("unchecked") + private final ObjectArrayList[] lists = new ObjectArrayList[BakedModelBufferer.CHUNK_LAYER_AMOUNT]; + private final Reference2ReferenceMap> map = new Reference2ReferenceOpenHashMap<>(); + + private ChunkLayerSortedListBuilder() { + for (int layerIndex = 0; layerIndex < BakedModelBufferer.CHUNK_LAYER_AMOUNT; layerIndex++) { + RenderType renderType = BakedModelBufferer.CHUNK_LAYERS[layerIndex]; + ObjectArrayList list = new ObjectArrayList<>(); + lists[layerIndex] = list; + map.put(renderType, list); + } + } + + @SuppressWarnings("unchecked") + public static ChunkLayerSortedListBuilder getThreadLocal() { + return (ChunkLayerSortedListBuilder) THREAD_LOCAL.get(); + } + + public void add(RenderType renderType, T obj) { + List list = map.get(renderType); + if (list == null) { + throw new IllegalArgumentException("RenderType '" + renderType + "' is not a chunk layer"); + } + list.add(obj); + } + + @SuppressWarnings("unchecked") + public ImmutableList build() { + int size = 0; + for (ObjectArrayList list : lists) { + size += list.size(); + } + + T[] array = (T[]) new Object[size]; + int destPos = 0; + for (ObjectArrayList list : lists) { + System.arraycopy(list.elements(), 0, array, destPos, list.size()); + destPos += list.size(); + list.clear(); + } + + return ImmutableList.copyOf(array); + } +} diff --git a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBakedModelBuilder.java b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBakedModelBuilder.java index a4b47d019..f853ac884 100644 --- a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBakedModelBuilder.java +++ b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBakedModelBuilder.java @@ -2,7 +2,6 @@ import java.util.function.BiFunction; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.vertex.VertexView; @@ -60,7 +59,7 @@ public SimpleModel build() { materialFunc = ModelUtil::getMaterial; } - var out = ImmutableList.builder(); + var builder = ChunkLayerSortedListBuilder.getThreadLocal(); BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), level, bakedModel, blockState, poseStack, (renderType, shaded, data) -> { Material material = materialFunc.apply(renderType, shaded); @@ -68,10 +67,10 @@ public SimpleModel build() { VertexView vertexView = new NoOverlayVertexView(); MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, vertexView); var mesh = new SimpleMesh(vertexView, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType + ",shaded=" + shaded); - out.add(new Model.ConfiguredMesh(material, mesh)); + builder.add(renderType, new Model.ConfiguredMesh(material, mesh)); } }); - return new SimpleModel(out.build()); + return new SimpleModel(builder.build()); } } diff --git a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBlockModelBuilder.java b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBlockModelBuilder.java index bfc2ab0ca..a64144135 100644 --- a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBlockModelBuilder.java +++ b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricBlockModelBuilder.java @@ -2,7 +2,6 @@ import java.util.function.BiFunction; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.vertex.VertexView; @@ -49,7 +48,7 @@ public SimpleModel build() { materialFunc = ModelUtil::getMaterial; } - var out = ImmutableList.builder(); + var builder = ChunkLayerSortedListBuilder.getThreadLocal(); BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, level, state, poseStack, (renderType, shaded, data) -> { Material material = materialFunc.apply(renderType, shaded); @@ -57,10 +56,10 @@ public SimpleModel build() { VertexView vertexView = new NoOverlayVertexView(); MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, vertexView); var mesh = new SimpleMesh(vertexView, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType + ",shaded=" + shaded); - out.add(new Model.ConfiguredMesh(material, mesh)); + builder.add(renderType, new Model.ConfiguredMesh(material, mesh)); } }); - return new SimpleModel(out.build()); + return new SimpleModel(builder.build()); } } diff --git a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricMultiBlockModelBuilder.java b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricMultiBlockModelBuilder.java index d3dbf408c..74a4f29f1 100644 --- a/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricMultiBlockModelBuilder.java +++ b/fabric/src/lib/java/com/jozufozu/flywheel/lib/model/baked/FabricMultiBlockModelBuilder.java @@ -2,7 +2,6 @@ import java.util.function.BiFunction; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.vertex.VertexView; @@ -46,7 +45,7 @@ public SimpleModel build() { materialFunc = ModelUtil::getMaterial; } - var out = ImmutableList.builder(); + var builder = ChunkLayerSortedListBuilder.getThreadLocal(); BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, positions.iterator(), level, poseStack, renderFluids, (renderType, shaded, data) -> { Material material = materialFunc.apply(renderType, shaded); @@ -54,10 +53,10 @@ public SimpleModel build() { VertexView vertexView = new NoOverlayVertexView(); MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, vertexView); var mesh = new SimpleMesh(vertexView, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded); - out.add(new Model.ConfiguredMesh(material, mesh)); + builder.add(renderType, new Model.ConfiguredMesh(material, mesh)); } }); - return new SimpleModel(out.build()); + return new SimpleModel(builder.build()); } } diff --git a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java index cb6882a4d..d62de8009 100644 --- a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java +++ b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java @@ -24,8 +24,8 @@ import net.minecraftforge.client.model.data.ModelData; final class BakedModelBufferer { - private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new); - private static final int CHUNK_LAYER_AMOUNT = CHUNK_LAYERS.length; + static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new); + static final int CHUNK_LAYER_AMOUNT = CHUNK_LAYERS.length; private static final ThreadLocal THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new); diff --git a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ChunkLayerSortedListBuilder.java b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ChunkLayerSortedListBuilder.java new file mode 100644 index 000000000..01890f7c7 --- /dev/null +++ b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ChunkLayerSortedListBuilder.java @@ -0,0 +1,54 @@ +package com.jozufozu.flywheel.lib.model.baked; + +import java.util.List; + +import com.google.common.collect.ImmutableList; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.client.renderer.RenderType; + +class ChunkLayerSortedListBuilder { + private static final ThreadLocal> THREAD_LOCAL = ThreadLocal.withInitial(ChunkLayerSortedListBuilder::new); + + @SuppressWarnings("unchecked") + private final ObjectArrayList[] lists = new ObjectArrayList[BakedModelBufferer.CHUNK_LAYER_AMOUNT]; + + private ChunkLayerSortedListBuilder() { + for (int layerIndex = 0; layerIndex < BakedModelBufferer.CHUNK_LAYER_AMOUNT; layerIndex++) { + ObjectArrayList list = new ObjectArrayList<>(); + lists[layerIndex] = list; + } + } + + @SuppressWarnings("unchecked") + public static ChunkLayerSortedListBuilder getThreadLocal() { + return (ChunkLayerSortedListBuilder) THREAD_LOCAL.get(); + } + + public void add(RenderType renderType, T obj) { + int layerIndex = renderType.getChunkLayerId(); + if (layerIndex == -1) { + throw new IllegalArgumentException("RenderType '" + renderType + "' is not a chunk layer"); + } + List list = lists[layerIndex]; + list.add(obj); + } + + @SuppressWarnings("unchecked") + public ImmutableList build() { + int size = 0; + for (ObjectArrayList list : lists) { + size += list.size(); + } + + T[] array = (T[]) new Object[size]; + int destPos = 0; + for (ObjectArrayList list : lists) { + System.arraycopy(list.elements(), 0, array, destPos, list.size()); + destPos += list.size(); + list.clear(); + } + + return ImmutableList.copyOf(array); + } +} diff --git a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBakedModelBuilder.java b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBakedModelBuilder.java index 8ad0e0404..515def783 100644 --- a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBakedModelBuilder.java +++ b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBakedModelBuilder.java @@ -4,7 +4,6 @@ import org.jetbrains.annotations.Nullable; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.vertex.VertexView; @@ -74,7 +73,7 @@ public SimpleModel build() { modelData = ModelData.EMPTY; } - var out = ImmutableList.builder(); + var builder = ChunkLayerSortedListBuilder.getThreadLocal(); BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), level, bakedModel, blockState, poseStack, modelData, (renderType, shaded, data) -> { Material material = materialFunc.apply(renderType, shaded); @@ -82,10 +81,10 @@ public SimpleModel build() { VertexView vertexView = new NoOverlayVertexView(); MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, vertexView); var mesh = new SimpleMesh(vertexView, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType + ",shaded=" + shaded); - out.add(new Model.ConfiguredMesh(material, mesh)); + builder.add(renderType, new Model.ConfiguredMesh(material, mesh)); } }); - return new SimpleModel(out.build()); + return new SimpleModel(builder.build()); } } diff --git a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBlockModelBuilder.java b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBlockModelBuilder.java index af06eadc9..ad385e40c 100644 --- a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBlockModelBuilder.java +++ b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeBlockModelBuilder.java @@ -4,7 +4,6 @@ import org.jetbrains.annotations.Nullable; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.vertex.VertexView; @@ -63,7 +62,7 @@ public SimpleModel build() { modelData = ModelData.EMPTY; } - var out = ImmutableList.builder(); + var builder = ChunkLayerSortedListBuilder.getThreadLocal(); BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, level, state, poseStack, modelData, (renderType, shaded, data) -> { Material material = materialFunc.apply(renderType, shaded); @@ -71,10 +70,10 @@ public SimpleModel build() { VertexView vertexView = new NoOverlayVertexView(); MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, vertexView); var mesh = new SimpleMesh(vertexView, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType + ",shaded=" + shaded); - out.add(new Model.ConfiguredMesh(material, mesh)); + builder.add(renderType, new Model.ConfiguredMesh(material, mesh)); } }); - return new SimpleModel(out.build()); + return new SimpleModel(builder.build()); } } diff --git a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeMultiBlockModelBuilder.java b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeMultiBlockModelBuilder.java index 48c3363b4..d84379598 100644 --- a/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeMultiBlockModelBuilder.java +++ b/forge/src/lib/java/com/jozufozu/flywheel/lib/model/baked/ForgeMultiBlockModelBuilder.java @@ -5,7 +5,6 @@ import org.jetbrains.annotations.Nullable; -import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.vertex.VertexView; @@ -61,7 +60,7 @@ public SimpleModel build() { modelDataLookup = pos -> ModelData.EMPTY; } - var out = ImmutableList.builder(); + var builder = ChunkLayerSortedListBuilder.getThreadLocal(); BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, positions.iterator(), level, poseStack, modelDataLookup, renderFluids, (renderType, shaded, data) -> { Material material = materialFunc.apply(renderType, shaded); @@ -69,10 +68,10 @@ public SimpleModel build() { VertexView vertexView = new NoOverlayVertexView(); MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, vertexView); var mesh = new SimpleMesh(vertexView, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded); - out.add(new Model.ConfiguredMesh(material, mesh)); + builder.add(renderType, new Model.ConfiguredMesh(material, mesh)); } }); - return new SimpleModel(out.build()); + return new SimpleModel(builder.build()); } }