1use cgmath::{Matrix3, Matrix4, One, Quaternion, Vector3, Zero};
2
3use crate::renderer;
4
5pub struct BindGroups<'a> {
6 pub camera: &'a wgpu::BindGroup,
7 pub light: &'a wgpu::BindGroup,
8 pub shadow: &'a wgpu::BindGroup,
9 pub wind: &'a wgpu::BindGroup,
10}
11
12pub trait Vertex {
13 fn desc() -> wgpu::VertexBufferLayout<'static>;
14}
15
16#[repr(C)]
17#[derive(Debug, Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)]
18pub struct ModelVertex {
19 pub position: [f32; 3],
20 pub text_cords: [f32; 2],
21 pub normal: [f32; 3],
22 pub color: [f32; 3],
23 pub tangent: [f32; 3],
24 pub bitangent: [f32; 3],
25}
26
27impl Vertex for ModelVertex {
28 fn desc() -> wgpu::VertexBufferLayout<'static> {
29 use std::mem;
30 wgpu::VertexBufferLayout {
31 array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
32 step_mode: wgpu::VertexStepMode::Vertex,
33 attributes: &[
34 wgpu::VertexAttribute {
35 offset: 0,
36 shader_location: 0,
37 format: wgpu::VertexFormat::Float32x3,
38 },
39 wgpu::VertexAttribute {
40 offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
41 shader_location: 1,
42 format: wgpu::VertexFormat::Float32x2,
43 },
44 wgpu::VertexAttribute {
45 offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
46 shader_location: 2,
47 format: wgpu::VertexFormat::Float32x3,
48 },
49 wgpu::VertexAttribute {
50 offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
51 shader_location: 3,
52 format: wgpu::VertexFormat::Float32x3,
53 },
54 wgpu::VertexAttribute {
55 offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
56 shader_location: 4,
57 format: wgpu::VertexFormat::Float32x3,
58 },
59 wgpu::VertexAttribute {
60 offset: mem::size_of::<[f32; 11]>() as wgpu::BufferAddress,
61 shader_location: 5,
62 format: wgpu::VertexFormat::Float32x3,
63 },
64 ],
65 }
66 }
67}
68
69pub trait DrawModel<'a> {
70 fn draw_mesh(
71 &mut self,
72 mesh: &'a renderer::Mesh,
73 material: &'a renderer::Material,
74 instances: std::ops::Range<u32>,
75 instance_buffer: &'a wgpu::Buffer,
76 bind_groups: BindGroups<'a>,
77 );
78
79 fn draw_model(
80 &mut self,
81 model: &'a Model,
82 camera_bind_group: &'a wgpu::BindGroup,
83 light_bind_group: &'a wgpu::BindGroup,
84 shadow_bind_group: &'a wgpu::BindGroup,
85 wind_bind_group: &'a wgpu::BindGroup,
86 );
87}
88
89impl<'a, 'b> DrawModel<'b> for wgpu::RenderPass<'a>
90where
91 'b: 'a,
92{
93 fn draw_mesh(
94 &mut self,
95 mesh: &'b renderer::Mesh,
96 material: &'b renderer::Material,
97 instances: std::ops::Range<u32>,
98 instance_buffer: &'a wgpu::Buffer,
99 bind_groups: BindGroups<'a>,
100 ) {
101 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
102 self.set_vertex_buffer(1, instance_buffer.slice(..));
103 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
104 self.set_bind_group(0, &material.bind_group, &[]);
105 self.set_bind_group(1, bind_groups.camera, &[]);
106 self.set_bind_group(2, bind_groups.light, &[]);
107 self.set_bind_group(3, bind_groups.shadow, &[]);
108 self.set_bind_group(4, bind_groups.wind, &[]);
109 self.draw_indexed(0..mesh.indices, 0, instances);
110 }
111
112 fn draw_model(
113 &mut self,
114 model: &'b Model,
115 camera_bind_group: &'b wgpu::BindGroup,
116 light_bind_group: &'a wgpu::BindGroup,
117 shadow_bind_group: &'a wgpu::BindGroup,
118 wind_bind_group: &'a wgpu::BindGroup,
119 ) {
120 for mesh in &model.meshes {
121 let material: &renderer::Material = &model.materials[mesh.material];
122 self.draw_mesh(
123 mesh,
124 material,
125 0..model.instances.len() as u32,
126 &model.instance_buffer,
127 BindGroups {
128 camera: camera_bind_group,
129 light: light_bind_group,
130 shadow: shadow_bind_group,
131 wind: wind_bind_group,
132 },
133 );
134 }
135 }
136}
137
138#[repr(C)]
139#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
140#[allow(dead_code)]
141pub struct InstanceRaw {
142 pub model: [[f32; 4]; 4],
143 pub normals: [[f32; 3]; 3],
144 pub wind_weight: f32,
145}
146
147impl InstanceRaw {
148 pub fn desc() -> wgpu::VertexBufferLayout<'static> {
149 use std::mem;
150
151 wgpu::VertexBufferLayout {
152 array_stride: mem::size_of::<InstanceRaw>() as wgpu::BufferAddress,
153 step_mode: wgpu::VertexStepMode::Instance,
154 attributes: &[
155 wgpu::VertexAttribute {
156 format: wgpu::VertexFormat::Float32x4,
157 offset: 0,
158 shader_location: 6,
159 },
160 wgpu::VertexAttribute {
161 format: wgpu::VertexFormat::Float32x4,
162 offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
163 shader_location: 7,
164 },
165 wgpu::VertexAttribute {
166 format: wgpu::VertexFormat::Float32x4,
167 offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
168 shader_location: 8,
169 },
170 wgpu::VertexAttribute {
171 format: wgpu::VertexFormat::Float32x4,
172 offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
173 shader_location: 9,
174 },
175 wgpu::VertexAttribute {
176 format: wgpu::VertexFormat::Float32x3,
177 offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress,
178 shader_location: 10,
179 },
180 wgpu::VertexAttribute {
181 format: wgpu::VertexFormat::Float32x3,
182 offset: mem::size_of::<[f32; 19]>() as wgpu::BufferAddress,
183 shader_location: 11,
184 },
185 wgpu::VertexAttribute {
186 format: wgpu::VertexFormat::Float32x3,
187 offset: mem::size_of::<[f32; 22]>() as wgpu::BufferAddress,
188 shader_location: 12,
189 },
190 wgpu::VertexAttribute {
191 format: wgpu::VertexFormat::Float32,
192 offset: mem::size_of::<[f32; 25]>() as wgpu::BufferAddress,
193 shader_location: 13,
194 },
195 ],
196 }
197 }
198}
199
200pub struct Instance {
201 pub position: cgmath::Vector3<f32>,
202 pub rotation: cgmath::Quaternion<f32>,
203 pub scale: cgmath::Vector3<f32>,
204 pub wind_weight: f32,
205}
206
207impl Instance {
208 pub fn new(
209 position: cgmath::Vector3<f32>,
210 rotation: cgmath::Quaternion<f32>,
211 scale: cgmath::Vector3<f32>,
212 ) -> Self {
213 Self {
214 position,
215 rotation,
216 scale,
217 wind_weight: 0.0,
218 }
219 }
220
221 pub fn with_wind(mut self, weight: f32) -> Self {
222 self.wind_weight = weight;
223 self
224 }
225
226 pub fn to_raw(&self) -> InstanceRaw {
227 let translation: Matrix4<f32> = cgmath::Matrix4::from_translation(self.position);
228 let rotation: Matrix4<f32> = cgmath::Matrix4::from(self.rotation);
229 let scale: Matrix4<f32> =
230 cgmath::Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z);
231
232 let normals: Matrix3<f32> = cgmath::Matrix3::from(self.rotation);
233
234 InstanceRaw {
235 model: (translation * rotation * scale).into(),
236 normals: normals.into(),
237 wind_weight: self.wind_weight,
238 }
239 }
240}
241
242impl Default for Instance {
243 fn default() -> Self {
244 Self {
245 position: Vector3::zero(),
246 rotation: Quaternion::one(),
247 scale: Vector3::new(1.0, 1.0, 1.0),
248 wind_weight: 0.0,
249 }
250 }
251}
252
253pub trait DrawLight<'a> {
254 fn draw_light_model(
255 &mut self,
256 model: &'a Model,
257 camera_bind_group: &'a wgpu::BindGroup,
258 light_bind_group: &'a wgpu::BindGroup,
259 );
260}
261
262impl<'a, 'b> DrawLight<'b> for wgpu::RenderPass<'a>
263where
264 'b: 'a,
265{
266 fn draw_light_model(
267 &mut self,
268 model: &'a Model,
269 camera_bind_group: &'b wgpu::BindGroup,
270 light_bind_group: &'b wgpu::BindGroup,
271 ) {
272 for mesh in &model.meshes {
273 let material: &renderer::Material = &model.materials[mesh.material];
274 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
275 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
276 self.set_bind_group(0, camera_bind_group, &[]);
277 self.set_bind_group(1, light_bind_group, &[]);
278 self.set_bind_group(2, &material.bind_group, &[]);
279 self.draw_indexed(0..mesh.indices, 0, 0..1);
280 }
281 }
282}
283
284pub trait DrawShadow<'a> {
285 fn draw_shadow_model(&mut self, model: &'a Model, light_bind_group: &'a wgpu::BindGroup);
286}
287
288impl<'a, 'b> DrawShadow<'b> for wgpu::RenderPass<'a>
289where
290 'b: 'a,
291{
292 fn draw_shadow_model(&mut self, model: &'a Model, light_bind_group: &'b wgpu::BindGroup) {
293 for mesh in &model.meshes {
294 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
295 self.set_vertex_buffer(1, model.instance_buffer.slice(..));
296 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
297 self.set_bind_group(0, light_bind_group, &[]);
298 self.draw_indexed(0..mesh.indices, 0, 0..model.instances.len() as u32);
299 }
300 }
301}
302
303pub struct Model {
304 pub meshes: Vec<renderer::Mesh>,
305 pub materials: Vec<renderer::Material>,
306 pub instances: Vec<Instance>,
307 pub instance_buffer: wgpu::Buffer,
308 pub type_model: TypeModel,
309}
310
311pub struct ModelDesc {
312 pub file_name: &'static str,
313 pub instances: Vec<Instance>,
314 pub kind: TypeModel,
315}
316
317impl ModelDesc {
318 pub fn new(file_name: &'static str, instances: Vec<Instance>, kind: TypeModel) -> Self {
319 Self {
320 file_name,
321 instances,
322 kind,
323 }
324 }
325}
326
327#[derive(Clone)]
328pub enum TypeModel {
329 StaticObj,
330 PointOfLight,
331}