Skip to main content

vec3

Function vec3 

Source
pub const fn vec3(x: f32, y: f32, z: f32) -> Vec3
Expand description

Shorthand Vec3 constructor.

Examples found in repository?
examples/chat/welcome.rs (line 553)
540fn axis_hit(origin: Vec3, direction: Vec3) -> (f32, bool, Vec3) {
541	let quadratic = direction.x * direction.x + direction.z * direction.z;
542	let linear = 2.0 * (origin.x * direction.x + origin.z * direction.z);
543	let constant = origin.x * origin.x + origin.z * origin.z - AXIS_RADIUS * AXIS_RADIUS;
544	let discriminant = linear * linear - 4.0 * quadratic * constant;
545	let root = (-linear - discriminant.max(0.0).sqrt()) / (2.0 * quadratic).max(1e-8);
546	let hit_y = origin.y + direction.y * root;
547	let cylinder = if discriminant >= 0.0 && root > 0.0 && (AXIS_BOTTOM..=AXIS_TOP).contains(&hit_y)
548	{
549		root
550	} else {
551		f32::INFINITY
552	};
553	let cap_center = vec3(0.0, AXIS_TOP, 0.0);
554	let cap = sphere_depth(origin, direction, cap_center, AXIS_RADIUS * 1.75);
555	let depth = cylinder.min(cap);
556	if !depth.is_finite() {
557		return (f32::INFINITY, false, vec3(0.0, 1.0, 0.0));
558	}
559	let point = origin + direction * depth;
560	let normal = if cap < cylinder {
561		(point - cap_center).normalize()
562	} else {
563		vec3(point.x, 0.0, point.z).normalize()
564	};
565	(depth, true, normal)
566}
567
568/// Terminal display lift in linear light so braille remains legible on the
569/// dark card.
570fn tone(color: Vec3) -> Vec3 {
571	color * 1.28 + Vec3::rgb(4, 4, 4)
572}
573
574/// Per-frame scene state shared by every ray: sun direction, disk spin,
575/// glass transition, and the pointer camera offsets.
576struct Platter {
577	sun:        Vec3,
578	angle:      f32,
579	transition: f32,
580	/// Smoothed pointer camera from [`Welcome`]: (lift, yaw).
581	pointer:    (f32, f32),
582}
583
584impl Platter {
585	fn new(pointer: (f32, f32)) -> Self {
586		Self { sun: vec3(-0.55, 1.0, 0.38).normalize(), angle: 0.0, transition: 0.0, pointer }
587	}
588
589	/// Floor glow: light shafts, the disk's shadow, tinted transmission
590	/// through the glass, and a soft rim reflection.
591	fn ground(&self, origin: Vec3, direction: Vec3) -> (Vec3, f32) {
592		if direction.y >= 0.0 {
593			return (BACKGROUND, 0.0);
594		}
595		let depth = (FLOOR_Y - origin.y) / direction.y;
596		if depth <= 0.0 {
597			return (BACKGROUND, 0.0);
598		}
599		let floor = origin + direction * depth;
600		let stage =
601			(-0.42 * ((floor.x.abs() / 2.30).powi(4) + ((floor.z + 0.15).abs() / 1.70).powi(4))).exp();
602
603		let sun_depth = (DISK_Y - DISK_HALF_THICKNESS - FLOOR_Y) / self.sun.y;
604		let sunlit = floor + self.sun * sun_depth;
605		let shadow_radius = sunlit.x.hypot(sunlit.z);
606		let occlusion = smooth(((DISK_RADIUS + 0.08 - shadow_radius) / 0.16).clamp(0.0, 1.0));
607		let rays = sun_rays(floor.x, floor.z);
608
609		let neutral_alpha = stage * rays * (1.0 - occlusion) * 0.36;
610		let neutral = (BACKGROUND + vec3(0.36, 0.33, 0.27) * (stage * rays)).clamp01();
611		let mut color = neutral * neutral_alpha + BACKGROUND * (1.0 - neutral_alpha);
612		let mut alpha = neutral_alpha;
613
614		let transmission_alpha =
615			stage * sun_rays(sunlit.x, sunlit.z) * occlusion * self.transition * 0.64;
616		let transmission =
617			(BACKGROUND + gradient(sunlit.z.atan2(sunlit.x) - self.angle) * 0.86).clamp01();
618		color = transmission * transmission_alpha + color * (1.0 - transmission_alpha);
619		alpha = transmission_alpha + alpha * (1.0 - transmission_alpha);
620
621		let mirrored = vec3(direction.x, -direction.y, direction.z);
622		let reflected_depth = (DISK_Y - DISK_HALF_THICKNESS - FLOOR_Y) / mirrored.y.max(1e-6);
623		let reflected = floor + mirrored * reflected_depth;
624		let reflected_radius = reflected.x.hypot(reflected.z);
625		if reflected_radius <= DISK_RADIUS {
626			let edge = smooth(((DISK_RADIUS - reflected_radius) / 0.13).clamp(0.0, 1.0));
627			let grazing = (1.0 + direction.y).clamp(0.0, 1.0);
628			let reflection_alpha = self.transition * edge * (0.22 + 0.28 * grazing);
629			let reflection = gradient(reflected.z.atan2(reflected.x) - self.angle);
630			color = reflection * reflection_alpha + color * (1.0 - reflection_alpha);
631			alpha = reflection_alpha + alpha * (1.0 - reflection_alpha);
632		}
633		(color, alpha)
634	}
635}
636
637impl Trace for Platter {
638	fn advance(&mut self, now: Duration) -> Camera {
639		let elapsed = now.as_secs_f32();
640		self.angle = disk_rotation(elapsed);
641		self.transition = color_mix(elapsed);
642		Camera {
643			target:   vec3(0.0, 0.08, 0.0),
644			yaw:      self.pointer.1 + reveal_orbit(elapsed) + (elapsed * 0.31).sin() * 0.018,
645			pitch:    CAMERA_PITCH,
646			distance: CAMERA_DISTANCE,
647			lift:     self.pointer.0.clamp(-0.42, 0.42) + (elapsed * 0.55).sin() * 0.014,
648			focal:    CAMERA_FOCAL,
649		}
650	}