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 bytemuck::{offset_of, Pod, Zeroable};
|
||||||
use gltf_json::accessor::{ComponentType, GenericComponentType, Type};
|
use gltf_json::accessor::{ComponentType, GenericComponentType, Type};
|
||||||
use gltf_json::buffer::{Target, View};
|
use gltf_json::buffer::{Target, View};
|
||||||
|
|
@ -9,7 +9,7 @@ use gltf_json::texture::Info;
|
||||||
use gltf_json::validation::Checked::Valid;
|
use gltf_json::validation::Checked::Valid;
|
||||||
use gltf_json::{Accessor, Extras, Image, Index, Material, Mesh, Texture, Value};
|
use gltf_json::{Accessor, Extras, Image, Index, Material, Mesh, Texture, Value};
|
||||||
use image::png::PngEncoder;
|
use image::png::PngEncoder;
|
||||||
use image::{DynamicImage, GenericImageView};
|
use image::GenericImageView;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use vmdl::{Model, SkinTable};
|
use vmdl::{Model, SkinTable};
|
||||||
|
|
||||||
|
|
@ -219,15 +219,9 @@ pub fn push_material(
|
||||||
images: &mut Vec<Image>,
|
images: &mut Vec<Image>,
|
||||||
material: MaterialData,
|
material: MaterialData,
|
||||||
) -> Material {
|
) -> Material {
|
||||||
let textures_start = textures.len() as u32;
|
let texture_index = material
|
||||||
|
|
||||||
let texture = material
|
|
||||||
.texture
|
.texture
|
||||||
.map(|tex| push_texture(buffer, views, images, tex));
|
.map(|tex| push_or_get_texture(buffer, views, textures, images, tex));
|
||||||
let texture_index = texture.map(|texture| {
|
|
||||||
textures.push(texture);
|
|
||||||
textures_start
|
|
||||||
});
|
|
||||||
|
|
||||||
let alpha_mode = match (material.translucent, material.alpha_test.is_some()) {
|
let alpha_mode = match (material.translucent, material.alpha_test.is_some()) {
|
||||||
(true, _) => AlphaMode::Blend,
|
(true, _) => AlphaMode::Blend,
|
||||||
|
|
@ -248,7 +242,7 @@ pub fn push_material(
|
||||||
material.color.map(|channel| channel as f32 / 255.0),
|
material.color.map(|channel| channel as f32 / 255.0),
|
||||||
),
|
),
|
||||||
base_color_texture: texture_index.map(|index| Info {
|
base_color_texture: texture_index.map(|index| Info {
|
||||||
index: Index::new(index),
|
index,
|
||||||
tex_coord: 0,
|
tex_coord: 0,
|
||||||
extensions: None,
|
extensions: None,
|
||||||
extras: Extras::default(),
|
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(
|
fn push_texture(
|
||||||
buffer: &mut Vec<u8>,
|
buffer: &mut Vec<u8>,
|
||||||
views: &mut Vec<View>,
|
views: &mut Vec<View>,
|
||||||
images: &mut Vec<Image>,
|
images: &mut Vec<Image>,
|
||||||
image: DynamicImage,
|
texture: TextureData,
|
||||||
) -> Texture {
|
) -> Texture {
|
||||||
|
let image = texture.image;
|
||||||
let buffer_start = buffer.len() as u32;
|
let buffer_start = buffer.len() as u32;
|
||||||
let view_start = views.len() as u32;
|
let view_start = views.len() as u32;
|
||||||
let image_start = images.len() as u32;
|
let image_start = images.len() as u32;
|
||||||
|
|
@ -291,7 +311,7 @@ fn push_texture(
|
||||||
byte_stride: None,
|
byte_stride: None,
|
||||||
extensions: Default::default(),
|
extensions: Default::default(),
|
||||||
extras: Default::default(),
|
extras: Default::default(),
|
||||||
name: None,
|
name: Some(texture.name.clone()),
|
||||||
target: None,
|
target: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -300,7 +320,7 @@ fn push_texture(
|
||||||
let image = Image {
|
let image = Image {
|
||||||
buffer_view: Some(Index::new(view_start)),
|
buffer_view: Some(Index::new(view_start)),
|
||||||
mime_type: Some(MimeType("image/png".into())),
|
mime_type: Some(MimeType("image/png".into())),
|
||||||
name: None,
|
name: Some(texture.name.clone()),
|
||||||
uri: None,
|
uri: None,
|
||||||
extensions: None,
|
extensions: None,
|
||||||
extras: Default::default(),
|
extras: Default::default(),
|
||||||
|
|
@ -308,7 +328,7 @@ fn push_texture(
|
||||||
images.push(image);
|
images.push(image);
|
||||||
|
|
||||||
Texture {
|
Texture {
|
||||||
name: None,
|
name: Some(texture.name),
|
||||||
sampler: None,
|
sampler: None,
|
||||||
source: Index::new(image_start),
|
source: Index::new(image_start),
|
||||||
extensions: None,
|
extensions: None,
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,18 @@ pub fn load_material_fallback(name: &str, search_dirs: &[String], loader: &Loade
|
||||||
pub struct MaterialData {
|
pub struct MaterialData {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub color: [u8; 4],
|
pub color: [u8; 4],
|
||||||
pub texture: Option<DynamicImage>,
|
pub texture: Option<TextureData>,
|
||||||
pub alpha_test: Option<f32>,
|
pub alpha_test: Option<f32>,
|
||||||
pub bump_map: Option<DynamicImage>,
|
pub bump_map: Option<TextureData>,
|
||||||
pub translucent: bool,
|
pub translucent: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TextureData {
|
||||||
|
pub name: String,
|
||||||
|
pub image: DynamicImage,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_material(
|
pub fn load_material(
|
||||||
name: &str,
|
name: &str,
|
||||||
search_dirs: &[String],
|
search_dirs: &[String],
|
||||||
|
|
@ -85,14 +91,20 @@ pub fn load_material(
|
||||||
.and_then(|val| f32::from_str(val).ok())
|
.and_then(|val| f32::from_str(val).ok())
|
||||||
.unwrap_or(1.0);
|
.unwrap_or(1.0);
|
||||||
|
|
||||||
let bump_map = get_path(&table, "$bumpmap")
|
let bump_map = get_path(&table, "$bumpmap").and_then(|path| {
|
||||||
.map(|path| load_texture(&path, loader, true).ok())
|
Some(TextureData {
|
||||||
.flatten();
|
image: load_texture(&path, loader, true).ok()?,
|
||||||
|
name: path,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
Ok(MaterialData {
|
Ok(MaterialData {
|
||||||
color: [255; 4],
|
color: [255; 4],
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
texture: Some(texture),
|
texture: Some(TextureData {
|
||||||
|
name: base_texture,
|
||||||
|
image: texture,
|
||||||
|
}),
|
||||||
bump_map,
|
bump_map,
|
||||||
alpha_test: alpha_test.then_some(alpha_cutout),
|
alpha_test: alpha_test.then_some(alpha_cutout),
|
||||||
translucent: translucent | glass | alpha_test,
|
translucent: translucent | glass | alpha_test,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue