Theme

alex/beta-minecraft-rust

Minecraft Beta 1.7.3 Rewrite

BRANCH main
main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
Download file

root / crates / client / src / render / scene / fishing.rs

use common::entity::Entity;
use common::math::{cos, sin};
use glam::{Mat3, Vec3};

use super::{Geometry, Vertex};
use crate::entities::{Entities, Kind};
use crate::player::LocalPlayer;

impl Geometry {
    pub(super) fn hook(&mut self, relative: Vec3, billboard: &Mat3) {
        let points = [
            Vec3::new(-0.25, 0.25, 0.0),
            Vec3::new(0.25, 0.25, 0.0),
            Vec3::new(0.25, -0.25, 0.0),
            Vec3::new(-0.25, -0.25, 0.0),
        ]
        .map(|p| relative + billboard * p);
        self.quad(
            points,
            [1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0, 1.0 / 16.0],
            crate::assets::entity_texture("particles.png"),
            0xffffffff,
        );
    }

    pub(super) fn fishing_lines(
        &mut self,
        entities: &Entities,
        player: &LocalPlayer,
        partial: f32,
    ) {
        for hook in entities.0.values() {
            let Kind::Hook(Some(owner)) = hook.kind else {
                continue;
            };
            let local = owner == player.entity.id;
            let Some(angler) = (if local {
                Some(&player.entity)
            } else {
                entities
                    .0
                    .get(&owner)
                    .and_then(|e| e.player.as_ref())
                    .map(|p| &p.entity)
            }) else {
                continue;
            };
            let start = hook.previous.lerp(hook.position, f64::from(partial)) - player.eye(partial);
            let end = rod_tip(angler, partial, player.third_person || !local) - player.eye(partial);
            let delta = (end - start).as_vec3() - Vec3::Y * 0.25;
            let start = start.as_vec3();
            let point = |i: u32| {
                let t = i as f32 / 16.0;
                start + Vec3::new(delta.x * t, delta.y * (t * t + t) * 0.5 + 0.25, delta.z * t)
            };
            for segment in 0..16 {
                for position in [point(segment), point(segment + 1)] {
                    self.vertices.push(Vertex {
                        position: position.to_array(),
                        uv: [0.0; 2],
                        color: 0xff000000,
                        texture: -1,
                    });
                }
            }
        }
    }
}

fn rod_tip(entity: &Entity, partial: f32, third_person: bool) -> glam::DVec3 {
    let yaw = super::lerp(entity.prev_yaw, entity.yaw, partial);
    let pitch = super::lerp(entity.prev_pitch, entity.pitch, partial);
    let pos = entity.prev_pos.lerp(entity.pos, f64::from(partial));
    if third_person {
        let body = entity
            .living
            .as_ref()
            .map_or(yaw, |l| {
                super::lerp(l.prev_render_yaw_offset, l.render_yaw_offset, partial)
            })
            .to_radians();
        pos + glam::DVec3::new(
            -f64::from(cos(body)) * 0.35 - f64::from(sin(body)) * 0.85,
            // `posY`: the local player's eyes, other players' feet
            -0.45,
            -f64::from(sin(body)) * 0.35 + f64::from(cos(body)) * 0.85,
        )
    } else {
        let living = entity.living.as_ref();
        let swing = living.map_or(0.0, |l| super::swing(l, partial));
        let wave = sin(swing.sqrt() * std::f32::consts::PI);
        let rotation = Mat3::from_rotation_x(wave * 0.7)
            * Mat3::from_rotation_y(wave * 0.5)
            * Mat3::from_rotation_y(-yaw.to_radians())
            * Mat3::from_rotation_x(pitch.to_radians());
        pos + (rotation * Vec3::new(-0.5, 0.03, 0.8)).as_dvec3()
    }
}