diff --git a/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java b/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java index ee09b87..be7ec95 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/model/RetexturingBakedModel.java @@ -32,14 +32,14 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel { this.wrapped = baseModel; //field from the superclass; vanilla getQuads etc. will delegate through to this this.tam = tam; - this.facePermutation = MeshTransformUtil.facePermutation(settings); +// this.facePermutation = MeshTransformUtil.facePermutation(settings); this.uvlock = settings.isUvLocked(); this.itemModelState = itemModelState; this.ao = ao; } protected final TemplateAppearanceManager tam; - protected final Map facePermutation; //immutable +// protected final Map facePermutation; protected final boolean uvlock; protected final BlockState itemModelState; protected final boolean ao; @@ -75,20 +75,26 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel { } if(theme.getBlock() == Blocks.BARRIER) return; - TemplateAppearance ta = tam.getTemplateAppearance(theme); + TemplateAppearance template_appearance = tam.getTemplateAppearance(theme); long seed = theme.getRenderingSeed(pos); int model_id = 0; - if (ta instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed); + if (template_appearance instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed); int tint = 0xFF000000 | MinecraftClient.getInstance().getBlockColors().getColor(theme, blockView, pos, 0); - Mesh untintedMesh = getUntintedRetexturedMesh(new MeshCacheKey(state, new TransformCacheKey(ta, model_id)), seed); + Mesh untintedMesh = getUntintedRetexturedMesh( + new MeshCacheKey( + state, + new TransformCacheKey(template_appearance, model_id) + ), + seed + ); //The specific tint might vary a lot; imagine grass color smoothly changing. Trying to bake the tint into //the cached mesh will pollute it with a ton of single-use meshes with only slightly different colors. if(tint == 0xFFFFFFFF) { untintedMesh.outputTo(quad_emitter); } else { - context.pushTransform(new TintingTransformer(ta, tint, seed)); + context.pushTransform(new TintingTransformer(template_appearance, tint, seed)); untintedMesh.outputTo(quad_emitter); context.popTransform(); } @@ -147,7 +153,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel { if(tag == 0) return true; //Pass the quad through unmodified. //The quad tag numbers were selected so this magic trick works: - Direction direction = facePermutation.get(DIRECTIONS[quad.tag() - 1]); + Direction direction = quad.nominalFace(); // facePermutation.get(quad.nominalFace()); quad.spriteBake(ta.getSprite(direction, seed), MutableQuadView.BAKE_NORMALIZED | ta.getBakeFlags(direction, seed) | (uvlock ? MutableQuadView.BAKE_LOCK_UV : 0)); return true; } @@ -168,9 +174,9 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel { public boolean transform(MutableQuadView quad) { int tag = quad.tag(); if(tag == 0) return true; - - Direction dir = facePermutation.get(DIRECTIONS[quad.tag() - 1]); - if(ta.hasColor(dir, seed)) quad.color(tint, tint, tint, tint); + +// Direction dir = facePermutation.get(DIRECTIONS[quad.tag() - 1]); + if(ta.hasColor(quad.nominalFace(), seed)) quad.color(tint, tint, tint, tint); return true; } diff --git a/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedAutoRetexturedModel.java b/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedAutoRetexturedModel.java index 037aa68..8f40007 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedAutoRetexturedModel.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedAutoRetexturedModel.java @@ -86,10 +86,10 @@ public class UnbakedAutoRetexturedModel implements UnbakedModel, TemplatesClient RenderMaterial mat = tam.getCachedMaterial(state, false); Random rand = Random.create(42); - - for(Direction cullFace : DIRECTIONS_AND_NULL) { - for(BakedQuad quad : wrapped.getQuads(state, cullFace, rand)) { - emitter.fromVanilla(quad, mat, cullFace); + + for(Direction direction : DIRECTIONS_AND_NULL) { + for(BakedQuad quad : wrapped.getQuads(state, direction, rand)) { + emitter.fromVanilla(quad, mat, direction); QuadUvBounds.read(emitter).normalizeUv(emitter, quad.getSprite()); emitter.tag(emitter.lightFace().ordinal() + 1); emitter.emit(); diff --git a/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedJsonRetexturedModel.java b/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedJsonRetexturedModel.java index a75738e..2e231c5 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedJsonRetexturedModel.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/model/UnbakedJsonRetexturedModel.java @@ -72,10 +72,6 @@ public class UnbakedJsonRetexturedModel implements UnbakedModel, TemplatesClient } BakedModel model = baker.bake(parent, modelBakeSettings); - if (model instanceof WeightedBakedModel weighted_model) { - System.out.println("weighted model"); - ((WeightedBakedModelAccessor) weighted_model).getModels(); - } return new RetexturingBakedModel( model, diff --git a/src/main/java/fr/adrien1106/reframedtemplates/model/apperance/TemplateAppearanceManager.java b/src/main/java/fr/adrien1106/reframedtemplates/model/apperance/TemplateAppearanceManager.java index 8883d89..92e0674 100644 --- a/src/main/java/fr/adrien1106/reframedtemplates/model/apperance/TemplateAppearanceManager.java +++ b/src/main/java/fr/adrien1106/reframedtemplates/model/apperance/TemplateAppearanceManager.java @@ -126,6 +126,7 @@ public class TemplateAppearanceManager { int[] flags = new int[6]; byte[] color_mask = {0b000000}; + System.out.println("new mesh"); // TODO remove //Read quads off the model by their `cullface` Arrays.stream(Direction.values()).forEach(direction -> { List quads = model.getQuads(null, direction, random); @@ -154,17 +155,58 @@ public class TemplateAppearanceManager { //are looked up with a simple table. quad_emitter.fromVanilla(quad, material, direction); - float spriteUAvg = (sprite.getMinU() + sprite.getMaxU()) / 2; - float spriteVAvg = (sprite.getMinV() + sprite.getMaxV()) / 2; - - flags[direction.ordinal()] = MAGIC_BAKEFLAGS_SBOX[ - (quad_emitter.u(0) < spriteUAvg ? 8 : 0) | - (quad_emitter.v(0) < spriteVAvg ? 4 : 0) | - (quad_emitter.u(1) < spriteUAvg ? 2 : 0) | - (quad_emitter.v(1) < spriteVAvg ? 1 : 0) - ]; + flags[direction.ordinal()] = getBakeFlags(quad_emitter, sprite); }); return new Appearance(sprites, flags, color_mask[0]); } + + private static int getBakeFlags(QuadEmitter emitter, Sprite sprite) { // TODO can probably receive tons of improvements + boolean[][] order_matrix = getOrderMatrix(emitter, sprite); + int flag = 0; + if (!isClockwise(order_matrix)) { // check if quad has been mirrored on model + // check which mirroring is more efficient in terms of rotations + int rotation_u = getRotation(flipOrderMatrix(order_matrix, MutableQuadView.BAKE_FLIP_U)); + int rotation_v = getRotation(flipOrderMatrix(order_matrix, MutableQuadView.BAKE_FLIP_V)); + if (rotation_u < rotation_v) flag = MutableQuadView.BAKE_FLIP_U | rotation_u; + else flag = MutableQuadView.BAKE_FLIP_V | rotation_v; + } else flag |= getRotation(order_matrix); + return flag; + } + + private static int getRotation(boolean[][] order_matrix) { + int rotations = MutableQuadView.BAKE_ROTATE_NONE; + rotations |= order_matrix[0][0] && !order_matrix[0][1] ? MutableQuadView.BAKE_ROTATE_90 : 0; + rotations |= !order_matrix[0][0] && !order_matrix[0][1] ? MutableQuadView.BAKE_ROTATE_180 : 0; + rotations |= !order_matrix[0][0] && order_matrix[0][1] ? MutableQuadView.BAKE_ROTATE_270 : 0; + return rotations; + } + + private static boolean isClockwise(boolean[][] rotation_matrix) { + for (int i = 1; i < rotation_matrix.length; i++) { + if (rotation_matrix[i][0] != rotation_matrix[i-1][1] && rotation_matrix[i][0] != rotation_matrix[i][1]) + return false; + } + return true; + } + + private static boolean[][] flipOrderMatrix(boolean[][] order_matrix, int flag) { + boolean[][] new_matrix = new boolean[4][2]; + for (int i = 0; i < 4; i++) { + new_matrix[i][0] = (flag == MutableQuadView.BAKE_FLIP_U) != order_matrix[i][0]; + new_matrix[i][1] = (flag == MutableQuadView.BAKE_FLIP_V) != order_matrix[i][1]; + } + return new_matrix; + } + + private static boolean[][] getOrderMatrix(QuadEmitter emitter, Sprite sprite) { + float u_center = (sprite.getMinU() + sprite.getMaxU()) / 2; + float v_center = (sprite.getMinV() + sprite.getMaxV()) / 2; + boolean[][] order_matrix = new boolean[4][2]; + for (int i = 0; i < 4; i++) { + order_matrix[i][0] = emitter.u(i) < u_center; + order_matrix[i][1] = emitter.v(i) < v_center; + } + return order_matrix; + } }