mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-13 15:56:07 +01:00
Compiling models
- Make model builders abstract - Move BakedModelBufferer as is into forge project - Create Forge*ModelBuilders with modeldata parameters - Wrap ModelBuilder ctors in factory methods - Add FlywheelLibPlatform api, similar to api.internal package but for lib-only/platform specific stuff - Move TransformStack wrapping into FlywheelLibPlatform - Create vanilla renderer through FlywheelLibPlatform - Handle partial model initialization in separate event handler class - Fix test configuration in common project
This commit is contained in:
parent
ff0a928479
commit
57ac1b08f4
20 changed files with 413 additions and 205 deletions
|
@ -6,9 +6,11 @@ dependencies {
|
|||
modCompileOnly "net.fabricmc:fabric-loader:$fabric_loader_version"
|
||||
|
||||
compileOnly "com.google.code.findbugs:jsr305:3.0.2"
|
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
|
||||
}
|
||||
|
||||
test.configure {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
|
|||
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
|
||||
import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
|
||||
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
||||
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
@ -94,6 +92,4 @@ public interface InternalFlywheelApi {
|
|||
<T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer);
|
||||
|
||||
<T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer);
|
||||
|
||||
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
|
||||
}
|
||||
|
|
|
@ -111,9 +111,4 @@ public final class InternalFlywheelImpl implements InternalFlywheelApi {
|
|||
public <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) {
|
||||
VisualizerRegistryImpl.setVisualizer(type, visualizer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
|
||||
return ((PoseStackExtension) stack).flywheel$transformStack();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package com.jozufozu.flywheel.lib.internal;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public interface FlywheelLibPlatform {
|
||||
FlywheelLibPlatform INSTANCE = load();
|
||||
|
||||
// Adapted from https://github.com/CaffeineMC/sodium-fabric/blob/bf4fc9dab16e1cca07b2f23a1201c9bf237c8044/src/api/java/net/caffeinemc/mods/sodium/api/internal/DependencyInjection.java
|
||||
private static FlywheelLibPlatform load() {
|
||||
Class<FlywheelLibPlatform> apiClass = FlywheelLibPlatform.class;
|
||||
Class<?> implClass;
|
||||
|
||||
try {
|
||||
implClass = Class.forName("com.jozufozu.flywheel.impl.FlywheelLibPlatformImpl");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Could not find implementation", e);
|
||||
}
|
||||
|
||||
if (!apiClass.isAssignableFrom(implClass)) {
|
||||
throw new RuntimeException("Class %s does not implement interface %s"
|
||||
.formatted(implClass.getName(), apiClass.getName()));
|
||||
}
|
||||
|
||||
Constructor<?> implConstructor;
|
||||
|
||||
try {
|
||||
implConstructor = implClass.getConstructor();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Could not find default constructor", e);
|
||||
}
|
||||
|
||||
Object implInstance;
|
||||
|
||||
try {
|
||||
implInstance = implConstructor.newInstance();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Could not instantiate implementation", e);
|
||||
}
|
||||
|
||||
return apiClass.cast(implInstance);
|
||||
}
|
||||
|
||||
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
|
||||
|
||||
BlockRenderDispatcher createVanillaRenderer();
|
||||
|
||||
BakedModelBuilder bakedModelBuilder(BakedModel bakedModel);
|
||||
|
||||
BlockModelBuilder blockModelBuilder(BlockState state);
|
||||
|
||||
MultiBlockModelBuilder multiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
@ApiStatus.Internal
|
||||
@ParametersAreNonnullByDefault
|
||||
@FieldsAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.lib.internal;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.FieldsAreNonnullByDefault;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -1,6 +1,5 @@
|
|||
package com.jozufozu.flywheel.lib.model;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
|
||||
|
@ -8,8 +7,8 @@ import org.jetbrains.annotations.Nullable;
|
|||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
|
@ -22,43 +21,21 @@ import com.jozufozu.flywheel.lib.vertex.PosVertexView;
|
|||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
|
||||
public final class ModelUtil {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
/**
|
||||
* An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency.
|
||||
* Meant to be used for virtual rendering.
|
||||
*/
|
||||
public static final BlockRenderDispatcher VANILLA_RENDERER = createVanillaRenderer();
|
||||
public static final BlockRenderDispatcher VANILLA_RENDERER = FlywheelLibPlatform.INSTANCE.createVanillaRenderer();
|
||||
private static final float BOUNDING_SPHERE_EPSILON = 1e-4f;
|
||||
|
||||
private ModelUtil() {
|
||||
}
|
||||
|
||||
private static BlockRenderDispatcher createVanillaRenderer() {
|
||||
BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer();
|
||||
BlockRenderDispatcher dispatcher = new BlockRenderDispatcher(null, null, null);
|
||||
try {
|
||||
for (Field field : BlockRenderDispatcher.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
field.set(dispatcher, field.get(defaultDispatcher));
|
||||
}
|
||||
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_");
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
|
||||
return defaultDispatcher;
|
||||
}
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
public static MemoryBlock convertVanillaBuffer(BufferBuilder.RenderedBuffer buffer, VertexView vertexView) {
|
||||
DrawState drawState = buffer.drawState();
|
||||
int vertexCount = drawState.vertexCount();
|
||||
|
|
|
@ -19,8 +19,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
* method with the same parameters will return the same object.
|
||||
*/
|
||||
public final class Models {
|
||||
private static final ModelCache<BlockState> BLOCK_STATE = new ModelCache<>(it -> new BlockModelBuilder(it).build());
|
||||
private static final ModelCache<PartialModel> PARTIAL = new ModelCache<>(it -> new BakedModelBuilder(it.get()).build());
|
||||
private static final ModelCache<BlockState> BLOCK_STATE = new ModelCache<>(it -> BlockModelBuilder.create(it)
|
||||
.build());
|
||||
private static final ModelCache<PartialModel> PARTIAL = new ModelCache<>(it -> BakedModelBuilder.create(it.get())
|
||||
.build());
|
||||
private static final ModelCache<TransformedPartial<?>> TRANSFORMED_PARTIAL = new ModelCache<>(TransformedPartial::create);
|
||||
|
||||
private Models() {
|
||||
|
@ -85,7 +87,7 @@ public final class Models {
|
|||
private Model create() {
|
||||
var stack = new PoseStack();
|
||||
transformer.accept(key, stack);
|
||||
return new BakedModelBuilder(partial.get())
|
||||
return BakedModelBuilder.create(partial.get())
|
||||
.poseStack(stack)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@ 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;
|
||||
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.BakedModelBufferer.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MeshEmitter.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
|
@ -21,22 +22,23 @@ import net.minecraft.client.resources.model.BakedModel;
|
|||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class BakedModelBuilder {
|
||||
private final BakedModel bakedModel;
|
||||
public abstract class BakedModelBuilder {
|
||||
protected final BakedModel bakedModel;
|
||||
@Nullable
|
||||
private BlockAndTintGetter level;
|
||||
protected BlockAndTintGetter level;
|
||||
@Nullable
|
||||
private BlockState blockState;
|
||||
protected BlockState blockState;
|
||||
@Nullable
|
||||
private PoseStack poseStack;
|
||||
protected PoseStack poseStack;
|
||||
@Nullable
|
||||
private ModelData modelData;
|
||||
@Nullable
|
||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||
protected BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||
|
||||
public BakedModelBuilder(BakedModel bakedModel) {
|
||||
public static BakedModelBuilder create(BakedModel bakedModel) {
|
||||
return FlywheelLibPlatform.INSTANCE.bakedModelBuilder(bakedModel);
|
||||
}
|
||||
|
||||
protected BakedModelBuilder(BakedModel bakedModel) {
|
||||
this.bakedModel = bakedModel;
|
||||
}
|
||||
|
||||
|
@ -55,43 +57,10 @@ public class BakedModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BakedModelBuilder modelData(ModelData modelData) {
|
||||
this.modelData = modelData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
||||
this.materialFunc = materialFunc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleModel build() {
|
||||
if (level == null) {
|
||||
level = VirtualEmptyBlockGetter.INSTANCE;
|
||||
}
|
||||
if (blockState == null) {
|
||||
blockState = Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
if (modelData == null) {
|
||||
modelData = ModelData.EMPTY;
|
||||
}
|
||||
if (materialFunc == null) {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
|
||||
ResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), level, bakedModel, blockState, poseStack, modelData, resultConsumer);
|
||||
|
||||
return new SimpleModel(out.build());
|
||||
}
|
||||
public abstract SimpleModel build();
|
||||
}
|
||||
|
|
|
@ -8,31 +8,33 @@ 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;
|
||||
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.BakedModelBufferer.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MeshEmitter.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class BlockModelBuilder {
|
||||
private final BlockState state;
|
||||
public abstract class BlockModelBuilder {
|
||||
protected final BlockState state;
|
||||
@Nullable
|
||||
private BlockAndTintGetter level;
|
||||
protected BlockAndTintGetter level;
|
||||
@Nullable
|
||||
private PoseStack poseStack;
|
||||
protected PoseStack poseStack;
|
||||
@Nullable
|
||||
private ModelData modelData;
|
||||
@Nullable
|
||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||
protected BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||
|
||||
public BlockModelBuilder(BlockState state) {
|
||||
public static BlockModelBuilder create(BlockState state) {
|
||||
return FlywheelLibPlatform.INSTANCE.blockModelBuilder(state);
|
||||
}
|
||||
|
||||
protected BlockModelBuilder(BlockState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
|
@ -46,40 +48,10 @@ public class BlockModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BlockModelBuilder modelData(ModelData modelData) {
|
||||
this.modelData = modelData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
||||
this.materialFunc = materialFunc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleModel build() {
|
||||
if (level == null) {
|
||||
level = VirtualEmptyBlockGetter.INSTANCE;
|
||||
}
|
||||
if (modelData == null) {
|
||||
modelData = ModelData.EMPTY;
|
||||
}
|
||||
if (materialFunc == null) {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
|
||||
ResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, level, state, poseStack, modelData, resultConsumer);
|
||||
|
||||
return new SimpleModel(out.build());
|
||||
}
|
||||
public abstract SimpleModel build();
|
||||
}
|
||||
|
|
|
@ -17,14 +17,14 @@ class MeshEmitter implements VertexConsumer {
|
|||
private boolean lastQuadWasShaded;
|
||||
private boolean seenFirstQuad;
|
||||
@Nullable
|
||||
private BakedModelBufferer.ResultConsumer resultConsumer;
|
||||
private MeshEmitter.ResultConsumer resultConsumer;
|
||||
|
||||
MeshEmitter(BufferBuilder bufferBuilder, RenderType renderType) {
|
||||
this.bufferBuilder = bufferBuilder;
|
||||
this.renderType = renderType;
|
||||
}
|
||||
|
||||
public void begin(BakedModelBufferer.ResultConsumer resultConsumer) {
|
||||
public void begin(ResultConsumer resultConsumer) {
|
||||
this.resultConsumer = resultConsumer;
|
||||
|
||||
begin();
|
||||
|
@ -112,4 +112,8 @@ class MeshEmitter implements VertexConsumer {
|
|||
public void unsetDefaultColor() {
|
||||
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
|
||||
}
|
||||
|
||||
public interface ResultConsumer {
|
||||
void accept(RenderType renderType, boolean shaded, BufferBuilder.RenderedBuffer data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,32 @@
|
|||
package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
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;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.BakedModelBufferer.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class MultiBlockModelBuilder {
|
||||
private final BlockAndTintGetter level;
|
||||
private final Iterable<BlockPos> positions;
|
||||
public abstract class MultiBlockModelBuilder {
|
||||
protected final BlockAndTintGetter level;
|
||||
protected final Iterable<BlockPos> positions;
|
||||
@Nullable
|
||||
private PoseStack poseStack;
|
||||
protected PoseStack poseStack;
|
||||
protected boolean renderFluids = false;
|
||||
@Nullable
|
||||
private Function<BlockPos, ModelData> modelDataLookup;
|
||||
private boolean renderFluids = false;
|
||||
@Nullable
|
||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||
protected BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||
|
||||
public MultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
|
||||
public static MultiBlockModelBuilder create(BlockAndTintGetter level, Iterable<BlockPos> positions) {
|
||||
return FlywheelLibPlatform.INSTANCE.multiBlockModelBuilder(level, positions);
|
||||
}
|
||||
|
||||
protected MultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
|
||||
this.level = level;
|
||||
this.positions = positions;
|
||||
}
|
||||
|
@ -43,11 +36,6 @@ public class MultiBlockModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public MultiBlockModelBuilder modelDataLookup(Function<BlockPos, ModelData> modelDataLookup) {
|
||||
this.modelDataLookup = modelDataLookup;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MultiBlockModelBuilder enableFluidRendering() {
|
||||
renderFluids = true;
|
||||
return this;
|
||||
|
@ -58,27 +46,5 @@ public class MultiBlockModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public SimpleModel build() {
|
||||
if (modelDataLookup == null) {
|
||||
modelDataLookup = pos -> ModelData.EMPTY;
|
||||
}
|
||||
if (materialFunc == null) {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
|
||||
ResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, positions.iterator(), level, poseStack, modelDataLookup, renderFluids, resultConsumer);
|
||||
|
||||
return new SimpleModel(out.build());
|
||||
}
|
||||
public abstract SimpleModel build();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
|||
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.event.ModelEvent;
|
||||
|
||||
/**
|
||||
* A helper class for loading and accessing json models.
|
||||
|
@ -19,8 +18,8 @@ import net.minecraftforge.client.event.ModelEvent;
|
|||
* Attempting to create a PartialModel after {@link ModelEvent.RegisterAdditional} will cause an error.
|
||||
*/
|
||||
public class PartialModel {
|
||||
private static final List<PartialModel> ALL = new ArrayList<>();
|
||||
private static boolean tooLate = false;
|
||||
static final List<PartialModel> ALL = new ArrayList<>();
|
||||
static boolean tooLate = false;
|
||||
|
||||
protected final ResourceLocation modelLocation;
|
||||
protected BakedModel bakedModel;
|
||||
|
@ -34,30 +33,11 @@ public class PartialModel {
|
|||
ALL.add(this);
|
||||
}
|
||||
|
||||
public static void onModelRegistry(ModelEvent.RegisterAdditional event) {
|
||||
for (PartialModel partial : ALL) {
|
||||
event.register(partial.getLocation());
|
||||
}
|
||||
|
||||
tooLate = true;
|
||||
}
|
||||
|
||||
public static void onModelBake(ModelEvent.BakingCompleted event) {
|
||||
var modelRegistry = event.getModels();
|
||||
for (PartialModel partial : ALL) {
|
||||
partial.set(modelRegistry.get(partial.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return getLocation()
|
||||
.toString();
|
||||
}
|
||||
|
||||
protected void set(BakedModel bakedModel) {
|
||||
this.bakedModel = bakedModel;
|
||||
}
|
||||
|
||||
public ResourceLocation getLocation() {
|
||||
return modelLocation;
|
||||
}
|
||||
|
@ -65,4 +45,8 @@ public class PartialModel {
|
|||
public BakedModel get() {
|
||||
return bakedModel;
|
||||
}
|
||||
|
||||
void set(BakedModel bakedModel) {
|
||||
this.bakedModel = bakedModel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.jozufozu.flywheel.lib.transform;
|
||||
|
||||
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
|
||||
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
public interface TransformStack<Self extends TransformStack<Self>> extends Transform<Self> {
|
||||
static PoseTransformStack of(PoseStack stack) {
|
||||
return InternalFlywheelApi.INSTANCE.getPoseTransformStackOf(stack);
|
||||
return FlywheelLibPlatform.INSTANCE.getPoseTransformStackOf(stack);
|
||||
}
|
||||
|
||||
Self pushPose();
|
||||
|
|
|
@ -19,7 +19,7 @@ import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler;
|
|||
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
|
||||
import com.jozufozu.flywheel.lib.model.ModelCache;
|
||||
import com.jozufozu.flywheel.lib.model.ModelHolder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.PartialModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.PartialModelEventHandler;
|
||||
import com.jozufozu.flywheel.lib.util.LevelAttached;
|
||||
import com.jozufozu.flywheel.lib.util.StringUtil;
|
||||
|
||||
|
@ -98,8 +98,8 @@ public class FlywheelForge {
|
|||
modEventBus.<EndClientResourceReloadEvent>addListener($ -> ModelCache.onEndClientResourceReload());
|
||||
modEventBus.<EndClientResourceReloadEvent>addListener($ -> ModelHolder.onEndClientResourceReload());
|
||||
|
||||
modEventBus.addListener(PartialModel::onModelRegistry);
|
||||
modEventBus.addListener(PartialModel::onModelBake);
|
||||
modEventBus.addListener(PartialModelEventHandler::onModelRegistry);
|
||||
modEventBus.addListener(PartialModelEventHandler::onModelBake);
|
||||
|
||||
Flywheel.earlyInit();
|
||||
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package com.jozufozu.flywheel.impl;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.jozufozu.flywheel.impl.extension.PoseStackExtension;
|
||||
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.ForgeBakedModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.ForgeBlockModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.ForgeMultiBlockModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
|
||||
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
|
||||
public class FlywheelLibPlatformImpl implements FlywheelLibPlatform {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@Override
|
||||
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
|
||||
return ((PoseStackExtension) stack).flywheel$transformStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderDispatcher createVanillaRenderer() {
|
||||
BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer();
|
||||
BlockRenderDispatcher dispatcher = new BlockRenderDispatcher(null, null, null);
|
||||
try {
|
||||
for (Field field : BlockRenderDispatcher.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
field.set(dispatcher, field.get(defaultDispatcher));
|
||||
}
|
||||
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_");
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
|
||||
return defaultDispatcher;
|
||||
}
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModelBuilder bakedModelBuilder(BakedModel bakedModel) {
|
||||
return new ForgeBakedModelBuilder(bakedModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockModelBuilder blockModelBuilder(BlockState state) {
|
||||
return new ForgeBlockModelBuilder(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiBlockModelBuilder multiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
|
||||
return new ForgeMultiBlockModelBuilder(level, positions);
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ final class BakedModelBufferer {
|
|||
private BakedModelBufferer() {
|
||||
}
|
||||
|
||||
public static void bufferSingle(ModelBlockRenderer blockRenderer, BlockAndTintGetter level, BakedModel model, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) {
|
||||
public static void bufferSingle(ModelBlockRenderer blockRenderer, BlockAndTintGetter level, BakedModel model, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, MeshEmitter.ResultConsumer resultConsumer) {
|
||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||
if (poseStack == null) {
|
||||
poseStack = objects.identityPoseStack;
|
||||
|
@ -59,7 +59,7 @@ final class BakedModelBufferer {
|
|||
}
|
||||
}
|
||||
|
||||
public static void bufferBlock(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) {
|
||||
public static void bufferBlock(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, MeshEmitter.ResultConsumer resultConsumer) {
|
||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
||||
return;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ final class BakedModelBufferer {
|
|||
bufferSingle(renderDispatcher.getModelRenderer(), level, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
||||
}
|
||||
|
||||
public static void bufferMultiBlock(BlockRenderDispatcher renderDispatcher, Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, Function<BlockPos, ModelData> modelDataLookup, boolean renderFluids, ResultConsumer resultConsumer) {
|
||||
public static void bufferMultiBlock(BlockRenderDispatcher renderDispatcher, Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, Function<BlockPos, ModelData> modelDataLookup, boolean renderFluids, MeshEmitter.ResultConsumer resultConsumer) {
|
||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||
if (poseStack == null) {
|
||||
poseStack = objects.identityPoseStack;
|
||||
|
@ -142,13 +142,13 @@ final class BakedModelBufferer {
|
|||
|
||||
public final TransformingVertexConsumer transformingWrapper = new TransformingVertexConsumer();
|
||||
|
||||
public final MeshEmitter[] emitters = new MeshEmitter[CHUNK_LAYER_AMOUNT];
|
||||
public final ForgeMeshEmitter[] emitters = new ForgeMeshEmitter[CHUNK_LAYER_AMOUNT];
|
||||
|
||||
{
|
||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||
var renderType = CHUNK_LAYERS[layerIndex];
|
||||
var buffer = new BufferBuilder(renderType.bufferSize());
|
||||
emitters[layerIndex] = new MeshEmitter(buffer, renderType);
|
||||
emitters[layerIndex] = new ForgeMeshEmitter(buffer, renderType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
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;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MeshEmitter.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class ForgeBakedModelBuilder extends BakedModelBuilder {
|
||||
@Nullable
|
||||
private ModelData modelData;
|
||||
|
||||
public ForgeBakedModelBuilder(BakedModel bakedModel) {
|
||||
super(bakedModel);
|
||||
}
|
||||
|
||||
public ForgeBakedModelBuilder modelData(ModelData modelData) {
|
||||
this.modelData = modelData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleModel build() {
|
||||
if (level == null) {
|
||||
level = VirtualEmptyBlockGetter.INSTANCE;
|
||||
}
|
||||
if (blockState == null) {
|
||||
blockState = Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
if (modelData == null) {
|
||||
modelData = ModelData.EMPTY;
|
||||
}
|
||||
if (materialFunc == null) {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
|
||||
ResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), level, bakedModel, blockState, poseStack, modelData, resultConsumer);
|
||||
|
||||
return new SimpleModel(out.build());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
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;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MeshEmitter.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class ForgeBlockModelBuilder extends BlockModelBuilder {
|
||||
@Nullable
|
||||
private ModelData modelData;
|
||||
|
||||
public ForgeBlockModelBuilder(BlockState state) {
|
||||
super(state);
|
||||
}
|
||||
|
||||
public ForgeBlockModelBuilder modelData(ModelData modelData) {
|
||||
this.modelData = modelData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleModel build() {
|
||||
if (level == null) {
|
||||
level = VirtualEmptyBlockGetter.INSTANCE;
|
||||
}
|
||||
if (modelData == null) {
|
||||
modelData = ModelData.EMPTY;
|
||||
}
|
||||
if (materialFunc == null) {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
|
||||
ResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, level, state, poseStack, modelData, resultConsumer);
|
||||
|
||||
return new SimpleModel(out.build());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
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;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
||||
import com.jozufozu.flywheel.lib.model.baked.MeshEmitter.ResultConsumer;
|
||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public class ForgeMultiBlockModelBuilder extends MultiBlockModelBuilder {
|
||||
@Nullable
|
||||
private Function<BlockPos, ModelData> modelDataLookup;
|
||||
|
||||
public ForgeMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
|
||||
super(level, positions);
|
||||
}
|
||||
|
||||
public ForgeMultiBlockModelBuilder modelDataLookup(Function<BlockPos, ModelData> modelDataLookup) {
|
||||
this.modelDataLookup = modelDataLookup;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleModel build() {
|
||||
if (modelDataLookup == null) {
|
||||
modelDataLookup = pos -> ModelData.EMPTY;
|
||||
}
|
||||
if (materialFunc == null) {
|
||||
materialFunc = ModelUtil::getMaterial;
|
||||
}
|
||||
|
||||
var out = ImmutableList.<Model.ConfiguredMesh>builder();
|
||||
|
||||
ResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, positions.iterator(), level, poseStack, modelDataLookup, renderFluids, resultConsumer);
|
||||
|
||||
return new SimpleModel(out.build());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.jozufozu.flywheel.lib.model.baked;
|
||||
|
||||
import net.minecraftforge.client.event.ModelEvent;
|
||||
|
||||
public class PartialModelEventHandler {
|
||||
public static void onModelRegistry(ModelEvent.RegisterAdditional event) {
|
||||
for (PartialModel partial : PartialModel.ALL) {
|
||||
event.register(partial.getLocation());
|
||||
}
|
||||
|
||||
PartialModel.tooLate = true;
|
||||
}
|
||||
|
||||
public static void onModelBake(ModelEvent.BakingCompleted event) {
|
||||
var modelRegistry = event.getModels();
|
||||
for (PartialModel partial : PartialModel.ALL) {
|
||||
partial.set(modelRegistry.get(partial.getLocation()));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue