alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH 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
root crates client src render scene vehicles.rs
use std::f32::consts::{FRAC_PI_2, PI};
use common::entity::vehicle::{self, VehicleKind};
use common::math::sin;
use glam::{Mat3, Mat4, Vec3};
use super::{
Geometry,
models::{Model, Part},
};
use crate::entities::RemoteEntity;
impl Geometry {
pub(super) fn vehicle(
&mut self,
world: &crate::world::ClientWorld,
kind: VehicleKind,
entity: &RemoteEntity,
mut position: Vec3,
partial: f32,
brightness: f32,
) {
let boat = kind == VehicleKind::Boat;
let previous = entity.previous_animation.rotation[0];
let mut yaw = super::models::angle(previous, entity.animation.rotation[0], partial);
let mut pitch = 0.0;
let interpolated = entity.previous.lerp(entity.position, f64::from(partial));
if !boat && let Some(snap) = vehicle::rail_position(world, interpolated) {
let [ahead, behind] = [0.3_f32, -0.3].map(|offset| {
vehicle::rail_offset(world, interpolated, f64::from(offset)).unwrap_or(snap)
});
position += (snap.with_y((ahead.y + behind.y) / 2.0) - interpolated).as_vec3();
let direction = behind - ahead;
if direction.length_squared() > 0.0 {
let direction = direction.normalize();
yaw = direction.z.atan2(direction.x).to_degrees() as f32;
pitch = (direction.y.atan() * 73.0) as f32;
}
}
let pose = entity.animation.vehicle;
let hit = pose.hit as f32 - partial;
let damage = (pose.damage as f32 - partial).max(0.0);
let rock = if hit > 0.0 {
(sin(hit) * hit * damage / 10.0 * pose.direction as f32).to_radians()
} else {
0.0
};
let rotation = Mat3::from_rotation_y((180.0 - yaw).to_radians())
* Mat3::from_rotation_z(-pitch.to_radians())
* Mat3::from_rotation_x(rock);
if matches!(kind, VehicleKind::StorageCart | VehicleKind::PoweredCart) {
let block = if kind == VehicleKind::StorageCart {
common::world::Block::CHEST
} else {
common::world::Block::FURNACE
};
let content = rotation * Mat3::from_rotation_y(FRAC_PI_2);
self.cuboid(
Vec3::splat(-0.5),
Vec3::splat(0.5),
|point| {
position + rotation * Vec3::Y * (0.75 * 5.0 / 16.0) + content * point * 0.75
},
std::array::from_fn(|side| common::world::texture::inventory_face(block, 0, side)),
[brightness; 6],
);
}
let texture = crate::assets::entity_texture(if boat {
"item/boat.png"
} else {
"item/cart.png"
});
let mut model = Model {
position,
transform: rotation * Mat3::from_diagonal(Vec3::new(-1.0, -1.0, 1.0) / 16.0),
..Model::new(self, Mat4::IDENTITY, texture, brightness)
};
let (min, size, [x, z]) = if boat {
model.part(
Part::new(
[-12.0, -8.0, -3.0],
[24.0, 16.0, 4.0],
[0.0, 4.0, 0.0],
[0.0, 8.0],
)
.rotate([FRAC_PI_2, 0.0, 0.0]),
);
([-10.0, -7.0, -1.0], [20.0, 6.0, 2.0], [11.0, 9.0])
} else {
model.part(
Part::new(
[-10.0, -8.0, -1.0],
[20.0, 16.0, 2.0],
[0.0, 4.0, 0.0],
[0.0, 10.0],
)
.rotate([FRAC_PI_2, 0.0, 0.0]),
);
model.part(
Part::new(
[-9.0, -7.0, -1.0],
[18.0, 14.0, 1.0],
[0.0, 4.1, 0.0],
[44.0, 10.0],
)
.rotate([-FRAC_PI_2, 0.0, 0.0]),
);
([-8.0, -9.0, -1.0], [16.0, 8.0, 2.0], [9.0, 7.0])
};
for (pivot, yaw) in [
([-x, 4.0, 0.0], PI * 1.5),
([x, 4.0, 0.0], FRAC_PI_2),
([0.0, 4.0, -z], PI),
([0.0, 4.0, z], 0.0),
] {
model.part(Part::new(min, size, pivot, [0.0; 2]).rotate([0.0, yaw, 0.0]));
}
}
}