/* wearechat - generic multiplayer game with voip Copyright (C) 2025 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use super::{meshops::{generate_normals, generate_tangents, generate_texcoords}, ScenePreparer}; use anyhow::Result; use log::debug; use std::{sync::Arc, time::Instant}; use wgpu::{ BufferUsages, util::{BufferInitDescriptor, DeviceExt}, }; impl ScenePreparer { pub fn update_vertex_buffers(&self, num_done: &mut usize) -> Result<()> { for pres in self.index_buffers.needed() { let start = Instant::now(); if let Some(buf) = self.downloader.try_get(pres.clone())? { let buffer = self.device.create_buffer_init(&BufferInitDescriptor { label: Some("index"), contents: bytemuck::cast_slice(buf.as_slice()), usage: BufferUsages::INDEX | BufferUsages::COPY_DST, }); self.index_buffers.insert( pres.clone(), (Arc::new(buffer), (buf.len() * 3) as u32), buf.len() * size_of::() * 3, ); debug!( "index buffer created (len={}, took {:?}) {pres}", buf.len() / size_of::(), start.elapsed(), ); *num_done += 1; } } for pres in self.vertex_buffers.needed() { let start = Instant::now(); if let Some(buf) = self.downloader.try_get(pres.clone())? { let buffer = self.device.create_buffer_init(&BufferInitDescriptor { contents: bytemuck::cast_slice(buf.as_slice()), label: Some("vertex attribute"), usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, }); self.vertex_buffers.insert( pres.clone(), Arc::new(buffer), buf.len() * size_of::(), ); debug!( "vertex attribute buffer created (len={}, took {:?}) {pres}", buf.len() / size_of::(), start.elapsed() ); *num_done += 1; } } for spec in self.generated_tangent_buffers.needed() { if let (Some(index), Some(position), texcoord) = ( self.downloader.try_get(spec.index.clone())?, self.downloader.try_get(spec.position.clone())?, spec.texcoord .clone() .map(|r| self.downloader.try_get(r)) .transpose()?, ) { let texcoord = match texcoord { Some(Some(x)) => Some(x), Some(None) => continue, // tangents provided but still loading None => None, }; let texcoord = texcoord.unwrap_or_else(|| generate_texcoords(&index, &position)); let tangents = generate_tangents(&index, &position, &texcoord); let buffer = self.device.create_buffer_init(&BufferInitDescriptor { label: Some("generated tangent"), usage: BufferUsages::COPY_DST | BufferUsages::VERTEX, contents: bytemuck::cast_slice(tangents.as_slice()), }); self.generated_tangent_buffers.insert( spec, Arc::new(buffer), size_of::() * tangents.len() * 3, ); } } for spec in self.generated_normal_buffers.needed() { if let (Some(index), Some(position)) = ( self.downloader.try_get(spec.index.clone())?, self.downloader.try_get(spec.position.clone())?, ) { let normals = generate_normals(&index, &position); let buffer = self.device.create_buffer_init(&BufferInitDescriptor { label: Some("generated normal"), usage: BufferUsages::COPY_DST | BufferUsages::VERTEX, contents: bytemuck::cast_slice(normals.as_slice()), }); self.generated_normal_buffers.insert( spec, Arc::new(buffer), size_of::() * normals.len() * 3, ); } } for spec in self.generated_texcoord_buffers.needed() { if let (Some(index), Some(position)) = ( self.downloader.try_get(spec.index.clone())?, self.downloader.try_get(spec.position.clone())?, ) { let texcoords = generate_texcoords(&index, &position); let buffer = self.device.create_buffer_init(&BufferInitDescriptor { label: Some("generated texcoord"), usage: BufferUsages::COPY_DST | BufferUsages::VERTEX, contents: bytemuck::cast_slice(texcoords.as_slice()), }); self.generated_texcoord_buffers.insert( spec, Arc::new(buffer), size_of::() * texcoords.len() * 3, ); } } Ok(()) } }