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 / signs.rs

//! `TileEntitySignRenderer`: sign boards and posts with their text.

use common::world::shape::BlockView;
use common::world::{Block, ChunkPos};
use glam::{DVec3, Mat4, Vec3};

use super::Geometry;
use super::models::{Model, Part};
use crate::world::ClientWorld;

const SIGN: i32 = crate::assets::entity_texture("item/sign.png");

impl Geometry {
    pub fn signs(
        &mut self,
        world: &ClientWorld,
        eye: DVec3,
        font: &crate::gui::Geometry,
        sky_darkness: u32,
    ) {
        let start = self.vertices.len() as u32;
        let center = ChunkPos::containing(
            common::math::floor_f64(eye.x),
            common::math::floor_f64(eye.z),
        );
        for ([x, y, z], lines) in world.signs_near(center, 4) {
            let origin = DVec3::new(f64::from(x), f64::from(y), f64::from(z)) + 0.5;
            // `TileEntityRenderer` only draws tile entities within 64 blocks
            if origin.distance_squared(eye) >= 4096.0 {
                continue;
            }
            let block = world.block(x, y, z);
            let metadata = world.metadata(x, y, z);
            let brightness = super::brightness_at(world, origin, sky_darkness);
            let size = 2.0_f32 / 3.0;
            let anchor = origin.with_y(f64::from(y) + 0.75 * f64::from(size));
            let mut transform = Mat4::from_translation((anchor - eye).as_vec3());
            let post = block == Block::SIGN;
            if post {
                transform *=
                    Mat4::from_rotation_y((-f32::from(metadata) * 360.0 / 16.0).to_radians());
            } else {
                let angle: f32 = match metadata {
                    2 => 180.0,
                    4 => 90.0,
                    5 => -90.0,
                    _ => 0.0,
                };
                transform *= Mat4::from_rotation_y((-angle).to_radians())
                    * Mat4::from_translation(Vec3::new(0.0, -5.0 / 16.0, -7.0 / 16.0));
            }
            let board = transform * Mat4::from_scale(Vec3::new(size, -size, -size));
            let mut model = Model::new(self, board, SIGN, brightness);
            model.transform /= 16.0;
            model.part(Part::new(
                [-12.0, -14.0, -1.0],
                [24.0, 12.0, 2.0],
                [0.0; 3],
                [0.0, 0.0],
            ));
            if post {
                model.part(Part::new(
                    [-1.0, -2.0, -1.0],
                    [2.0, 14.0, 2.0],
                    [0.0; 3],
                    [0.0, 14.0],
                ));
            }
            let scale = size / 60.0;
            let text = transform
                * Mat4::from_translation(Vec3::new(0.0, 0.5 * size, 0.07 * size))
                * Mat4::from_scale(Vec3::new(scale, -scale, scale));
            for (i, line) in lines.iter().enumerate() {
                let (glyphs, width) = font.layout(line, 0xff000000);
                let left = -(width / 2.0).floor();
                let top = i as f32 * 10.0 - lines.len() as f32 * 5.0;
                self.glyphs(glyphs, Vec3::new(left, top, 0.0), text);
            }
        }
        self.signs = start..self.vertices.len() as u32;
    }
}