Keeping it shrimple

- Bake a model layer and then compile each part into a separate mesh
- Move vanilla mixins to lib
- Move caching logic into MeshTree
This commit is contained in:
Jozufozu 2024-04-12 19:38:49 -07:00
parent d2aa2e0013
commit 209da68c52
22 changed files with 166 additions and 470 deletions

View file

@ -98,7 +98,7 @@ mixin {
config 'flywheel.backend.mixins.json'
config 'flywheel.impl.mixins.json'
config 'flywheel.impl.sodium.mixins.json'
config 'flywheel.vanilla.mixins.json'
config 'flywheel.lib.mixins.json'
debug.verbose = true
debug.export = true

View file

@ -27,11 +27,11 @@ 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.part.MeshTree;
import com.jozufozu.flywheel.lib.util.LevelAttached;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.jozufozu.flywheel.lib.util.StringUtil;
import com.jozufozu.flywheel.vanilla.VanillaVisuals;
import com.jozufozu.flywheel.vanilla.model.MeshTreeCache;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
@ -107,7 +107,7 @@ public class Flywheel {
modEventBus.addListener(BackendManagerImpl::onEndClientResourceReload);
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload(e));
modEventBus.addListener(MeshTreeCache::onEndClientResourceReload);
modEventBus.addListener(MeshTree::onEndClientResourceReload);
modEventBus.addListener(ModelHolder::onEndClientResourceReload);
modEventBus.addListener(PartialModel::onModelRegistry);

View file

@ -0,0 +1,21 @@
package com.jozufozu.flywheel.lib.mixin;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.geom.ModelPart;
@Mixin(ModelPart.class)
public interface ModelPartAccessor {
@Accessor("children")
Map<String, ModelPart> flywheel$children();
@Invoker("compile")
void flywheel$compile(PoseStack.Pose pPose, VertexConsumer pVertexConsumer, int pPackedLight, int pPackedOverlay, float pRed, float pGreen, float pBlue, float pAlpha);
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.vanilla.mixin;
package com.jozufozu.flywheel.lib.mixin;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.vanilla.model;
package com.jozufozu.flywheel.lib.model;
import org.joml.Vector4fc;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.vanilla.model;
package com.jozufozu.flywheel.lib.model;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.lib.vertex.WrappedVertexList;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.vanilla.model;
package com.jozufozu.flywheel.lib.model.part;
import java.util.HashMap;
import java.util.Map;

View file

@ -0,0 +1,114 @@
package com.jozufozu.flywheel.lib.model.part;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.lib.mixin.ModelPartAccessor;
import com.jozufozu.flywheel.lib.model.SimpleMesh;
import com.jozufozu.flywheel.lib.vertex.PosTexNormalVertexView;
import com.mojang.blaze3d.vertex.PoseStack;
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.model.geom.PartPose;
public class MeshTree {
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
private static final PoseStack.Pose IDENTITY = new PoseStack().last();
private static final Map<ModelLayerLocation, MeshTree> MESH_TREES = new ConcurrentHashMap<>();
private final PartPose initialPose;
@Nullable
private final Mesh mesh;
private final Map<String, MeshTree> children;
private MeshTree(PartPose initialPose, @Nullable Mesh mesh, Map<String, MeshTree> children) {
this.initialPose = initialPose;
this.mesh = mesh;
this.children = children;
}
public static MeshTree get(ModelLayerLocation key) {
return MESH_TREES.computeIfAbsent(key, MeshTree::convert);
}
@ApiStatus.Internal
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
MESH_TREES.values()
.forEach(MeshTree::delete);
MESH_TREES.clear();
}
public PartPose initialPose() {
return initialPose;
}
@Nullable
public Mesh mesh() {
return mesh;
}
public Map<String, MeshTree> children() {
return children;
}
@Nullable
public MeshTree child(String name) {
return children.get(name);
}
public void delete() {
if (mesh != null) {
mesh.delete();
}
children.values()
.forEach(MeshTree::delete);
}
public static MeshTree convert(ModelLayerLocation location) {
EntityModelSet entityModels = Minecraft.getInstance()
.getEntityModels();
ModelPart modelPart = entityModels.bakeLayer(location);
return convert(modelPart, THREAD_LOCAL_OBJECTS.get());
}
private static MeshTree convert(ModelPart modelPart, ThreadLocalObjects objects) {
var accessor = cast(modelPart);
var childModelParts = accessor.flywheel$children();
Map<String, MeshTree> children = new HashMap<>();
for (Map.Entry<String, ModelPart> entry : childModelParts.entrySet()) {
children.put(entry.getKey(), convert(entry.getValue(), objects));
}
return new MeshTree(modelPart.getInitialPose(), compile(accessor, objects), children);
}
private static Mesh compile(ModelPartAccessor accessor, ThreadLocalObjects objects) {
var vertexWriter = objects.vertexWriter;
accessor.flywheel$compile(IDENTITY, vertexWriter, 0, 0, 1.0F, 1.0F, 1.0F, 1.0F);
var data = vertexWriter.copyDataAndReset();
return new SimpleMesh(new PosTexNormalVertexView(), data, "source=ModelPartConverter");
}
private static ModelPartAccessor cast(ModelPart cube) {
return (ModelPartAccessor) (Object) cube;
}
private static class ThreadLocalObjects {
public final VertexWriter vertexWriter = new VertexWriter();
}
}

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.vanilla;
import com.jozufozu.flywheel.vanilla.model.InstanceTree;
import com.jozufozu.flywheel.lib.model.part.InstanceTree;
import com.mojang.blaze3d.vertex.PoseStack;
public abstract class AgeableListComponent {

View file

@ -15,12 +15,12 @@ import com.jozufozu.flywheel.lib.instance.OrientedInstance;
import com.jozufozu.flywheel.lib.instance.TransformedInstance;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.ModelCache;
import com.jozufozu.flywheel.lib.model.RetexturedMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.jozufozu.flywheel.lib.model.part.MeshTree;
import com.jozufozu.flywheel.lib.util.Pair;
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
import com.jozufozu.flywheel.vanilla.model.MeshTreeCache;
import com.jozufozu.flywheel.vanilla.model.RetexturedMesh;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
import net.minecraft.client.model.geom.ModelLayerLocation;
@ -173,7 +173,7 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
}
public static Model chestModel(Pair<ChestType, Material> key, String child) {
var mesh = MeshTreeCache.get(LAYER_LOCATIONS.get(key.first()))
var mesh = MeshTree.get(LAYER_LOCATIONS.get(key.first()))
.child(child)
.mesh();
var sprite = key.second()

View file

@ -4,8 +4,8 @@ import java.util.List;
import com.jozufozu.flywheel.api.instance.InstancerProvider;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.vanilla.model.InstanceTree;
import com.jozufozu.flywheel.vanilla.model.MeshTreeCache;
import com.jozufozu.flywheel.lib.model.part.InstanceTree;
import com.jozufozu.flywheel.lib.model.part.MeshTree;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.util.Mth;
@ -23,7 +23,7 @@ public class QuadrupedComponent extends AgeableListComponent {
public QuadrupedComponent(InstancerProvider instancerProvider, ModelLayerLocation layer, Material material, Config config) {
super(config);
var meshTree = MeshTreeCache.get(layer);
var meshTree = MeshTree.get(layer);
this.root = InstanceTree.create(instancerProvider, meshTree, material);

View file

@ -11,12 +11,12 @@ import com.jozufozu.flywheel.lib.instance.InstanceTypes;
import com.jozufozu.flywheel.lib.instance.TransformedInstance;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.ModelCache;
import com.jozufozu.flywheel.lib.model.RetexturedMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.jozufozu.flywheel.lib.model.part.MeshTree;
import com.jozufozu.flywheel.lib.transform.TransformStack;
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
import com.jozufozu.flywheel.vanilla.model.MeshTreeCache;
import com.jozufozu.flywheel.vanilla.model.RetexturedMesh;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
@ -138,7 +138,7 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
}
private static Model shulkerModel(Material texture, String child) {
var mesh = MeshTreeCache.get(ModelLayers.SHULKER)
var mesh = MeshTree.get(ModelLayers.SHULKER)
.child(child)
.mesh();
return new SingleMeshModel(new RetexturedMesh(mesh, texture.sprite()), Materials.SHULKER);

View file

@ -1,36 +0,0 @@
package com.jozufozu.flywheel.vanilla.mixin;
import java.util.Set;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.geom.builders.CubeDefinition;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import net.minecraft.client.model.geom.builders.UVPair;
import net.minecraft.core.Direction;
@Mixin(CubeDefinition.class)
public interface CubeDefinitionAccessor {
@Accessor("origin")
Vector3f vanillin$origin();
@Accessor("dimensions")
Vector3f vanillin$dimensions();
@Accessor("grow")
CubeDeformation vanillin$grow();
@Accessor("mirror")
boolean vanillin$mirror();
@Accessor("texCoord")
UVPair vanillin$texCoord();
@Accessor("texScale")
UVPair vanillin$texScale();
@Accessor("visibleFaces")
Set<Direction> vanillin$visibleFaces();
}

View file

@ -1,18 +0,0 @@
package com.jozufozu.flywheel.vanilla.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.geom.builders.CubeDeformation;
@Mixin(CubeDeformation.class)
public interface CubeDeformationAccessor {
@Accessor("growX")
float vanillin$growX();
@Accessor("growY")
float vanillin$growY();
@Accessor("growZ")
float vanillin$growZ();
}

View file

@ -1,16 +0,0 @@
package com.jozufozu.flywheel.vanilla.mixin;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
@Mixin(EntityModelSet.class)
public interface EntityModelSetAccessor {
@Accessor("roots")
Map<ModelLayerLocation, LayerDefinition> vanillin$roots();
}

View file

@ -1,17 +0,0 @@
package com.jozufozu.flywheel.vanilla.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.MaterialDefinition;
import net.minecraft.client.model.geom.builders.MeshDefinition;
@Mixin(LayerDefinition.class)
public interface LayerDefinitionAccessor {
@Accessor("mesh")
MeshDefinition vanillin$mesh();
@Accessor("material")
MaterialDefinition vanillin$material();
}

View file

@ -1,15 +0,0 @@
package com.jozufozu.flywheel.vanilla.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.geom.builders.MaterialDefinition;
@Mixin(MaterialDefinition.class)
public interface MaterialDefinitionAccessor {
@Accessor("xTexSize")
int vanillin$xTexSize();
@Accessor("yTexSize")
int vanillin$yTexSize();
}

View file

@ -1,23 +0,0 @@
package com.jozufozu.flywheel.vanilla.mixin;
import java.util.List;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
@Mixin(PartDefinition.class)
public interface PartDefinitionAccessor {
@Accessor("cubes")
List<CubeDefinition> vanillin$cubes();
@Accessor("partPose")
PartPose vanillin$partPose();
@Accessor("children")
Map<String, PartDefinition> vanillin$children();
}

View file

@ -1,281 +0,0 @@
package com.jozufozu.flywheel.vanilla.model;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.SimpleMesh;
import com.jozufozu.flywheel.lib.vertex.PosTexNormalVertexView;
import com.jozufozu.flywheel.vanilla.mixin.CubeDefinitionAccessor;
import com.jozufozu.flywheel.vanilla.mixin.CubeDeformationAccessor;
import com.jozufozu.flywheel.vanilla.mixin.EntityModelSetAccessor;
import com.jozufozu.flywheel.vanilla.mixin.LayerDefinitionAccessor;
import com.jozufozu.flywheel.vanilla.mixin.MaterialDefinitionAccessor;
import com.jozufozu.flywheel.vanilla.mixin.PartDefinitionAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeDefinition;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
import net.minecraft.core.Direction;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class MeshTree {
private final PartPose initialPose;
@Nullable
private final Mesh mesh;
private final Map<String, MeshTree> children;
private MeshTree(PartPose initialPose, @Nullable Mesh mesh, Map<String, MeshTree> children) {
this.initialPose = initialPose;
this.mesh = mesh;
this.children = children;
}
public PartPose initialPose() {
return initialPose;
}
@Nullable
public Mesh mesh() {
return mesh;
}
public Map<String, MeshTree> children() {
return children;
}
@Nullable
public MeshTree child(String name) {
return children.get(name);
}
public void delete() {
if (mesh != null) {
mesh.delete();
}
children.values()
.forEach(MeshTree::delete);
}
public static MeshTree convert(ModelLayerLocation location) {
var entityModels = (EntityModelSetAccessor) Minecraft.getInstance()
.getEntityModels();
return convert(entityModels.vanillin$roots()
.get(location));
}
public static MeshTree convert(LayerDefinition layerDefinition) {
var accessor = (LayerDefinitionAccessor) layerDefinition;
var root = accessor.vanillin$mesh()
.getRoot();
var material = (MaterialDefinitionAccessor) accessor.vanillin$material();
int xTexSize = material.vanillin$xTexSize();
int yTexSize = material.vanillin$yTexSize();
return convert(root, xTexSize, yTexSize);
}
private static MeshTree convert(PartDefinition part, int xTexSize, int yTexSize) {
var accessor = (PartDefinitionAccessor) part;
var cubes = accessor.vanillin$cubes();
var initialPose = accessor.vanillin$partPose();
var childDefinitions = accessor.vanillin$children();
Map<String, MeshTree> children = new HashMap<>();
for (Map.Entry<String, PartDefinition> entry : childDefinitions.entrySet()) {
children.put(entry.getKey(), convert(entry.getValue(), xTexSize, yTexSize));
}
return new MeshTree(initialPose, convertCubes(cubes, xTexSize, yTexSize), children);
}
private static Mesh convertCubes(List<CubeDefinition> cubes, int xTexSize, int yTexSize) {
if (cubes.isEmpty()) {
return null;
}
var totalVisibleFaces = countVisibleFaces(cubes);
if (totalVisibleFaces == 0) {
return null;
}
var totalVertices = totalVisibleFaces * 4;
var block = MemoryBlock.malloc(totalVertices * PosTexNormalVertexView.STRIDE);
var view = new PosTexNormalVertexView();
view.ptr(block.ptr());
view.vertexCount(totalVertices);
int vertexIndex = 0;
for (CubeDefinition cube : cubes) {
CubeDefinitionAccessor accessor = cast(cube);
var origin = accessor.vanillin$origin();
var dimensions = accessor.vanillin$dimensions();
var grow = (CubeDeformationAccessor) accessor.vanillin$grow();
var pMirror = accessor.vanillin$mirror();
var texCoord = accessor.vanillin$texCoord();
var texScale = accessor.vanillin$texScale();
var visibleFaces = accessor.vanillin$visibleFaces();
float pOriginX = origin.x();
float pOriginY = origin.y();
float pOriginZ = origin.z();
float pDimensionX = dimensions.x();
float pDimensionY = dimensions.y();
float pDimensionZ = dimensions.z();
float pGrowX = grow.vanillin$growX();
float pGrowY = grow.vanillin$growY();
float pGrowZ = grow.vanillin$growZ();
float pTexCoordU = texCoord.u();
float pTexCoordV = texCoord.v();
float pTexScaleU = xTexSize * texScale.u();
float pTexScaleV = yTexSize * texScale.v();
float f = pOriginX + pDimensionX;
float f1 = pOriginY + pDimensionY;
float f2 = pOriginZ + pDimensionZ;
pOriginX -= pGrowX;
pOriginY -= pGrowY;
pOriginZ -= pGrowZ;
f += pGrowX;
f1 += pGrowY;
f2 += pGrowZ;
if (pMirror) {
float f3 = f;
f = pOriginX;
pOriginX = f3;
}
Vertex modelpart$vertex7 = new Vertex(pOriginX, pOriginY, pOriginZ, 0.0F, 0.0F);
Vertex modelpart$vertex = new Vertex(f, pOriginY, pOriginZ, 0.0F, 8.0F);
Vertex modelpart$vertex1 = new Vertex(f, f1, pOriginZ, 8.0F, 8.0F);
Vertex modelpart$vertex2 = new Vertex(pOriginX, f1, pOriginZ, 8.0F, 0.0F);
Vertex modelpart$vertex3 = new Vertex(pOriginX, pOriginY, f2, 0.0F, 0.0F);
Vertex modelpart$vertex4 = new Vertex(f, pOriginY, f2, 0.0F, 8.0F);
Vertex modelpart$vertex5 = new Vertex(f, f1, f2, 8.0F, 8.0F);
Vertex modelpart$vertex6 = new Vertex(pOriginX, f1, f2, 8.0F, 0.0F);
float f4 = pTexCoordU;
float f5 = pTexCoordU + pDimensionZ;
float f6 = pTexCoordU + pDimensionZ + pDimensionX;
float f7 = pTexCoordU + pDimensionZ + pDimensionX + pDimensionX;
float f8 = pTexCoordU + pDimensionZ + pDimensionX + pDimensionZ;
float f9 = pTexCoordU + pDimensionZ + pDimensionX + pDimensionZ + pDimensionX;
float f10 = pTexCoordV;
float f11 = pTexCoordV + pDimensionZ;
float f12 = pTexCoordV + pDimensionZ + pDimensionY;
if (visibleFaces.contains(Direction.DOWN)) {
addFace(view, vertexIndex, new Vertex[]{modelpart$vertex4, modelpart$vertex3, modelpart$vertex7, modelpart$vertex}, f5, f10, f6, f11, pTexScaleU, pTexScaleV, pMirror, Direction.DOWN);
vertexIndex += 4;
}
if (visibleFaces.contains(Direction.UP)) {
addFace(view, vertexIndex, new Vertex[]{modelpart$vertex1, modelpart$vertex2, modelpart$vertex6, modelpart$vertex5}, f6, f11, f7, f10, pTexScaleU, pTexScaleV, pMirror, Direction.UP);
vertexIndex += 4;
}
if (visibleFaces.contains(Direction.WEST)) {
addFace(view, vertexIndex, new Vertex[]{modelpart$vertex7, modelpart$vertex3, modelpart$vertex6, modelpart$vertex2}, f4, f11, f5, f12, pTexScaleU, pTexScaleV, pMirror, Direction.WEST);
vertexIndex += 4;
}
if (visibleFaces.contains(Direction.NORTH)) {
addFace(view, vertexIndex, new Vertex[]{modelpart$vertex, modelpart$vertex7, modelpart$vertex2, modelpart$vertex1}, f5, f11, f6, f12, pTexScaleU, pTexScaleV, pMirror, Direction.NORTH);
vertexIndex += 4;
}
if (visibleFaces.contains(Direction.EAST)) {
addFace(view, vertexIndex, new Vertex[]{modelpart$vertex4, modelpart$vertex, modelpart$vertex1, modelpart$vertex5}, f6, f11, f8, f12, pTexScaleU, pTexScaleV, pMirror, Direction.EAST);
vertexIndex += 4;
}
if (visibleFaces.contains(Direction.SOUTH)) {
addFace(view, vertexIndex, new Vertex[]{modelpart$vertex3, modelpart$vertex4, modelpart$vertex5, modelpart$vertex6}, f8, f11, f9, f12, pTexScaleU, pTexScaleV, pMirror, Direction.SOUTH);
vertexIndex += 4;
}
}
return new SimpleMesh(view, block);
}
private static void addFace(PosTexNormalVertexView view, int index, Vertex[] pVertices, float pU1, float pV1, float pU2, float pV2, float pTextureWidth, float pTextureHeight, boolean pMirror, Direction pDirection) {
float f = 0.0F / pTextureWidth;
float f1 = 0.0F / pTextureHeight;
pVertices[0] = pVertices[0].remap(pU2 / pTextureWidth - f, pV1 / pTextureHeight + f1);
pVertices[1] = pVertices[1].remap(pU1 / pTextureWidth + f, pV1 / pTextureHeight + f1);
pVertices[2] = pVertices[2].remap(pU1 / pTextureWidth + f, pV2 / pTextureHeight - f1);
pVertices[3] = pVertices[3].remap(pU2 / pTextureWidth - f, pV2 / pTextureHeight - f1);
if (pMirror) {
int i = pVertices.length;
for (int j = 0; j < i / 2; ++j) {
Vertex modelpart$vertex = pVertices[j];
pVertices[j] = pVertices[i - 1 - j];
pVertices[i - 1 - j] = modelpart$vertex;
}
}
var normal = pDirection.step();
if (pMirror) {
normal.mul(-1.0F, 1.0F, 1.0F);
}
int i = index;
for (Vertex modelpart$vertex : pVertices) {
float f3 = modelpart$vertex.x() / 16.0F;
float f4 = modelpart$vertex.y() / 16.0F;
float f5 = modelpart$vertex.z() / 16.0F;
view.x(i, f3);
view.y(i, f4);
view.z(i, f5);
view.u(i, modelpart$vertex.u());
view.v(i, modelpart$vertex.v());
view.normalX(i, normal.x());
view.normalY(i, normal.y());
view.normalZ(i, normal.z());
++i;
}
}
private static int countVisibleFaces(List<CubeDefinition> cubes) {
int totalVisibleFaces = 0;
for (CubeDefinition cube : cubes) {
totalVisibleFaces += cast(cube).vanillin$visibleFaces()
.size();
}
return totalVisibleFaces;
}
@NotNull
private static CubeDefinitionAccessor cast(CubeDefinition cube) {
return (CubeDefinitionAccessor) (Object) cube;
}
@OnlyIn(Dist.CLIENT)
record Vertex(float x, float y, float z, float u, float v) {
public Vertex remap(float pU, float pV) {
return new Vertex(x, y, z, pU, pV);
}
}
}

View file

@ -1,28 +0,0 @@
package com.jozufozu.flywheel.vanilla.model;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
import net.minecraft.client.model.geom.ModelLayerLocation;
public class MeshTreeCache {
private static final Map<ModelLayerLocation, MeshTree> MESH_TREES = new ConcurrentHashMap<>();
public static MeshTree get(ModelLayerLocation key) {
return MESH_TREES.computeIfAbsent(key, MeshTree::convert);
}
@ApiStatus.Internal
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
MESH_TREES.values()
.forEach(MeshTree::delete);
MESH_TREES.clear();
}
private MeshTreeCache() {
}
}

View file

@ -0,0 +1,14 @@
{
"required" : true,
"minVersion" : "0.8",
"package" : "com.jozufozu.flywheel.lib.mixin",
"compatibilityLevel" : "JAVA_17",
"refmap" : "flywheel.refmap.json",
"client" : [
"ModelPartAccessor",
"VertexMultiConsumerDoubleMixin"
],
"injectors" : {
"defaultRequire" : 1
}
}

View file

@ -1,19 +0,0 @@
{
"required" : true,
"minVersion" : "0.8",
"package" : "com.jozufozu.flywheel.vanilla.mixin",
"compatibilityLevel" : "JAVA_17",
"refmap" : "flywheel.refmap.json",
"client" : [
"CubeDefinitionAccessor",
"CubeDeformationAccessor",
"EntityModelSetAccessor",
"LayerDefinitionAccessor",
"MaterialDefinitionAccessor",
"PartDefinitionAccessor",
"VertexMultiConsumerDoubleMixin"
],
"injectors" : {
"defaultRequire" : 1
}
}