diff options
-rw-r--r-- | src/earth.proto | 2 | ||||
-rw-r--r-- | src/main.rs | 93 | ||||
-rw-r--r-- | src/mesh.rs | 43 |
3 files changed, 77 insertions, 61 deletions
diff --git a/src/earth.proto b/src/earth.proto index 0f0b3d0..90288d1 100644 --- a/src/earth.proto +++ b/src/earth.proto @@ -1,3 +1,5 @@ +// Adapted from https://github.com/retroplasma/earth-reverse-engineering + syntax = "proto2"; package earth.proto; diff --git a/src/main.rs b/src/main.rs index 733dbcc..988a5ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,10 @@ #![feature(array_chunks)] +pub mod mesh; + use anyhow::{Result, bail}; -use glam::Vec3; +use glam::{DAffine3, DMat4, Vec3}; use log::{debug, error}; +use mesh::convert_mesh; use prost::{Message, bytes::Bytes}; use proto::{BulkMetadata, NodeData, NodeMetadata, PlanetoidMetadata}; use reqwest::{ @@ -10,15 +13,14 @@ use reqwest::{ }; use std::path::PathBuf; use tokio::{ - fs::{File, create_dir, create_dir_all}, + fs::{File, create_dir_all}, io::{AsyncReadExt, AsyncWriteExt}, }; use weareshared::{ - Affine3A, Vec3A, - resources::{MeshPart, Prefab, RespackEntry}, + Affine3A, + resources::{Prefab, RespackEntry}, respack::save_full_respack, store::ResourceStore, - vec3a, }; #[tokio::main] @@ -28,77 +30,44 @@ async fn main() -> Result<()> { let c = GeClient::new().await?; let entry = c.planetoid_metdata().await?; - eprintln!("{:#?}", entry); - - let mut bulk = c + let bulk = c .bulk_metadata("", entry.root_node_metadata.unwrap().bulk_metadata_epoch()) .await?; - eprintln!("{:#?}", bulk); - let store = ResourceStore::new_memory(); - let mut meshes = Vec::new(); - + let mut prefabs = Vec::new(); for node_meta in &bulk.node_metadata { - let Ok(mut node_data) = c.node_data(&bulk, &node_meta).await else { + if unpack_path_and_id(node_meta.path_and_flags()).0.len() != 4 { + // toplevel octs are not found + // also i want most subdivided continue; - }; - - for m in node_data.meshes { - let mut index_strip = Vec::new(); + } - let strip_len = m.indices[0]; - let mut zeros = 0; - for i in 0..strip_len { - let val = m.indices[i as usize + 1]; - index_strip.push((zeros - val) as u32); - if val == 0 { - zeros += 1; - } - } - let mut index = Vec::new(); - for i in 0..index_strip.len() - 2 { - if i & 1 == 0 { - index.push([index_strip[i + 0], index_strip[i + 1], index_strip[i + 2]]); - } else { - index.push([index_strip[i + 0], index_strip[i + 2], index_strip[i + 1]]); - } - } + let Ok(node_data) = c.node_data(&bulk, &node_meta).await else { + continue; + }; - let mut positions = Vec::new(); - let vert = m.vertices(); - let vertex_count = vert.len() / 3; - let (mut x, mut y, mut z) = (0u8, 0u8, 0u8); - for i in 0..vertex_count { - x = x.wrapping_add(vert[vertex_count * 0 + i]); - y = y.wrapping_add(vert[vertex_count * 1 + i]); - z = z.wrapping_add(vert[vertex_count * 2 + i]); - positions.push(vec3a(x as f32, y as f32, z as f32)); - } - // eprintln!("{index:?}"); - // eprintln!("{positions:?}"); + let transform = DMat4::from_cols_slice(&node_data.matrix_globe_from_mesh); + let mut meshes = Vec::new(); + for m in node_data.meshes { + let mesh = convert_mesh(m, &store)?; meshes.push(( - Affine3A::from_scale(Vec3::splat(0.01)), - store.set(&MeshPart { - index: Some(store.set(&index)?), - va_position: Some(store.set(&positions)?), - g_double_sided: Some(()), - ..Default::default() - })?, + Affine3A::from_mat4((transform / 3_000_000.).as_mat4()), + mesh, )) } - } - eprintln!("{}", meshes.len()); - let prefab = store.set(&Prefab { - mesh: meshes, - ..Default::default() - })?; + prefabs.push(store.set(&Prefab { + transform: Some(DAffine3::from_mat4(transform)), + mesh: meshes, + ..Default::default() + })?); + } let entry = store.set(&RespackEntry { - c_prefab: vec![prefab], + c_prefab: prefabs, ..Default::default() })?; @@ -167,7 +136,9 @@ impl GeClient { let texture_format = bulk.default_available_texture_formats(); let imagery_epoch = node.imagery_epoch.unwrap_or(bulk.default_imagery_epoch()); - let node_epoch = bulk.head_node_key.as_ref().unwrap().epoch.unwrap(); // ? + let node_epoch = node + .epoch + .unwrap_or(bulk.head_node_key.as_ref().unwrap().epoch.unwrap()); // ? let image_epoch_part = if flags & 16 != 0 { format!("!3u{imagery_epoch}") diff --git a/src/mesh.rs b/src/mesh.rs new file mode 100644 index 0000000..d491a97 --- /dev/null +++ b/src/mesh.rs @@ -0,0 +1,43 @@ +use crate::proto::Mesh; +use anyhow::Result; +use glam::vec3a; +use weareshared::{packets::Resource, resources::MeshPart, store::ResourceStore}; + +pub fn convert_mesh(m: Mesh, store: &ResourceStore) -> Result<Resource<MeshPart>> { + let mut index_strip = Vec::new(); + let strip_len = m.indices[0]; + let mut zeros = 0; + for i in 0..strip_len { + let val = m.indices[i as usize + 1]; + index_strip.push((zeros - val) as u32); + if val == 0 { + zeros += 1; + } + } + let mut index = Vec::new(); + for i in 0..index_strip.len() - 2 { + if i & 1 == 0 { + index.push([index_strip[i + 0], index_strip[i + 1], index_strip[i + 2]]); + } else { + index.push([index_strip[i + 0], index_strip[i + 2], index_strip[i + 1]]); + } + } + + let mut positions = Vec::new(); + let vert = m.vertices(); + let vertex_count = vert.len() / 3; + let (mut x, mut y, mut z) = (0u8, 0u8, 0u8); + for i in 0..vertex_count { + x = x.wrapping_add(vert[vertex_count * 0 + i]); + y = y.wrapping_add(vert[vertex_count * 1 + i]); + z = z.wrapping_add(vert[vertex_count * 2 + i]); + positions.push(vec3a(x as f32, y as f32, z as f32)); + } + + Ok(store.set(&MeshPart { + index: Some(store.set(&index)?), + va_position: Some(store.set(&positions)?), + g_double_sided: Some(()), + ..Default::default() + })?) +} |