mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-13 13:06:21 +00:00
pr3d
This commit is contained in:
1
rust/Cargo.lock
generated
1
rust/Cargo.lock
generated
@@ -492,6 +492,7 @@ dependencies = [
|
|||||||
"godot",
|
"godot",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lightwave-3d",
|
"lightwave-3d",
|
||||||
|
"powerrender-3d",
|
||||||
"springylib",
|
"springylib",
|
||||||
"starforcelib",
|
"starforcelib",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ itertools = "0.10.5"
|
|||||||
dds-rs = "0.7.0"
|
dds-rs = "0.7.0"
|
||||||
starforcelib = { path = "../starforcelib" }
|
starforcelib = { path = "../starforcelib" }
|
||||||
springylib = { path = "../springylib" }
|
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 data_installer;
|
||||||
pub mod lightwave_object;
|
pub mod lightwave_object;
|
||||||
|
pub mod pr3d;
|
||||||
pub mod sproing;
|
pub mod sproing;
|
||||||
pub mod starforce;
|
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"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
binrw = "0.11.1"
|
binrw = "0.11.1"
|
||||||
half = "2.2.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
|
*index
|
||||||
} else {
|
} else {
|
||||||
surface.vertices.push([
|
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[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([
|
surface.normals.push([
|
||||||
point.normal[0] as f32 / 1024.0,
|
point.normal[0] as f32 / 1024.0,
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ use binrw::BinRead;
|
|||||||
use binrw::BinResult;
|
use binrw::BinResult;
|
||||||
use binrw::Endian;
|
use binrw::Endian;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::fs::File;
|
||||||
use std::io::{Read, Seek};
|
use std::io::{Read, Seek};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub(crate) mod chunk;
|
pub(crate) mod chunk;
|
||||||
pub(crate) mod internal;
|
pub(crate) mod internal;
|
||||||
@@ -57,6 +59,13 @@ pub struct PowerRenderMaterial {
|
|||||||
pub vert_shader: Option<String>,
|
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 {
|
impl ReadEndian for PowerRenderObject {
|
||||||
const ENDIAN: EndianKind = EndianKind::Endian(Endian::Little);
|
const ENDIAN: EndianKind = EndianKind::Endian(Endian::Little);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user