diff --git a/godot/mhgd.gdextension b/godot/mhgd.gdextension new file mode 100644 index 0000000..bd87779 --- /dev/null +++ b/godot/mhgd.gdextension @@ -0,0 +1,12 @@ +[configuration] +entry_symbol = "gdext_rust_init" + +[libraries] +linux.debug.x86_64 = "res://../rust/target/debug/libmhgd.so" +linux.release.x86_64 = "res://../rust/target/release/libmhgd.so" +windows.debug.x86_64 = "res://../rust/target/debug/mhgd.dll" +windows.release.x86_64 = "res://../rust/target/release/mhgd.dll" +macos.debug = "res://../rust/target/debug/mhgd.dylib" +macos.release = "res://../rust/target/release/mhgd.dylib" +macos.debug.arm64 = "res://../rust/target/aarch64-apple-darwin/debug/mhgd.dylib" +macos.release.arm64 = "res://../rust/target/aarch64-apple-darwin/release/mhgd.dylib" \ No newline at end of file diff --git a/godot/mhjnr.gdextension b/godot/mhjnr.gdextension deleted file mode 100644 index 99f902e..0000000 --- a/godot/mhjnr.gdextension +++ /dev/null @@ -1,12 +0,0 @@ -[configuration] -entry_symbol = "gdext_rust_init" - -[libraries] -linux.debug.x86_64 = "res://../rust/target/debug/libmhjnr.so" -linux.release.x86_64 = "res://../rust/target/release/libmhjnr.so" -windows.debug.x86_64 = "res://../rust/target/debug/mhjnr.dll" -windows.release.x86_64 = "res://../rust/target/release/mhjnr.dll" -macos.debug = "res://../rust/target/debug/mhjnr.dylib" -macos.release = "res://../rust/target/release/mhjnr.dylib" -macos.debug.arm64 = "res://../rust/target/aarch64-apple-darwin/debug/mhjnr.dylib" -macos.release.arm64 = "res://../rust/target/aarch64-apple-darwin/release/mhjnr.dylib" \ No newline at end of file diff --git a/godot/starforce/test.gd b/godot/starforce/test.gd new file mode 100644 index 0000000..54ab456 --- /dev/null +++ b/godot/starforce/test.gd @@ -0,0 +1,12 @@ +@tool +extends Node3D + +@export var click = false: + get: + return false + set(value): + var lwo = Lwo.new() + var mesh = lwo.get_mesh("E:\\Games\\Moorhuhn Kart 3\\extract\\D\\Moorhuhnkart\\3dobjects_cars\\affe.lwo") + var instance = MeshInstance3D.new() + instance.mesh = mesh + add_child(instance) diff --git a/godot/starforce/test.tscn b/godot/starforce/test.tscn new file mode 100644 index 0000000..0311418 --- /dev/null +++ b/godot/starforce/test.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://kyw4wuusc33g"] + +[ext_resource type="Script" path="res://starforce/test.gd" id="1_uc463"] + +[node name="test" type="Node3D"] +script = ExtResource("1_uc463") diff --git a/rust/mhgd/src/lightwave_object.rs b/rust/mhgd/src/lightwave_object.rs index 0b51d92..4a55cb0 100644 --- a/rust/mhgd/src/lightwave_object.rs +++ b/rust/mhgd/src/lightwave_object.rs @@ -1,32 +1,51 @@ use godot::bind::godot_api; -use godot::builtin::{GodotString, PackedInt32Array, PackedVector3Array, Vector3}; -use godot::engine::mesh::ArrayType; +use godot::builtin::{ + Dictionary, GodotString, PackedInt32Array, PackedVector2Array, PackedVector3Array, + VariantArray, Vector2, Vector3, +}; +use godot::engine::mesh::{ArrayFormat, ArrayType, PrimitiveType}; use godot::engine::{ArrayMesh, PackedScene}; use godot::obj::{EngineEnum, Gd}; -use godot::prelude::{Array, GodotClass, ToVariant}; +use godot::prelude::{Array, GodotClass, Share, ToVariant}; +use itertools::Itertools; use lightwave_3d::lwo2::tags::Tag; use lightwave_3d::LightWaveObject; use std::fs::File; #[derive(GodotClass)] +#[class(init)] struct Lwo {} #[godot_api] impl Lwo { + #[func] pub fn get_mesh(path: GodotString) -> Gd { lightwave_to_gd(LightWaveObject::read_file(path.to_string()).unwrap()) } } pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd { - let mesh = ArrayMesh::new(); - let mut arrays = Array::new(); - arrays.resize(ArrayType::ARRAY_MAX.ord() as usize); + let mut mesh = ArrayMesh::new(); + let mut arrays: Option = None; for tag in lightwave.data { match tag { Tag::PointList(points) => { - arrays.set( + if let Some(arrays) = &arrays { + mesh.add_surface_from_arrays( + PrimitiveType::PRIMITIVE_TRIANGLES, + arrays.share(), + Array::new(), + Dictionary::new(), + ArrayFormat::ARRAY_FORMAT_NORMAL, + ); + } + let mut ars = Array::new(); + ars.resize(ArrayType::ARRAY_MAX.ord() as usize); + let mut norm = PackedVector3Array::new(); + norm.resize(points.point_location.len()); + ars.set(ArrayType::ARRAY_NORMAL.ord() as usize, norm.to_variant()); + ars.set( ArrayType::ARRAY_VERTEX.ord() as usize, PackedVector3Array::from( points @@ -42,21 +61,46 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd { ) .to_variant(), ); + arrays = Some(ars); + } + Tag::VertexMapping(vmap) => { + if let b"TXUV" = &vmap.kind { + if let Some(arrays) = &mut arrays { + arrays.set( + ArrayType::ARRAY_TEX_UV.ord() as usize, + PackedVector2Array::from( + vmap.mapping + .iter() + .map(|uv| Vector2 { + x: uv.value[0], + y: uv.value[1], + }) + .collect::>() + .as_slice(), + ) + .to_variant(), + ); + } + } } Tag::PolygonList(polygons) => match &polygons.kind { b"FACE" => { - arrays.set( - ArrayType::ARRAY_INDEX.ord() as usize, - PackedInt32Array::from( - polygons - .polygons - .iter() - .flat_map(|it| it.vert.iter().map(|it| *it as i32)) - .collect::>() + if let Some(arrays) = &mut arrays { + arrays.set( + ArrayType::ARRAY_INDEX.ord() as usize, + PackedInt32Array::from( + get_rendering_vertex_indices( + polygons + .polygons + .iter() + .flat_map(|it| it.vert.iter().map(|it| *it as i32)) + .collect::>(), + ) .as_slice(), - ) - .to_variant(), - ); + ) + .to_variant(), + ); + } } _ => panic!(), }, @@ -64,5 +108,49 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd { } } + if let Some(arrays) = &arrays { + mesh.add_surface_from_arrays( + PrimitiveType::PRIMITIVE_TRIANGLES, + arrays.share(), + Array::new(), + Dictionary::new(), + ArrayFormat::ARRAY_FORMAT_VERTEX, + ); + } + + mesh.regen_normal_maps(); + mesh } + +fn get_rendering_vertex_indices(strip: Vec) -> Vec { + if strip.len() == 2 { + return vec![strip[0], strip[1], strip[0]]; + } + + let mut p = strip.into_iter(); + let mut vertex_indices = vec![]; + + let mut f1 = p.next().unwrap(); + let mut f2 = p.next().unwrap(); + let mut face_direction = 1; + for f3 in p { + // face_direction *= -1; + if f1 != f2 && f2 != f3 && f3 != f1 { + if face_direction > 0 { + vertex_indices.push(f3); + vertex_indices.push(f2); + vertex_indices.push(f1); + } else { + vertex_indices.push(f2); + vertex_indices.push(f3); + vertex_indices.push(f1); + } + } + + f1 = f2; + f2 = f3; + } + + vertex_indices +}