added full support for random models and fixed some issues with the previously implemented permutations

This commit is contained in:
Adrien1106 2024-02-14 15:23:47 +01:00
parent 55b8e55015
commit 6e08148733
4 changed files with 71 additions and 27 deletions

View File

@ -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<Direction, Direction> facePermutation; //immutable
// protected final Map<Direction, Direction> 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;
}
@ -169,8 +175,8 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
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;
}

View File

@ -87,9 +87,9 @@ public class UnbakedAutoRetexturedModel implements UnbakedModel, TemplatesClient
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();

View File

@ -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,

View File

@ -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<BakedQuad> 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;
}
}