update dependencies

This commit is contained in:
2023-05-29 20:58:47 +02:00
parent 527a1ef0c7
commit 12647bd5e7
8 changed files with 180 additions and 104 deletions

View File

@@ -1,21 +1,69 @@
use godot::engine::{load, Image};
use godot::engine::{load, AnimatedTexture, Image, ImageTexture, Texture2D};
use godot::log::godot_error;
use godot::obj::Gd;
use lightwave_3d::lwo2::tags::image_clip::{ImageClip, ImageClipSubChunk};
use std::collections::HashMap;
pub fn collect_clip(target: &mut HashMap<u32, Gd<Image>>, clip: ImageClip) {
for img in clip.attributes.iter() {
match img {
ImageClipSubChunk::StillImage(still) => {
let path = format!("sar://{}", still.name.replace('\\', "/").replace(':', ":/"));
let mut image: Gd<Image> = load(path);
image.set_name(still.name.clone().into());
target.insert(clip.index, image);
fn convert_path(path: &str) -> String {
path.replace('\\', "/").replace(':', ":/")
}
fn load_texture(path: &str, name: &str) -> Gd<ImageTexture> {
let mut image: Gd<Image> = load(path);
image.set_name(name.into());
let mut texture = ImageTexture::new();
texture.set_name(name.into());
texture.set_image(image);
texture
}
pub fn collect_clip(target: &mut HashMap<u32, Gd<Texture2D>>, clip: ImageClip) {
let mut attributes = clip.attributes.iter();
match attributes.next().unwrap() {
ImageClipSubChunk::StillImage(still) => {
let path = format!("sar://{}", convert_path(&still.name));
for meta in attributes {
godot_error!("TODO: {:?}", meta)
}
x => {
godot_error!("TODO: Clip chunk {:?}", x)
target.insert(clip.index, load_texture(&path, &still.name).upcast());
}
ImageClipSubChunk::ImageSequence(sequence) => {
let mut texture = AnimatedTexture::new();
texture.set_frames(sequence.data.end as i64 - sequence.data.start as i64);
if sequence.data.flags & 0x1 != 1 {
godot_error!("Non-looping animated textures are not supported!")
}
let mut frame_duration = 15.0 / 60.0;
for meta in attributes {
match meta {
ImageClipSubChunk::Time(time) => {
frame_duration = time.frame_rate as f64 / 60.0;
}
x => godot_error!("TODO: {:?}", x),
}
}
for i in sequence.data.start..sequence.data.end {
let path = format!(
"sar://{}{:0width$}{}",
convert_path(&sequence.data.prefix),
i,
sequence.data.suffix,
width = sequence.data.num_digits as usize
);
let frame = i as i64 - sequence.data.start as i64;
texture.set_frame_texture(frame, load_texture(&path, &i.to_string()).upcast());
texture.set_frame_duration(frame, frame_duration);
}
// texture.set_current_frame(sequence.data.offset as i64);
target.insert(clip.index, texture.upcast());
}
x => {
godot_error!("TODO: Clip chunk {:?}", x)
}
}
}

View File

@@ -3,6 +3,7 @@ use crate::lwo::surface_info::SurfaceInfo;
use godot::builtin::{Array, Dictionary, Vector2, Vector3};
use godot::engine::mesh::{ArrayFormat, PrimitiveType};
use godot::engine::{ArrayMesh, SurfaceTool};
use godot::log::godot_print;
use godot::obj::{Gd, Share};
use itertools::Itertools;
use lightwave_3d::lwo2::tags::polygon_list::PolygonList;
@@ -24,16 +25,13 @@ pub struct IntermediateLayer {
}
impl IntermediateLayer {
pub fn commit(mut self, materials: &HashMap<u16, MaterialUvInfo>) -> Gd<ArrayMesh> {
pub fn commit(self, materials: &HashMap<u16, MaterialUvInfo>) -> Gd<ArrayMesh> {
let mut mesh = ArrayMesh::new();
mesh.set_name(self.name.clone().into());
let mut surface_material_ids = Vec::<u16>::new();
self.uv_mappings.sort_by(|a, b| a.0.cmp(&b.0));
for material_id in self.material_mappings.values().unique() {
let material = &materials[material_id];
let surface_info = SurfaceInfo::collect_from_layer(&self, material);
let surface_info = SurfaceInfo::collect_from_layer(&self, &materials[material_id]);
if !surface_info.is_empty() {
mesh.add_surface_from_arrays(
@@ -47,6 +45,16 @@ impl IntermediateLayer {
}
}
godot_print!(
"{}: {:?}",
&self.name,
surface_material_ids
.iter()
.unique()
.map(|id| { (*id, materials[id].material.get_name().to_string()) })
.collect_vec()
);
let mut final_mesh = post_process_mesh(
mesh,
materials,

View File

@@ -1,5 +1,5 @@
use godot::builtin::{Basis, Color, EulerOrder, ToVariant, Transform3D, Variant, Vector3};
use godot::engine::{load, Image, ImageTexture, ShaderMaterial};
use godot::engine::{load, PlaceholderTexture2D, ShaderMaterial, Texture2D};
use godot::log::{godot_error, godot_print};
use godot::obj::{Gd, Share};
use lightwave_3d::lwo2::sub_tags::blocks::image_texture::{
@@ -24,7 +24,11 @@ pub struct MaterialUvInfo {
}
impl MaterialUvInfo {
pub fn collect(surface: SurfaceDefinition, images: &HashMap<u32, Gd<Image>>, id: u16) -> Self {
pub fn collect(
surface: SurfaceDefinition,
textures: &HashMap<u32, Gd<Texture2D>>,
id: u16,
) -> Self {
let mut m = MaterialUvInfo {
diffuse_channel: None,
color_channel: None,
@@ -39,7 +43,7 @@ impl MaterialUvInfo {
match attr {
SurfaceParameterSubChunk::Blocks(blocks) => {
if let SurfaceBlocks::ImageMapTexture { header, attributes } = blocks.data {
let mut texture = ImageTexture::new();
let mut texture: Gd<Texture2D> = PlaceholderTexture2D::new().upcast();
let mut chan = TextureChannel::Color;
let mut uv_channel = None;
let mut major_axis = 0;
@@ -67,9 +71,12 @@ impl MaterialUvInfo {
for attr in attributes {
match attr {
SurfaceBlockImageTextureSubChunk::ImageMap(r) => {
if let Some(i) = images.get(&r.texture_image) {
godot_print!("{}", i.get_name());
texture.set_image(i.share());
if let Some(tex) = textures.get(&r.texture_image) {
godot_print!("{}", tex.get_name());
debug_assert!(texture
.try_cast::<PlaceholderTexture2D>()
.is_some());
texture = tex.share()
} else {
godot_error!("Missing texture {:?}", r);
}

View File

@@ -4,7 +4,7 @@ use crate::lwo::mapping::{collect_discontinuous_mappings, collect_mappings};
use crate::lwo::material::MaterialUvInfo;
use godot::builtin::{Vector2, Vector3};
use godot::engine::node::InternalMode;
use godot::engine::{Image, MeshInstance3D, Node3D, PackedScene};
use godot::engine::{MeshInstance3D, Node3D, PackedScene, Texture2D};
use godot::log::{godot_error, godot_print, godot_warn};
use godot::obj::{Gd, Share};
use itertools::Itertools;
@@ -13,8 +13,8 @@ use lightwave_3d::LightWaveObject;
use std::collections::HashMap;
pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd<PackedScene> {
let mut surfaces = HashMap::<u16, MaterialUvInfo>::new();
let mut images = HashMap::<u32, Gd<Image>>::new();
let mut materials = HashMap::<u16, MaterialUvInfo>::new();
let mut textures = HashMap::<u32, Gd<Texture2D>>::new();
let mut layers = vec![];
let mut tag_strings = vec![];
@@ -26,7 +26,11 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd<PackedScene> {
}
Tag::Layer(layer_tag) => {
layers.push(IntermediateLayer {
name: layer_tag.name.clone(),
name: if layer_tag.name.is_empty() {
format!("layer_{}", layer_tag.number)
} else {
layer_tag.name.clone()
},
parent: layer_tag.parent,
id: layer_tag.number,
pivot: Vector3 {
@@ -132,7 +136,7 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd<PackedScene> {
}
x => godot_warn!("{}", String::from_utf8(x.to_vec()).unwrap()),
},
Tag::ImageClip(clip) => collect_clip(&mut images, clip.data),
Tag::ImageClip(clip) => collect_clip(&mut textures, clip.data),
Tag::SurfaceDefinition(surf) => {
let surf_name = surf.name.clone();
let (tag_index, _) = tag_strings
@@ -141,9 +145,9 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd<PackedScene> {
.expect("Invalid File");
godot_print!("'{}': {}", surf_name, tag_index);
surfaces.insert(
materials.insert(
tag_index as u16,
MaterialUvInfo::collect(surf.data, &images, tag_index as u16),
MaterialUvInfo::collect(surf.data, &textures, tag_index as u16),
);
}
Tag::BoundingBox(_) => (),
@@ -171,7 +175,7 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd<PackedScene> {
for layer in layers {
let mut instance = MeshInstance3D::new_alloc();
instance.set_name(layer.name.clone().into());
instance.set_mesh(layer.commit(&surfaces).upcast());
instance.set_mesh(layer.commit(&materials).upcast());
root_node.add_child(
instance.share().upcast(),

View File

@@ -68,46 +68,42 @@ impl SurfaceInfo {
);
#[cfg(debug_assertions)]
for (i, inc) in self.material_incomplete.into_iter().enumerate() {
if inc != 0 {
godot_error!(
"{} ({}%) incomplete UVs",
inc,
(inc as f32 / self.vertices.len() as f32) * 100.0
);
}
for inc in self.material_incomplete.into_iter().filter(|it| it != &0) {
let percentage = (inc as f32 / self.vertices.len() as f32) * 100.0;
godot_error!("{} ({}%) incomplete UVs", inc, percentage);
}
arrays
}
pub fn collect_from_layer(layer: &IntermediateLayer, material: &MaterialUvInfo) -> Self {
let material_uv_names = [
let uv_names = [
material.diffuse_channel.as_ref(),
material.color_channel.as_ref(),
];
let materials_subset = material_uv_names
let uv_subset = uv_names
.iter()
.map(|it| it.and_then(|it| layer.uv_mappings.iter().find(|(name, _)| name == it)))
.collect_vec();
let mut surface_info = SurfaceInfo {
uv_sets: materials_subset
uv_sets: uv_subset
.iter()
.map(|it| it.map(|_| PackedVector2Array::new()))
.collect(),
material_incomplete: material_uv_names.iter().map(|_| 0).collect_vec(),
material_incomplete: uv_names.iter().map(|_| 0).collect_vec(),
..SurfaceInfo::default()
};
let mut surface_polygons = layer.polygons.iter().enumerate().filter(|(id, _)| {
layer.material_mappings.get(&(*id as i32)).unwrap_or(&0) == &material.id
});
let surface_polygons =
layer.polygons.iter().enumerate().filter(|(id, _)| {
layer.material_mappings.get(&(*id as i32)).unwrap() == &material.id
});
for (id, poly) in surface_polygons {
for index in triangulate(&poly.vert) {
let uv = materials_subset
let uv = uv_subset
.iter()
.map(|it| it.and_then(|(_, it)| find_mapping(it, id, index)))
.collect_vec();