mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-14 08:16:13 +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"
|
modCompileOnly "net.fabricmc:fabric-loader:$fabric_loader_version"
|
||||||
|
|
||||||
compileOnly "com.google.code.findbugs:jsr305:3.0.2"
|
compileOnly "com.google.code.findbugs:jsr305:3.0.2"
|
||||||
|
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
test.configure {
|
test {
|
||||||
useJUnitPlatform()
|
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.BlockEntityVisualizer;
|
||||||
import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
|
import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
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 com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
import net.minecraft.world.entity.Entity;
|
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 BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer);
|
||||||
|
|
||||||
<T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? 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) {
|
public <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) {
|
||||||
VisualizerRegistryImpl.setVisualizer(type, 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;
|
package com.jozufozu.flywheel.lib.model;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -8,8 +7,8 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
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.material.Material;
|
||||||
import com.jozufozu.flywheel.api.model.Mesh;
|
import com.jozufozu.flywheel.api.model.Mesh;
|
||||||
import com.jozufozu.flywheel.api.model.Model;
|
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;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
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.RenderType;
|
||||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
|
||||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
|
||||||
|
|
||||||
public final class ModelUtil {
|
public final class ModelUtil {
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency.
|
* An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency.
|
||||||
* Meant to be used for virtual rendering.
|
* 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 static final float BOUNDING_SPHERE_EPSILON = 1e-4f;
|
||||||
|
|
||||||
private ModelUtil() {
|
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) {
|
public static MemoryBlock convertVanillaBuffer(BufferBuilder.RenderedBuffer buffer, VertexView vertexView) {
|
||||||
DrawState drawState = buffer.drawState();
|
DrawState drawState = buffer.drawState();
|
||||||
int vertexCount = drawState.vertexCount();
|
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.
|
* method with the same parameters will return the same object.
|
||||||
*/
|
*/
|
||||||
public final class Models {
|
public final class Models {
|
||||||
private static final ModelCache<BlockState> BLOCK_STATE = new ModelCache<>(it -> new BlockModelBuilder(it).build());
|
private static final ModelCache<BlockState> BLOCK_STATE = new ModelCache<>(it -> BlockModelBuilder.create(it)
|
||||||
private static final ModelCache<PartialModel> PARTIAL = new ModelCache<>(it -> new BakedModelBuilder(it.get()).build());
|
.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 static final ModelCache<TransformedPartial<?>> TRANSFORMED_PARTIAL = new ModelCache<>(TransformedPartial::create);
|
||||||
|
|
||||||
private Models() {
|
private Models() {
|
||||||
|
@ -85,7 +87,7 @@ public final class Models {
|
||||||
private Model create() {
|
private Model create() {
|
||||||
var stack = new PoseStack();
|
var stack = new PoseStack();
|
||||||
transformer.accept(key, stack);
|
transformer.accept(key, stack);
|
||||||
return new BakedModelBuilder(partial.get())
|
return BakedModelBuilder.create(partial.get())
|
||||||
.poseStack(stack)
|
.poseStack(stack)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,12 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
import com.jozufozu.flywheel.api.model.Model;
|
import com.jozufozu.flywheel.api.model.Model;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexView;
|
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.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
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.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
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.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.client.model.data.ModelData;
|
|
||||||
|
|
||||||
public class BakedModelBuilder {
|
public abstract class BakedModelBuilder {
|
||||||
private final BakedModel bakedModel;
|
protected final BakedModel bakedModel;
|
||||||
@Nullable
|
@Nullable
|
||||||
private BlockAndTintGetter level;
|
protected BlockAndTintGetter level;
|
||||||
@Nullable
|
@Nullable
|
||||||
private BlockState blockState;
|
protected BlockState blockState;
|
||||||
@Nullable
|
@Nullable
|
||||||
private PoseStack poseStack;
|
protected PoseStack poseStack;
|
||||||
@Nullable
|
@Nullable
|
||||||
private ModelData modelData;
|
protected BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
@Nullable
|
|
||||||
private 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;
|
this.bakedModel = bakedModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,43 +57,10 @@ public class BakedModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BakedModelBuilder modelData(ModelData modelData) {
|
|
||||||
this.modelData = modelData;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
public BakedModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
||||||
this.materialFunc = materialFunc;
|
this.materialFunc = materialFunc;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleModel build() {
|
public abstract 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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,31 +8,33 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
import com.jozufozu.flywheel.api.model.Model;
|
import com.jozufozu.flywheel.api.model.Model;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexView;
|
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.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
import com.jozufozu.flywheel.lib.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
import com.jozufozu.flywheel.lib.model.SimpleMesh;
|
||||||
import com.jozufozu.flywheel.lib.model.SimpleModel;
|
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.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.client.model.data.ModelData;
|
|
||||||
|
|
||||||
public class BlockModelBuilder {
|
public abstract class BlockModelBuilder {
|
||||||
private final BlockState state;
|
protected final BlockState state;
|
||||||
@Nullable
|
@Nullable
|
||||||
private BlockAndTintGetter level;
|
protected BlockAndTintGetter level;
|
||||||
@Nullable
|
@Nullable
|
||||||
private PoseStack poseStack;
|
protected PoseStack poseStack;
|
||||||
@Nullable
|
@Nullable
|
||||||
private ModelData modelData;
|
protected BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
@Nullable
|
|
||||||
private 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;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,40 +48,10 @@ public class BlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelBuilder modelData(ModelData modelData) {
|
|
||||||
this.modelData = modelData;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
public BlockModelBuilder materialFunc(BiFunction<RenderType, Boolean, Material> materialFunc) {
|
||||||
this.materialFunc = materialFunc;
|
this.materialFunc = materialFunc;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleModel build() {
|
public abstract 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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,14 @@ class MeshEmitter implements VertexConsumer {
|
||||||
private boolean lastQuadWasShaded;
|
private boolean lastQuadWasShaded;
|
||||||
private boolean seenFirstQuad;
|
private boolean seenFirstQuad;
|
||||||
@Nullable
|
@Nullable
|
||||||
private BakedModelBufferer.ResultConsumer resultConsumer;
|
private MeshEmitter.ResultConsumer resultConsumer;
|
||||||
|
|
||||||
MeshEmitter(BufferBuilder bufferBuilder, RenderType renderType) {
|
MeshEmitter(BufferBuilder bufferBuilder, RenderType renderType) {
|
||||||
this.bufferBuilder = bufferBuilder;
|
this.bufferBuilder = bufferBuilder;
|
||||||
this.renderType = renderType;
|
this.renderType = renderType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void begin(BakedModelBufferer.ResultConsumer resultConsumer) {
|
public void begin(ResultConsumer resultConsumer) {
|
||||||
this.resultConsumer = resultConsumer;
|
this.resultConsumer = resultConsumer;
|
||||||
|
|
||||||
begin();
|
begin();
|
||||||
|
@ -112,4 +112,8 @@ class MeshEmitter implements VertexConsumer {
|
||||||
public void unsetDefaultColor() {
|
public void unsetDefaultColor() {
|
||||||
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
|
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;
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
import com.jozufozu.flywheel.api.model.Model;
|
import com.jozufozu.flywheel.lib.internal.FlywheelLibPlatform;
|
||||||
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.SimpleModel;
|
||||||
import com.jozufozu.flywheel.lib.model.baked.BakedModelBufferer.ResultConsumer;
|
|
||||||
import com.jozufozu.flywheel.lib.vertex.NoOverlayVertexView;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraftforge.client.model.data.ModelData;
|
|
||||||
|
|
||||||
public class MultiBlockModelBuilder {
|
public abstract class MultiBlockModelBuilder {
|
||||||
private final BlockAndTintGetter level;
|
protected final BlockAndTintGetter level;
|
||||||
private final Iterable<BlockPos> positions;
|
protected final Iterable<BlockPos> positions;
|
||||||
@Nullable
|
@Nullable
|
||||||
private PoseStack poseStack;
|
protected PoseStack poseStack;
|
||||||
|
protected boolean renderFluids = false;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Function<BlockPos, ModelData> modelDataLookup;
|
protected BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
private boolean renderFluids = false;
|
|
||||||
@Nullable
|
|
||||||
private 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.level = level;
|
||||||
this.positions = positions;
|
this.positions = positions;
|
||||||
}
|
}
|
||||||
|
@ -43,11 +36,6 @@ public class MultiBlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiBlockModelBuilder modelDataLookup(Function<BlockPos, ModelData> modelDataLookup) {
|
|
||||||
this.modelDataLookup = modelDataLookup;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiBlockModelBuilder enableFluidRendering() {
|
public MultiBlockModelBuilder enableFluidRendering() {
|
||||||
renderFluids = true;
|
renderFluids = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -58,27 +46,5 @@ public class MultiBlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleModel build() {
|
public abstract 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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
||||||
|
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraftforge.client.event.ModelEvent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for loading and accessing json models.
|
* 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.
|
* Attempting to create a PartialModel after {@link ModelEvent.RegisterAdditional} will cause an error.
|
||||||
*/
|
*/
|
||||||
public class PartialModel {
|
public class PartialModel {
|
||||||
private static final List<PartialModel> ALL = new ArrayList<>();
|
static final List<PartialModel> ALL = new ArrayList<>();
|
||||||
private static boolean tooLate = false;
|
static boolean tooLate = false;
|
||||||
|
|
||||||
protected final ResourceLocation modelLocation;
|
protected final ResourceLocation modelLocation;
|
||||||
protected BakedModel bakedModel;
|
protected BakedModel bakedModel;
|
||||||
|
@ -34,30 +33,11 @@ public class PartialModel {
|
||||||
ALL.add(this);
|
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() {
|
public String getName() {
|
||||||
return getLocation()
|
return getLocation()
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void set(BakedModel bakedModel) {
|
|
||||||
this.bakedModel = bakedModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceLocation getLocation() {
|
public ResourceLocation getLocation() {
|
||||||
return modelLocation;
|
return modelLocation;
|
||||||
}
|
}
|
||||||
|
@ -65,4 +45,8 @@ public class PartialModel {
|
||||||
public BakedModel get() {
|
public BakedModel get() {
|
||||||
return bakedModel;
|
return bakedModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set(BakedModel bakedModel) {
|
||||||
|
this.bakedModel = bakedModel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package com.jozufozu.flywheel.lib.transform;
|
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;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
public interface TransformStack<Self extends TransformStack<Self>> extends Transform<Self> {
|
public interface TransformStack<Self extends TransformStack<Self>> extends Transform<Self> {
|
||||||
static PoseTransformStack of(PoseStack stack) {
|
static PoseTransformStack of(PoseStack stack) {
|
||||||
return InternalFlywheelApi.INSTANCE.getPoseTransformStackOf(stack);
|
return FlywheelLibPlatform.INSTANCE.getPoseTransformStackOf(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self pushPose();
|
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.memory.FlwMemoryTracker;
|
||||||
import com.jozufozu.flywheel.lib.model.ModelCache;
|
import com.jozufozu.flywheel.lib.model.ModelCache;
|
||||||
import com.jozufozu.flywheel.lib.model.ModelHolder;
|
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.LevelAttached;
|
||||||
import com.jozufozu.flywheel.lib.util.StringUtil;
|
import com.jozufozu.flywheel.lib.util.StringUtil;
|
||||||
|
|
||||||
|
@ -98,8 +98,8 @@ public class FlywheelForge {
|
||||||
modEventBus.<EndClientResourceReloadEvent>addListener($ -> ModelCache.onEndClientResourceReload());
|
modEventBus.<EndClientResourceReloadEvent>addListener($ -> ModelCache.onEndClientResourceReload());
|
||||||
modEventBus.<EndClientResourceReloadEvent>addListener($ -> ModelHolder.onEndClientResourceReload());
|
modEventBus.<EndClientResourceReloadEvent>addListener($ -> ModelHolder.onEndClientResourceReload());
|
||||||
|
|
||||||
modEventBus.addListener(PartialModel::onModelRegistry);
|
modEventBus.addListener(PartialModelEventHandler::onModelRegistry);
|
||||||
modEventBus.addListener(PartialModel::onModelBake);
|
modEventBus.addListener(PartialModelEventHandler::onModelBake);
|
||||||
|
|
||||||
Flywheel.earlyInit();
|
Flywheel.earlyInit();
|
||||||
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
|
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() {
|
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();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
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) {
|
if (state.getRenderShape() != RenderShape.MODEL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ final class BakedModelBufferer {
|
||||||
bufferSingle(renderDispatcher.getModelRenderer(), level, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
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();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
|
@ -142,13 +142,13 @@ final class BakedModelBufferer {
|
||||||
|
|
||||||
public final TransformingVertexConsumer transformingWrapper = new TransformingVertexConsumer();
|
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++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
var renderType = CHUNK_LAYERS[layerIndex];
|
var renderType = CHUNK_LAYERS[layerIndex];
|
||||||
var buffer = new BufferBuilder(renderType.bufferSize());
|
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