/// <summary> /// Creates a preview of the given <see cref="SkeletalMesh"/>. /// </summary> /// <param name="Device">The Direct3D device to use for buffer creation.</param> /// <param name="m">The mesh to generate a preview for.</param> /// <param name="texcache">The texture cache for loading textures.</param> public ModelPreview(Device Device, SkeletalMesh m, PreviewTextureCache texcache, PackageCache assetCache, PreloadedModelData preloadedData = null) { // STEP 1: MATERIALS if (preloadedData == null) { for (int i = 0; i < m.Materials.Length; i++) { UIndex materialUIndex = m.Materials[i]; MaterialInstanceConstant mat = null; if (materialUIndex.value > 0) { mat = new MaterialInstanceConstant(m.Export.FileRef.GetUExport(materialUIndex.value)); } else if (materialUIndex.value < 0) { // The material instance is an import! ImportEntry matImport = m.Export.FileRef.GetImport(materialUIndex.value); var externalAsset = EntryImporter.ResolveImport(matImport, null, assetCache); if (externalAsset != null) { mat = new MaterialInstanceConstant(externalAsset); } } if (mat != null) { ModelPreviewMaterial material; // TODO: pick what material class best fits based on what properties the // MaterialInstanceConstant mat has. // For now, just use the default material. material = new TexturedPreviewMaterial(texcache, mat, assetCache); AddMaterial(material.Properties["Name"], material); } } } else { //Preloaded //sections = preloadedData.sections; var uniqueMaterials = preloadedData.texturePreviewMaterials.Select(x => x.MaterialExport).Distinct(); foreach (var mat in uniqueMaterials) { var material = new TexturedPreviewMaterial(texcache, new MaterialInstanceConstant(mat), assetCache, preloadedData.texturePreviewMaterials); AddMaterial(mat.ObjectName.Name, material); } } // STEP 2: LODS foreach (var lodmodel in m.LODModels) { // Vertices List <WorldVertex> vertices = new List <WorldVertex>(m.Export.Game == MEGame.ME1 ? lodmodel.ME1VertexBufferGPUSkin.Length : lodmodel.VertexBufferGPUSkin.VertexData.Length); if (m.Export.Game == MEGame.ME1) { foreach (var vertex in lodmodel.ME1VertexBufferGPUSkin) { vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UV.X, vertex.UV.Y))); } } else { foreach (var vertex in lodmodel.VertexBufferGPUSkin.VertexData) { vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UV.X, vertex.UV.Y))); } } // Triangles List <Triangle> triangles = new List <Triangle>(lodmodel.IndexBuffer.Length / 3); for (int i = 0; i < lodmodel.IndexBuffer.Length; i += 3) { triangles.Add(new Triangle(lodmodel.IndexBuffer[i], lodmodel.IndexBuffer[i + 1], lodmodel.IndexBuffer[i + 2])); } WorldMesh mesh = new WorldMesh(Device, triangles, vertices); // Sections List <ModelPreviewSection> sections = new List <ModelPreviewSection>(); foreach (var section in lodmodel.Sections) { if (section.MaterialIndex < Materials.Count) { sections.Add(new ModelPreviewSection(Materials.Keys.ElementAt(section.MaterialIndex), section.BaseIndex, (uint)section.NumTriangles)); } } LODs.Add(new ModelPreviewLOD(mesh, sections)); } }
public static StaticMesh ConvertToME3StaticMesh(this SkeletalMesh skeletalMesh) { StaticLODModel lodModel = skeletalMesh.LODModels[0]; uint numVertices = lodModel.NumVertices; var stm = new StaticMesh { Bounds = skeletalMesh.Bounds, BodySetup = new UIndex(0), LODModels = new[] { new StaticMeshRenderData { IndexBuffer = lodModel.IndexBuffer.TypedClone(), NumVertices = numVertices, Edges = new MeshEdge[0], RawTriangles = new StaticMeshTriangle[0], ColorVertexBuffer = new ColorVertexBuffer(), ShadowTriangleDoubleSided = new byte[0], WireframeIndexBuffer = new ushort[0], ShadowExtrusionVertexBuffer = new ExtrusionVertexBuffer { Stride = 4, VertexData = new float[0] }, PositionVertexBuffer = new PositionVertexBuffer { NumVertices = numVertices, Stride = 12, VertexData = new Vector3[numVertices] }, VertexBuffer = new StaticMeshVertexBuffer { bUseFullPrecisionUVs = false, NumTexCoords = 1, NumVertices = numVertices, VertexData = new StaticMeshVertexBuffer.StaticMeshFullVertex[numVertices] }, Elements = lodModel.Sections.Select(sec => { var indices = lodModel.IndexBuffer.Skip((int)sec.BaseIndex).Take(sec.NumTriangles * 3).ToList(); return(new StaticMeshElement { bEnableShadowCasting = true, EnableCollision = true, OldEnableCollision = true, FirstIndex = sec.BaseIndex, NumTriangles = (uint)sec.NumTriangles, MaterialIndex = sec.MaterialIndex, Material = skeletalMesh.Materials[sec.MaterialIndex], Fragments = new FragmentRange[0], MinVertexIndex = indices.Min(), MaxVertexIndex = indices.Max() }); }).ToArray() } }, InternalVersion = 18, LightingGuid = Guid.NewGuid() }; Vector3[] posVertData = stm.LODModels[0].PositionVertexBuffer.VertexData; StaticMeshVertexBuffer.StaticMeshFullVertex[] stmVertData = stm.LODModels[0].VertexBuffer.VertexData; if (lodModel.ME1VertexBufferGPUSkin != null) { for (int i = 0; i < lodModel.ME1VertexBufferGPUSkin.Length; i++) { SoftSkinVertex vert = lodModel.ME1VertexBufferGPUSkin[i]; posVertData[i] = vert.Position; stmVertData[i] = new StaticMeshVertexBuffer.StaticMeshFullVertex { HalfPrecisionUVs = new Vector2DHalf[] { vert.UV }, TangentX = vert.TangentX, TangentZ = vert.TangentZ }; } } else { for (int i = 0; i < lodModel.VertexBufferGPUSkin.VertexData.Length; i++) { GPUSkinVertex vert = lodModel.VertexBufferGPUSkin.VertexData[i]; posVertData[i] = vert.Position; stmVertData[i] = new StaticMeshVertexBuffer.StaticMeshFullVertex { HalfPrecisionUVs = new[] { vert.UV }, TangentX = vert.TangentX, TangentZ = vert.TangentZ }; } } var tris = new kDOPCollisionTriangle[lodModel.IndexBuffer.Length / 3]; for (int i = 0, elIdx = 0, triCount = 0; i < lodModel.IndexBuffer.Length; i += 3, ++triCount) { if (triCount > lodModel.Sections[elIdx].NumTriangles) { triCount = 0; ++elIdx; } tris[i / 3] = new kDOPCollisionTriangle(lodModel.IndexBuffer[i], lodModel.IndexBuffer[i + 1], lodModel.IndexBuffer[i + 2], lodModel.Sections[elIdx].MaterialIndex); } stm.kDOPTreeME3UDK = KDOPTreeBuilder.ToCompact(tris, stm.LODModels[0].PositionVertexBuffer.VertexData); return(stm); }