mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
dedup textures
This commit is contained in:
parent
9dc540db5c
commit
44be60641b
2 changed files with 53 additions and 21 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use crate::material::MaterialData;
|
||||
use crate::material::{MaterialData, TextureData};
|
||||
use bytemuck::{offset_of, Pod, Zeroable};
|
||||
use gltf_json::accessor::{ComponentType, GenericComponentType, Type};
|
||||
use gltf_json::buffer::{Target, View};
|
||||
|
|
@ -9,7 +9,7 @@ use gltf_json::texture::Info;
|
|||
use gltf_json::validation::Checked::Valid;
|
||||
use gltf_json::{Accessor, Extras, Image, Index, Material, Mesh, Texture, Value};
|
||||
use image::png::PngEncoder;
|
||||
use image::{DynamicImage, GenericImageView};
|
||||
use image::GenericImageView;
|
||||
use std::mem::size_of;
|
||||
use vmdl::{Model, SkinTable};
|
||||
|
||||
|
|
@ -219,15 +219,9 @@ pub fn push_material(
|
|||
images: &mut Vec<Image>,
|
||||
material: MaterialData,
|
||||
) -> Material {
|
||||
let textures_start = textures.len() as u32;
|
||||
|
||||
let texture = material
|
||||
let texture_index = material
|
||||
.texture
|
||||
.map(|tex| push_texture(buffer, views, images, tex));
|
||||
let texture_index = texture.map(|texture| {
|
||||
textures.push(texture);
|
||||
textures_start
|
||||
});
|
||||
.map(|tex| push_or_get_texture(buffer, views, textures, images, tex));
|
||||
|
||||
let alpha_mode = match (material.translucent, material.alpha_test.is_some()) {
|
||||
(true, _) => AlphaMode::Blend,
|
||||
|
|
@ -248,7 +242,7 @@ pub fn push_material(
|
|||
material.color.map(|channel| channel as f32 / 255.0),
|
||||
),
|
||||
base_color_texture: texture_index.map(|index| Info {
|
||||
index: Index::new(index),
|
||||
index,
|
||||
tex_coord: 0,
|
||||
extensions: None,
|
||||
extras: Extras::default(),
|
||||
|
|
@ -259,12 +253,38 @@ pub fn push_material(
|
|||
}
|
||||
}
|
||||
|
||||
fn push_or_get_texture(
|
||||
buffer: &mut Vec<u8>,
|
||||
views: &mut Vec<View>,
|
||||
textures: &mut Vec<Texture>,
|
||||
images: &mut Vec<Image>,
|
||||
texture: TextureData,
|
||||
) -> Index<Texture> {
|
||||
match get_texture_index(textures, &texture.name) {
|
||||
Some(index) => index,
|
||||
None => {
|
||||
let index = textures.len() as u32;
|
||||
textures.push(push_texture(buffer, views, images, texture));
|
||||
Index::new(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_texture_index(textures: &[Texture], name: &str) -> Option<Index<Texture>> {
|
||||
textures
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, tex)| (tex.name.as_deref() == Some(name)).then_some(i))
|
||||
.map(|i| Index::new(i as u32))
|
||||
}
|
||||
|
||||
fn push_texture(
|
||||
buffer: &mut Vec<u8>,
|
||||
views: &mut Vec<View>,
|
||||
images: &mut Vec<Image>,
|
||||
image: DynamicImage,
|
||||
texture: TextureData,
|
||||
) -> Texture {
|
||||
let image = texture.image;
|
||||
let buffer_start = buffer.len() as u32;
|
||||
let view_start = views.len() as u32;
|
||||
let image_start = images.len() as u32;
|
||||
|
|
@ -291,7 +311,7 @@ fn push_texture(
|
|||
byte_stride: None,
|
||||
extensions: Default::default(),
|
||||
extras: Default::default(),
|
||||
name: None,
|
||||
name: Some(texture.name.clone()),
|
||||
target: None,
|
||||
};
|
||||
|
||||
|
|
@ -300,7 +320,7 @@ fn push_texture(
|
|||
let image = Image {
|
||||
buffer_view: Some(Index::new(view_start)),
|
||||
mime_type: Some(MimeType("image/png".into())),
|
||||
name: None,
|
||||
name: Some(texture.name.clone()),
|
||||
uri: None,
|
||||
extensions: None,
|
||||
extras: Default::default(),
|
||||
|
|
@ -308,7 +328,7 @@ fn push_texture(
|
|||
images.push(image);
|
||||
|
||||
Texture {
|
||||
name: None,
|
||||
name: Some(texture.name),
|
||||
sampler: None,
|
||||
source: Index::new(image_start),
|
||||
extensions: None,
|
||||
|
|
|
|||
|
|
@ -28,12 +28,18 @@ pub fn load_material_fallback(name: &str, search_dirs: &[String], loader: &Loade
|
|||
pub struct MaterialData {
|
||||
pub name: String,
|
||||
pub color: [u8; 4],
|
||||
pub texture: Option<DynamicImage>,
|
||||
pub texture: Option<TextureData>,
|
||||
pub alpha_test: Option<f32>,
|
||||
pub bump_map: Option<DynamicImage>,
|
||||
pub bump_map: Option<TextureData>,
|
||||
pub translucent: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TextureData {
|
||||
pub name: String,
|
||||
pub image: DynamicImage,
|
||||
}
|
||||
|
||||
pub fn load_material(
|
||||
name: &str,
|
||||
search_dirs: &[String],
|
||||
|
|
@ -85,14 +91,20 @@ pub fn load_material(
|
|||
.and_then(|val| f32::from_str(val).ok())
|
||||
.unwrap_or(1.0);
|
||||
|
||||
let bump_map = get_path(&table, "$bumpmap")
|
||||
.map(|path| load_texture(&path, loader, true).ok())
|
||||
.flatten();
|
||||
let bump_map = get_path(&table, "$bumpmap").and_then(|path| {
|
||||
Some(TextureData {
|
||||
image: load_texture(&path, loader, true).ok()?,
|
||||
name: path,
|
||||
})
|
||||
});
|
||||
|
||||
Ok(MaterialData {
|
||||
color: [255; 4],
|
||||
name: name.into(),
|
||||
texture: Some(texture),
|
||||
texture: Some(TextureData {
|
||||
name: base_texture,
|
||||
image: texture,
|
||||
}),
|
||||
bump_map,
|
||||
alpha_test: alpha_test.then_some(alpha_cutout),
|
||||
translucent: translucent | glass | alpha_test,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue