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 / common / src / entity / painting.rs

use crate::physics::Aabb;
use glam::{DVec3, Vec3};

pub struct Art {
    pub name: &'static str,
    pub size: [u16; 2],
    pub uv: [u16; 2],
}

const fn art(name: &'static str, size: [u16; 2], uv: [u16; 2]) -> Art {
    Art { name, size, uv }
}

pub const ART: &[Art] = &[
    art("Kebab", [16, 16], [0, 0]),
    art("Aztec", [16, 16], [16, 0]),
    art("Alban", [16, 16], [32, 0]),
    art("Aztec2", [16, 16], [48, 0]),
    art("Bomb", [16, 16], [64, 0]),
    art("Plant", [16, 16], [80, 0]),
    art("Wasteland", [16, 16], [96, 0]),
    art("Pool", [32, 16], [0, 32]),
    art("Courbet", [32, 16], [32, 32]),
    art("Sea", [32, 16], [64, 32]),
    art("Sunset", [32, 16], [96, 32]),
    art("Creebet", [32, 16], [128, 32]),
    art("Wanderer", [16, 32], [0, 64]),
    art("Graham", [16, 32], [16, 64]),
    art("Match", [32, 32], [0, 128]),
    art("Bust", [32, 32], [32, 128]),
    art("Stage", [32, 32], [64, 128]),
    art("Void", [32, 32], [96, 128]),
    art("SkullAndRoses", [32, 32], [128, 128]),
    art("Fighters", [64, 32], [0, 96]),
    art("Pointer", [64, 64], [0, 192]),
    art("Pigscene", [64, 64], [64, 192]),
    art("BurningSkull", [64, 64], [128, 192]),
    art("Skeleton", [64, 48], [192, 64]),
    art("DonkeyKong", [64, 48], [192, 112]),
];

#[derive(Clone, Copy, Debug)]
pub struct Painting {
    pub art: u8,
    pub anchor: [i32; 3],
    pub direction: u8,
}

impl Painting {
    pub fn from_name(name: &str, anchor: [i32; 3], direction: u8) -> Self {
        Self {
            art: ART.iter().position(|a| a.name == name).unwrap_or(0) as u8,
            anchor,
            direction: direction & 3,
        }
    }

    pub fn art(self) -> &'static Art {
        &ART[usize::from(self.art)]
    }

    pub fn position(self) -> DVec3 {
        let [width, height] = self.art().size;
        let offset = |size| if matches!(size, 32 | 64) { 0.5 } else { 0.0 };
        let (normal, side) = match self.direction {
            0 => (Vec3::NEG_Z, Vec3::NEG_X),
            1 => (Vec3::NEG_X, Vec3::Z),
            2 => (Vec3::Z, Vec3::X),
            _ => (Vec3::X, Vec3::NEG_Z),
        };
        let pos = Vec3::from_array(self.anchor.map(|v| v as f32)) + 0.5;
        let pos = pos + normal * (9.0 / 16.0) + side * offset(width) + Vec3::Y * offset(height);
        pos.as_dvec3()
    }

    pub fn bounds(self) -> Aabb {
        let [width, height] = self.art().size;
        let half = if self.direction & 1 == 0 {
            Vec3::new(f32::from(width), f32::from(height), 0.5)
        } else {
            Vec3::new(0.5, f32::from(height), f32::from(width))
        } / 32.0
            - 0.1 / 16.0;
        // Java computes each bound in float before widening to double
        let pos = self.position().as_vec3();
        Aabb::new((pos - half).as_dvec3(), (pos + half).as_dvec3())
    }
}