Skip to content

Commit

Permalink
Rename QuadTransformers to FabricQuadTransformers
Browse files Browse the repository at this point in the history
Add vanilla version of QuadTransformers
  • Loading branch information
AlphaMode committed Nov 13, 2024
1 parent 98cda99 commit 60a1f16
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBu
// If there is a root transform, undo the ModelState transform, apply it, then re-apply the ModelState transform.
// This is necessary because of things like UV locking, which should only respond to the ModelState, and as such
// that is the only transform that should be applied during face bake.
var postTransform = QuadTransformers.empty();
var postTransform = FabricQuadTransformers.empty();
var rootTransform = context.getRootTransform();
if (!rootTransform.isIdentity())
postTransform = UnbakedGeometryHelper.applyRootTransform(modelState, rootTransform);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package io.github.fabricators_of_create.porting_lib.models;

import com.google.common.base.Preconditions;
import com.mojang.math.Transformation;

import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.Util;
import net.minecraft.client.renderer.LightTexture;

import org.joml.Vector3f;
import org.joml.Vector4f;

import java.util.Arrays;

/**
* A collection of {@link net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform} implementations.
* For working with vanilla quads see {@link QuadTransformers}.
*
* @see net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform
*/
public final class FabricQuadTransformers {

private static final RenderContext.QuadTransform EMPTY = quad -> {
return true;
};

private static final RenderContext.QuadTransform[] EMISSIVE_TRANSFORMERS = Util.make(new RenderContext.QuadTransform[16], array -> {
Arrays.setAll(array, i -> applyingLightmap(LightTexture.pack(i, i)));
});

/**
* {@return a {@link MutableQuadView} transformer that does nothing}
*/
public static RenderContext.QuadTransform empty() {
return EMPTY;
}

/**
* {@return a new {@link MutableQuadView} transformer that applies the specified {@link Transformation }}
*/
public static RenderContext.QuadTransform applying(Transformation transform) {
if (transform.isIdentity())
return empty();
return quad -> {
for (int i = 0; i < 4; i++) {
float x = quad.x(i);
float y = quad.y(i);
float z = quad.z(i);

Vector4f pos = new Vector4f(x, y, z, 1);
transform.transformPosition(pos);
pos.div(pos.w);

quad.pos(i, pos.x(), pos.y(), pos.z());
}

for (int i = 0; i < 4; i++) {
if (quad.hasNormal(i)) {
float x = quad.normalX(i);
float y = quad.normalY(i);
float z = quad.normalZ(i);

Vector3f pos = new Vector3f(x, y, z);
transform.transformNormal(pos);

quad.normal(i, pos);
}
}
return true;
};
}

/**
* @return A new {@link MutableQuadView} transformer that applies the specified packed light value.
*/
public static RenderContext.QuadTransform applyingLightmap(int packedLight) {
return quad -> {
for (int i = 0; i < 4; i++)
quad.lightmap(i, packedLight);
return true;
};
}

/**
* @return A new {@link MutableQuadView} transformer that applies the specified block and sky light values.
*/
public static RenderContext.QuadTransform applyingLightmap(int blockLight, int skyLight) {
return applyingLightmap(LightTexture.pack(blockLight, skyLight));
}

/**
* @return A {@link MutableQuadView} transformer that sets the lightmap to the given emissivity (0-15)
*/
public static RenderContext.QuadTransform settingEmissivity(int emissivity) {
Preconditions.checkArgument(emissivity >= 0 && emissivity < 16, "Emissivity must be between 0 and 15.");
return EMISSIVE_TRANSFORMERS[emissivity];
}

/**
* @return A {@link MutableQuadView} transformer that sets the lightmap to its max value
*/
public static RenderContext.QuadTransform settingMaxEmissivity() {
return EMISSIVE_TRANSFORMERS[15];
}

/**
* @param color The color in ARGB format.
* @return A {@link MutableQuadView} transformer that sets the color to the specified value.
*/
public static RenderContext.QuadTransform applyingColor(int color) {
final int fixedColor = toABGR(color);
return quad -> {
for (int i = 0; i < 4; i++)
quad.spriteColor(i, 0, fixedColor);
return true;
};
}

/**
* This method supplies a default alpha value of 255 (no transparency)
* @param red The red value (0-255)
* @param green The green value (0-255)
* @param blue The blue value (0-255)
* @return A {@link MutableQuadView} transformer that sets the color to the specified value.
*/
public static RenderContext.QuadTransform applyingColor(int red, int green, int blue) {
return applyingColor(255, red, green, blue);
}

/**
* @param alpha The alpha value (0-255)
* @param red The red value (0-255)
* @param green The green value (0-255)
* @param blue The blue value (0-255)
* @return A {@link MutableQuadView} transformer that sets the color to the specified value.
*/
public static RenderContext.QuadTransform applyingColor(int alpha, int red, int green, int blue) {
return applyingColor(alpha << 24 | red << 16 | green << 8 | blue);
}

/**
* Converts an ARGB color to an ABGR color, as the commonly used color format is not the format colors end up packed into.
* This function doubles as its own inverse.
* @param color ARGB color
* @return ABGR color
*/
public static int toABGR(int color) {
return (color & 0xFF00FF00) // alpha and green same spot
| ((color >> 16) & 0x000000FF) // red moves to blue
| ((color << 16) & 0x00FF0000); // blue moves to red
}

private FabricQuadTransformers() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/**
* Transformer for {@link BakedQuad baked quads}.
*
* @see QuadTransformers
* @see FabricQuadTransformers
*/
public interface IQuadTransformer {
int STRIDE = DefaultVertexFormat.BLOCK.getVertexSize() / 4;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,152 +2,156 @@

import com.google.common.base.Preconditions;
import com.mojang.math.Transformation;

import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import java.util.Arrays;
import net.minecraft.Util;
import net.minecraft.client.renderer.LightTexture;

import net.minecraft.client.renderer.block.model.BakedQuad;
import org.joml.Vector3f;
import org.joml.Vector4f;

import java.util.Arrays;

/**
* A collection of {@link net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform} implementations.
* A collection of {@link IQuadTransformer} implementations.
* For working with {@link net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView}'s see {@link FabricQuadTransformers}.
*
* @see net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform
* @see IQuadTransformer
*/
public final class QuadTransformers {

private static final RenderContext.QuadTransform EMPTY = quad -> {
return true;
};

private static final RenderContext.QuadTransform[] EMISSIVE_TRANSFORMERS = Util.make(new RenderContext.QuadTransform[16], array -> {
private static final IQuadTransformer EMPTY = quad -> {};
private static final IQuadTransformer[] EMISSIVE_TRANSFORMERS = Util.make(new IQuadTransformer[16], array -> {
Arrays.setAll(array, i -> applyingLightmap(LightTexture.pack(i, i)));
});

/**
* {@return a {@link MutableQuadView} transformer that does nothing}
* {@return a {@link BakedQuad} transformer that does nothing}
*/
public static RenderContext.QuadTransform empty() {
public static IQuadTransformer empty() {
return EMPTY;
}

/**
* {@return a new {@link MutableQuadView} transformer that applies the specified {@link Transformation }}
* {@return a new {@link BakedQuad} transformer that applies the specified {@link Transformation}}
*/
public static RenderContext.QuadTransform applying(Transformation transform) {
public static IQuadTransformer applying(Transformation transform) {
if (transform.isIdentity())
return empty();
return quad -> {
var vertices = quad.getVertices();
for (int i = 0; i < 4; i++) {
float x = quad.x(i);
float y = quad.y(i);
float z = quad.z(i);
int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.POSITION;
float x = Float.intBitsToFloat(vertices[offset]);
float y = Float.intBitsToFloat(vertices[offset + 1]);
float z = Float.intBitsToFloat(vertices[offset + 2]);

Vector4f pos = new Vector4f(x, y, z, 1);
transform.transformPosition(pos);
pos.div(pos.w);

quad.pos(i, pos.x(), pos.y(), pos.z());
vertices[offset] = Float.floatToRawIntBits(pos.x());
vertices[offset + 1] = Float.floatToRawIntBits(pos.y());
vertices[offset + 2] = Float.floatToRawIntBits(pos.z());
}

for (int i = 0; i < 4; i++) {
if (quad.hasNormal(i)) {
float x = quad.normalX(i);
float y = quad.normalY(i);
float z = quad.normalZ(i);
int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.NORMAL;
int normalIn = vertices[offset];
if ((normalIn & 0x00FFFFFF) != 0) // The ignored byte is padding and may be filled with user data
{
float x = ((byte) (normalIn & 0xFF)) / 127.0f;
float y = ((byte) ((normalIn >> 8) & 0xFF)) / 127.0f;
float z = ((byte) ((normalIn >> 16) & 0xFF)) / 127.0f;

Vector3f pos = new Vector3f(x, y, z);
transform.transformNormal(pos);

quad.normal(i, pos);
vertices[offset] = (((byte) (pos.x() * 127.0f)) & 0xFF) |
((((byte) (pos.y() * 127.0f)) & 0xFF) << 8) |
((((byte) (pos.z() * 127.0f)) & 0xFF) << 16) |
(normalIn & 0xFF000000); // Restore padding, just in case
}
}
return true;
};
}

/**
* @return A new {@link MutableQuadView} transformer that applies the specified packed light value.
* @return A new {@link BakedQuad} transformer that applies the specified packed light value.
*/
public static RenderContext.QuadTransform applyingLightmap(int packedLight) {
public static IQuadTransformer applyingLightmap(int packedLight) {
return quad -> {
var vertices = quad.getVertices();
for (int i = 0; i < 4; i++)
quad.lightmap(i, packedLight);
return true;
vertices[i * IQuadTransformer.STRIDE + IQuadTransformer.UV2] = packedLight;
};
}

/**
* @return A new {@link MutableQuadView} transformer that applies the specified block and sky light values.
* @return A new {@link BakedQuad} transformer that applies the specified block and sky light values.
*/
public static RenderContext.QuadTransform applyingLightmap(int blockLight, int skyLight) {
public static IQuadTransformer applyingLightmap(int blockLight, int skyLight) {
return applyingLightmap(LightTexture.pack(blockLight, skyLight));
}

/**
* @return A {@link MutableQuadView} transformer that sets the lightmap to the given emissivity (0-15)
* @return A {@link BakedQuad} transformer that sets the lightmap to the given emissivity (0-15)
*/
public static RenderContext.QuadTransform settingEmissivity(int emissivity) {
public static IQuadTransformer settingEmissivity(int emissivity) {
Preconditions.checkArgument(emissivity >= 0 && emissivity < 16, "Emissivity must be between 0 and 15.");
return EMISSIVE_TRANSFORMERS[emissivity];
}

/**
* @return A {@link MutableQuadView} transformer that sets the lightmap to its max value
* @return A {@link BakedQuad} transformer that sets the lightmap to its max value
*/
public static RenderContext.QuadTransform settingMaxEmissivity() {
public static IQuadTransformer settingMaxEmissivity() {
return EMISSIVE_TRANSFORMERS[15];
}

/**
* @param color The color in ARGB format.
* @return A {@link MutableQuadView} transformer that sets the color to the specified value.
* @return A {@link BakedQuad} transformer that sets the color to the specified value.
*/
public static RenderContext.QuadTransform applyingColor(int color) {
public static IQuadTransformer applyingColor(int color) {
final int fixedColor = toABGR(color);
return quad -> {
var vertices = quad.getVertices();
for (int i = 0; i < 4; i++)
quad.spriteColor(i, 0, fixedColor);
return true;
vertices[i * IQuadTransformer.STRIDE + IQuadTransformer.COLOR] = fixedColor;
};
}

/**
* This method supplies a default alpha value of 255 (no transparency)
* @param red The red value (0-255)
*
* @param red The red value (0-255)
* @param green The green value (0-255)
* @param blue The blue value (0-255)
* @return A {@link MutableQuadView} transformer that sets the color to the specified value.
* @param blue The blue value (0-255)
* @return A {@link BakedQuad} transformer that sets the color to the specified value.
*/
public static RenderContext.QuadTransform applyingColor(int red, int green, int blue) {
public static IQuadTransformer applyingColor(int red, int green, int blue) {
return applyingColor(255, red, green, blue);
}

/**
* @param alpha The alpha value (0-255)
* @param red The red value (0-255)
* @param red The red value (0-255)
* @param green The green value (0-255)
* @param blue The blue value (0-255)
* @return A {@link MutableQuadView} transformer that sets the color to the specified value.
* @param blue The blue value (0-255)
* @return A {@link BakedQuad} transformer that sets the color to the specified value.
*/
public static RenderContext.QuadTransform applyingColor(int alpha, int red, int green, int blue) {
public static IQuadTransformer applyingColor(int alpha, int red, int green, int blue) {
return applyingColor(alpha << 24 | red << 16 | green << 8 | blue);
}

/**
* Converts an ARGB color to an ABGR color, as the commonly used color format is not the format colors end up packed into.
* This function doubles as its own inverse.
* @param color ARGB color
*
* @param argb color
* @return ABGR color
*/
public static int toABGR(int color) {
return (color & 0xFF00FF00) // alpha and green same spot
| ((color >> 16) & 0x000000FF) // red moves to blue
| ((color << 16) & 0x00FF0000); // blue moves to red
public static int toABGR(int argb) {
return (argb & 0xFF00FF00) // alpha and green same spot
| ((argb >> 16) & 0x000000FF) // red moves to blue
| ((argb << 16) & 0x00FF0000); // blue moves to red
}

private QuadTransformers() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public static RenderContext.QuadTransform applyRootTransform(ModelState modelSta
// to replicate the way the ModelState transform is applied in the FaceBakery by moving the vertices such that
// the negative corner acts as the block center
Transformation transform = modelState.getRotation().applyOrigin(new Vector3f(.5F, .5F, .5F));
return QuadTransformers.applying(transform.compose(rootTransform).compose(transform.inverse()));
return FabricQuadTransformers.applying(transform.compose(rootTransform).compose(transform.inverse()));
}

/**
Expand Down

0 comments on commit 60a1f16

Please sign in to comment.