mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-10 12:34:11 +01:00
Fix mesh order of models from model builders
Meshes are now always sorted by chunk layer first, then in order of how the BakedModel returned quads. This should exactly match vanilla's chunk buffering and avoid any rendering issues.
This commit is contained in:
parent
914ce0a7de
commit
7ef9ce3907
@ -4,14 +4,13 @@ import java.util.List;
|
||||
|
||||
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<ConfiguredMesh> meshes;
|
||||
private final List<ConfiguredMesh> meshes;
|
||||
private final Vector4fc boundingSphere;
|
||||
|
||||
public SimpleModel(ImmutableList<ConfiguredMesh> meshes) {
|
||||
public SimpleModel(List<ConfiguredMesh> meshes) {
|
||||
this.meshes = meshes;
|
||||
this.boundingSphere = ModelUtil.computeBoundingSphere(meshes);
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
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<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||
|
||||
|
@ -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<T> {
|
||||
private static final ThreadLocal<ChunkLayerSortedListBuilder<?>> THREAD_LOCAL = ThreadLocal.withInitial(ChunkLayerSortedListBuilder::new);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final ObjectArrayList<T>[] lists = new ObjectArrayList[BakedModelBufferer.CHUNK_LAYER_AMOUNT];
|
||||
private final Reference2ReferenceMap<RenderType, ObjectArrayList<T>> map = new Reference2ReferenceOpenHashMap<>();
|
||||
|
||||
private ChunkLayerSortedListBuilder() {
|
||||
for (int layerIndex = 0; layerIndex < BakedModelBufferer.CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||
RenderType renderType = BakedModelBufferer.CHUNK_LAYERS[layerIndex];
|
||||
ObjectArrayList<T> list = new ObjectArrayList<>();
|
||||
lists[layerIndex] = list;
|
||||
map.put(renderType, list);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ChunkLayerSortedListBuilder<T> getThreadLocal() {
|
||||
return (ChunkLayerSortedListBuilder<T>) THREAD_LOCAL.get();
|
||||
}
|
||||
|
||||
public void add(RenderType renderType, T obj) {
|
||||
List<T> list = map.get(renderType);
|
||||
if (list == null) {
|
||||
throw new IllegalArgumentException("RenderType '" + renderType + "' is not a chunk layer");
|
||||
}
|
||||
list.add(obj);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ImmutableList<T> build() {
|
||||
int size = 0;
|
||||
for (ObjectArrayList<T> list : lists) {
|
||||
size += list.size();
|
||||
}
|
||||
|
||||
T[] array = (T[]) new Object[size];
|
||||
int destPos = 0;
|
||||
for (ObjectArrayList<T> list : lists) {
|
||||
System.arraycopy(list.elements(), 0, array, destPos, list.size());
|
||||
destPos += list.size();
|
||||
list.clear();
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(array);
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
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 final class FabricBakedModelBuilder extends BakedModelBuilder {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
var builder = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>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 final class FabricBakedModelBuilder extends BakedModelBuilder {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
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 final class FabricBlockModelBuilder extends BlockModelBuilder {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
var builder = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
|
||||
|
||||
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, level, state, poseStack, (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
@ -57,10 +56,10 @@ public final class FabricBlockModelBuilder extends BlockModelBuilder {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
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 final class FabricMultiBlockModelBuilder extends MultiBlockModelBuilder {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
var builder = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>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 final class FabricMultiBlockModelBuilder extends MultiBlockModelBuilder {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||
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<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||
|
||||
|
@ -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<T> {
|
||||
private static final ThreadLocal<ChunkLayerSortedListBuilder<?>> THREAD_LOCAL = ThreadLocal.withInitial(ChunkLayerSortedListBuilder::new);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final ObjectArrayList<T>[] lists = new ObjectArrayList[BakedModelBufferer.CHUNK_LAYER_AMOUNT];
|
||||
|
||||
private ChunkLayerSortedListBuilder() {
|
||||
for (int layerIndex = 0; layerIndex < BakedModelBufferer.CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||
ObjectArrayList<T> list = new ObjectArrayList<>();
|
||||
lists[layerIndex] = list;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ChunkLayerSortedListBuilder<T> getThreadLocal() {
|
||||
return (ChunkLayerSortedListBuilder<T>) 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<T> list = lists[layerIndex];
|
||||
list.add(obj);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ImmutableList<T> build() {
|
||||
int size = 0;
|
||||
for (ObjectArrayList<T> list : lists) {
|
||||
size += list.size();
|
||||
}
|
||||
|
||||
T[] array = (T[]) new Object[size];
|
||||
int destPos = 0;
|
||||
for (ObjectArrayList<T> list : lists) {
|
||||
System.arraycopy(list.elements(), 0, array, destPos, list.size());
|
||||
destPos += list.size();
|
||||
list.clear();
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(array);
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ import java.util.function.BiFunction;
|
||||
|
||||
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 final class ForgeBakedModelBuilder extends BakedModelBuilder {
|
||||
modelData = ModelData.EMPTY;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
var builder = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>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 final class ForgeBakedModelBuilder extends BakedModelBuilder {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import java.util.function.BiFunction;
|
||||
|
||||
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 final class ForgeBlockModelBuilder extends BlockModelBuilder {
|
||||
modelData = ModelData.EMPTY;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
var builder = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
|
||||
|
||||
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, level, state, poseStack, modelData, (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
@ -71,10 +70,10 @@ public final class ForgeBlockModelBuilder extends BlockModelBuilder {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import java.util.function.Function;
|
||||
|
||||
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 final class ForgeMultiBlockModelBuilder extends MultiBlockModelBuilder {
|
||||
modelDataLookup = pos -> ModelData.EMPTY;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
var builder = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>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 final class ForgeMultiBlockModelBuilder extends MultiBlockModelBuilder {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user