public override void Initialize(FObjectInitializer initializer) { base.Initialize(initializer); if (baseMaterial.Value == null) { baseMaterial.Value = ConstructorHelpers.FObjectFinder <UMaterialInterface> .Find("Material'/Game/Puzzle/Meshes/BaseMaterial.BaseMaterial'"); } if (blueMaterial.Value == null) { blueMaterial.Value = ConstructorHelpers.FObjectFinder <UMaterialInterface> .Find("MaterialInstanceConstant'/Game/Puzzle/Meshes/BlueMaterial.BlueMaterial'"); } if (orangeMaterial.Value == null) { orangeMaterial.Value = ConstructorHelpers.FObjectFinder <UMaterialInterface> .Find("MaterialInstanceConstant'/Game/Puzzle/Meshes/OrangeMaterial.OrangeMaterial'"); } UStaticMesh mesh = ConstructorHelpers.FObjectFinder <UStaticMesh> .Find("StaticMesh'/Game/Puzzle/Meshes/PuzzleCube.PuzzleCube'"); if (mesh != null) { BlockMesh = initializer.CreateDefaultSubobject <UStaticMeshComponent>(this, new FName("BlockMesh")); BlockMesh.SetStaticMesh(mesh); BlockMesh.RelativeLocation = new FVector(0, 0, 25); BlockMesh.RelativeScale3D = new FVector(1, 1, 0.25f); RootComponent = BlockMesh; if (blueMaterial.Value != null) { BlockMesh.SetMaterial(0, blueMaterial.Value); } } }
public void Init(UStaticMesh mesh, OpenGL gl) { int i = 0; var materials = mesh.GetMaterials(); foreach (SMeshFace face in mesh.Faces) { MeshSurfice s = new MeshSurfice(); int end_offset = face.index_offset + (face.triangle_count * 3); for (int j = face.index_offset; j < end_offset; j += 3) { s.Vertices.Add(mesh.Verteces[mesh.vertex_indicies_1[j]].Location.ToVertex()); s.Vertices.Add(mesh.Verteces[mesh.vertex_indicies_1[j + 1]].Location.ToVertex()); s.Vertices.Add(mesh.Verteces[mesh.vertex_indicies_1[j + 2]].Location.ToVertex()); s.UVs.Add(mesh.texture_coords[0].elements[mesh.vertex_indicies_1[j]].UV.ToUV()); s.UVs.Add(mesh.texture_coords[0].elements[mesh.vertex_indicies_1[j + 1]].UV.ToUV()); s.UVs.Add(mesh.texture_coords[0].elements[mesh.vertex_indicies_1[j + 2]].UV.ToUV()); s.Normals.Add(mesh.Verteces[mesh.vertex_indicies_1[j]].Normal.ToVertex()); s.Normals.Add(mesh.Verteces[mesh.vertex_indicies_1[j + 1]].Normal.ToVertex()); s.Normals.Add(mesh.Verteces[mesh.vertex_indicies_1[j + 2]].Normal.ToVertex()); } SceneGraph.Assets.Material mat = new SharpGL.SceneGraph.Assets.Material(); Texture texture = new Texture(); System.Drawing.Bitmap image = LibSquish.GetImage(materials[i].Texture); texture.Create(gl, image); mat.Texture = texture; s.Material = mat; s.TriangleCount = face.triangle_count; Surfices.Add(s); i++; } vertices = Surfices.SelectMany(s => s.Vertices).ToList(); Console.WriteLine(); }
public MeshExporter(UStaticMesh originalMesh, ELodFormat lodFormat = ELodFormat.FirstLod, bool exportMaterials = true) { _meshName = originalMesh.Owner?.Name ?? originalMesh.Name; if (!originalMesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Length <= 0) { Log.Logger.Warning($"Mesh '{_meshName}' has no LODs"); _meshLods = new Mesh[0]; return; } _meshLods = new Mesh[lodFormat == ELodFormat.AllLods ? convertedMesh.LODs.Length : 1]; for (var i = 0; i < _meshLods.Length; i++) { if (convertedMesh.LODs[i].Sections.Value.Length <= 0 || convertedMesh.LODs[i].Indices.Value == null) { Log.Logger.Warning($"LOD {i} in mesh '{_meshName}' has no section"); continue; } using var writer = new FCustomArchiveWriter(); var materialExports = exportMaterials ? new List <MaterialExporter>() : null; ExportStaticMeshLods(convertedMesh.LODs[i], writer, materialExports); _meshLods[i] = new Mesh($"{_meshName}_LOD{i}.pskx", writer.GetBuffer(), materialExports ?? new List <MaterialExporter>()); } }
public MeshExporter(UStaticMesh originalMesh, ELodFormat lodFormat = ELodFormat.FirstLod, bool exportMaterials = true, EMeshFormat meshFormat = EMeshFormat.ActorX, ETexturePlatform platform = ETexturePlatform.DesktopMobile) { MeshLods = new List <Mesh>(); MeshName = originalMesh.Owner?.Name ?? originalMesh.Name; if (!originalMesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count == 0) { Log.Logger.Warning($"Mesh '{MeshName}' has no LODs"); return; } var i = 0; foreach (var lod in convertedMesh.LODs) { if (lod.SkipLod) { Log.Logger.Warning($"LOD {i} in mesh '{MeshName}' should be skipped"); continue; } using var Ar = new FArchiveWriter(); var materialExports = exportMaterials ? new List <MaterialExporter>() : null; string ext; switch (meshFormat) { case EMeshFormat.ActorX: ext = "pskx"; ExportStaticMeshLods(lod, Ar, materialExports); break; case EMeshFormat.Gltf2: ext = "glb"; new Gltf(MeshName.SubstringAfterLast("/"), lod, materialExports).Save(meshFormat, Ar); break; case EMeshFormat.OBJ: ext = "obj"; new Gltf(MeshName.SubstringAfterLast("/"), lod, materialExports).Save(meshFormat, Ar); break; default: throw new ArgumentOutOfRangeException(nameof(meshFormat), meshFormat, null); } MeshLods.Add(new Mesh($"{MeshName}_LOD{i}.{ext}", Ar.GetBuffer(), materialExports ?? new List <MaterialExporter>())); if (lodFormat == ELodFormat.FirstLod) { break; } i++; } }
private void cloneToolStripMenuItem_Click(object sender, EventArgs e) { int Sel = -1; TreeNode t = treeView1.SelectedNode; if (t != null && t.Parent != null) { TreeNode t2 = t.Parent; if (t2.Text == "Static Meshes") { Sel = t.Index; } } if (Sel == -1) { return; } if (Level.UStat[Sel].LP.source == 1)//Collection { int index = Level.UStat[Sel].LP.sourceentry; int index2 = Level.UStat[Sel].index2; for (int i = 0; i < Level.UStatColl.Count; i++) { if (Level.UStatColl[i].LP.sourceentry == index) { for (int j = 0; j < Level.UStatColl[i].Entries.Count; j++) { if (Level.UStatColl[i].Entries[j] == index2) { Level.UStatColl[i].CloneObject(j); UStaticMesh u = Level.UStat[Sel]; UStaticMesh u2 = new UStaticMesh(); u2.LP = u.LP; u2.DirectX = u.DirectX; u2.bound = u.bound; u2.index = u.index; u2.index2 = u.index2; Level.UStat.Add(u2); GenerateTree(); TreeNode t2 = treeView1.Nodes[0]; t2.Expand(); treeView1.SelectedNode = t2.Nodes[Sel]; MessageBox.Show("Done."); return; } } } } } }
public static bool TryConvert(this UStaticMesh originalMesh, out CStaticMesh convertedMesh) { convertedMesh = new CStaticMesh(); if (originalMesh.RenderData == null) { return(false); } convertedMesh.BoundingSphere = new FSphere(0f, 0f, 0f, originalMesh.RenderData.Bounds.SphereRadius / 2); convertedMesh.BoundingBox = new FBox( originalMesh.RenderData.Bounds.Origin - originalMesh.RenderData.Bounds.BoxExtent, originalMesh.RenderData.Bounds.Origin + originalMesh.RenderData.Bounds.BoxExtent); foreach (var srcLod in originalMesh.RenderData.LODs) { if (srcLod.SkipLod) { continue; } var numTexCoords = srcLod.VertexBuffer !.NumTexCoords; var numVerts = srcLod.PositionVertexBuffer !.Verts.Length; if (numVerts == 0 && numTexCoords == 0) { continue; } if (numTexCoords > Constants.MAX_MESH_UV_SETS) { throw new ParserException($"Static mesh has too many UV sets ({numTexCoords})"); } var staticMeshLod = new CStaticMeshLod { NumTexCoords = numTexCoords, HasNormals = true, HasTangents = true, Indices = new Lazy <FRawStaticIndexBuffer>(srcLod.IndexBuffer !), Sections = new Lazy <CMeshSection[]>(() => { var sections = new CMeshSection[srcLod.Sections.Length]; for (var j = 0; j < sections.Length; j++) { sections[j] = new CMeshSection(srcLod.Sections[j].MaterialIndex, originalMesh.StaticMaterials?[srcLod.Sections[j].MaterialIndex].MaterialSlotName.Text, // materialName originalMesh.Materials?[srcLod.Sections[j].MaterialIndex], // material srcLod.Sections[j].FirstIndex, // firstIndex srcLod.Sections[j].NumTriangles); // numFaces } return(sections); }) }; staticMeshLod.AllocateVerts(numVerts); if (srcLod.ColorVertexBuffer !.NumVertices != 0) { staticMeshLod.AllocateVertexColorBuffer(); } for (var j = 0; j < numVerts; j++) { var suv = srcLod.VertexBuffer.UV[j]; if (suv.Normal[1].Data != 0) { throw new ParserException("Not implemented: should only be used in UE3"); } staticMeshLod.Verts[j].Position = srcLod.PositionVertexBuffer.Verts[j]; UnpackNormals(suv.Normal, staticMeshLod.Verts[j]); staticMeshLod.Verts[j].UV.U = suv.UV[0].U; staticMeshLod.Verts[j].UV.V = suv.UV[0].V; for (var k = 1; k < numTexCoords; k++) { staticMeshLod.ExtraUV.Value[k - 1][j].U = suv.UV[k].U; staticMeshLod.ExtraUV.Value[k - 1][j].V = suv.UV[k].V; } if (srcLod.ColorVertexBuffer.NumVertices != 0) { staticMeshLod.VertexColors ![j] = srcLod.ColorVertexBuffer.Data[j];
public static bool TryConvert(this UStaticMesh originalMesh, out CStaticMesh convertedMesh) { convertedMesh = new CStaticMesh(); if (originalMesh.RenderData == null) { return(false); } convertedMesh.BoundingShere = new FSphere(0f, 0f, 0f, originalMesh.RenderData.Bounds.SphereRadius / 2); convertedMesh.BoundingBox = new FBox( originalMesh.RenderData.Bounds.Origin - originalMesh.RenderData.Bounds.BoxExtent, originalMesh.RenderData.Bounds.Origin + originalMesh.RenderData.Bounds.BoxExtent); var numLods = originalMesh.RenderData.LODs.Length; convertedMesh.LODs = new CStaticMeshLod[numLods]; for (var i = 0; i < convertedMesh.LODs.Length; i++) { if (originalMesh.RenderData.LODs[i] is not { VertexBuffer: not null, PositionVertexBuffer: not null, ColorVertexBuffer: not null, IndexBuffer: not null } srcLod) { continue; } var numTexCoords = srcLod.VertexBuffer.NumTexCoords; var numVerts = srcLod.PositionVertexBuffer.Verts.Length; if (numVerts == 0 && numTexCoords == 0 && i < numLods - 1) { Log.Logger.Debug($"LOD {i} is stripped, skipping..."); continue; } if (numTexCoords > _MAX_MESH_UV_SETS) { throw new ParserException($"Static mesh has too many UV sets ({numTexCoords})"); } convertedMesh.LODs[i] = new CStaticMeshLod { NumTexCoords = numTexCoords, HasNormals = true, HasTangents = true, Indices = new Lazy <FRawStaticIndexBuffer>(srcLod.IndexBuffer), Sections = new Lazy <CMeshSection[]>(() => { var sections = new CMeshSection[srcLod.Sections.Length]; for (var j = 0; j < sections.Length; j++) { sections[j] = new CMeshSection(originalMesh.Materials?[srcLod.Sections[j].MaterialIndex], srcLod.Sections[j].FirstIndex, srcLod.Sections[j].NumTriangles); } return(sections); }) }; convertedMesh.LODs[i].AllocateVerts(numVerts); if (srcLod.ColorVertexBuffer.NumVertices != 0) { convertedMesh.LODs[i].AllocateVertexColorBuffer(); } for (var j = 0; j < numVerts; j++) { var suv = srcLod.VertexBuffer.UV[j]; if (suv.Normal[1].Data != 0) { throw new ParserException("Not implemented: should only be used in UE3"); } convertedMesh.LODs[i].Verts[j].Position = srcLod.PositionVertexBuffer.Verts[j]; UnpackNormals(suv.Normal, convertedMesh.LODs[i].Verts[j]); convertedMesh.LODs[i].Verts[j].UV.U = suv.UV[0].U; convertedMesh.LODs[i].Verts[j].UV.V = suv.UV[0].V; for (var k = 1; k < numTexCoords; k++) { convertedMesh.LODs[i].ExtraUV.Value[k - 1][j].U = suv.UV[k].U; convertedMesh.LODs[i].ExtraUV.Value[k - 1][j].V = suv.UV[k].V; } if (srcLod.ColorVertexBuffer.NumVertices != 0) convertedMesh.LODs[i].VertexColors[j] = srcLod.ColorVertexBuffer.Data[j]; } } convertedMesh.FinalizeMesh(); return(true); }