mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-11 03:56:18 +00:00
pr3d
This commit is contained in:
1
rust/Cargo.lock
generated
1
rust/Cargo.lock
generated
@@ -492,6 +492,7 @@ dependencies = [
|
||||
"godot",
|
||||
"itertools",
|
||||
"lightwave-3d",
|
||||
"powerrender-3d",
|
||||
"springylib",
|
||||
"starforcelib",
|
||||
]
|
||||
|
||||
@@ -14,3 +14,4 @@ itertools = "0.10.5"
|
||||
dds-rs = "0.7.0"
|
||||
starforcelib = { path = "../starforcelib" }
|
||||
springylib = { path = "../springylib" }
|
||||
powerrender-3d = { path = "../powerrender-3d" }
|
||||
|
||||
@@ -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
21
rust/mhgd/src/pr3d/mod.rs
Normal 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
129
rust/mhgd/src/pr3d/pro.rs
Normal 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
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
1
rust/powerrender-3d/src/lib.rs
Normal file
1
rust/powerrender-3d/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod pro;
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user