diff --git a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java index ec4ae991cd..447df2df5f 100644 --- a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java +++ b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java @@ -195,6 +195,7 @@ public final class ItemLayerModel implements IModel int vMax = sprite.getIconHeight(); FaceData faceData = new FaceData(uMax, vMax); + boolean translucent = false; for(int f = 0; f < sprite.getFrameCount(); f++) { @@ -207,7 +208,14 @@ public final class ItemLayerModel implements IModel ptu = true; for(int u = 0; u < uMax; u++) { - boolean t = isTransparent(pixels, uMax, vMax, u, v); + int alpha = getAlpha(pixels, uMax, vMax, u, v); + boolean t = alpha == 0; + + if (!t && alpha < 255) + { + translucent = true; + } + if(ptu && !t) // left - transparent, right - opaque { faceData.set(EnumFacing.WEST, u, v); @@ -224,6 +232,7 @@ public final class ItemLayerModel implements IModel { faceData.set(EnumFacing.DOWN, u, v-1); } + ptu = t; ptv[u] = t; } @@ -247,29 +256,44 @@ public final class ItemLayerModel implements IModel { for (int v = 0; v < vMax; v++) { - int uStart = 0; + int uStart = 0, uEnd = uMax; boolean building = false; for (int u = 0; u < uMax; u++) { boolean face = faceData.get(facing, u, v); - if (building && !face) // finish current quad + if (!translucent) { - // make quad [uStart, u] - int off = facing == EnumFacing.DOWN ? 1 : 0; - builder.add(buildSideQuad(format, transform, facing, tint, sprite, uStart, v+off, u-uStart)); - building = false; + if (face) + { + if (!building) + { + building = true; + uStart = u; + } + uEnd = u + 1; + } } - else if (!building && face) // start new quad + else { - building = true; - uStart = u; + if (building && !face) // finish current quad + { + // make quad [uStart, u] + int off = facing == EnumFacing.DOWN ? 1 : 0; + builder.add(buildSideQuad(format, transform, facing, tint, sprite, uStart, v+off, u-uStart)); + building = false; + } + else if (!building && face) // start new quad + { + building = true; + uStart = u; + } } } - if (building) // quad extends to far edge + if (building) // build remaining quad { - // make quad [uStart, uMax] + // make quad [uStart, uEnd] int off = facing == EnumFacing.DOWN ? 1 : 0; - builder.add(buildSideQuad(format, transform, facing, tint, sprite, uStart, v+off, uMax-uStart)); + builder.add(buildSideQuad(format, transform, facing, tint, sprite, uStart, v+off, uEnd-uStart)); } } } @@ -279,29 +303,44 @@ public final class ItemLayerModel implements IModel { for (int u = 0; u < uMax; u++) { - int vStart = 0; + int vStart = 0, vEnd = vMax; boolean building = false; for (int v = 0; v < vMax; v++) { boolean face = faceData.get(facing, u, v); - if (building && !face) // finish current quad + if (!translucent) { - // make quad [vStart, v] - int off = facing == EnumFacing.EAST ? 1 : 0; - builder.add(buildSideQuad(format, transform, facing, tint, sprite, u+off, vStart, v-vStart)); - building = false; + if (face) + { + if (!building) + { + building = true; + vStart = v; + } + vEnd = v + 1; + } } - else if (!building && face) // start new quad + else { - building = true; - vStart = v; + if (building && !face) // finish current quad + { + // make quad [vStart, v] + int off = facing == EnumFacing.EAST ? 1 : 0; + builder.add(buildSideQuad(format, transform, facing, tint, sprite, u+off, vStart, v-vStart)); + building = false; + } + else if (!building && face) // start new quad + { + building = true; + vStart = v; + } } } - if (building) // quad extends to far edge + if (building) // build remaining quad { - // make quad [vStart, vMax] + // make quad [vStart, vEnd] int off = facing == EnumFacing.EAST ? 1 : 0; - builder.add(buildSideQuad(format, transform, facing, tint, sprite, u+off, vStart, vMax-vStart)); + builder.add(buildSideQuad(format, transform, facing, tint, sprite, u+off, vStart, vEnd-vStart)); } } } @@ -356,88 +395,55 @@ public final class ItemLayerModel implements IModel } } - private static boolean isTransparent(int[] pixels, int uMax, int vMax, int u, int v) + private static int getAlpha(int[] pixels, int uMax, int vMax, int u, int v) { - return (pixels[u + (vMax - 1 - v) * uMax] >> 24 & 0xFF) == 0; + return pixels[u + (vMax - 1 - v) * uMax] >> 24 & 0xFF; } private static BakedQuad buildSideQuad(VertexFormat format, Optional transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int u, int v, int size) { - final float eps0 = 30e-5f; - final float eps1 = 45e-5f; - final float eps2 = .5f; - final float eps3 = .5f; - float x0 = (float)u / sprite.getIconWidth(); - float y0 = (float)v / sprite.getIconHeight(); + final float eps = 1e-2f; + + int width = sprite.getIconWidth(); + int height = sprite.getIconHeight(); + + float x0 = (float) u / width; + float y0 = (float) v / height; float x1 = x0, y1 = y0; - float z1 = 7.5f / 16f - eps1, z2 = 8.5f / 16f + eps1; + float z0 = 7.5f / 16f, z1 = 8.5f / 16f; + switch(side) { case WEST: - z1 = 8.5f / 16f + eps1; - z2 = 7.5f / 16f - eps1; + z0 = 8.5f / 16f; + z1 = 7.5f / 16f; case EAST: - y1 = (float) (v + size) / sprite.getIconHeight(); + y1 = (float) (v + size) / height; break; case DOWN: - z1 = 8.5f / 16f + eps1; - z2 = 7.5f / 16f - eps1; + z0 = 8.5f / 16f; + z1 = 7.5f / 16f; case UP: - x1 = (float) (u + size) / sprite.getIconWidth(); - break; - default: - throw new IllegalArgumentException("can't handle z-oriented side"); - } - float u0 = 16f * (x0 - side.getDirectionVec().getX() * eps3 / sprite.getIconWidth()); - float u1 = 16f * (x1 - side.getDirectionVec().getX() * eps3 / sprite.getIconWidth()); - float v0 = 16f * (1f - y0 - side.getDirectionVec().getY() * eps3 / sprite.getIconHeight()); - float v1 = 16f * (1f - y1 - side.getDirectionVec().getY() * eps3 / sprite.getIconHeight()); - switch(side) - { - case WEST: - case EAST: - y0 -= eps1; - y1 += eps1; - v0 -= eps2 / sprite.getIconHeight(); - v1 += eps2 / sprite.getIconHeight(); - break; - case DOWN: - case UP: - x0 -= eps1; - x1 += eps1; - u0 += eps2 / sprite.getIconWidth(); - u1 -= eps2 / sprite.getIconWidth(); - break; - default: - throw new IllegalArgumentException("can't handle z-oriented side"); - } - switch(side) - { - case WEST: - x0 += eps0; - x1 += eps0; - break; - case EAST: - x0 -= eps0; - x1 -= eps0; - break; - case DOWN: - y0 -= eps0; - y1 -= eps0; - break; - case UP: - y0 += eps0; - y1 += eps0; + x1 = (float) (u + size) / width; break; default: throw new IllegalArgumentException("can't handle z-oriented side"); } + + float dx = side.getDirectionVec().getX() * eps / width; + float dy = side.getDirectionVec().getY() * eps / height; + + float u0 = 16f * (x0 - dx); + float u1 = 16f * (x1 - dx); + float v0 = 16f * (1f - y0 - dy); + float v1 = 16f * (1f - y1 - dy); + return buildQuad( format, transform, side.getOpposite(), sprite, tint, // getOpposite is related either to the swapping of V direction, or something else - x0, y0, z1, sprite.getInterpolatedU(u0), sprite.getInterpolatedV(v0), + x0, y0, z0, sprite.getInterpolatedU(u0), sprite.getInterpolatedV(v0), + x1, y1, z0, sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1), x1, y1, z1, sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1), - x1, y1, z2, sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1), - x0, y0, z2, sprite.getInterpolatedU(u0), sprite.getInterpolatedV(v0) + x0, y0, z1, sprite.getInterpolatedU(u0), sprite.getInterpolatedV(v0) ); } diff --git a/src/test/java/net/minecraftforge/debug/ItemModelGenerationTest.java b/src/test/java/net/minecraftforge/debug/ItemModelGenerationTest.java new file mode 100644 index 0000000000..1a98850a32 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/ItemModelGenerationTest.java @@ -0,0 +1,80 @@ +package net.minecraftforge.debug; + +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.fml.relauncher.Side; + +@Mod.EventBusSubscriber +@Mod(modid = ItemModelGenerationTest.MOD_ID, name = "Item model generation test", version = "1.0") +public class ItemModelGenerationTest +{ + static final String MOD_ID = "item_model_generation_test"; + + @GameRegistry.ObjectHolder("animation_test") + public static final Item ANIMATION_TEST = null; + + @GameRegistry.ObjectHolder("intersection_test") + public static final Item INTERSECTION_TEST = null; + + @GameRegistry.ObjectHolder("opacity_test") + public static final Item OPACITY_TEST = null; + + @GameRegistry.ObjectHolder("overlap_test") + public static final Item OVERLAP_TEST = null; + + @GameRegistry.ObjectHolder("pattern_test") + public static final Item PATTERN_TEST = null; + + @SubscribeEvent + public static void registerItems(RegistryEvent.Register event) + { + event.getRegistry().registerAll( + new Item() + .setRegistryName("animation_test") + .setUnlocalizedName(MOD_ID + ".animation_test") + .setCreativeTab(CreativeTabs.MISC), + new Item() + .setRegistryName("intersection_test") + .setUnlocalizedName(MOD_ID + ".intersection_test") + .setCreativeTab(CreativeTabs.MISC), + new Item() + .setRegistryName("opacity_test") + .setUnlocalizedName(MOD_ID + ".opacity_test") + .setCreativeTab(CreativeTabs.MISC), + new Item() + .setRegistryName("overlap_test") + .setUnlocalizedName(MOD_ID + ".overlap_test") + .setCreativeTab(CreativeTabs.MISC), + new Item() + .setRegistryName("pattern_test") + .setUnlocalizedName(MOD_ID + ".pattern_test") + .setCreativeTab(CreativeTabs.MISC) + ); + } + + @Mod.EventBusSubscriber(modid = MOD_ID, value = Side.CLIENT) + public static class ClientEventHandler + { + @SubscribeEvent + public static void registerModels(ModelRegistryEvent event) + { + setCustomMRL(ANIMATION_TEST); + setCustomMRL(INTERSECTION_TEST); + setCustomMRL(OPACITY_TEST); + setCustomMRL(OVERLAP_TEST); + setCustomMRL(PATTERN_TEST); + } + + private static void setCustomMRL(Item item) + { + ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory")); + } + } +} diff --git a/src/test/resources/assets/item_model_generation_test/models/item/animation_test.json b/src/test/resources/assets/item_model_generation_test/models/item/animation_test.json new file mode 100644 index 0000000000..e22fa65b6c --- /dev/null +++ b/src/test/resources/assets/item_model_generation_test/models/item/animation_test.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "item_model_generation_test:items/animation_test" + } +} diff --git a/src/test/resources/assets/item_model_generation_test/models/item/intersection_test.json b/src/test/resources/assets/item_model_generation_test/models/item/intersection_test.json new file mode 100644 index 0000000000..3cd2bb53c0 --- /dev/null +++ b/src/test/resources/assets/item_model_generation_test/models/item/intersection_test.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "item_model_generation_test:items/intersection_test" + } +} diff --git a/src/test/resources/assets/item_model_generation_test/models/item/opacity_test.json b/src/test/resources/assets/item_model_generation_test/models/item/opacity_test.json new file mode 100644 index 0000000000..2c5c59d499 --- /dev/null +++ b/src/test/resources/assets/item_model_generation_test/models/item/opacity_test.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "item_model_generation_test:items/opacity_test" + } +} diff --git a/src/test/resources/assets/item_model_generation_test/models/item/overlap_test.json b/src/test/resources/assets/item_model_generation_test/models/item/overlap_test.json new file mode 100644 index 0000000000..a2c60380b7 --- /dev/null +++ b/src/test/resources/assets/item_model_generation_test/models/item/overlap_test.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "item_model_generation_test:items/overlap_test" + } +} diff --git a/src/test/resources/assets/item_model_generation_test/models/item/pattern_test.json b/src/test/resources/assets/item_model_generation_test/models/item/pattern_test.json new file mode 100644 index 0000000000..ef91718ecf --- /dev/null +++ b/src/test/resources/assets/item_model_generation_test/models/item/pattern_test.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "item_model_generation_test:items/pattern_test" + } +} diff --git a/src/test/resources/assets/item_model_generation_test/textures/items/animation_test.png b/src/test/resources/assets/item_model_generation_test/textures/items/animation_test.png new file mode 100644 index 0000000000..c3a6d0e929 Binary files /dev/null and b/src/test/resources/assets/item_model_generation_test/textures/items/animation_test.png differ diff --git a/src/test/resources/assets/item_model_generation_test/textures/items/animation_test.png.mcmeta b/src/test/resources/assets/item_model_generation_test/textures/items/animation_test.png.mcmeta new file mode 100644 index 0000000000..dd1bedb120 --- /dev/null +++ b/src/test/resources/assets/item_model_generation_test/textures/items/animation_test.png.mcmeta @@ -0,0 +1,3 @@ +{ + "animation": {} +} diff --git a/src/test/resources/assets/item_model_generation_test/textures/items/intersection_test.png b/src/test/resources/assets/item_model_generation_test/textures/items/intersection_test.png new file mode 100644 index 0000000000..4a02e6224f Binary files /dev/null and b/src/test/resources/assets/item_model_generation_test/textures/items/intersection_test.png differ diff --git a/src/test/resources/assets/item_model_generation_test/textures/items/opacity_test.png b/src/test/resources/assets/item_model_generation_test/textures/items/opacity_test.png new file mode 100644 index 0000000000..177d6758f2 Binary files /dev/null and b/src/test/resources/assets/item_model_generation_test/textures/items/opacity_test.png differ diff --git a/src/test/resources/assets/item_model_generation_test/textures/items/overlap_test.png b/src/test/resources/assets/item_model_generation_test/textures/items/overlap_test.png new file mode 100644 index 0000000000..4400c01479 Binary files /dev/null and b/src/test/resources/assets/item_model_generation_test/textures/items/overlap_test.png differ diff --git a/src/test/resources/assets/item_model_generation_test/textures/items/pattern_test.png b/src/test/resources/assets/item_model_generation_test/textures/items/pattern_test.png new file mode 100644 index 0000000000..b6e24cb9dd Binary files /dev/null and b/src/test/resources/assets/item_model_generation_test/textures/items/pattern_test.png differ