FaceBakery.java

net.minecraft.client.resources.model.cuboid.FaceBakery

信息

  • 全限定名:net.minecraft.client.resources.model.cuboid.FaceBakery
  • 类型:public class
  • 包:net.minecraft.client.resources.model.cuboid
  • 源码路径:src/main/java/net/minecraft/client/resources/model/cuboid/FaceBakery.java
  • 起始行号:L25
  • 职责:

    TODO

字段/常量

  • BLOCK_MIDDLE
    • 类型: Vector3fc
    • 修饰符: private static final
    • 源码定位: L26
    • 说明:

      TODO

内部类/嵌套类型

构造器

方法

下面的方法块按源码顺序生成。

static CuboidFace.UVs defaultFaceUV(Vector3fc from, Vector3fc to, Direction facing) @ L28

  • 方法名:defaultFaceUV
  • 源码定位:L28
  • 返回类型:CuboidFace.UVs
  • 修饰符:static

参数:

  • from: Vector3fc
  • to: Vector3fc
  • facing: Direction

说明:

TODO

private static Transparency computeMaterialTransparency(Material.Baked material, CuboidFace.UVs uvs) @ L40

  • 方法名:computeMaterialTransparency
  • 源码定位:L40
  • 返回类型:Transparency
  • 修饰符:private static

参数:

  • material: Material.Baked
  • uvs: CuboidFace.UVs

说明:

TODO

public static BakedQuad bakeQuad(ModelBaker modelBaker, Vector3fc from, Vector3fc to, CuboidFace face, Material.Baked material, Direction facing, ModelState modelState, CuboidRotation elementRotation, boolean shade, int lightEmission) @ L53

  • 方法名:bakeQuad
  • 源码定位:L53
  • 返回类型:BakedQuad
  • 修饰符:public static

参数:

  • modelBaker: ModelBaker
  • from: Vector3fc
  • to: Vector3fc
  • face: CuboidFace
  • material: Material.Baked
  • facing: Direction
  • modelState: ModelState
  • elementRotation: CuboidRotation
  • shade: boolean
  • lightEmission: int

说明:

TODO

public static BakedQuad bakeQuad(ModelBaker.Interner interner, Vector3fc from, Vector3fc to, CuboidFace.UVs uvs, Quadrant uvRotation, BakedQuad.MaterialInfo materialInfo, Direction facing, ModelState modelState, CuboidRotation elementRotation) @ L76

  • 方法名:bakeQuad
  • 源码定位:L76
  • 返回类型:BakedQuad
  • 修饰符:public static

参数:

  • interner: ModelBaker.Interner
  • from: Vector3fc
  • to: Vector3fc
  • uvs: CuboidFace.UVs
  • uvRotation: Quadrant
  • materialInfo: BakedQuad.MaterialInfo
  • facing: Direction
  • modelState: ModelState
  • elementRotation: CuboidRotation

说明:

TODO

private static void bakeVertex(int index, FaceInfo faceInfo, CuboidFace.UVs uvs, Quadrant uvRotation, Matrix4fc uvTransform, Vector3fc from, Vector3fc to, BakedQuad.MaterialInfo materialInfo, Transformation rotation, CuboidRotation elementRotation, Vector3fc[] positionOutput, long[] uvOutput, ModelBaker.Interner interner) @ L129

  • 方法名:bakeVertex
  • 源码定位:L129
  • 返回类型:void
  • 修饰符:private static

参数:

  • index: int
  • faceInfo: FaceInfo
  • uvs: CuboidFace.UVs
  • uvRotation: Quadrant
  • uvTransform: Matrix4fc
  • from: Vector3fc
  • to: Vector3fc
  • materialInfo: BakedQuad.MaterialInfo
  • rotation: Transformation
  • elementRotation: CuboidRotation
  • positionOutput: Vector3fc[]
  • uvOutput: long[]
  • interner: ModelBaker.Interner

说明:

TODO

private static float cornerToCenter(float value) @ L171

  • 方法名:cornerToCenter
  • 源码定位:L171
  • 返回类型:float
  • 修饰符:private static

参数:

  • value: float

说明:

TODO

private static float centerToCorner(float value) @ L175

  • 方法名:centerToCorner
  • 源码定位:L175
  • 返回类型:float
  • 修饰符:private static

参数:

  • value: float

说明:

TODO

private static void rotateVertexBy(Vector3f vertex, Vector3fc origin, Matrix4fc transformation) @ L179

  • 方法名:rotateVertexBy
  • 源码定位:L179
  • 返回类型:void
  • 修饰符:private static

参数:

  • vertex: Vector3f
  • origin: Vector3fc
  • transformation: Matrix4fc

说明:

TODO

private static Direction calculateFacing(Vector3fc[] positions) @ L185

  • 方法名:calculateFacing
  • 源码定位:L185
  • 返回类型:Direction
  • 修饰符:private static

参数:

  • positions: Vector3fc[]

说明:

TODO

private static Direction findClosestDirection(Vector3f direction) @ L191

  • 方法名:findClosestDirection
  • 源码定位:L191
  • 返回类型:Direction
  • 修饰符:private static

参数:

  • direction: Vector3f

说明:

TODO

private static void recalculateWinding(Vector3fc[] positions, long[] uvs, Direction direction) @ L210

  • 方法名:recalculateWinding
  • 源码定位:L210
  • 返回类型:void
  • 修饰符:private static

参数:

  • positions: Vector3fc[]
  • uvs: long[]
  • direction: Direction

说明:

TODO

private static int findVertex(Vector3fc[] positions, int start, float x, float y, float z) @ L267

  • 方法名:findVertex
  • 源码定位:L267
  • 返回类型:int
  • 修饰符:private static

参数:

  • positions: Vector3fc[]
  • start: int
  • x: float
  • y: float
  • z: float

说明:

TODO

private static void swap(Vector3fc[] array, int indexA, int indexB) @ L278

  • 方法名:swap
  • 源码定位:L278
  • 返回类型:void
  • 修饰符:private static

参数:

  • array: Vector3fc[]
  • indexA: int
  • indexB: int

说明:

TODO

private static void swap(long[] array, int indexA, int indexB) @ L284

  • 方法名:swap
  • 源码定位:L284
  • 返回类型:void
  • 修饰符:private static

参数:

  • array: long[]
  • indexA: int
  • indexB: int

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class FaceBakery {
    private static final Vector3fc BLOCK_MIDDLE = new Vector3f(0.5F, 0.5F, 0.5F);
 
    @VisibleForTesting
    static CuboidFace.UVs defaultFaceUV(Vector3fc from, Vector3fc to, Direction facing) {
        return switch (facing) {
            case DOWN -> new CuboidFace.UVs(from.x(), 16.0F - to.z(), to.x(), 16.0F - from.z());
            case UP -> new CuboidFace.UVs(from.x(), from.z(), to.x(), to.z());
            case NORTH -> new CuboidFace.UVs(16.0F - to.x(), 16.0F - to.y(), 16.0F - from.x(), 16.0F - from.y());
            case SOUTH -> new CuboidFace.UVs(from.x(), 16.0F - to.y(), to.x(), 16.0F - from.y());
            case WEST -> new CuboidFace.UVs(from.z(), 16.0F - to.y(), to.z(), 16.0F - from.y());
            case EAST -> new CuboidFace.UVs(16.0F - to.z(), 16.0F - to.y(), 16.0F - from.z(), 16.0F - from.y());
        };
    }
 
    private static Transparency computeMaterialTransparency(Material.Baked material, CuboidFace.UVs uvs) {
        return material.forceTranslucent()
            ? Transparency.TRANSLUCENT
            : material.sprite()
                .contents()
                .computeTransparency(
                    Math.min(uvs.minU(), uvs.maxU()) / 16.0F,
                    Math.min(uvs.minV(), uvs.maxV()) / 16.0F,
                    Math.max(uvs.minU(), uvs.maxU()) / 16.0F,
                    Math.max(uvs.minV(), uvs.maxV()) / 16.0F
                );
    }
 
    public static BakedQuad bakeQuad(
        ModelBaker modelBaker,
        Vector3fc from,
        Vector3fc to,
        CuboidFace face,
        Material.Baked material,
        Direction facing,
        ModelState modelState,
        @Nullable CuboidRotation elementRotation,
        boolean shade,
        int lightEmission
    ) {
        CuboidFace.UVs uvs = face.uvs();
        if (uvs == null) {
            uvs = defaultFaceUV(from, to, facing);
        }
 
        Transparency transparency = computeMaterialTransparency(material, uvs);
        ModelBaker.Interner interner = modelBaker.interner();
        BakedQuad.MaterialInfo materialInfo = interner.materialInfo(BakedQuad.MaterialInfo.of(material, transparency, face.tintIndex(), shade, lightEmission));
        return bakeQuad(interner, from, to, uvs, face.rotation(), materialInfo, facing, modelState, elementRotation);
    }
 
    public static BakedQuad bakeQuad(
        ModelBaker.Interner interner,
        Vector3fc from,
        Vector3fc to,
        CuboidFace.UVs uvs,
        Quadrant uvRotation,
        BakedQuad.MaterialInfo materialInfo,
        Direction facing,
        ModelState modelState,
        @Nullable CuboidRotation elementRotation
    ) {
        Matrix4fc uvTransform = modelState.inverseFaceTransformation(facing);
        Vector3fc[] vertexPositions = new Vector3fc[4];
        long[] vertexPackedUvs = new long[4];
        FaceInfo faceInfo = FaceInfo.fromFacing(facing);
 
        for (int i = 0; i < 4; i++) {
            bakeVertex(
                i,
                faceInfo,
                uvs,
                uvRotation,
                uvTransform,
                from,
                to,
                materialInfo,
                modelState.transformation(),
                elementRotation,
                vertexPositions,
                vertexPackedUvs,
                interner
            );
        }
 
        Direction finalDirection = calculateFacing(vertexPositions);
        if (elementRotation == null && finalDirection != null) {
            recalculateWinding(vertexPositions, vertexPackedUvs, finalDirection);
        }
 
        return new BakedQuad(
            vertexPositions[0],
            vertexPositions[1],
            vertexPositions[2],
            vertexPositions[3],
            vertexPackedUvs[0],
            vertexPackedUvs[1],
            vertexPackedUvs[2],
            vertexPackedUvs[3],
            Objects.requireNonNullElse(finalDirection, Direction.UP),
            materialInfo
        );
    }
 
    private static void bakeVertex(
        int index,
        FaceInfo faceInfo,
        CuboidFace.UVs uvs,
        Quadrant uvRotation,
        Matrix4fc uvTransform,
        Vector3fc from,
        Vector3fc to,
        BakedQuad.MaterialInfo materialInfo,
        Transformation rotation,
        @Nullable CuboidRotation elementRotation,
        Vector3fc[] positionOutput,
        long[] uvOutput,
        ModelBaker.Interner interner
    ) {
        FaceInfo.VertexInfo vertexInfo = faceInfo.getVertexInfo(index);
        Vector3f vertex = vertexInfo.select(from, to).div(16.0F);
        if (elementRotation != null) {
            rotateVertexBy(vertex, elementRotation.origin(), elementRotation.transform());
        }
 
        if (rotation != Transformation.IDENTITY) {
            rotateVertexBy(vertex, BLOCK_MIDDLE, rotation.getMatrix());
        }
 
        float rawU = CuboidFace.getU(uvs, uvRotation, index);
        float rawV = CuboidFace.getV(uvs, uvRotation, index);
        float transformedV;
        float transformedU;
        if (MatrixUtil.isIdentity(uvTransform)) {
            transformedU = rawU;
            transformedV = rawV;
        } else {
            Vector3f transformedUV = uvTransform.transformPosition(new Vector3f(cornerToCenter(rawU), cornerToCenter(rawV), 0.0F));
            transformedU = centerToCorner(transformedUV.x);
            transformedV = centerToCorner(transformedUV.y);
        }
 
        positionOutput[index] = interner.vector(vertex);
        uvOutput[index] = UVPair.pack(materialInfo.sprite().getU(transformedU), materialInfo.sprite().getV(transformedV));
    }
 
    private static float cornerToCenter(float value) {
        return value - 0.5F;
    }
 
    private static float centerToCorner(float value) {
        return value + 0.5F;
    }
 
    private static void rotateVertexBy(Vector3f vertex, Vector3fc origin, Matrix4fc transformation) {
        vertex.sub(origin);
        transformation.transformPosition(vertex);
        vertex.add(origin);
    }
 
    private static @Nullable Direction calculateFacing(Vector3fc[] positions) {
        Vector3f normal = new Vector3f();
        GeometryUtils.normal(positions[0], positions[1], positions[2], normal);
        return findClosestDirection(normal);
    }
 
    private static @Nullable Direction findClosestDirection(Vector3f direction) {
        if (!direction.isFinite()) {
            return null;
        } else {
            Direction best = null;
            float closestProduct = 0.0F;
 
            for (Direction candidate : Direction.values()) {
                float product = direction.dot(candidate.getUnitVec3f());
                if (product >= 0.0F && product > closestProduct) {
                    closestProduct = product;
                    best = candidate;
                }
            }
 
            return best;
        }
    }
 
    private static void recalculateWinding(Vector3fc[] positions, long[] uvs, Direction direction) {
        float minX = 999.0F;
        float minY = 999.0F;
        float minZ = 999.0F;
        float maxX = -999.0F;
        float maxY = -999.0F;
        float maxZ = -999.0F;
 
        for (int i = 0; i < 4; i++) {
            Vector3fc position = positions[i];
            float x = position.x();
            float y = position.y();
            float z = position.z();
            if (x < minX) {
                minX = x;
            }
 
            if (y < minY) {
                minY = y;
            }
 
            if (z < minZ) {
                minZ = z;
            }
 
            if (x > maxX) {
                maxX = x;
            }
 
            if (y > maxY) {
                maxY = y;
            }
 
            if (z > maxZ) {
                maxZ = z;
            }
        }
 
        FaceInfo info = FaceInfo.fromFacing(direction);
 
        for (int vertex = 0; vertex < 4; vertex++) {
            FaceInfo.VertexInfo vertInfo = info.getVertexInfo(vertex);
            float newX = vertInfo.xFace().select(minX, minY, minZ, maxX, maxY, maxZ);
            float newY = vertInfo.yFace().select(minX, minY, minZ, maxX, maxY, maxZ);
            float newZ = vertInfo.zFace().select(minX, minY, minZ, maxX, maxY, maxZ);
            int vertexToSwap = findVertex(positions, vertex, newX, newY, newZ);
            if (vertexToSwap == -1) {
                throw new IllegalStateException("Can't find vertex to swap");
            }
 
            if (vertexToSwap != vertex) {
                swap(positions, vertexToSwap, vertex);
                swap(uvs, vertexToSwap, vertex);
            }
        }
    }
 
    private static int findVertex(Vector3fc[] positions, int start, float x, float y, float z) {
        for (int i = start; i < 4; i++) {
            Vector3fc position = positions[i];
            if (x == position.x() && y == position.y() && z == position.z()) {
                return i;
            }
        }
 
        return -1;
    }
 
    private static void swap(Vector3fc[] array, int indexA, int indexB) {
        Vector3fc tmp = array[indexA];
        array[indexA] = array[indexB];
        array[indexB] = tmp;
    }
 
    private static void swap(long[] array, int indexA, int indexB) {
        long tmp = array[indexA];
        array[indexA] = array[indexB];
        array[indexB] = tmp;
    }
}

引用的其他类

  • Transparency

    • 引用位置: 返回值
  • MatrixUtil

    • 引用位置: 方法调用
    • 关联成员: MatrixUtil.isIdentity()
  • Quadrant

    • 引用位置: 参数
  • Transformation

    • 引用位置: 参数
  • UVPair

    • 引用位置: 方法调用
    • 关联成员: UVPair.pack()
  • FaceInfo

    • 引用位置: 参数/方法调用
    • 关联成员: FaceInfo.fromFacing()
  • ModelState

    • 引用位置: 参数
  • ModelBaker

    • 引用位置: 参数
  • CuboidFace

    • 引用位置: 参数/方法调用/构造调用/返回值
    • 关联成员: CuboidFace.UVs(), CuboidFace.getU(), CuboidFace.getV(), UVs()
  • CuboidRotation

    • 引用位置: 参数
  • BakedQuad

    • 引用位置: 参数/方法调用/构造调用/返回值
    • 关联成员: BakedQuad(), BakedQuad.MaterialInfo.of()
  • Material

    • 引用位置: 参数
  • Direction

    • 引用位置: 参数/方法调用/返回值
    • 关联成员: Direction.values()