extrude_custom/
extrude_custom.rs1use std::f64::consts::PI;
5
6use glam::{DVec2, DVec3};
7use lerp::Lerp;
8use lib_curveball::curve::CurveResult;
9use lib_curveball::curve::extrude::path::Path;
10use lib_curveball::curve::extrude::profile::Profile;
11use lib_curveball::curve::extrude::{FrenetFrame, ProfileOrientation, extrude};
12use lib_curveball::map::{
13 entity::SimpleWorldspawn,
14 geometry::Brush,
15 qmap::{QEntity, QMap},
16};
17
18fn brushes_to_string(brushes: Vec<Brush>) -> CurveResult<String> {
21 let simple_worldspawn = SimpleWorldspawn::new(brushes);
22 let entity = QEntity::from(simple_worldspawn);
23 let map = QMap::new(vec![entity]).with_tb_neverball_metadata();
24 Ok(String::from(format!("{map}")))
25}
26
27#[derive(Debug, Clone)]
46pub struct MyRevolve {
47 radius: f64,
48 start_angle_rad: f64,
49 end_angle_rad: f64,
50}
51
52impl MyRevolve {
53 pub fn new(radius: f64, start_angle: f64, end_angle: f64) -> Self {
54 Self {
55 radius,
56 start_angle_rad: start_angle * PI / 180.0,
57 end_angle_rad: end_angle * PI / 180.0,
58 }
59 }
60}
61
62impl Path for MyRevolve {
63 fn point(&self, t: f64) -> DVec3 {
64 let theta = self.start_angle_rad.lerp(self.end_angle_rad, t);
65 DVec3 {
66 x: self.radius * theta.cos(),
67 y: self.radius * theta.sin(),
68 z: 0.0,
69 }
70 }
71 fn frame(&self, t: f64) -> FrenetFrame {
72 let theta = self.start_angle_rad.lerp(self.end_angle_rad, t);
73 FrenetFrame {
74 tangent: DVec3 {
75 x: -theta.sin(),
76 y: theta.cos(),
77 z: 0.0,
78 },
79 normal: DVec3 {
80 x: -theta.cos(),
81 y: -theta.sin(),
82 z: 0.0,
83 },
84 binormal: DVec3 {
85 x: 0.0,
86 y: 0.0,
87 z: 1.0,
88 },
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
113pub struct MyRectangle {
114 width: f64,
115 height: f64,
116}
117
118impl MyRectangle {
119 pub fn new(width: f64, height: f64) -> MyRectangle {
120 Self { width, height }
121 }
122}
123
124impl Profile for MyRectangle {
125 fn profile(&self, _t: f64) -> Vec<DVec2> {
126 vec![
127 DVec2 {
128 x: self.width / 2.0,
129 y: self.height / 2.0,
130 },
131 DVec2 {
132 x: self.width / 2.0,
133 y: -self.height / 2.0,
134 },
135 DVec2 {
136 x: -self.width / 2.0,
137 y: self.height / 2.0,
138 },
139 DVec2 {
140 x: -self.width / 2.0,
141 y: -self.height / 2.0,
142 },
143 ]
144 }
145}
146
147fn main() {
150 let width = 32.0;
152 let height = 8.0;
153 let rectangle_profile = MyRectangle::new(width, height);
154
155 let radius = 128.0;
157 let start_angle = 0.0;
158 let end_angle = 180.0;
159 let revolve_profile = MyRevolve::new(radius, start_angle, end_angle);
160
161 let num_segments = 12;
163 let profile_orientation = ProfileOrientation::FollowPath;
164 let brushes = extrude(
165 num_segments,
166 &rectangle_profile,
167 &revolve_profile,
168 profile_orientation,
169 )
170 .unwrap();
171
172 let string = brushes_to_string(brushes).unwrap();
174 println!("{}", string);
175}