This commit is contained in:
2023-05-11 22:48:20 +02:00
parent f5d7e99f71
commit 2777d540ba

View File

@@ -4,13 +4,14 @@ use godot::builtin::{
VariantArray, Vector2, Vector3, VariantArray, Vector2, Vector3,
}; };
use godot::engine::mesh::{ArrayFormat, ArrayType, PrimitiveType}; use godot::engine::mesh::{ArrayFormat, ArrayType, PrimitiveType};
use godot::engine::{ArrayMesh, PackedScene}; use godot::engine::{ArrayMesh, SurfaceTool};
use godot::obj::{EngineEnum, Gd}; use godot::obj::{EngineEnum, Gd};
use godot::prelude::{Array, GodotClass, Share, ToVariant}; use godot::prelude::{godot_warn, Array, GodotClass, Share, ToVariant};
use itertools::Itertools; use lightwave_3d::iff::Chunk;
use lightwave_3d::lwo2::tags::point_list::PointList;
use lightwave_3d::lwo2::tags::polygon_list::PolygonLists;
use lightwave_3d::lwo2::tags::Tag; use lightwave_3d::lwo2::tags::Tag;
use lightwave_3d::LightWaveObject; use lightwave_3d::LightWaveObject;
use std::fs::File;
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(init)] #[class(init)]
@@ -28,129 +29,108 @@ pub fn lightwave_to_gd(lightwave: LightWaveObject) -> Gd<ArrayMesh> {
let mut mesh = ArrayMesh::new(); let mut mesh = ArrayMesh::new();
let mut arrays: Option<VariantArray> = None; let mut arrays: Option<VariantArray> = None;
let mut vert_count = 0;
for tag in lightwave.data { for tag in lightwave.data {
match tag { match tag {
Tag::PointList(points) => { Tag::PointList(points) => {
if let Some(arrays) = &arrays { try_commit(&mut mesh, &arrays);
mesh.add_surface_from_arrays( vert_count = points.point_location.len();
PrimitiveType::PRIMITIVE_TRIANGLES,
arrays.share(),
Array::new(),
Dictionary::new(),
ArrayFormat::ARRAY_FORMAT_NORMAL,
);
}
let mut ars = Array::new(); let mut ars = Array::new();
ars.resize(ArrayType::ARRAY_MAX.ord() as usize); 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( ars.set(
ArrayType::ARRAY_VERTEX.ord() as usize, ArrayType::ARRAY_VERTEX.ord() as usize,
PackedVector3Array::from( collect_points(points).to_variant(),
points
.point_location
.iter()
.map(|[x, y, z]| Vector3 {
x: *x,
y: *y,
z: *z,
})
.collect::<Vec<Vector3>>()
.as_slice(),
)
.to_variant(),
); );
arrays = Some(ars); arrays = Some(ars);
} }
Tag::VertexMapping(vmap) => { Tag::VertexMapping(vmap) => match &vmap.kind {
if let b"TXUV" = &vmap.kind { b"TXUV" => {
if let Some(arrays) = &mut arrays { if let Some(arrays) = &mut arrays {
arrays.set( let mut arr = PackedVector2Array::new();
ArrayType::ARRAY_TEX_UV.ord() as usize, arr.resize(vert_count);
PackedVector2Array::from(
vmap.mapping for uv in vmap.data.mapping {
.iter() arr.set(
.map(|uv| Vector2 { uv.vert as usize,
x: uv.value[0], Vector2 {
y: uv.value[1], x: uv.value[0],
}) y: uv.value[1],
.collect::<Vec<Vector2>>() },
.as_slice(), );
) }
.to_variant(),
); arrays.set(ArrayType::ARRAY_TEX_UV.ord() as usize, arr.to_variant());
} }
} }
} x => godot_warn!("{}", String::from_utf8(x.to_vec()).unwrap()),
},
Tag::PolygonList(polygons) => match &polygons.kind { Tag::PolygonList(polygons) => match &polygons.kind {
b"FACE" => { b"FACE" => {
if let Some(arrays) = &mut arrays { if let Some(arrays) = &mut arrays {
arrays.set( let indices = collect_polygons(polygons);
ArrayType::ARRAY_INDEX.ord() as usize, arrays.set(ArrayType::ARRAY_INDEX.ord() as usize, indices.to_variant());
PackedInt32Array::from(
get_rendering_vertex_indices(
polygons
.polygons
.iter()
.flat_map(|it| it.vert.iter().map(|it| *it as i32))
.collect::<Vec<i32>>(),
)
.as_slice(),
)
.to_variant(),
);
} }
} }
_ => panic!(), x => godot_warn!("{}", String::from_utf8(x.to_vec()).unwrap()),
}, },
_ => (), _ => (),
} }
} }
if let Some(arrays) = &arrays { try_commit(&mut mesh, &arrays);
let mut out_mesh = ArrayMesh::new();
for i in 0..mesh.get_surface_count() {
let mut tool = SurfaceTool::new();
tool.create_from(mesh.share().upcast(), i);
tool.generate_normals(false);
tool.generate_tangents();
try_commit(&mut out_mesh, &Some(tool.commit_to_arrays()));
}
out_mesh
}
fn try_commit(mesh: &mut ArrayMesh, arrays: &Option<VariantArray>) {
if let Some(arrays) = arrays {
mesh.add_surface_from_arrays( mesh.add_surface_from_arrays(
PrimitiveType::PRIMITIVE_TRIANGLES, PrimitiveType::PRIMITIVE_TRIANGLES,
arrays.share(), arrays.share(),
Array::new(), Array::new(),
Dictionary::new(), Dictionary::new(),
ArrayFormat::ARRAY_FORMAT_VERTEX, ArrayFormat::ARRAY_FORMAT_NORMAL,
); );
} }
mesh.regen_normal_maps();
mesh
} }
fn get_rendering_vertex_indices(strip: Vec<i32>) -> Vec<i32> { fn collect_points(chunk: Chunk<PointList>) -> PackedVector3Array {
if strip.len() == 2 { PackedVector3Array::from(
return vec![strip[0], strip[1], strip[0]]; chunk
} .data
.point_location
let mut p = strip.into_iter(); .into_iter()
let mut vertex_indices = vec![]; .map(|[x, y, z]| Vector3 { x, y, z })
.collect::<Vec<Vector3>>()
let mut f1 = p.next().unwrap(); .as_slice(),
let mut f2 = p.next().unwrap(); )
let mut face_direction = 1; }
for f3 in p {
// face_direction *= -1; fn collect_polygons(chunk: Chunk<PolygonLists>) -> PackedInt32Array {
if f1 != f2 && f2 != f3 && f3 != f1 { debug_assert!(chunk.polygons.len() >= 3, "{:?}", chunk);
if face_direction > 0 { PackedInt32Array::from(
vertex_indices.push(f3); chunk
vertex_indices.push(f2); .data
vertex_indices.push(f1); .polygons
} else { .into_iter()
vertex_indices.push(f2); .flat_map(|mut it| {
vertex_indices.push(f3); let fan_v = it.vert.remove(0) as i32;
vertex_indices.push(f1); it.vert
} .windows(2)
} .flat_map(|w| [w[1] as i32, w[0] as i32, fan_v])
.collect::<Vec<i32>>()
f1 = f2; })
f2 = f3; .collect::<Vec<i32>>()
} .as_slice(),
)
vertex_indices
} }