Camera.java

net.minecraft.client.Camera

信息

  • 全限定名:net.minecraft.client.Camera
  • 类型:public class
  • 包:net.minecraft.client
  • 源码路径:src/main/java/net/minecraft/client/Camera.java
  • 起始行号:L42
  • 实现:TrackedWaypoint.Camera
  • 职责:

    TODO

字段/常量

  • PROJECTION_Z_NEAR

    • 类型: float
    • 修饰符: public static final
    • 源码定位: L43
    • 说明:

      TODO

  • DEFAULT_CAMERA_DISTANCE

    • 类型: float
    • 修饰符: private static final
    • 源码定位: L44
    • 说明:

      TODO

  • FORWARDS

    • 类型: Vector3f
    • 修饰符: private static final
    • 源码定位: L45
    • 说明:

      TODO

  • UP

    • 类型: Vector3f
    • 修饰符: private static final
    • 源码定位: L46
    • 说明:

      TODO

  • LEFT

    • 类型: Vector3f
    • 修饰符: private static final
    • 源码定位: L47
    • 说明:

      TODO

  • BASE_HUD_FOV

    • 类型: float
    • 修饰符: public static final
    • 源码定位: L48
    • 说明:

      TODO

  • initialized

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L49
    • 说明:

      TODO

  • level

    • 类型: Level
    • 修饰符: private
    • 源码定位: L50
    • 说明:

      TODO

  • entity

    • 类型: Entity
    • 修饰符: private
    • 源码定位: L51
    • 说明:

      TODO

  • position

    • 类型: Vec3
    • 修饰符: private
    • 源码定位: L52
    • 说明:

      TODO

  • blockPosition

    • 类型: BlockPos.MutableBlockPos
    • 修饰符: private final
    • 源码定位: L53
    • 说明:

      TODO

  • forwards

    • 类型: Vector3f
    • 修饰符: private final
    • 源码定位: L54
    • 说明:

      TODO

  • panoramicForwards

    • 类型: Vector3f
    • 修饰符: private final
    • 源码定位: L55
    • 说明:

      TODO

  • up

    • 类型: Vector3f
    • 修饰符: private final
    • 源码定位: L56
    • 说明:

      TODO

  • left

    • 类型: Vector3f
    • 修饰符: private final
    • 源码定位: L57
    • 说明:

      TODO

  • xRot

    • 类型: float
    • 修饰符: private
    • 源码定位: L58
    • 说明:

      TODO

  • yRot

    • 类型: float
    • 修饰符: private
    • 源码定位: L59
    • 说明:

      TODO

  • rotation

    • 类型: Quaternionf
    • 修饰符: private final
    • 源码定位: L60
    • 说明:

      TODO

  • detached

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L61
    • 说明:

      TODO

  • eyeHeight

    • 类型: float
    • 修饰符: private
    • 源码定位: L62
    • 说明:

      TODO

  • eyeHeightOld

    • 类型: float
    • 修饰符: private
    • 源码定位: L63
    • 说明:

      TODO

  • projection

    • 类型: Projection
    • 修饰符: private final
    • 源码定位: L64
    • 说明:

      TODO

  • cullFrustum

    • 类型: Frustum
    • 修饰符: private
    • 源码定位: L65
    • 说明:

      TODO

  • capturedFrustum

    • 类型: Frustum
    • 修饰符: private
    • 源码定位: L66
    • 说明:

      TODO

  • captureFrustum

    • 类型: boolean
    • 修饰符: package-private
    • 源码定位: L67
    • 说明:

      TODO

  • cachedViewRotMatrix

    • 类型: Matrix4f
    • 修饰符: private final
    • 源码定位: L68
    • 说明:

      TODO

  • cachedViewRotProjMatrix

    • 类型: Matrix4f
    • 修饰符: private final
    • 源码定位: L69
    • 说明:

      TODO

  • lastProjectionVersion

    • 类型: long
    • 修饰符: private
    • 源码定位: L70
    • 说明:

      TODO

  • matrixPropertiesDirty

    • 类型: int
    • 修饰符: private
    • 源码定位: L71
    • 说明:

      TODO

  • DIRTY_VIEW_ROT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L72
    • 说明:

      TODO

  • DIRTY_VIEW_ROT_PROJ

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L73
    • 说明:

      TODO

  • fovModifier

    • 类型: float
    • 修饰符: private
    • 源码定位: L74
    • 说明:

      TODO

  • oldFovModifier

    • 类型: float
    • 修饰符: private
    • 源码定位: L75
    • 说明:

      TODO

  • fov

    • 类型: float
    • 修饰符: private
    • 源码定位: L76
    • 说明:

      TODO

  • hudFov

    • 类型: float
    • 修饰符: private
    • 源码定位: L77
    • 说明:

      TODO

  • depthFar

    • 类型: float
    • 修饰符: private
    • 源码定位: L78
    • 说明:

      TODO

  • isPanoramicMode

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L79
    • 说明:

      TODO

  • attributeProbe

    • 类型: EnvironmentAttributeProbe
    • 修饰符: private final
    • 源码定位: L80
    • 说明:

      TODO

  • minecraft

    • 类型: Minecraft
    • 修饰符: private final
    • 源码定位: L81
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.Camera.NearPlane
    • 类型: class
    • 修饰符: public static
    • 源码定位: L499
    • 说明:

      TODO

构造器

方法

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

public void tick() @ L83

  • 方法名:tick
  • 源码定位:L83
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void update(DeltaTracker deltaTracker) @ L93

  • 方法名:update
  • 源码定位:L93
  • 返回类型:void
  • 修饰符:public

参数:

  • deltaTracker: DeltaTracker

说明:

TODO

public float getCameraEntityPartialTicks(DeltaTracker deltaTracker) @ L114

  • 方法名:getCameraEntityPartialTicks
  • 源码定位:L114
  • 返回类型:float
  • 修饰符:public

参数:

  • deltaTracker: DeltaTracker

说明:

TODO

public void extractRenderState(CameraRenderState cameraState, float cameraEntityPartialTicks) @ L118

  • 方法名:extractRenderState
  • 源码定位:L118
  • 返回类型:void
  • 修饰符:public

参数:

  • cameraState: CameraRenderState
  • cameraEntityPartialTicks: float

说明:

TODO

private void tickFov() @ L157

  • 方法名:tickFov
  • 源码定位:L157
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private Matrix4f createProjectionMatrixForCulling() @ L173

  • 方法名:createProjectionMatrixForCulling
  • 源码定位:L173
  • 返回类型:Matrix4f
  • 修饰符:private

参数:

说明:

TODO

public Frustum getCullFrustum() @ L185

  • 方法名:getCullFrustum
  • 源码定位:L185
  • 返回类型:Frustum
  • 修饰符:public

参数:

说明:

TODO

private void prepareCullFrustum(Matrix4fc modelViewMatrix, Matrix4f projectionMatrixForCulling, Vec3 cameraPos) @ L189

  • 方法名:prepareCullFrustum
  • 源码定位:L189
  • 返回类型:void
  • 修饰符:private

参数:

  • modelViewMatrix: Matrix4fc
  • projectionMatrixForCulling: Matrix4f
  • cameraPos: Vec3

说明:

TODO

public Frustum getCapturedFrustum() @ L203

  • 方法名:getCapturedFrustum
  • 源码定位:L203
  • 返回类型:Frustum
  • 修饰符:public

参数:

说明:

TODO

public void captureFrustum() @ L207

  • 方法名:captureFrustum
  • 源码定位:L207
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void killFrustum() @ L211

  • 方法名:killFrustum
  • 源码定位:L211
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private float calculateFov(float partialTicks) @ L215

  • 方法名:calculateFov
  • 源码定位:L215
  • 返回类型:float
  • 修饰符:private

参数:

  • partialTicks: float

说明:

TODO

private float calculateHudFov(float partialTicks) @ L224

  • 方法名:calculateHudFov
  • 源码定位:L224
  • 返回类型:float
  • 修饰符:private

参数:

  • partialTicks: float

说明:

TODO

private float modifyFovBasedOnDeathOrFluid(float partialTicks, float fov) @ L228

  • 方法名:modifyFovBasedOnDeathOrFluid
  • 源码定位:L228
  • 返回类型:float
  • 修饰符:private

参数:

  • partialTicks: float
  • fov: float

说明:

TODO

private void alignWithEntity(float partialTicks) @ L243

  • 方法名:alignWithEntity
  • 源码定位:L243
  • 返回类型:void
  • 修饰符:private

参数:

  • partialTicks: float

说明:

TODO

private float getMaxZoom(float cameraDist) @ L291

  • 方法名:getMaxZoom
  • 源码定位:L291
  • 返回类型:float
  • 修饰符:private

参数:

  • cameraDist: float

说明:

TODO

public boolean isPanoramicMode() @ L312

  • 方法名:isPanoramicMode
  • 源码定位:L312
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public float getFov() @ L316

  • 方法名:getFov
  • 源码定位:L316
  • 返回类型:float
  • 修饰符:public

参数:

说明:

TODO

private void setupPerspective(float zNear, float zFar, float fov, float width, float height) @ L320

  • 方法名:setupPerspective
  • 源码定位:L320
  • 返回类型:void
  • 修饰符:private

参数:

  • zNear: float
  • zFar: float
  • fov: float
  • width: float
  • height: float

说明:

TODO

private void setupOrtho(float zNear, float zFar, float width, float height, boolean invertY) @ L324

  • 方法名:setupOrtho
  • 源码定位:L324
  • 返回类型:void
  • 修饰符:private

参数:

  • zNear: float
  • zFar: float
  • width: float
  • height: float
  • invertY: boolean

说明:

TODO

protected void move(float forwards, float up, float right) @ L328

  • 方法名:move
  • 源码定位:L328
  • 返回类型:void
  • 修饰符:protected

参数:

  • forwards: float
  • up: float
  • right: float

说明:

TODO

protected void setRotation(float yRot, float xRot) @ L333

  • 方法名:setRotation
  • 源码定位:L333
  • 返回类型:void
  • 修饰符:protected

参数:

  • yRot: float
  • xRot: float

说明:

TODO

protected void setPosition(double x, double y, double z) @ L343

  • 方法名:setPosition
  • 源码定位:L343
  • 返回类型:void
  • 修饰符:protected

参数:

  • x: double
  • y: double
  • z: double

说明:

TODO

protected void setPosition(Vec3 position) @ L347

  • 方法名:setPosition
  • 源码定位:L347
  • 返回类型:void
  • 修饰符:protected

参数:

  • position: Vec3

说明:

TODO

public Vec3 position() @ L352

  • 方法名:position
  • 源码定位:L352
  • 返回类型:Vec3
  • 修饰符:public

参数:

说明:

TODO

public BlockPos blockPosition() @ L357

  • 方法名:blockPosition
  • 源码定位:L357
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public float xRot() @ L361

  • 方法名:xRot
  • 源码定位:L361
  • 返回类型:float
  • 修饰符:public

参数:

说明:

TODO

public float yRot() @ L365

  • 方法名:yRot
  • 源码定位:L365
  • 返回类型:float
  • 修饰符:public

参数:

说明:

TODO

public float yaw() @ L369

  • 方法名:yaw
  • 源码定位:L369
  • 返回类型:float
  • 修饰符:public

参数:

说明:

TODO

public Quaternionf rotation() @ L374

  • 方法名:rotation
  • 源码定位:L374
  • 返回类型:Quaternionf
  • 修饰符:public

参数:

说明:

TODO

public Matrix4f getViewRotationMatrix(Matrix4f dest) @ L378

  • 方法名:getViewRotationMatrix
  • 源码定位:L378
  • 返回类型:Matrix4f
  • 修饰符:public

参数:

  • dest: Matrix4f

说明:

TODO

public Matrix4f getViewRotationProjectionMatrix(Matrix4f dest) @ L388

  • 方法名:getViewRotationProjectionMatrix
  • 源码定位:L388
  • 返回类型:Matrix4f
  • 修饰符:public

参数:

  • dest: Matrix4f

说明:

TODO

public Entity entity() @ L401

  • 方法名:entity
  • 源码定位:L401
  • 返回类型:Entity
  • 修饰符:public

参数:

说明:

TODO

public void setEntity(Entity entity) @ L405

  • 方法名:setEntity
  • 源码定位:L405
  • 返回类型:void
  • 修饰符:public

参数:

  • entity: Entity

说明:

TODO

public boolean isInitialized() @ L409

  • 方法名:isInitialized
  • 源码定位:L409
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public boolean isDetached() @ L413

  • 方法名:isDetached
  • 源码定位:L413
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public EnvironmentAttributeProbe attributeProbe() @ L417

  • 方法名:attributeProbe
  • 源码定位:L417
  • 返回类型:EnvironmentAttributeProbe
  • 修饰符:public

参数:

说明:

TODO

public Camera.NearPlane getNearPlane(float fov) @ L421

  • 方法名:getNearPlane
  • 源码定位:L421
  • 返回类型:Camera.NearPlane
  • 修饰符:public

参数:

  • fov: float

说明:

TODO

public FogType getFluidInCamera() @ L431

  • 方法名:getFluidInCamera
  • 源码定位:L431
  • 返回类型:FogType
  • 修饰符:public

参数:

说明:

TODO

public Vector3fc forwardVector() @ L462

  • 方法名:forwardVector
  • 源码定位:L462
  • 返回类型:Vector3fc
  • 修饰符:public

参数:

说明:

TODO

public Vector3fc panoramicForwards() @ L466

  • 方法名:panoramicForwards
  • 源码定位:L466
  • 返回类型:Vector3fc
  • 修饰符:public

参数:

说明:

TODO

public Vector3fc upVector() @ L470

  • 方法名:upVector
  • 源码定位:L470
  • 返回类型:Vector3fc
  • 修饰符:public

参数:

说明:

TODO

public Vector3fc leftVector() @ L474

  • 方法名:leftVector
  • 源码定位:L474
  • 返回类型:Vector3fc
  • 修饰符:public

参数:

说明:

TODO

public void reset() @ L478

  • 方法名:reset
  • 源码定位:L478
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void setLevel(ClientLevel level) @ L485

  • 方法名:setLevel
  • 源码定位:L485
  • 返回类型:void
  • 修饰符:public

参数:

  • level: ClientLevel

说明:

TODO

public void enablePanoramicMode() @ L489

  • 方法名:enablePanoramicMode
  • 源码定位:L489
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void disablePanoramicMode() @ L494

  • 方法名:disablePanoramicMode
  • 源码定位:L494
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class Camera implements TrackedWaypoint.Camera {
    public static final float PROJECTION_Z_NEAR = 0.05F;
    private static final float DEFAULT_CAMERA_DISTANCE = 4.0F;
    private static final Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
    private static final Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
    private static final Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
    public static final float BASE_HUD_FOV = 70.0F;
    private boolean initialized;
    private @Nullable Level level;
    private @Nullable Entity entity;
    private Vec3 position = Vec3.ZERO;
    private final BlockPos.MutableBlockPos blockPosition = new BlockPos.MutableBlockPos();
    private final Vector3f forwards = new Vector3f(FORWARDS);
    private final Vector3f panoramicForwards = new Vector3f(FORWARDS);
    private final Vector3f up = new Vector3f(UP);
    private final Vector3f left = new Vector3f(LEFT);
    private float xRot;
    private float yRot;
    private final Quaternionf rotation = new Quaternionf();
    private boolean detached;
    private float eyeHeight;
    private float eyeHeightOld;
    private final Projection projection = new Projection();
    private Frustum cullFrustum = new Frustum(new Matrix4f(), new Matrix4f());
    private @Nullable Frustum capturedFrustum;
    boolean captureFrustum;
    private final Matrix4f cachedViewRotMatrix = new Matrix4f();
    private final Matrix4f cachedViewRotProjMatrix = new Matrix4f();
    private long lastProjectionVersion = -1L;
    private int matrixPropertiesDirty = -1;
    private static final int DIRTY_VIEW_ROT = 1;
    private static final int DIRTY_VIEW_ROT_PROJ = 2;
    private float fovModifier;
    private float oldFovModifier;
    private float fov;
    private float hudFov;
    private float depthFar;
    private boolean isPanoramicMode;
    private final EnvironmentAttributeProbe attributeProbe = new EnvironmentAttributeProbe();
    private final Minecraft minecraft = Minecraft.getInstance();
 
    public void tick() {
        if (this.level != null && this.entity != null) {
            this.eyeHeightOld = this.eyeHeight;
            this.eyeHeight = this.eyeHeight + (this.entity.getEyeHeight() - this.eyeHeight) * 0.5F;
            this.attributeProbe.tick(this.level, this.position);
        }
 
        this.tickFov();
    }
 
    public void update(DeltaTracker deltaTracker) {
        float renderDistance = this.minecraft.options.getEffectiveRenderDistance() * 16;
        this.depthFar = Math.max(renderDistance * 4.0F, (float)(this.minecraft.options.cloudRange().get() * 16));
        LocalPlayer player = this.minecraft.player;
        if (player != null && this.level != null) {
            if (this.entity == null) {
                this.setEntity(player);
            }
 
            float partialTicks = this.getCameraEntityPartialTicks(deltaTracker);
            this.alignWithEntity(partialTicks);
            this.fov = this.calculateFov(partialTicks);
            this.hudFov = this.calculateHudFov(partialTicks);
            this.prepareCullFrustum(this.getViewRotationMatrix(this.cachedViewRotMatrix), this.createProjectionMatrixForCulling(), this.position);
            float windowWidth = this.minecraft.getWindow().getWidth();
            float windowHeight = this.minecraft.getWindow().getHeight();
            this.setupPerspective(0.05F, this.depthFar, this.fov, windowWidth, windowHeight);
            this.initialized = true;
        }
    }
 
    public float getCameraEntityPartialTicks(DeltaTracker deltaTracker) {
        return this.level.tickRateManager().isEntityFrozen(this.entity) ? 1.0F : deltaTracker.getGameTimeDeltaPartialTick(true);
    }
 
    public void extractRenderState(CameraRenderState cameraState, float cameraEntityPartialTicks) {
        cameraState.initialized = this.isInitialized();
        cameraState.isPanoramicMode = this.isPanoramicMode;
        cameraState.pos = this.position();
        cameraState.xRot = this.xRot;
        cameraState.yRot = this.yRot;
        cameraState.blockPos = this.blockPosition();
        cameraState.orientation.set(this.rotation());
        cameraState.cullFrustum.set(this.cullFrustum);
        cameraState.depthFar = this.depthFar;
        this.projection.getMatrix(cameraState.projectionMatrix);
        this.getViewRotationMatrix(cameraState.viewRotationMatrix);
        if (this.entity instanceof LivingEntity livingEntity) {
            cameraState.entityRenderState.isLiving = true;
            cameraState.entityRenderState.isSleeping = livingEntity.isSleeping();
            cameraState.entityRenderState.doesMobEffectBlockSky = livingEntity.hasEffect(MobEffects.BLINDNESS) || livingEntity.hasEffect(MobEffects.DARKNESS);
            cameraState.entityRenderState.isDeadOrDying = livingEntity.isDeadOrDying();
            cameraState.entityRenderState.hurtDir = livingEntity.getHurtDir();
            cameraState.entityRenderState.hurtTime = livingEntity.hurtTime - cameraEntityPartialTicks;
            cameraState.entityRenderState.deathTime = livingEntity.deathTime + cameraEntityPartialTicks;
            cameraState.entityRenderState.hurtDuration = livingEntity.hurtDuration;
        } else {
            cameraState.entityRenderState.isLiving = false;
            cameraState.entityRenderState.isSleeping = false;
            cameraState.entityRenderState.doesMobEffectBlockSky = false;
        }
 
        if (this.entity instanceof AbstractClientPlayer player) {
            cameraState.entityRenderState.isPlayer = true;
            ClientAvatarState avatarState = player.avatarState();
            cameraState.entityRenderState.backwardsInterpolatedWalkDistance = avatarState.getBackwardsInterpolatedWalkDistance(cameraEntityPartialTicks);
            cameraState.entityRenderState.bob = avatarState.getInterpolatedBob(cameraEntityPartialTicks);
        } else {
            cameraState.entityRenderState.isPlayer = false;
        }
 
        cameraState.hudFov = this.hudFov;
    }
 
    private void tickFov() {
        float targetFovModifier;
        if (this.minecraft.getCameraEntity() instanceof AbstractClientPlayer player) {
            Options options = this.minecraft.options;
            boolean firstPerson = options.getCameraType().isFirstPerson();
            float effectScale = options.fovEffectScale().get().floatValue();
            targetFovModifier = player.getFieldOfViewModifier(firstPerson, effectScale);
        } else {
            targetFovModifier = 1.0F;
        }
 
        this.oldFovModifier = this.fovModifier;
        this.fovModifier = this.fovModifier + (targetFovModifier - this.fovModifier) * 0.5F;
        this.fovModifier = Mth.clamp(this.fovModifier, 0.1F, 1.5F);
    }
 
    private Matrix4f createProjectionMatrixForCulling() {
        float fovForCulling = Math.max(this.fov, (float)this.minecraft.options.fov().get().intValue());
        Matrix4f projection = new Matrix4f();
        return projection.perspective(
            fovForCulling * (float) (Math.PI / 180.0),
            (float)this.minecraft.getWindow().getWidth() / this.minecraft.getWindow().getHeight(),
            0.05F,
            this.depthFar,
            RenderSystem.getDevice().isZZeroToOne()
        );
    }
 
    public Frustum getCullFrustum() {
        return this.cullFrustum;
    }
 
    private void prepareCullFrustum(Matrix4fc modelViewMatrix, Matrix4f projectionMatrixForCulling, Vec3 cameraPos) {
        if (this.capturedFrustum != null && !this.captureFrustum) {
            this.cullFrustum = this.capturedFrustum;
        } else {
            this.cullFrustum = new Frustum(modelViewMatrix, projectionMatrixForCulling);
            this.cullFrustum.prepare(cameraPos.x(), cameraPos.y(), cameraPos.z());
        }
 
        if (this.captureFrustum) {
            this.capturedFrustum = this.cullFrustum;
            this.captureFrustum = false;
        }
    }
 
    public @Nullable Frustum getCapturedFrustum() {
        return this.capturedFrustum;
    }
 
    public void captureFrustum() {
        this.captureFrustum = true;
    }
 
    public void killFrustum() {
        this.capturedFrustum = null;
    }
 
    private float calculateFov(float partialTicks) {
        if (this.isPanoramicMode) {
            return 90.0F;
        } else {
            float fov = this.minecraft.options.fov().get().intValue() * Mth.lerp(partialTicks, this.oldFovModifier, this.fovModifier);
            return this.modifyFovBasedOnDeathOrFluid(partialTicks, fov);
        }
    }
 
    private float calculateHudFov(float partialTicks) {
        return this.modifyFovBasedOnDeathOrFluid(partialTicks, 70.0F);
    }
 
    private float modifyFovBasedOnDeathOrFluid(float partialTicks, float fov) {
        if (this.entity instanceof LivingEntity cameraEntity && cameraEntity.isDeadOrDying()) {
            float duration = Math.min(cameraEntity.deathTime + partialTicks, 20.0F);
            fov /= (1.0F - 500.0F / (duration + 500.0F)) * 2.0F + 1.0F;
        }
 
        FogType state = this.getFluidInCamera();
        if (state == FogType.LAVA || state == FogType.WATER) {
            float effectScale = this.minecraft.options.fovEffectScale().get().floatValue();
            fov *= Mth.lerp(effectScale, 1.0F, 0.85714287F);
        }
 
        return fov;
    }
 
    private void alignWithEntity(float partialTicks) {
        if (this.entity.isPassenger()
            && this.entity.getVehicle() instanceof Minecart minecart
            && minecart.getBehavior() instanceof NewMinecartBehavior behavior
            && behavior.cartHasPosRotLerp()) {
            Vec3 positionOffset = minecart.getPassengerRidingPosition(this.entity)
                .subtract(minecart.position())
                .subtract(this.entity.getVehicleAttachmentPoint(minecart))
                .add(new Vec3(0.0, Mth.lerp(partialTicks, this.eyeHeightOld, this.eyeHeight), 0.0));
            this.setRotation(this.entity.getViewYRot(partialTicks), this.entity.getViewXRot(partialTicks));
            this.setPosition(behavior.getCartLerpPosition(partialTicks).add(positionOffset));
        } else {
            this.setRotation(this.entity.getViewYRot(partialTicks), this.entity.getViewXRot(partialTicks));
            this.setPosition(
                Mth.lerp((double)partialTicks, this.entity.xo, this.entity.getX()),
                Mth.lerp((double)partialTicks, this.entity.yo, this.entity.getY()) + Mth.lerp(partialTicks, this.eyeHeightOld, this.eyeHeight),
                Mth.lerp((double)partialTicks, this.entity.zo, this.entity.getZ())
            );
        }
 
        this.detached = !this.minecraft.options.getCameraType().isFirstPerson();
        if (this.detached) {
            if (this.minecraft.options.getCameraType().isMirrored()) {
                this.setRotation(this.yRot + 180.0F, -this.xRot);
            }
 
            float cameraDistance = 4.0F;
            float cameraScale = 1.0F;
            if (this.entity instanceof LivingEntity living) {
                cameraScale = living.getScale();
                cameraDistance = (float)living.getAttributeValue(Attributes.CAMERA_DISTANCE);
            }
 
            float mountScale = cameraScale;
            float mountDistance = cameraDistance;
            if (this.entity.isPassenger() && this.entity.getVehicle() instanceof LivingEntity mount) {
                mountScale = mount.getScale();
                mountDistance = (float)mount.getAttributeValue(Attributes.CAMERA_DISTANCE);
            }
 
            this.move(-this.getMaxZoom(Math.max(cameraScale * cameraDistance, mountScale * mountDistance)), 0.0F, 0.0F);
        } else if (this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isSleeping()) {
            Direction bedOrientation = ((LivingEntity)this.entity).getBedOrientation();
            this.setRotation(bedOrientation != null ? bedOrientation.toYRot() - 180.0F : 0.0F, 0.0F);
            this.move(0.0F, 0.3F, 0.0F);
        }
    }
 
    private float getMaxZoom(float cameraDist) {
        float jitterScale = 0.1F;
 
        for (int i = 0; i < 8; i++) {
            float offsetX = (i & 1) * 2 - 1;
            float offsetY = (i >> 1 & 1) * 2 - 1;
            float offsetZ = (i >> 2 & 1) * 2 - 1;
            Vec3 from = this.position.add(offsetX * 0.1F, offsetY * 0.1F, offsetZ * 0.1F);
            Vec3 to = from.add(new Vec3(this.forwards).scale(-cameraDist));
            HitResult hitResult = this.level.clip(new ClipContext(from, to, ClipContext.Block.VISUAL, ClipContext.Fluid.NONE, this.entity));
            if (hitResult.getType() != HitResult.Type.MISS) {
                float distSq = (float)hitResult.getLocation().distanceToSqr(this.position);
                if (distSq < Mth.square(cameraDist)) {
                    cameraDist = Mth.sqrt(distSq);
                }
            }
        }
 
        return cameraDist;
    }
 
    public boolean isPanoramicMode() {
        return this.isPanoramicMode;
    }
 
    public float getFov() {
        return this.fov;
    }
 
    private void setupPerspective(float zNear, float zFar, float fov, float width, float height) {
        this.projection.setupPerspective(zNear, zFar, fov, width, height);
    }
 
    private void setupOrtho(float zNear, float zFar, float width, float height, boolean invertY) {
        this.projection.setupOrtho(zNear, zFar, width, height, invertY);
    }
 
    protected void move(float forwards, float up, float right) {
        Vector3f offset = new Vector3f(right, up, -forwards).rotate(this.rotation);
        this.setPosition(new Vec3(this.position.x + offset.x, this.position.y + offset.y, this.position.z + offset.z));
    }
 
    protected void setRotation(float yRot, float xRot) {
        this.xRot = xRot;
        this.yRot = yRot;
        this.rotation.rotationYXZ((float) Math.PI - yRot * (float) (Math.PI / 180.0), -xRot * (float) (Math.PI / 180.0), 0.0F);
        FORWARDS.rotate(this.rotation, this.forwards);
        UP.rotate(this.rotation, this.up);
        LEFT.rotate(this.rotation, this.left);
        this.matrixPropertiesDirty |= 3;
    }
 
    protected void setPosition(double x, double y, double z) {
        this.setPosition(new Vec3(x, y, z));
    }
 
    protected void setPosition(Vec3 position) {
        this.position = position;
        this.blockPosition.set(position.x, position.y, position.z);
    }
 
    @Override
    public Vec3 position() {
        return this.position;
    }
 
    public BlockPos blockPosition() {
        return this.blockPosition;
    }
 
    public float xRot() {
        return this.xRot;
    }
 
    public float yRot() {
        return this.yRot;
    }
 
    @Override
    public float yaw() {
        return Mth.wrapDegrees(this.yRot());
    }
 
    public Quaternionf rotation() {
        return this.rotation;
    }
 
    public Matrix4f getViewRotationMatrix(Matrix4f dest) {
        if ((this.matrixPropertiesDirty & 1) != 0) {
            Quaternionf inverseRotation = this.rotation().conjugate(new Quaternionf());
            this.cachedViewRotMatrix.rotation(inverseRotation);
            this.matrixPropertiesDirty &= -2;
        }
 
        return dest.set(this.cachedViewRotMatrix);
    }
 
    public Matrix4f getViewRotationProjectionMatrix(Matrix4f dest) {
        long projectionVersion = this.projection.getMatrixVersion();
        if ((this.matrixPropertiesDirty & 2) != 0 || this.lastProjectionVersion != this.projection.getMatrixVersion()) {
            this.getViewRotationMatrix(this.cachedViewRotMatrix);
            this.projection.getMatrix(this.cachedViewRotProjMatrix);
            this.cachedViewRotProjMatrix.mul(this.cachedViewRotMatrix);
            this.matrixPropertiesDirty &= -3;
            this.lastProjectionVersion = projectionVersion;
        }
 
        return dest.set(this.cachedViewRotProjMatrix);
    }
 
    public @Nullable Entity entity() {
        return this.entity;
    }
 
    public void setEntity(Entity entity) {
        this.entity = entity;
    }
 
    public boolean isInitialized() {
        return this.initialized;
    }
 
    public boolean isDetached() {
        return this.detached;
    }
 
    public EnvironmentAttributeProbe attributeProbe() {
        return this.attributeProbe;
    }
 
    public Camera.NearPlane getNearPlane(float fov) {
        double aspectRatio = (double)this.projection.width() / this.projection.height();
        double planeHeight = Math.tan(fov * (float) (Math.PI / 180.0) / 2.0) * this.projection.zNear();
        double planeWidth = planeHeight * aspectRatio;
        Vec3 forwardsVec3 = new Vec3(this.forwards).scale(this.projection.zNear());
        Vec3 leftVec3 = new Vec3(this.left).scale(planeWidth);
        Vec3 upVec3 = new Vec3(this.up).scale(planeHeight);
        return new Camera.NearPlane(forwardsVec3, leftVec3, upVec3);
    }
 
    public FogType getFluidInCamera() {
        if (!this.initialized) {
            return FogType.NONE;
        } else {
            FluidState fluidState1 = this.level.getFluidState(this.blockPosition);
            if (fluidState1.is(FluidTags.WATER) && this.position.y < this.blockPosition.getY() + fluidState1.getHeight(this.level, this.blockPosition)) {
                return FogType.WATER;
            } else {
                Camera.NearPlane plane = this.getNearPlane(this.minecraft.options.fov().get().intValue());
 
                for (Vec3 point : Arrays.asList(plane.forward, plane.getTopLeft(), plane.getTopRight(), plane.getBottomLeft(), plane.getBottomRight())) {
                    Vec3 offsetPos = this.position.add(point);
                    BlockPos checkPos = BlockPos.containing(offsetPos);
                    FluidState fluidState = this.level.getFluidState(checkPos);
                    if (fluidState.is(FluidTags.LAVA)) {
                        if (offsetPos.y <= fluidState.getHeight(this.level, checkPos) + checkPos.getY()) {
                            return FogType.LAVA;
                        }
                    } else {
                        BlockState state = this.level.getBlockState(checkPos);
                        if (state.is(Blocks.POWDER_SNOW)) {
                            return FogType.POWDER_SNOW;
                        }
                    }
                }
 
                return FogType.NONE;
            }
        }
    }
 
    public Vector3fc forwardVector() {
        return this.forwards;
    }
 
    public Vector3fc panoramicForwards() {
        return this.panoramicForwards;
    }
 
    public Vector3fc upVector() {
        return this.up;
    }
 
    public Vector3fc leftVector() {
        return this.left;
    }
 
    public void reset() {
        this.level = null;
        this.entity = null;
        this.attributeProbe.reset();
        this.initialized = false;
    }
 
    public void setLevel(@Nullable ClientLevel level) {
        this.level = level;
    }
 
    public void enablePanoramicMode() {
        this.isPanoramicMode = true;
        this.panoramicForwards.set(this.forwards);
    }
 
    public void disablePanoramicMode() {
        this.isPanoramicMode = false;
    }
 
    @OnlyIn(Dist.CLIENT)
    public static class NearPlane {
        private final Vec3 forward;
        private final Vec3 left;
        private final Vec3 up;
 
        private NearPlane(Vec3 forward, Vec3 left, Vec3 up) {
            this.forward = forward;
            this.left = left;
            this.up = up;
        }
 
        public Vec3 getTopLeft() {
            return this.forward.add(this.up).add(this.left);
        }
 
        public Vec3 getTopRight() {
            return this.forward.add(this.up).subtract(this.left);
        }
 
        public Vec3 getBottomLeft() {
            return this.forward.subtract(this.up).add(this.left);
        }
 
        public Vec3 getBottomRight() {
            return this.forward.subtract(this.up).subtract(this.left);
        }
 
        public Vec3 getPointOnPlane(float x, float y) {
            return this.forward.add(this.up.scale(y)).subtract(this.left.scale(x));
        }
    }
}

引用的其他类

  • RenderSystem

    • 引用位置: 方法调用
    • 关联成员: RenderSystem.getDevice()
  • DeltaTracker

    • 引用位置: 参数
  • Minecraft

    • 引用位置: 字段/方法调用
    • 关联成员: Minecraft.getInstance()
  • ClientLevel

    • 引用位置: 参数
  • Projection

    • 引用位置: 字段/构造调用
    • 关联成员: Projection()
  • Frustum

    • 引用位置: 字段/构造调用/返回值
    • 关联成员: Frustum()
  • CameraRenderState

    • 引用位置: 参数
  • BlockPos

    • 引用位置: 字段/方法调用/构造调用/返回值
    • 关联成员: BlockPos.MutableBlockPos(), BlockPos.containing(), MutableBlockPos()
  • Mth

    • 引用位置: 方法调用
    • 关联成员: Mth.clamp(), Mth.lerp(), Mth.sqrt(), Mth.square(), Mth.wrapDegrees()
  • EnvironmentAttributeProbe

    • 引用位置: 字段/构造调用/返回值
    • 关联成员: EnvironmentAttributeProbe()
  • Entity

    • 引用位置: 参数/字段/返回值
  • ClipContext

    • 引用位置: 构造调用
    • 关联成员: ClipContext()
  • Level

    • 引用位置: 字段
  • FogType

    • 引用位置: 返回值
  • Vec3

    • 引用位置: 参数/字段/构造调用/返回值
    • 关联成员: Vec3()
  • TrackedWaypoint

    • 引用位置: 实现