This commit is contained in:
2023-05-18 16:19:54 +02:00
parent e366c5830a
commit f2736c87fa
9 changed files with 165 additions and 4 deletions

1
rust/Cargo.lock generated
View File

@@ -492,6 +492,7 @@ dependencies = [
"godot",
"itertools",
"lightwave-3d",
"powerrender-3d",
"springylib",
"starforcelib",
]

View File

@@ -14,3 +14,4 @@ itertools = "0.10.5"
dds-rs = "0.7.0"
starforcelib = { path = "../starforcelib" }
springylib = { path = "../springylib" }
powerrender-3d = { path = "../powerrender-3d" }

View File

@@ -7,6 +7,7 @@ use ::godot::prelude::{ExtensionLibrary, Gd, InitHandle, InitLevel, Share};
pub mod data_installer;
pub mod lightwave_object;
pub mod pr3d;
pub mod sproing;
pub mod starforce;

21
rust/mhgd/src/pr3d/mod.rs Normal file
View File

@@ -0,0 +1,21 @@
use crate::pr3d::pro::pro_to_gd;
use godot::bind::godot_api;
use godot::builtin::GodotString;
use godot::engine::PackedScene;
use godot::obj::Gd;
use godot::prelude::GodotClass;
use powerrender_3d::pro::PowerRenderObject;
pub mod pro;
#[derive(GodotClass)]
#[class(init)]
pub struct ProLoader {}
#[godot_api]
impl ProLoader {
#[func]
pub fn load(path: GodotString) -> Gd<PackedScene> {
pro_to_gd(PowerRenderObject::from_file(path.to_string()).unwrap())
}
}

129
rust/mhgd/src/pr3d/pro.rs Normal file
View File

@@ -0,0 +1,129 @@
use godot::builtin::{
Array, Color, Dictionary, PackedByteArray, PackedColorArray, PackedInt32Array,
PackedVector2Array, PackedVector3Array, ToVariant, VariantArray, Vector2, Vector3,
};
use godot::engine::base_material_3d::{CullMode, TextureParam, Transparency};
use godot::engine::image::AlphaMode;
use godot::engine::mesh::{ArrayFormat, ArrayType, PrimitiveType};
use godot::engine::node::InternalMode;
use godot::engine::{
ArrayMesh, Image, ImageTexture, MeshInstance3D, Node3D, PackedScene, StandardMaterial3D,
};
use godot::obj::{EngineEnum, Gd, Share};
use powerrender_3d::pro::PowerRenderObject;
use std::fs::File;
use std::io::Read;
pub fn pro_to_gd(pro: PowerRenderObject) -> Gd<PackedScene> {
let mut root = Node3D::new_alloc();
root.set_name(pro.name.into());
let materials: Vec<Gd<StandardMaterial3D>> = pro
.materials
.into_iter()
.map(|m| {
let mut material = StandardMaterial3D::new();
material.set_name(m.name.into());
let pr_tex = &pro.textures[m.texture_index];
let mut image_file =
File::open(format!("E:\\Games\\Moorhuhn Kart\\data\\{}", pr_tex.name)).unwrap();
let mut image = Image::new();
let mut buffer = vec![];
image_file.read_to_end(&mut buffer).unwrap();
image.load_tga_from_buffer(PackedByteArray::from(buffer.as_slice()));
let mut texture = ImageTexture::new();
texture.set_name(pr_tex.name.clone().into());
texture.set_image(image);
material.set_texture(TextureParam::TEXTURE_ALBEDO, texture.upcast());
if pr_tex.has_alpha {
material.set_transparency(Transparency::TRANSPARENCY_ALPHA_SCISSOR);
material.set_alpha_scissor_threshold(0.5);
}
material.set_cull_mode(if m.two_sided {
CullMode::CULL_DISABLED
} else {
CullMode::CULL_BACK
});
material
})
.collect();
for segment in pro.segments {
let mut mesh = ArrayMesh::new();
mesh.set_name(segment.name.clone().into());
for surface in segment.surfaces {
let mut arrays = VariantArray::new();
arrays.resize(ArrayType::ARRAY_MAX.ord() as usize);
arrays.set(
ArrayType::ARRAY_VERTEX.ord() as usize,
PackedVector3Array::from_iter(surface.vertices.into_iter().map(|v| Vector3 {
x: v[0],
y: v[1],
z: v[2],
}))
.to_variant(),
);
arrays.set(
ArrayType::ARRAY_INDEX.ord() as usize,
PackedInt32Array::from_iter(surface.indices.into_iter()).to_variant(),
);
arrays.set(
ArrayType::ARRAY_NORMAL.ord() as usize,
PackedVector3Array::from_iter(surface.normals.into_iter().map(|n| Vector3 {
x: n[0],
y: n[1],
z: n[2],
}))
.to_variant(),
);
arrays.set(
ArrayType::ARRAY_COLOR.ord() as usize,
PackedColorArray::from_iter(surface.colors.into_iter().map(|c| Color {
r: c[0],
g: c[1],
b: c[2],
a: 1.0,
}))
.to_variant(),
);
arrays.set(
ArrayType::ARRAY_TEX_UV.ord() as usize,
PackedVector2Array::from_iter(
surface
.uvs
.into_iter()
.map(|uv| Vector2 { x: uv[0], y: uv[1] }),
)
.to_variant(),
);
mesh.add_surface_from_arrays(
PrimitiveType::PRIMITIVE_TRIANGLES,
arrays,
Array::new(),
Dictionary::new(),
ArrayFormat::default(),
);
let surf_idx = mesh.get_surface_count() - 1;
mesh.surface_set_material(surf_idx, materials[surface.material_index].share().upcast());
}
let mut instance = MeshInstance3D::new_alloc();
instance.set_name(segment.name.into());
instance.set_mesh(mesh.upcast());
root.add_child(
instance.share().upcast(),
false,
InternalMode::INTERNAL_MODE_DISABLED,
);
instance.set_owner(root.share().upcast());
}
let mut scene = PackedScene::new();
scene.pack(root.share().upcast());
root.queue_free();
scene
}

View File

@@ -3,8 +3,6 @@ name = "powerrender-3d"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
binrw = "0.11.1"
half = "2.2.1"

View File

@@ -0,0 +1 @@
pub mod pro;

View File

@@ -51,9 +51,9 @@ impl PrVertices {
*index
} else {
surface.vertices.push([
f32::from_ne_bytes(point.pos[0].to_ne_bytes()),
f32::from_ne_bytes(point.pos[1].to_ne_bytes()),
f32::from_ne_bytes(point.pos[2].to_ne_bytes()),
f32::from_ne_bytes(point.pos[1].to_ne_bytes()),
f32::from_ne_bytes(point.pos[0].to_ne_bytes()),
]);
surface.normals.push([
point.normal[0] as f32 / 1024.0,

View File

@@ -8,7 +8,9 @@ use binrw::BinRead;
use binrw::BinResult;
use binrw::Endian;
use std::fmt::Debug;
use std::fs::File;
use std::io::{Read, Seek};
use std::path::Path;
pub(crate) mod chunk;
pub(crate) mod internal;
@@ -57,6 +59,13 @@ pub struct PowerRenderMaterial {
pub vert_shader: Option<String>,
}
impl PowerRenderObject {
pub fn from_file<P: AsRef<Path>>(path: P) -> BinResult<Self> {
let mut file = File::open(path).map_err(binrw::Error::Io)?;
Self::read(&mut file)
}
}
impl ReadEndian for PowerRenderObject {
const ENDIAN: EndianKind = EndianKind::Endian(Endian::Little);
}