mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
all objects
This commit is contained in:
1 parent
14a2658a83
commit
965acadc3f
3 files changed
+116
-80
No files matched your search
@@ -224,10 +224,24 @@ public partial class GameInterface
|
|||||||
|
|
||||||
var visualData = row.Get<UObject>("VisualData");
|
var visualData = row.Get<UObject>("VisualData");
|
||||||
var meshSettings = visualData.Get<FStructFallback>("MeshSettings");
|
var meshSettings = visualData.Get<FStructFallback>("MeshSettings");
|
||||||
// var collisionMesh = meshSettings.Get<UStaticMesh>("CollisionMesh");
|
var meshes = new List<UStaticMesh>();
|
||||||
var mesh = meshSettings.Get<UStaticMesh>("Mesh");
|
|
||||||
|
|
||||||
var gltf = new MonoGltf(mesh);
|
foreach (var property in meshSettings.Properties)
|
||||||
|
{
|
||||||
|
var name = property.Name.Text;
|
||||||
|
|
||||||
|
if (name == "CollisionMesh")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meshSettings.TryGet<UStaticMesh>(name, out var mesh))
|
||||||
|
{
|
||||||
|
meshes.Add(mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var gltf = new MonoGltf(meshes);
|
||||||
|
|
||||||
return gltf.Write($"{tag}/{part}");
|
return gltf.Write($"{tag}/{part}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,88 +41,91 @@ public class MonoGltf
|
|||||||
};
|
};
|
||||||
readonly byte[] stubBytes = File.ReadAllBytes("../game/stub/small.png");
|
readonly byte[] stubBytes = File.ReadAllBytes("../game/stub/small.png");
|
||||||
|
|
||||||
public MonoGltf(UStaticMesh staticMesh)
|
public MonoGltf(List<UStaticMesh> meshes)
|
||||||
{
|
{
|
||||||
var options = new ExporterOptions() { TextureFormat = ETextureFormat.Jpeg };
|
var options = new ExporterOptions() { TextureFormat = ETextureFormat.Jpeg };
|
||||||
|
|
||||||
staticMesh.TryConvert(out var convertedMesh);
|
foreach (var mesh in meshes)
|
||||||
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<string, MaterialBuilder>();
|
|
||||||
|
|
||||||
int sectionIndex = 0;
|
|
||||||
foreach (var section in lod0.Sections.Value)
|
|
||||||
{
|
{
|
||||||
var meshBuilder = new ConfiguredMeshBuilder();
|
mesh.TryConvert(out var converted);
|
||||||
MaterialBuilder materialBuilder;
|
var lod0 =
|
||||||
|
converted.LODs.Find(lod => !lod.SkipLod) ?? throw new Exception("Failed to find lod0");
|
||||||
|
|
||||||
if (section.Material == null || section.MaterialName == null)
|
var emptyMaterial = new MaterialBuilder("empty_material");
|
||||||
{
|
var materialMap = new Dictionary<string, MaterialBuilder>();
|
||||||
materialBuilder = emptyMaterial;
|
|
||||||
}
|
|
||||||
else if (materialMap.TryGetValue(section.MaterialName, out MaterialBuilder? value))
|
|
||||||
{
|
|
||||||
materialBuilder = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var materialInterface = section.Material.Load<UMaterialInterface>()!;
|
|
||||||
var materialData = new MaterialData() { Parameters = new() };
|
|
||||||
|
|
||||||
materialInterface.GetParams(materialData.Parameters, options.MaterialFormat);
|
int sectionIndex = 0;
|
||||||
materialBuilder = new();
|
foreach (var section in lod0.Sections.Value)
|
||||||
materialMap.Add(section.MaterialName, materialBuilder);
|
{
|
||||||
|
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<UMaterialInterface>()!;
|
||||||
|
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;
|
if (knownChannels.TryGetValue(parameterTexture.Key, out var channel))
|
||||||
var name = Path.GetFileNameWithoutExtension(texture.GetPathName());
|
{
|
||||||
var path = $"../../../textures/{name}.webp";
|
var texture = parameterTexture.Value;
|
||||||
|
var name = Path.GetFileNameWithoutExtension(texture.GetPathName());
|
||||||
|
var path = $"../../../textures/{name}.webp";
|
||||||
|
|
||||||
var lastIndex = stubBytes.Length - 1;
|
var lastIndex = stubBytes.Length - 1;
|
||||||
stubBytes[lastIndex] = (byte)(++stubBytes[lastIndex] % 255);
|
stubBytes[lastIndex] = (byte)(++stubBytes[lastIndex] % 255);
|
||||||
var uniqueBytes = (byte[])stubBytes.Clone();
|
var uniqueBytes = (byte[])stubBytes.Clone();
|
||||||
var stubImage = new MemoryImage(uniqueBytes);
|
var stubImage = new MemoryImage(uniqueBytes);
|
||||||
|
|
||||||
// Console.WriteLine(
|
// Console.WriteLine(
|
||||||
// $"created stub image {stubImage} @ {stubImage.SourcePath} w/ byte {uniqueBytes[lastIndex]}"
|
// $"created stub image {stubImage} @ {stubImage.SourcePath} w/ byte {uniqueBytes[lastIndex]}"
|
||||||
// );
|
// );
|
||||||
|
|
||||||
materialBuilder.WithChannelImage(channel, stubImage);
|
materialBuilder.WithChannelImage(channel, stubImage);
|
||||||
materialBuilder.GetChannel(channel).Texture.PrimaryImage.Name = path;
|
materialBuilder.GetChannel(channel).Texture.PrimaryImage.Name = path;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Console.WriteLine($"Unsupported texture type: {parameterTexture.Key}");
|
// 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++)
|
for (int faceIndex = 0; faceIndex < section.NumFaces; faceIndex++)
|
||||||
{
|
|
||||||
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 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]];
|
scene.AddRigidMesh(meshBuilder, Matrix4x4.Identity);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { OrbitControls } from "@react-three/drei";
|
|||||||
import { Canvas, useLoader } from "@react-three/fiber";
|
import { Canvas, useLoader } from "@react-three/fiber";
|
||||||
import { Mesh, MeshStandardMaterial } from "three";
|
import { Mesh, MeshStandardMaterial } from "three";
|
||||||
import { GLTFLoader } from "three-stdlib";
|
import { GLTFLoader } from "three-stdlib";
|
||||||
|
import { useProtagonist } from "../../hooks/useProtagonist";
|
||||||
import styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
export function TankopediaSandbox() {
|
export function TankopediaSandbox() {
|
||||||
@@ -22,28 +23,46 @@ export function TankopediaSandbox() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
const gltf = useLoader(
|
const tank = useProtagonist();
|
||||||
|
|
||||||
|
const turret = useLoader(
|
||||||
GLTFLoader,
|
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) => {
|
const gltfs = [turret, gun, hull, chassis];
|
||||||
if (
|
|
||||||
child instanceof Mesh &&
|
|
||||||
child.material instanceof MeshStandardMaterial
|
|
||||||
) {
|
|
||||||
// TODO: remove this hack and fix the gltf
|
|
||||||
child.material.vertexColors = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
child.castShadow = true;
|
for (const gltf of gltfs) {
|
||||||
child.receiveShadow = true;
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<group>
|
<group>
|
||||||
<primitive object={gltf.scene} />
|
<primitive object={chassis.scene} />
|
||||||
|
<primitive object={hull.scene} />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group position={[0, 0, 5]}>
|
||||||
|
<primitive object={turret.scene} />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group position={[0, 0, -5]}>
|
||||||
|
<primitive object={gun.scene} />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<spotLight
|
<spotLight
|
||||||
@@ -54,7 +73,7 @@ function Content() {
|
|||||||
/>
|
/>
|
||||||
<ambientLight />
|
<ambientLight />
|
||||||
|
|
||||||
<mesh receiveShadow position={[0, -1, 0]} rotation={[-Math.PI / 2, 0, 0]}>
|
<mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]}>
|
||||||
<planeGeometry args={[2 ** 8, 2 ** 8]} />
|
<planeGeometry args={[2 ** 8, 2 ** 8]} />
|
||||||
<meshStandardMaterial color="gray" />
|
<meshStandardMaterial color="gray" />
|
||||||
</mesh>
|
</mesh>
|
||||||
|
|||||||
Reference in new issue
Block a user