public Guid LightingGuid; //ME3/UDK protected override void Serialize(SerializingContainer2 sc) { sc.Serialize(ref Bounds); sc.Serialize(ref BodySetup); if (sc.IsSaving) { if (sc.Game >= MEGame.ME3 && kDOPTreeME3UDK == null) { kDOPTreeME3UDK = KDOPTreeBuilder.ToCompact(kDOPTreeME1ME2.Triangles, LODModels[0].PositionVertexBuffer.VertexData); } else if (sc.Game < MEGame.ME3 && kDOPTreeME1ME2 == null) { //todo: need to convert kDOPTreeCompact to kDOPTree throw new NotImplementedException("Cannot convert ME3 StaticMeshes to ME1 or ME2 format :("); } } if (sc.Game >= MEGame.ME3) { sc.Serialize(ref kDOPTreeME3UDK); } else { sc.Serialize(ref kDOPTreeME1ME2); } if (sc.IsSaving) { //This will improve loading times by preventing the engine from rebuilding the mesh if (sc.Game == MEGame.ME1) { InternalVersion = 15; } if (sc.Game == MEGame.ME2) { InternalVersion = 16; } if (sc.Game == MEGame.ME3) { InternalVersion = 18; } if (sc.Game == MEGame.UDK) { InternalVersion = 18; } } sc.Serialize(ref InternalVersion); if (sc.Game == MEGame.UDK) { int dummy = 0; sc.Serialize(ref dummy); sc.Serialize(ref dummy); sc.Serialize(ref dummy); sc.Serialize(ref dummy); } sc.Serialize(ref LODModels, SCExt.Serialize); if (sc.Game == MEGame.ME1) { sc.Serialize(ref unk2); sc.Serialize(ref unk3); sc.Serialize(ref unk4); sc.Serialize(ref unk5); sc.Serialize(ref unk6); } else { sc.Serialize(ref unk1); sc.Serialize(ref ThumbnailAngle); sc.Serialize(ref ThumbnailDistance); if (sc.Game != MEGame.UDK) { sc.Serialize(ref unk7); } if (sc.Game >= MEGame.ME3) { sc.Serialize(ref HighResSourceMeshName); sc.Serialize(ref HighResSourceMeshCRC); sc.Serialize(ref LightingGuid); } } if (sc.IsLoading && sc.Game < MEGame.ME3) { LightingGuid = Guid.NewGuid(); } }
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); }