From 965acadc3f4789342fafccf878a072d0d5b36de3 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Tue, 9 Jun 2026 14:00:24 -0500 Subject: [PATCH] all objects --- packages/game/JSExport/GameInterface.cs | 20 ++- packages/game/Models/MonoGltf.cs | 127 +++++++++--------- .../components/TankopediaSandbox/index.tsx | 49 ++++--- 3 files changed, 116 insertions(+), 80 deletions(-) diff --git a/packages/game/JSExport/GameInterface.cs b/packages/game/JSExport/GameInterface.cs index 45271458d..51d2e1c4c 100644 --- a/packages/game/JSExport/GameInterface.cs +++ b/packages/game/JSExport/GameInterface.cs @@ -224,10 +224,24 @@ public partial class GameInterface var visualData = row.Get("VisualData"); var meshSettings = visualData.Get("MeshSettings"); - // var collisionMesh = meshSettings.Get("CollisionMesh"); - var mesh = meshSettings.Get("Mesh"); + var meshes = new List(); - var gltf = new MonoGltf(mesh); + foreach (var property in meshSettings.Properties) + { + var name = property.Name.Text; + + if (name == "CollisionMesh") + { + continue; + } + + if (meshSettings.TryGet(name, out var mesh)) + { + meshes.Add(mesh); + } + } + + var gltf = new MonoGltf(meshes); return gltf.Write($"{tag}/{part}"); } diff --git a/packages/game/Models/MonoGltf.cs b/packages/game/Models/MonoGltf.cs index a7d16212e..1cde75a9d 100644 --- a/packages/game/Models/MonoGltf.cs +++ b/packages/game/Models/MonoGltf.cs @@ -41,88 +41,91 @@ public class MonoGltf }; readonly byte[] stubBytes = File.ReadAllBytes("../game/stub/small.png"); - public MonoGltf(UStaticMesh staticMesh) + public MonoGltf(List meshes) { var options = new ExporterOptions() { TextureFormat = ETextureFormat.Jpeg }; - staticMesh.TryConvert(out var convertedMesh); - var lod0 = - convertedMesh.LODs.Find(lod => !lod.SkipLod) ?? throw new Exception("Failed to find lod0"); - - var emptyMaterial = new MaterialBuilder("empty_material"); - var materialMap = new Dictionary(); - - int sectionIndex = 0; - foreach (var section in lod0.Sections.Value) + foreach (var mesh in meshes) { - var meshBuilder = new ConfiguredMeshBuilder(); - MaterialBuilder materialBuilder; + mesh.TryConvert(out var converted); + var lod0 = + converted.LODs.Find(lod => !lod.SkipLod) ?? throw new Exception("Failed to find lod0"); - if (section.Material == null || section.MaterialName == null) - { - materialBuilder = emptyMaterial; - } - else if (materialMap.TryGetValue(section.MaterialName, out MaterialBuilder? value)) - { - materialBuilder = value; - } - else - { - var materialInterface = section.Material.Load()!; - var materialData = new MaterialData() { Parameters = new() }; + var emptyMaterial = new MaterialBuilder("empty_material"); + var materialMap = new Dictionary(); - materialInterface.GetParams(materialData.Parameters, options.MaterialFormat); - materialBuilder = new(); - materialMap.Add(section.MaterialName, materialBuilder); + int sectionIndex = 0; + foreach (var section in lod0.Sections.Value) + { + var meshBuilder = new ConfiguredMeshBuilder(); + MaterialBuilder materialBuilder; - foreach (var parameterTexture in materialData.Parameters.Textures) + if (section.Material == null || section.MaterialName == null) { - if (knownChannels.TryGetValue(parameterTexture.Key, out var channel)) + materialBuilder = emptyMaterial; + } + else if (materialMap.TryGetValue(section.MaterialName, out MaterialBuilder? value)) + { + materialBuilder = value; + } + else + { + var materialInterface = section.Material.Load()!; + var materialData = new MaterialData() { Parameters = new() }; + + materialInterface.GetParams(materialData.Parameters, options.MaterialFormat); + materialBuilder = new(); + materialMap.Add(section.MaterialName, materialBuilder); + + foreach (var parameterTexture in materialData.Parameters.Textures) { - var texture = parameterTexture.Value; - var name = Path.GetFileNameWithoutExtension(texture.GetPathName()); - var path = $"../../../textures/{name}.webp"; + if (knownChannels.TryGetValue(parameterTexture.Key, out var channel)) + { + var texture = parameterTexture.Value; + var name = Path.GetFileNameWithoutExtension(texture.GetPathName()); + var path = $"../../../textures/{name}.webp"; - var lastIndex = stubBytes.Length - 1; - stubBytes[lastIndex] = (byte)(++stubBytes[lastIndex] % 255); - var uniqueBytes = (byte[])stubBytes.Clone(); - var stubImage = new MemoryImage(uniqueBytes); + var lastIndex = stubBytes.Length - 1; + stubBytes[lastIndex] = (byte)(++stubBytes[lastIndex] % 255); + var uniqueBytes = (byte[])stubBytes.Clone(); + var stubImage = new MemoryImage(uniqueBytes); - // Console.WriteLine( - // $"created stub image {stubImage} @ {stubImage.SourcePath} w/ byte {uniqueBytes[lastIndex]}" - // ); + // Console.WriteLine( + // $"created stub image {stubImage} @ {stubImage.SourcePath} w/ byte {uniqueBytes[lastIndex]}" + // ); - materialBuilder.WithChannelImage(channel, stubImage); - materialBuilder.GetChannel(channel).Texture.PrimaryImage.Name = path; - } - else - { - // Console.WriteLine($"Unsupported texture type: {parameterTexture.Key}"); + materialBuilder.WithChannelImage(channel, stubImage); + materialBuilder.GetChannel(channel).Texture.PrimaryImage.Name = path; + } + else + { + // Console.WriteLine($"Unsupported texture type: {parameterTexture.Key}"); + } } } - } - var primitive = meshBuilder.UsePrimitive(materialBuilder); + var primitive = meshBuilder.UsePrimitive(materialBuilder); - for (int faceIndex = 0; faceIndex < section.NumFaces; faceIndex++) - { - var wedgeIndex = new int[3]; - for (var k = 0; k < wedgeIndex.Length; k++) + for (int faceIndex = 0; faceIndex < section.NumFaces; faceIndex++) { - wedgeIndex[k] = (int)lod0.Indices.Value[section.FirstIndex + faceIndex * 3 + k]; + var wedgeIndex = new int[3]; + for (var k = 0; k < wedgeIndex.Length; k++) + { + wedgeIndex[k] = (int)lod0.Indices.Value[section.FirstIndex + faceIndex * 3 + k]; + } + + var vertex1 = lod0.Verts[wedgeIndex[0]]; + var vertex2 = lod0.Verts[wedgeIndex[1]]; + var vertex3 = lod0.Verts[wedgeIndex[2]]; + + var (v1, v2, v3) = PrepareTris(vertex1, vertex2, vertex3); + var (c1, c2, c3) = PrepareUVsAndTexCoords(lod0, vertex1, vertex2, vertex3, wedgeIndex); + + primitive.AddTriangle((v1, c1), (v2, c2), (v3, c3)); } - var vertex1 = lod0.Verts[wedgeIndex[0]]; - var vertex2 = lod0.Verts[wedgeIndex[1]]; - var vertex3 = lod0.Verts[wedgeIndex[2]]; - - var (v1, v2, v3) = PrepareTris(vertex1, vertex2, vertex3); - var (c1, c2, c3) = PrepareUVsAndTexCoords(lod0, vertex1, vertex2, vertex3, wedgeIndex); - - primitive.AddTriangle((v1, c1), (v2, c2), (v3, c3)); + scene.AddRigidMesh(meshBuilder, Matrix4x4.Identity); } - - scene.AddRigidMesh(meshBuilder, Matrix4x4.Identity); } } diff --git a/packages/website-ue/src/components/TankopediaSandbox/index.tsx b/packages/website-ue/src/components/TankopediaSandbox/index.tsx index 9e3b93535..fff6e4096 100644 --- a/packages/website-ue/src/components/TankopediaSandbox/index.tsx +++ b/packages/website-ue/src/components/TankopediaSandbox/index.tsx @@ -2,6 +2,7 @@ import { OrbitControls } from "@react-three/drei"; import { Canvas, useLoader } from "@react-three/fiber"; import { Mesh, MeshStandardMaterial } from "three"; import { GLTFLoader } from "three-stdlib"; +import { useProtagonist } from "../../hooks/useProtagonist"; import styles from "./index.module.css"; export function TankopediaSandbox() { @@ -22,28 +23,46 @@ export function TankopediaSandbox() { } function Content() { - const gltf = useLoader( + const tank = useProtagonist(); + + const turret = useLoader( GLTFLoader, - "/models/tanks/TankEntity.A128_Concept_1b/hull.glb", + `/models/tanks/${tank.id}/turret_01.glb`, ); + const gun = useLoader(GLTFLoader, `/models/tanks/${tank.id}/gun_01.glb`); + const hull = useLoader(GLTFLoader, `/models/tanks/${tank.id}/hull.glb`); + const chassis = useLoader(GLTFLoader, `/models/tanks/${tank.id}/chassis.glb`); - gltf.scene.traverse((child) => { - if ( - child instanceof Mesh && - child.material instanceof MeshStandardMaterial - ) { - // TODO: remove this hack and fix the gltf - child.material.vertexColors = false; - } + const gltfs = [turret, gun, hull, chassis]; - child.castShadow = true; - child.receiveShadow = true; - }); + for (const gltf of gltfs) { + gltf.scene.traverse((child) => { + if ( + child instanceof Mesh && + child.material instanceof MeshStandardMaterial + ) { + // TODO: remove this hack and fix the gltf + child.material.vertexColors = false; + } + + child.castShadow = true; + child.receiveShadow = true; + }); + } return ( <> - + + + + + + + + + + - +