mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-10 12:34:11 +01:00
Get shulked
- Convert ShulkerBoxVisual to use InstanceTree - Add "pruning" helper visitors - Remove ModelPartConverter - Remove TextureMapper and related code from VertexWriter
This commit is contained in:
parent
31b3507d62
commit
d342ae740c
@ -1,6 +1,7 @@
|
||||
package dev.engine_room.flywheel.lib.model.part;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -24,14 +25,48 @@ public interface LoweringVisitor {
|
||||
return ModelTree.create(model, initialPose, new ModelTree[0], new String[0]);
|
||||
}
|
||||
|
||||
static LoweringVisitor materialApplyingVisitor(Material material) {
|
||||
static LoweringVisitor create(Material material) {
|
||||
return (path, mesh) -> new SingleMeshModel(mesh, material);
|
||||
}
|
||||
|
||||
static LoweringVisitor retexturingVisitor(Material material, TextureAtlasSprite sprite) {
|
||||
static LoweringVisitor create(Material material, TextureAtlasSprite sprite) {
|
||||
return (path, mesh) -> new SingleMeshModel(new RetexturedMesh(mesh, sprite), material);
|
||||
}
|
||||
|
||||
static LoweringVisitor pruning(Set<String> prune, Material material) {
|
||||
return new LoweringVisitor() {
|
||||
@Override
|
||||
public @Nullable ModelTree visit(String path, MeshTree meshTree) {
|
||||
if (prune.contains(path)) {
|
||||
return null;
|
||||
}
|
||||
return LoweringVisitor.super.visit(path, meshTree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model visit(String path, Mesh mesh) {
|
||||
return new SingleMeshModel(mesh, material);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static LoweringVisitor pruning(Set<String> prune, Material material, TextureAtlasSprite sprite) {
|
||||
return new LoweringVisitor() {
|
||||
@Override
|
||||
public @Nullable ModelTree visit(String path, MeshTree meshTree) {
|
||||
if (prune.contains(path)) {
|
||||
return null;
|
||||
}
|
||||
return LoweringVisitor.super.visit(path, meshTree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model visit(String path, Mesh mesh) {
|
||||
return new SingleMeshModel(new RetexturedMesh(mesh, sprite), material);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static String append(String path, String child) {
|
||||
if (path.isEmpty()) {
|
||||
return child;
|
||||
|
@ -1,70 +0,0 @@
|
||||
package dev.engine_room.flywheel.lib.model.part;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import dev.engine_room.flywheel.api.model.Mesh;
|
||||
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
|
||||
import dev.engine_room.flywheel.lib.model.SimpleQuadMesh;
|
||||
import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView;
|
||||
import dev.engine_room.flywheel.lib.vertex.VertexView;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.geom.EntityModelSet;
|
||||
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public final class ModelPartConverter {
|
||||
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||
|
||||
private ModelPartConverter() {
|
||||
}
|
||||
|
||||
public static Mesh convert(ModelPart modelPart, @Nullable PoseStack poseStack, @Nullable TextureMapper textureMapper) {
|
||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||
if (poseStack == null) {
|
||||
poseStack = objects.identityPoseStack;
|
||||
}
|
||||
VertexWriter vertexWriter = objects.vertexWriter;
|
||||
|
||||
vertexWriter.setTextureMapper(textureMapper);
|
||||
modelPart.render(poseStack, vertexWriter, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY);
|
||||
MemoryBlock data = vertexWriter.copyDataAndReset();
|
||||
|
||||
VertexView vertexView = new PosTexNormalVertexView();
|
||||
vertexView.load(data);
|
||||
return new SimpleQuadMesh(vertexView, "source=ModelPartConverter");
|
||||
}
|
||||
|
||||
public static Mesh convert(ModelLayerLocation layer, @Nullable TextureAtlasSprite sprite, String... childPath) {
|
||||
EntityModelSet entityModels = Minecraft.getInstance().getEntityModels();
|
||||
ModelPart modelPart = entityModels.bakeLayer(layer);
|
||||
for (String pathPart : childPath) {
|
||||
modelPart = modelPart.getChild(pathPart);
|
||||
}
|
||||
TextureMapper textureMapper = sprite == null ? null : TextureMapper.toSprite(sprite);
|
||||
return convert(modelPart, null, textureMapper);
|
||||
}
|
||||
|
||||
public static Mesh convert(ModelLayerLocation layer, String... childPath) {
|
||||
return convert(layer, null, childPath);
|
||||
}
|
||||
|
||||
public interface TextureMapper {
|
||||
void map(Vector2f uv);
|
||||
|
||||
static TextureMapper toSprite(TextureAtlasSprite sprite) {
|
||||
return uv -> uv.set(sprite.getU(uv.x * 16), sprite.getV(uv.y * 16));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThreadLocalObjects {
|
||||
public final PoseStack identityPoseStack = new PoseStack();
|
||||
public final VertexWriter vertexWriter = new VertexWriter();
|
||||
}
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
package dev.engine_room.flywheel.lib.model.part;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector2f;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
|
||||
import dev.engine_room.flywheel.lib.math.DataPacker;
|
||||
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
|
||||
import dev.engine_room.flywheel.lib.model.part.ModelPartConverter.TextureMapper;
|
||||
import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView;
|
||||
|
||||
class VertexWriter implements VertexConsumer {
|
||||
@ -16,10 +13,6 @@ class VertexWriter implements VertexConsumer {
|
||||
|
||||
private MemoryBlock data;
|
||||
|
||||
@Nullable
|
||||
private TextureMapper textureMapper;
|
||||
private final Vector2f uvVec = new Vector2f();
|
||||
|
||||
private int vertexCount;
|
||||
private boolean filledPosition;
|
||||
private boolean filledTexture;
|
||||
@ -29,10 +22,6 @@ class VertexWriter implements VertexConsumer {
|
||||
data = MemoryBlock.malloc(128 * STRIDE);
|
||||
}
|
||||
|
||||
public void setTextureMapper(@Nullable TextureMapper mapper) {
|
||||
textureMapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer vertex(double x, double y, double z) {
|
||||
if (!filledPosition) {
|
||||
@ -54,13 +43,6 @@ class VertexWriter implements VertexConsumer {
|
||||
@Override
|
||||
public VertexConsumer uv(float u, float v) {
|
||||
if (!filledTexture) {
|
||||
if (textureMapper != null) {
|
||||
uvVec.set(u, v);
|
||||
textureMapper.map(uvVec);
|
||||
u = uvVec.x;
|
||||
v = uvVec.y;
|
||||
}
|
||||
|
||||
long ptr = vertexPtr();
|
||||
MemoryUtil.memPutFloat(ptr + 12, u);
|
||||
MemoryUtil.memPutFloat(ptr + 16, v);
|
||||
@ -131,7 +113,6 @@ class VertexWriter implements VertexConsumer {
|
||||
filledPosition = false;
|
||||
filledTexture = false;
|
||||
filledNormal = false;
|
||||
textureMapper = null;
|
||||
|
||||
return dataCopy;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
|
||||
.build();
|
||||
|
||||
// Need to hold the visitor in a ResourceReloadHolder to ensure we have a valid sprite.
|
||||
private static final ResourceReloadHolder<LoweringVisitor> VISITOR = new ResourceReloadHolder<>(() -> LoweringVisitor.retexturingVisitor(MATERIAL, BellRenderer.BELL_RESOURCE_LOCATION.sprite()));
|
||||
private static final ResourceReloadHolder<LoweringVisitor> VISITOR = new ResourceReloadHolder<>(() -> LoweringVisitor.create(MATERIAL, BellRenderer.BELL_RESOURCE_LOCATION.sprite()));
|
||||
|
||||
private final InstanceTree instances;
|
||||
private final InstanceTree bellBody;
|
||||
|
@ -12,7 +12,6 @@ import org.joml.Matrix4fc;
|
||||
|
||||
import dev.engine_room.flywheel.api.instance.Instance;
|
||||
import dev.engine_room.flywheel.api.material.Material;
|
||||
import dev.engine_room.flywheel.api.model.Model;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.lib.material.CutoutShaders;
|
||||
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
|
||||
@ -20,7 +19,6 @@ import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
|
||||
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
|
||||
import dev.engine_room.flywheel.lib.model.part.LoweringVisitor;
|
||||
import dev.engine_room.flywheel.lib.model.part.ModelTree;
|
||||
import dev.engine_room.flywheel.lib.transform.TransformStack;
|
||||
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
|
||||
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
|
||||
@ -57,7 +55,7 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||
LAYER_LOCATIONS.put(ChestType.RIGHT, ModelLayers.DOUBLE_CHEST_RIGHT);
|
||||
}
|
||||
|
||||
private static final Function<TextureAtlasSprite, LoweringVisitor> VISITOR = new ResourceReloadCache<>(s -> LoweringVisitor.retexturingVisitor(MATERIAL, s));
|
||||
private static final Function<TextureAtlasSprite, LoweringVisitor> VISITOR = new ResourceReloadCache<>(s -> LoweringVisitor.create(MATERIAL, s));
|
||||
|
||||
@Nullable
|
||||
private final InstanceTree instances;
|
||||
|
@ -36,7 +36,7 @@ public class MinecartVisual<T extends AbstractMinecart> extends ComponentEntityV
|
||||
.texture(TEXTURE)
|
||||
.mipmap(false)
|
||||
.build();
|
||||
private static final LoweringVisitor VISITOR = LoweringVisitor.materialApplyingVisitor(MATERIAL);
|
||||
private static final LoweringVisitor VISITOR = LoweringVisitor.create(MATERIAL);
|
||||
|
||||
private final InstanceTree instances;
|
||||
@Nullable
|
||||
|
@ -1,28 +1,26 @@
|
||||
package dev.engine_room.flywheel.vanilla;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.joml.Quaternionf;
|
||||
|
||||
import com.mojang.math.Axis;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import dev.engine_room.flywheel.api.instance.Instance;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
|
||||
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
|
||||
import dev.engine_room.flywheel.lib.material.CutoutShaders;
|
||||
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
|
||||
import dev.engine_room.flywheel.lib.model.ModelCache;
|
||||
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
|
||||
import dev.engine_room.flywheel.lib.model.part.ModelPartConverter;
|
||||
import dev.engine_room.flywheel.lib.transform.TransformStack;
|
||||
import dev.engine_room.flywheel.lib.util.RecyclingPoseStack;
|
||||
import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
|
||||
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
|
||||
import dev.engine_room.flywheel.lib.model.part.LoweringVisitor;
|
||||
import dev.engine_room.flywheel.lib.model.part.ModelTree;
|
||||
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
|
||||
import net.minecraft.client.model.geom.ModelLayers;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
||||
@ -35,17 +33,13 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
||||
.backfaceCulling(false)
|
||||
.build();
|
||||
|
||||
private static final ModelCache<Material> BASE_MODELS = new ModelCache<>(texture -> {
|
||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "base"), MATERIAL);
|
||||
});
|
||||
private static final ModelCache<Material> LID_MODELS = new ModelCache<>(texture -> {
|
||||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), MATERIAL);
|
||||
});
|
||||
|
||||
private final TransformedInstance base;
|
||||
private final TransformedInstance lid;
|
||||
private static final Function<Material, LoweringVisitor> VISITORS = new ResourceReloadCache<>(m -> LoweringVisitor.pruning(Set.of("head"), MATERIAL, m.sprite()));
|
||||
|
||||
private final RecyclingPoseStack stack = new RecyclingPoseStack();
|
||||
private final InstanceTree instances;
|
||||
private final InstanceTree lid;
|
||||
|
||||
private final Matrix4f initialPose;
|
||||
|
||||
private float lastProgress = Float.NaN;
|
||||
|
||||
@ -60,31 +54,22 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
||||
texture = Sheets.SHULKER_TEXTURE_LOCATION.get(color.getId());
|
||||
}
|
||||
|
||||
var rotation = getDirection().getRotation();
|
||||
instances = InstanceTree.create(instancerProvider(), ModelTree.of(ModelLayers.SHULKER, VISITORS.apply(texture)));
|
||||
|
||||
stack.setIdentity();
|
||||
TransformStack.of(stack)
|
||||
.translate(getVisualPosition())
|
||||
.translate(0.5f)
|
||||
initialPose = createInitialPose();
|
||||
|
||||
lid = instances.childOrThrow("lid");
|
||||
}
|
||||
|
||||
private Matrix4f createInitialPose() {
|
||||
var rotation = getDirection().getRotation();
|
||||
var visualPosition = getVisualPosition();
|
||||
return new Matrix4f().translate(visualPosition.getX(), visualPosition.getY(), visualPosition.getZ())
|
||||
.translate(0.5f, 0.5f, 0.5f)
|
||||
.scale(0.9995f)
|
||||
.rotate(rotation)
|
||||
.scale(1, -1, -1)
|
||||
.translateY(-1);
|
||||
|
||||
base = createBaseInstance(texture).setTransform(stack);
|
||||
base.setChanged();
|
||||
lid = createLidInstance(texture).setTransform(stack);
|
||||
lid.setChanged();
|
||||
}
|
||||
|
||||
private TransformedInstance createBaseInstance(Material texture) {
|
||||
return instancerProvider().instancer(InstanceTypes.TRANSFORMED, BASE_MODELS.get(texture))
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private TransformedInstance createLidInstance(Material texture) {
|
||||
return instancerProvider().instancer(InstanceTypes.TRANSFORMED, LID_MODELS.get(texture))
|
||||
.createInstance();
|
||||
.translate(0, -1, 0);
|
||||
}
|
||||
|
||||
private Direction getDirection() {
|
||||
@ -107,33 +92,28 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
||||
}
|
||||
lastProgress = progress;
|
||||
|
||||
Quaternionf spin = Axis.YP.rotationDegrees(270.0f * progress);
|
||||
lid.yRot(1.5f * Mth.PI * progress);
|
||||
lid.yPos(24f - progress * 8f);
|
||||
|
||||
TransformStack.of(stack)
|
||||
.pushPose()
|
||||
.translateY(-progress * 0.5f)
|
||||
.rotate(spin);
|
||||
|
||||
lid.setTransform(stack)
|
||||
.setChanged();
|
||||
|
||||
stack.popPose();
|
||||
instances.updateInstancesStatic(initialPose);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight(float partialTick) {
|
||||
relight(base, lid);
|
||||
int packedLight = computePackedLight();
|
||||
instances.traverse(instance -> {
|
||||
instance.light(packedLight)
|
||||
.setChanged();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectCrumblingInstances(Consumer<Instance> consumer) {
|
||||
consumer.accept(base);
|
||||
consumer.accept(lid);
|
||||
instances.traverse(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _delete() {
|
||||
base.delete();
|
||||
lid.delete();
|
||||
instances.delete();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user