mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-12 20:46:20 +00:00
update dependencies
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user