ModelPart.java
net.minecraft.client.model.geom.ModelPart
信息
- 全限定名:net.minecraft.client.model.geom.ModelPart
- 类型:public final class
- 包:net.minecraft.client.model.geom
- 源码路径:src/main/java/net/minecraft/client/model/geom/ModelPart.java
- 起始行号:L28
- 职责:
TODO
字段/常量
-
DEFAULT_SCALE- 类型:
float - 修饰符:
public static final - 源码定位:
L29 - 说明:
TODO
- 类型:
-
x- 类型:
float - 修饰符:
public - 源码定位:
L30 - 说明:
TODO
- 类型:
-
y- 类型:
float - 修饰符:
public - 源码定位:
L31 - 说明:
TODO
- 类型:
-
z- 类型:
float - 修饰符:
public - 源码定位:
L32 - 说明:
TODO
- 类型:
-
xRot- 类型:
float - 修饰符:
public - 源码定位:
L33 - 说明:
TODO
- 类型:
-
yRot- 类型:
float - 修饰符:
public - 源码定位:
L34 - 说明:
TODO
- 类型:
-
zRot- 类型:
float - 修饰符:
public - 源码定位:
L35 - 说明:
TODO
- 类型:
-
xScale- 类型:
float - 修饰符:
public - 源码定位:
L36 - 说明:
TODO
- 类型:
-
yScale- 类型:
float - 修饰符:
public - 源码定位:
L37 - 说明:
TODO
- 类型:
-
zScale- 类型:
float - 修饰符:
public - 源码定位:
L38 - 说明:
TODO
- 类型:
-
visible- 类型:
boolean - 修饰符:
public - 源码定位:
L39 - 说明:
TODO
- 类型:
-
skipDraw- 类型:
boolean - 修饰符:
public - 源码定位:
L40 - 说明:
TODO
- 类型:
-
cubes- 类型:
List<ModelPart.Cube> - 修饰符:
private final - 源码定位:
L41 - 说明:
TODO
- 类型:
-
children- 类型:
Map<String,ModelPart> - 修饰符:
private final - 源码定位:
L42 - 说明:
TODO
- 类型:
-
initialPose- 类型:
PartPose - 修饰符:
private - 源码定位:
L43 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.model.geom.ModelPart.Cube- 类型:
class - 修饰符:
public static - 源码定位:
L234 - 说明:
TODO
- 类型:
-
net.minecraft.client.model.geom.ModelPart.Polygon- 类型:
record - 修饰符:
public - 源码定位:
L349 - 说明:
TODO
- 类型:
-
net.minecraft.client.model.geom.ModelPart.Vertex- 类型:
record - 修饰符:
public - 源码定位:
L375 - 说明:
TODO
- 类型:
-
net.minecraft.client.model.geom.ModelPart.Visitor- 类型:
interface - 修饰符:
public - 源码定位:
L397 - 说明:
TODO
- 类型:
构造器
public ModelPart(List<ModelPart.Cube> cubes, Map<String,ModelPart> children) @ L45
- 构造器名:ModelPart
- 源码定位:L45
- 修饰符:public
参数:
- cubes: List<ModelPart.Cube>
- children: Map<String,ModelPart>
说明:
TODO
方法
下面的方法块按源码顺序生成。
public PartPose storePose() @ L50
- 方法名:storePose
- 源码定位:L50
- 返回类型:PartPose
- 修饰符:public
参数:
- 无
说明:
TODO
public PartPose getInitialPose() @ L54
- 方法名:getInitialPose
- 源码定位:L54
- 返回类型:PartPose
- 修饰符:public
参数:
- 无
说明:
TODO
public void setInitialPose(PartPose initialPose) @ L58
- 方法名:setInitialPose
- 源码定位:L58
- 返回类型:void
- 修饰符:public
参数:
- initialPose: PartPose
说明:
TODO
public void resetPose() @ L62
- 方法名:resetPose
- 源码定位:L62
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void loadPose(PartPose pose) @ L66
- 方法名:loadPose
- 源码定位:L66
- 返回类型:void
- 修饰符:public
参数:
- pose: PartPose
说明:
TODO
public boolean hasChild(String name) @ L78
- 方法名:hasChild
- 源码定位:L78
- 返回类型:boolean
- 修饰符:public
参数:
- name: String
说明:
TODO
public ModelPart getChild(String name) @ L82
- 方法名:getChild
- 源码定位:L82
- 返回类型:ModelPart
- 修饰符:public
参数:
- name: String
说明:
TODO
public void setPos(float x, float y, float z) @ L91
- 方法名:setPos
- 源码定位:L91
- 返回类型:void
- 修饰符:public
参数:
- x: float
- y: float
- z: float
说明:
TODO
public void setRotation(float xRot, float yRot, float zRot) @ L97
- 方法名:setRotation
- 源码定位:L97
- 返回类型:void
- 修饰符:public
参数:
- xRot: float
- yRot: float
- zRot: float
说明:
TODO
public void render(PoseStack poseStack, VertexConsumer buffer, int lightCoords, int overlayCoords) @ L103
- 方法名:render
- 源码定位:L103
- 返回类型:void
- 修饰符:public
参数:
- poseStack: PoseStack
- buffer: VertexConsumer
- lightCoords: int
- overlayCoords: int
说明:
TODO
public void render(PoseStack poseStack, VertexConsumer buffer, int lightCoords, int overlayCoords, int color) @ L107
- 方法名:render
- 源码定位:L107
- 返回类型:void
- 修饰符:public
参数:
- poseStack: PoseStack
- buffer: VertexConsumer
- lightCoords: int
- overlayCoords: int
- color: int
说明:
TODO
public void rotateBy(Quaternionf rotation) @ L125
- 方法名:rotateBy
- 源码定位:L125
- 返回类型:void
- 修饰符:public
参数:
- rotation: Quaternionf
说明:
TODO
public void getExtentsForGui(PoseStack poseStack, Consumer<Vector3fc> output) @ L132
- 方法名:getExtentsForGui
- 源码定位:L132
- 返回类型:void
- 修饰符:public
参数:
- poseStack: PoseStack
- output: Consumer
说明:
TODO
public void visit(PoseStack poseStack, ModelPart.Visitor visitor) @ L146
- 方法名:visit
- 源码定位:L146
- 返回类型:void
- 修饰符:public
参数:
- poseStack: PoseStack
- visitor: ModelPart.Visitor
说明:
TODO
private void visit(PoseStack poseStack, ModelPart.Visitor visitor, String path) @ L150
- 方法名:visit
- 源码定位:L150
- 返回类型:void
- 修饰符:private
参数:
- poseStack: PoseStack
- visitor: ModelPart.Visitor
- path: String
说明:
TODO
public void translateAndRotate(PoseStack poseStack) @ L166
- 方法名:translateAndRotate
- 源码定位:L166
- 返回类型:void
- 修饰符:public
参数:
- poseStack: PoseStack
说明:
TODO
private void compile(PoseStack.Pose pose, VertexConsumer builder, int lightCoords, int overlayCoords, int color) @ L177
- 方法名:compile
- 源码定位:L177
- 返回类型:void
- 修饰符:private
参数:
- pose: PoseStack.Pose
- builder: VertexConsumer
- lightCoords: int
- overlayCoords: int
- color: int
说明:
TODO
public ModelPart.Cube getRandomCube(RandomSource random) @ L183
- 方法名:getRandomCube
- 源码定位:L183
- 返回类型:ModelPart.Cube
- 修饰符:public
参数:
- random: RandomSource
说明:
TODO
public boolean isEmpty() @ L187
- 方法名:isEmpty
- 源码定位:L187
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public void offsetPos(Vector3f offset) @ L191
- 方法名:offsetPos
- 源码定位:L191
- 返回类型:void
- 修饰符:public
参数:
- offset: Vector3f
说明:
TODO
public void offsetRotation(Vector3f offset) @ L197
- 方法名:offsetRotation
- 源码定位:L197
- 返回类型:void
- 修饰符:public
参数:
- offset: Vector3f
说明:
TODO
public void offsetScale(Vector3f offset) @ L203
- 方法名:offsetScale
- 源码定位:L203
- 返回类型:void
- 修饰符:public
参数:
- offset: Vector3f
说明:
TODO
public List<ModelPart> getAllParts() @ L209
- 方法名:getAllParts
- 源码定位:L209
- 返回类型:List
- 修饰符:public
参数:
- 无
说明:
TODO
public Function<String,ModelPart> createPartLookup() @ L216
- 方法名:createPartLookup
- 源码定位:L216
- 返回类型:Function<String,ModelPart>
- 修饰符:public
参数:
- 无
说明:
TODO
private void addAllChildren(BiConsumer<String,ModelPart> output) @ L223
- 方法名:addAllChildren
- 源码定位:L223
- 返回类型:void
- 修饰符:private
参数:
- output: BiConsumer<String,ModelPart>
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public final class ModelPart {
public static final float DEFAULT_SCALE = 1.0F;
public float x;
public float y;
public float z;
public float xRot;
public float yRot;
public float zRot;
public float xScale = 1.0F;
public float yScale = 1.0F;
public float zScale = 1.0F;
public boolean visible = true;
public boolean skipDraw;
private final List<ModelPart.Cube> cubes;
private final Map<String, ModelPart> children;
private PartPose initialPose = PartPose.ZERO;
public ModelPart(List<ModelPart.Cube> cubes, Map<String, ModelPart> children) {
this.cubes = cubes;
this.children = children;
}
public PartPose storePose() {
return PartPose.offsetAndRotation(this.x, this.y, this.z, this.xRot, this.yRot, this.zRot);
}
public PartPose getInitialPose() {
return this.initialPose;
}
public void setInitialPose(PartPose initialPose) {
this.initialPose = initialPose;
}
public void resetPose() {
this.loadPose(this.initialPose);
}
public void loadPose(PartPose pose) {
this.x = pose.x();
this.y = pose.y();
this.z = pose.z();
this.xRot = pose.xRot();
this.yRot = pose.yRot();
this.zRot = pose.zRot();
this.xScale = pose.xScale();
this.yScale = pose.yScale();
this.zScale = pose.zScale();
}
public boolean hasChild(String name) {
return this.children.containsKey(name);
}
public ModelPart getChild(String name) {
ModelPart result = this.children.get(name);
if (result == null) {
throw new NoSuchElementException("Can't find part " + name);
} else {
return result;
}
}
public void setPos(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public void setRotation(float xRot, float yRot, float zRot) {
this.xRot = xRot;
this.yRot = yRot;
this.zRot = zRot;
}
public void render(PoseStack poseStack, VertexConsumer buffer, int lightCoords, int overlayCoords) {
this.render(poseStack, buffer, lightCoords, overlayCoords, -1);
}
public void render(PoseStack poseStack, VertexConsumer buffer, int lightCoords, int overlayCoords, int color) {
if (this.visible) {
if (!this.cubes.isEmpty() || !this.children.isEmpty()) {
poseStack.pushPose();
this.translateAndRotate(poseStack);
if (!this.skipDraw) {
this.compile(poseStack.last(), buffer, lightCoords, overlayCoords, color);
}
for (ModelPart child : this.children.values()) {
child.render(poseStack, buffer, lightCoords, overlayCoords, color);
}
poseStack.popPose();
}
}
}
public void rotateBy(Quaternionf rotation) {
Matrix3f oldRotation = new Matrix3f().rotationZYX(this.zRot, this.yRot, this.xRot);
Matrix3f newRotation = oldRotation.rotate(rotation);
Vector3f newAngles = newRotation.getEulerAnglesZYX(new Vector3f());
this.setRotation(newAngles.x, newAngles.y, newAngles.z);
}
public void getExtentsForGui(PoseStack poseStack, Consumer<Vector3fc> output) {
this.visit(poseStack, (pose, partPath, cubeIndex, cube) -> {
for (ModelPart.Polygon polygon : cube.polygons) {
for (ModelPart.Vertex vertex : polygon.vertices()) {
float x = vertex.worldX();
float y = vertex.worldY();
float z = vertex.worldZ();
Vector3f pos = pose.pose().transformPosition(x, y, z, new Vector3f());
output.accept(pos);
}
}
});
}
public void visit(PoseStack poseStack, ModelPart.Visitor visitor) {
this.visit(poseStack, visitor, "");
}
private void visit(PoseStack poseStack, ModelPart.Visitor visitor, String path) {
if (!this.cubes.isEmpty() || !this.children.isEmpty()) {
poseStack.pushPose();
this.translateAndRotate(poseStack);
PoseStack.Pose pose = poseStack.last();
for (int i = 0; i < this.cubes.size(); i++) {
visitor.visit(pose, path, i, this.cubes.get(i));
}
String childPath = path + "/";
this.children.forEach((name, child) -> child.visit(poseStack, visitor, childPath + name));
poseStack.popPose();
}
}
public void translateAndRotate(PoseStack poseStack) {
poseStack.translate(this.x / 16.0F, this.y / 16.0F, this.z / 16.0F);
if (this.xRot != 0.0F || this.yRot != 0.0F || this.zRot != 0.0F) {
poseStack.mulPose(new Quaternionf().rotationZYX(this.zRot, this.yRot, this.xRot));
}
if (this.xScale != 1.0F || this.yScale != 1.0F || this.zScale != 1.0F) {
poseStack.scale(this.xScale, this.yScale, this.zScale);
}
}
private void compile(PoseStack.Pose pose, VertexConsumer builder, int lightCoords, int overlayCoords, int color) {
for (ModelPart.Cube cube : this.cubes) {
cube.compile(pose, builder, lightCoords, overlayCoords, color);
}
}
public ModelPart.Cube getRandomCube(RandomSource random) {
return Util.getRandom(this.cubes, random);
}
public boolean isEmpty() {
return this.cubes.isEmpty();
}
public void offsetPos(Vector3f offset) {
this.x = this.x + offset.x();
this.y = this.y + offset.y();
this.z = this.z + offset.z();
}
public void offsetRotation(Vector3f offset) {
this.xRot = this.xRot + offset.x();
this.yRot = this.yRot + offset.y();
this.zRot = this.zRot + offset.z();
}
public void offsetScale(Vector3f offset) {
this.xScale = this.xScale + offset.x();
this.yScale = this.yScale + offset.y();
this.zScale = this.zScale + offset.z();
}
public List<ModelPart> getAllParts() {
List<ModelPart> allParts = new ArrayList<>();
allParts.add(this);
this.addAllChildren((name, part) -> allParts.add(part));
return List.copyOf(allParts);
}
public Function<String, @Nullable ModelPart> createPartLookup() {
Map<String, ModelPart> parts = new HashMap<>();
parts.put("root", this);
this.addAllChildren(parts::putIfAbsent);
return parts::get;
}
private void addAllChildren(BiConsumer<String, ModelPart> output) {
for (Entry<String, ModelPart> entry : this.children.entrySet()) {
output.accept(entry.getKey(), entry.getValue());
}
for (ModelPart part : this.children.values()) {
part.addAllChildren(output);
}
}
@OnlyIn(Dist.CLIENT)
public static class Cube {
public final ModelPart.Polygon[] polygons;
public final float minX;
public final float minY;
public final float minZ;
public final float maxX;
public final float maxY;
public final float maxZ;
public Cube(
int xTexOffs,
int yTexOffs,
float minX,
float minY,
float minZ,
float width,
float height,
float depth,
float growX,
float growY,
float growZ,
boolean mirror,
float xTexSize,
float yTexSize,
Set<Direction> visibleFaces
) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = minX + width;
this.maxY = minY + height;
this.maxZ = minZ + depth;
this.polygons = new ModelPart.Polygon[visibleFaces.size()];
float maxX = minX + width;
float maxY = minY + height;
float maxZ = minZ + depth;
minX -= growX;
minY -= growY;
minZ -= growZ;
maxX += growX;
maxY += growY;
maxZ += growZ;
if (mirror) {
float tmp = maxX;
maxX = minX;
minX = tmp;
}
ModelPart.Vertex t0 = new ModelPart.Vertex(minX, minY, minZ, 0.0F, 0.0F);
ModelPart.Vertex t1 = new ModelPart.Vertex(maxX, minY, minZ, 0.0F, 8.0F);
ModelPart.Vertex t2 = new ModelPart.Vertex(maxX, maxY, minZ, 8.0F, 8.0F);
ModelPart.Vertex t3 = new ModelPart.Vertex(minX, maxY, minZ, 8.0F, 0.0F);
ModelPart.Vertex l0 = new ModelPart.Vertex(minX, minY, maxZ, 0.0F, 0.0F);
ModelPart.Vertex l1 = new ModelPart.Vertex(maxX, minY, maxZ, 0.0F, 8.0F);
ModelPart.Vertex l2 = new ModelPart.Vertex(maxX, maxY, maxZ, 8.0F, 8.0F);
ModelPart.Vertex l3 = new ModelPart.Vertex(minX, maxY, maxZ, 8.0F, 0.0F);
float u0 = xTexOffs;
float u1 = xTexOffs + depth;
float u2 = xTexOffs + depth + width;
float u22 = xTexOffs + depth + width + width;
float u3 = xTexOffs + depth + width + depth;
float u4 = xTexOffs + depth + width + depth + width;
float v0 = yTexOffs;
float v1 = yTexOffs + depth;
float v2 = yTexOffs + depth + height;
int pos = 0;
if (visibleFaces.contains(Direction.DOWN)) {
this.polygons[pos++] = new ModelPart.Polygon(new ModelPart.Vertex[]{l1, l0, t0, t1}, u1, v0, u2, v1, xTexSize, yTexSize, mirror, Direction.DOWN);
}
if (visibleFaces.contains(Direction.UP)) {
this.polygons[pos++] = new ModelPart.Polygon(new ModelPart.Vertex[]{t2, t3, l3, l2}, u2, v1, u22, v0, xTexSize, yTexSize, mirror, Direction.UP);
}
if (visibleFaces.contains(Direction.WEST)) {
this.polygons[pos++] = new ModelPart.Polygon(new ModelPart.Vertex[]{t0, l0, l3, t3}, u0, v1, u1, v2, xTexSize, yTexSize, mirror, Direction.WEST);
}
if (visibleFaces.contains(Direction.NORTH)) {
this.polygons[pos++] = new ModelPart.Polygon(
new ModelPart.Vertex[]{t1, t0, t3, t2}, u1, v1, u2, v2, xTexSize, yTexSize, mirror, Direction.NORTH
);
}
if (visibleFaces.contains(Direction.EAST)) {
this.polygons[pos++] = new ModelPart.Polygon(new ModelPart.Vertex[]{l1, t1, t2, l2}, u2, v1, u3, v2, xTexSize, yTexSize, mirror, Direction.EAST);
}
if (visibleFaces.contains(Direction.SOUTH)) {
this.polygons[pos] = new ModelPart.Polygon(new ModelPart.Vertex[]{l0, l1, l2, l3}, u3, v1, u4, v2, xTexSize, yTexSize, mirror, Direction.SOUTH);
}
}
public void compile(PoseStack.Pose pose, VertexConsumer builder, int lightCoords, int overlayCoords, int color) {
Matrix4f matrix = pose.pose();
Vector3f scratchVector = new Vector3f();
for (ModelPart.Polygon polygon : this.polygons) {
Vector3f normal = pose.transformNormal(polygon.normal, scratchVector);
float nx = normal.x();
float ny = normal.y();
float nz = normal.z();
for (ModelPart.Vertex vertex : polygon.vertices) {
float x = vertex.worldX();
float y = vertex.worldY();
float z = vertex.worldZ();
Vector3f pos = matrix.transformPosition(x, y, z, scratchVector);
builder.addVertex(pos.x(), pos.y(), pos.z(), color, vertex.u, vertex.v, overlayCoords, lightCoords, nx, ny, nz);
}
}
}
}
@OnlyIn(Dist.CLIENT)
public record Polygon(ModelPart.Vertex[] vertices, Vector3fc normal) {
public Polygon(ModelPart.Vertex[] vertices, float u0, float v0, float u1, float v1, float xTexSize, float yTexSize, boolean mirror, Direction facing) {
this(vertices, (mirror ? mirrorFacing(facing) : facing).getUnitVec3f());
float us = 0.0F / xTexSize;
float vs = 0.0F / yTexSize;
vertices[0] = vertices[0].remap(u1 / xTexSize - us, v0 / yTexSize + vs);
vertices[1] = vertices[1].remap(u0 / xTexSize + us, v0 / yTexSize + vs);
vertices[2] = vertices[2].remap(u0 / xTexSize + us, v1 / yTexSize - vs);
vertices[3] = vertices[3].remap(u1 / xTexSize - us, v1 / yTexSize - vs);
if (mirror) {
int length = vertices.length;
for (int i = 0; i < length / 2; i++) {
ModelPart.Vertex tmp = vertices[i];
vertices[i] = vertices[length - 1 - i];
vertices[length - 1 - i] = tmp;
}
}
}
private static Direction mirrorFacing(Direction facing) {
return facing.getAxis() == Direction.Axis.X ? facing.getOpposite() : facing;
}
}
@OnlyIn(Dist.CLIENT)
public record Vertex(float x, float y, float z, float u, float v) {
public static final float SCALE_FACTOR = 16.0F;
public ModelPart.Vertex remap(float u, float v) {
return new ModelPart.Vertex(this.x, this.y, this.z, u, v);
}
public float worldX() {
return this.x / 16.0F;
}
public float worldY() {
return this.y / 16.0F;
}
public float worldZ() {
return this.z / 16.0F;
}
}
@FunctionalInterface
@OnlyIn(Dist.CLIENT)
public interface Visitor {
void visit(final PoseStack.Pose pose, final String partPath, final int cubeIndex, final ModelPart.Cube cube);
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/方法调用/返回值 - 关联成员:
PartPose.offsetAndRotation()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.getRandom()
- 引用位置: