1use image::io::Reader as ImageReader;
2use nalgebra::{Matrix4, Vector3};
3use rapier3d::math::Point;
4use wgpu::util::{DeviceExt, TextureDataOrder};
5
6use crate::renderer::core::Vertex;
7
8use crate::renderer::Transform::{matrix4_to_raw_array, Transform};
9
10use crate::renderer::core::LandscapeData;
11
12pub struct Landscape {
13 pub transform: Transform,
14 pub vertex_buffer: wgpu::Buffer,
15 pub index_buffer: wgpu::Buffer,
16 pub index_count: u32,
17 pub bind_group: wgpu::BindGroup,
18 pub texture_bind_group: wgpu::BindGroup,
19}
20
21impl Landscape {
22 pub fn new(
23 data: &LandscapeData,
24 device: &wgpu::Device,
25 queue: &wgpu::Queue,
26 bind_group_layout: &wgpu::BindGroupLayout,
27 texture_bind_group_layout: &wgpu::BindGroupLayout,
28 color_render_mode_buffer: &wgpu::Buffer,
29 ) -> Self {
30 let scale = 1.0;
61 let (vertices, indices, rapier_vertices) = Self::generate_terrain(data, scale);
62
63 let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
64 label: Some("Landscape Vertex Buffer"),
65 contents: bytemuck::cast_slice(&vertices),
66 usage: wgpu::BufferUsages::VERTEX,
67 });
68
69 let index_buffer: wgpu::Buffer =
70 device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
71 label: Some("Landscape Index Buffer"),
72 contents: bytemuck::cast_slice(&indices),
73 usage: wgpu::BufferUsages::INDEX,
74 });
75
76 let empty_buffer = Matrix4::<f32>::identity();
78 let raw_matrix = matrix4_to_raw_array(&empty_buffer);
79
80 let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
81 label: Some("Model GLB Uniform Buffer"),
82 contents: bytemuck::cast_slice(&raw_matrix),
83 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
84 });
85
86 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
87 layout: &bind_group_layout,
88 entries: &[wgpu::BindGroupEntry {
89 binding: 0,
90 resource: uniform_buffer.as_entire_binding(),
91 }],
92 label: None,
93 });
94
95 let default_texture = device.create_texture(&wgpu::TextureDescriptor {
98 label: Some("Default Empty Texture"),
99 size: wgpu::Extent3d {
100 width: 1,
101 height: 1,
102 depth_or_array_layers: 1,
103 },
104 mip_level_count: 1,
105 sample_count: 1,
106 dimension: wgpu::TextureDimension::D2,
107 format: wgpu::TextureFormat::Rgba8UnormSrgb,
108 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
109 view_formats: &[],
110 });
111
112 let default_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
113 address_mode_u: wgpu::AddressMode::ClampToEdge,
114 address_mode_v: wgpu::AddressMode::ClampToEdge,
115 address_mode_w: wgpu::AddressMode::ClampToEdge,
116 mag_filter: wgpu::FilterMode::Linear,
117 min_filter: wgpu::FilterMode::Linear,
118 mipmap_filter: wgpu::FilterMode::Nearest,
119 ..Default::default()
120 });
121
122 let default_texture_view =
123 default_texture.create_view(&wgpu::TextureViewDescriptor::default());
124
125 let texture_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
127 layout: &texture_bind_group_layout,
128 entries: &[
129 wgpu::BindGroupEntry {
130 binding: 0,
131 resource: wgpu::BindingResource::TextureView(&default_texture_view),
132 },
133 wgpu::BindGroupEntry {
134 binding: 1,
135 resource: wgpu::BindingResource::Sampler(&default_sampler),
136 },
137 wgpu::BindGroupEntry {
138 binding: 2,
139 resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
140 buffer: color_render_mode_buffer,
141 offset: 0,
142 size: None,
143 }),
144 },
145 ],
146 label: None,
147 });
148
149 Self {
150 index_count: indices.len() as u32,
151 vertex_buffer,
152 index_buffer,
153 bind_group,
154 texture_bind_group,
155 transform: Transform::new(
156 Vector3::new(0.0, 0.0, 0.0),
157 Vector3::new(0.0, 0.0, 0.0),
158 Vector3::new(1.0, 1.0, 1.0),
159 uniform_buffer,
160 ),
161 }
162 }
163
164 pub fn generate_terrain(
166 data: &LandscapeData,
167 scale: f32,
168 ) -> (Vec<Vertex>, Vec<u32>, Vec<Point<f32>>) {
169 let mut vertices = Vec::with_capacity(data.width * data.height);
172 let mut rapier_vertices = Vec::with_capacity(data.width * data.height);
173 let mut indices = Vec::new();
174
175 for y in 0..data.height {
176 for x in 0..data.width {
177 vertices.push(Vertex {
186 position: data.pixel_data[y][x].position,
187 normal: [0.0, 0.0, 0.0],
188 tex_coords: data.pixel_data[y][x].tex_coords,
189 color: [1.0, 1.0, 1.0],
190 });
191 rapier_vertices.push(Point::new(
192 data.pixel_data[y][x].position[0],
193 data.pixel_data[y][x].position[1],
194 data.pixel_data[y][x].position[2],
195 ));
196 }
197 }
198
199 for y in 0..(data.height - 1) {
200 for x in 0..(data.width - 1) {
201 let top_left = (y * data.width + x) as u32;
202 let top_right = top_left + 1;
203 let bottom_left = top_left + data.width as u32;
204 let bottom_right = bottom_left + 1;
205
206 indices.push(top_left);
218 indices.push(top_right);
219 indices.push(bottom_right);
220
221 indices.push(bottom_right);
222 indices.push(bottom_left);
223 indices.push(top_left);
224 }
225 }
226
227 (vertices, indices, rapier_vertices)
228 }
229}