Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
self review
  • Loading branch information
Jozufozu committed Nov 2, 2025
commit 15cef3fa3e8425047bfb62e8ad759fb6c3b42925
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.engine_room.flywheel.api.material;

import org.jetbrains.annotations.Nullable;

import net.minecraft.resources.ResourceLocation;

public interface Material {
Expand Down Expand Up @@ -52,4 +54,39 @@ public interface Material {
* @return The cardinal lighting mode.
*/
CardinalLightingMode cardinalLightingMode();

/**
* Check for field-wise equality between this Material and another.
*
* @param other The nullable material to check equality against.
* @return True if the materials represent the same configuration.
*/
default boolean equals(@Nullable Material other) {
if (this == other) {
return true;
}

if (other == null) {
return false;
}

// @formatter:off
return this.blur() == other.blur()
&& this.mipmap() == other.mipmap()
&& this.backfaceCulling() == other.backfaceCulling()
&& this.polygonOffset() == other.polygonOffset()
&& this.depthTest() == other.depthTest()
&& this.transparency() == other.transparency()
&& this.writeMask() == other.writeMask()
&& this.useOverlay() == other.useOverlay()
&& this.useLight() == other.useLight()
&& this.cardinalLightingMode() == other.cardinalLightingMode()
&& this.shaders().fragmentSource().equals(other.shaders().fragmentSource())
&& this.shaders().vertexSource().equals(other.shaders().vertexSource())
&& this.fog().source().equals(other.fog().source())
&& this.cutout().source().equals(other.cutout().source())
&& this.light().source().equals(other.light().source())
&& this.texture().equals(other.texture());
// @formatter:on
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dev.engine_room.flywheel.lib.model.baked;

import com.mojang.blaze3d.vertex.BufferBuilder;

import it.unimi.dsi.fastutil.objects.ReferenceArrayList;

class BufferBuilderStack {
private static final int INITIAL_CAPACITY_VERTICES = 256;

private int nextBufferBuilderIndex = 0;
private final ReferenceArrayList<BufferBuilder> bufferBuilders = new ReferenceArrayList<>();

BufferBuilder getOrCreateBufferBuilder() {
BufferBuilder bufferBuilder;
if (nextBufferBuilderIndex < bufferBuilders.size()) {
bufferBuilder = bufferBuilders.get(nextBufferBuilderIndex);
} else {
// Need to allocate at least some memory up front, as BufferBuilder internally
// only calls `ensureCapacity` after writing a vertex.
bufferBuilder = new BufferBuilder(INITIAL_CAPACITY_VERTICES);
bufferBuilders.add(bufferBuilder);
}
nextBufferBuilderIndex++;
return bufferBuilder;
}

public void reset() {
nextBufferBuilderIndex = 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,33 @@

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

import org.jetbrains.annotations.UnknownNullability;

import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;

import dev.engine_room.flywheel.api.material.Material;

class MeshEmitter {
private final Supplier<BufferBuilder> bufferBuilderSupplier;
private final BufferBuilderStack bufferBuilderStack;

private final List<BufferBuilder> activeBufferBuilders = new ArrayList<>();
private final List<Object> activeKeys = new ArrayList<>();
private final List<Material> activeKeys = new ArrayList<>();

@UnknownNullability
ResultConsumer<Object> resultConsumer;
ModelBuilderResultConsumer resultConsumer;

private int currentIndex = -1;
@UnknownNullability
private BufferBuilder currentBufferBuilder;
@UnknownNullability
private Object currentKey;

MeshEmitter(Supplier<BufferBuilder> bufferBuilderSupplier) {
this.bufferBuilderSupplier = bufferBuilderSupplier;
MeshEmitter(BufferBuilderStack bufferBuilderStack) {
this.bufferBuilderStack = bufferBuilderStack;
}

@SuppressWarnings("unchecked")
public void prepare(ResultConsumer<?> resultConsumer) {
this.resultConsumer = (ResultConsumer<Object>) resultConsumer;
public void prepare(ModelBuilderResultConsumer resultConsumer) {
this.resultConsumer = resultConsumer;
}

public void prepareForBlock() {
currentIndex = -1;
currentBufferBuilder = null;
currentKey = null;
}

public void end() {
Expand All @@ -54,34 +45,27 @@ public void end() {
activeKeys.clear();
resultConsumer = null;
currentIndex = -1;
currentBufferBuilder = null;
currentKey = null;
}

public BufferBuilder getBuffer(Object key) {
if (currentIndex < 0 || !key.equals(currentKey)) {
public BufferBuilder getBuffer(Material key) {
if (currentIndex < 0 || !key.equals(activeKeys.get(currentIndex))) {
while (true) {
currentIndex++;

if (currentIndex >= activeBufferBuilders.size()) {
BufferBuilder bufferBuilder = bufferBuilderSupplier.get();
BufferBuilder bufferBuilder = bufferBuilderStack.getOrCreateBufferBuilder();
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
activeBufferBuilders.add(bufferBuilder);
activeKeys.add(key);
currentBufferBuilder = bufferBuilder;
currentKey = key;
break;
}

Object searchKey = activeKeys.get(currentIndex);
if (key.equals(searchKey)) {
currentBufferBuilder = activeBufferBuilders.get(currentIndex);
currentKey = searchKey;
if (key.equals(activeKeys.get(currentIndex))) {
break;
}
}
}

return currentBufferBuilder;
return activeBufferBuilders.get(currentIndex);
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
package dev.engine_room.flywheel.lib.model.baked;

import java.util.function.BiFunction;
import java.util.function.Supplier;

import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnknownNullability;

import com.mojang.blaze3d.vertex.BufferBuilder;

import it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap;
import dev.engine_room.flywheel.api.material.Material;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceArrayMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import net.minecraft.client.renderer.RenderType;

class MeshEmitterManager<T extends MeshEmitter> {
private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new);

final Reference2ReferenceMap<RenderType, T> emitterMap = new Reference2ReferenceLinkedOpenHashMap<>();
private final ReferenceArrayList<BufferBuilder> bufferBuilders = new ReferenceArrayList<>();
final Reference2ReferenceMap<RenderType, T> emitterMap = new Reference2ReferenceArrayMap<>();

@UnknownNullability
private ResultConsumer<?> resultConsumer;
private int nextBufferBuilderIndex;
private ModelBuilderResultConsumer resultConsumer;

MeshEmitterManager(BiFunction<Supplier<BufferBuilder>, RenderType, T> meshEmitterFactory) {
private final BufferBuilderStack bufferBuilderStack = new BufferBuilderStack();

MeshEmitterManager(BiFunction<BufferBuilderStack, RenderType, T> meshEmitterFactory) {
for (RenderType renderType : CHUNK_LAYERS) {
T emitter = meshEmitterFactory.apply(this::getOrCreateBufferBuilder, renderType);
T emitter = meshEmitterFactory.apply(bufferBuilderStack, renderType);
emitterMap.put(renderType, emitter);
}
}

public void prepare(ResultConsumer<?> resultConsumer) {
public T getEmitter(RenderType renderType) {
return emitterMap.get(renderType);
}

public void prepare(ModelBuilderResultConsumer resultConsumer) {
this.resultConsumer = resultConsumer;
nextBufferBuilderIndex = 0;
bufferBuilderStack.reset();

for (MeshEmitter emitter : emitterMap.values()) {
emitter.prepare(resultConsumer);
Expand All @@ -47,7 +48,7 @@ public void prepareForBlock() {

public void end() {
resultConsumer = null;
nextBufferBuilderIndex = 0;
bufferBuilderStack.reset();

for (MeshEmitter emitter : emitterMap.values()) {
emitter.end();
Expand All @@ -56,23 +57,11 @@ public void end() {

@Nullable
public BufferBuilder getBuffer(RenderType renderType, boolean shade, boolean ao) {
Object key = resultConsumer.createKey(renderType, shade, ao);
Material key = resultConsumer.createKey(renderType, shade, ao);
if (key != null) {
return emitterMap.get(renderType).getBuffer(key);
} else {
return null;
}
}

private BufferBuilder getOrCreateBufferBuilder() {
BufferBuilder bufferBuilder;
if (nextBufferBuilderIndex < bufferBuilders.size()) {
bufferBuilder = bufferBuilders.get(nextBufferBuilderIndex);
} else {
bufferBuilder = new BufferBuilder(0);
bufferBuilders.add(bufferBuilder);
}
nextBufferBuilderIndex++;
return bufferBuilder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,19 @@
import dev.engine_room.flywheel.lib.model.SimpleModel;
import net.minecraft.client.renderer.RenderType;

class ModelBuilderResultConsumer implements ResultConsumer<Material> {
class ModelBuilderResultConsumer {
private final BlockMaterialFunction materialFunc;
private final ImmutableList.Builder<Model.ConfiguredMesh> meshes = ImmutableList.builder();

ModelBuilderResultConsumer(BlockMaterialFunction materialFunc) {
this.materialFunc = materialFunc;
}

@Override
@Nullable
public Material createKey(RenderType renderType, boolean shade, boolean ambientOcclusion) {
return materialFunc.apply(renderType, shade, ambientOcclusion);
}

@Override
public void accept(Material material, BufferBuilder.RenderedBuffer data) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=ModelBuilder" + ",material=" + material);
meshes.add(new Model.ConfiguredMesh(material, mesh));
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class BakedModelBufferer {
private BakedModelBufferer() {
}

public static void bufferModel(BakedModel model, BlockPos pos, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer<?> resultConsumer) {
public static void bufferModel(BakedModel model, BlockPos pos, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelBuilderResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (poseStack == null) {
poseStack = objects.identityPoseStack;
Expand All @@ -54,7 +54,7 @@ public static void bufferModel(BakedModel model, BlockPos pos, BlockAndTintGette
emitters.end();
}

public static void bufferBlocks(Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, boolean renderFluids, ResultConsumer<?> resultConsumer) {
public static void bufferBlocks(Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, boolean renderFluids, ModelBuilderResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (poseStack == null) {
poseStack = objects.identityPoseStack;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ final class BakedModelBufferer {
private BakedModelBufferer() {
}

public static void bufferModel(BakedModel model, BlockPos pos, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer<?> resultConsumer) {
public static void bufferModel(BakedModel model, BlockPos pos, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ModelBuilderResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (poseStack == null) {
poseStack = objects.identityPoseStack;
}
RandomSource random = objects.random;
ForgeMeshEmitterManager emitters = objects.emitters;
MeshEmitterManager<ForgeMeshEmitter> emitters = objects.emitters;

emitters.prepare(resultConsumer);

Expand Down Expand Up @@ -65,13 +65,13 @@ public static void bufferModel(BakedModel model, BlockPos pos, BlockAndTintGette
emitters.end();
}

public static void bufferBlocks(Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, Function<BlockPos, ModelData> modelDataLookup, boolean renderFluids, ResultConsumer<?> resultConsumer) {
public static void bufferBlocks(Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, Function<BlockPos, ModelData> modelDataLookup, boolean renderFluids, ModelBuilderResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (poseStack == null) {
poseStack = objects.identityPoseStack;
}
RandomSource random = objects.random;
ForgeMeshEmitterManager emitters = objects.emitters;
MeshEmitterManager<ForgeMeshEmitter> emitters = objects.emitters;
TransformingVertexConsumer transformingWrapper = objects.transformingWrapper;

emitters.prepare(resultConsumer);
Expand Down Expand Up @@ -141,7 +141,7 @@ private static class ThreadLocalObjects {
public final PoseStack identityPoseStack = new PoseStack();
public final RandomSource random = RandomSource.createNewThreadLocalInstance();

public final ForgeMeshEmitterManager emitters = new ForgeMeshEmitterManager();
public final MeshEmitterManager<ForgeMeshEmitter> emitters = new MeshEmitterManager<>(ForgeMeshEmitter::new);
public final TransformingVertexConsumer transformingWrapper = new TransformingVertexConsumer();
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package dev.engine_room.flywheel.lib.model.baked;

import java.util.function.Supplier;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;

import dev.engine_room.flywheel.api.material.Material;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.block.model.BakedQuad;
Expand All @@ -19,8 +18,8 @@ public class ForgeMeshEmitter extends MeshEmitter implements VertexConsumer {

private boolean defaultAo;

ForgeMeshEmitter(Supplier<BufferBuilder> bufferBuilderSupplier, RenderType renderType) {
super(bufferBuilderSupplier);
ForgeMeshEmitter(BufferBuilderStack bufferBuilderStack, RenderType renderType) {
super(bufferBuilderStack);
this.renderType = renderType;
}

Expand All @@ -37,7 +36,7 @@ public void prepareForModelLayer(boolean defaultAo) {

@Nullable
private BufferBuilder getBuffer(boolean shade, boolean ao) {
Object key = resultConsumer.createKey(renderType, shade, ao);
Material key = resultConsumer.createKey(renderType, shade, ao);
if (key != null) {
return getBuffer(key);
} else {
Expand Down
Loading