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