示例#1
0
        //Component_MeshInSpace contains only one Component_Mesh.
        static void MergeGeometries(Component_Mesh mesh, DocumentInstance document, UndoMultiAction undo)
        {
            Component_MeshGeometry[] geometries = mesh.GetComponents <Component_MeshGeometry>();
            if (geometries == null || geometries.Length < 2)
            {
                return;
            }

            Reference <Component_Material> material = geometries[0].Material;
            //for( int i = 1; i < geometries.Length; i++ )
            //{
            //	if( !( material.Value == null && geometries[ i ].Material.Value == null || material.Equals( geometries[ i ].Material ) ) )
            //	{
            //		//??? Если разные Material какой вариант лучше: 1) Брать из первого geometry с вопросом в MessageBox; 2) Disable в меню для Action. 3) Соединять те, которые с одинаковым материалом.
            //		if( EditorMessageBox.ShowQuestion( "Mesh geometries have different materials. Merge them using a material from the first geometry?", MessageBoxButtons.OKCancel ) == DialogResult.Cancel )
            //		{
            //			return;
            //		}
            //	}
            //}

            var extracted = mesh.ExtractStructure();

            var newIndices         = new List <int>();
            var newVertices        = new List <byte>();
            var newVertexStructure = extracted.MeshGeometries[0].VertexStructure;
            var newVertexFormat    = new MeshData.MeshGeometryFormat(newVertexStructure);

            for (int geomIndex = 0; geomIndex < extracted.MeshGeometries.Length; geomIndex++)
            {
                var g = extracted.MeshGeometries[geomIndex];


                if (g.Vertices == null || g.Indices == null)
                {
                    continue;
                }
                int indexOffset = newVertices.Count / newVertexFormat.vertexSize;

                for (int i = 0; i < g.Indices.Length; i++)
                {
                    newIndices.Add(g.Indices[i] + indexOffset);
                }

                if (!CommonFunctions.IsSameVertexStructure(newVertexStructure, g.VertexStructure))
                {
                    g.Vertices = MeshData.ConvertToFormat(new MeshData.MeshGeometryFormat(g.VertexStructure), g.Vertices, newVertexFormat);
                }

                newVertices.AddRange(g.Vertices);

                foreach (var face in extracted.Structure.Faces)
                {
                    for (int i = 0; i < face.Triangles.Length; i++)
                    {
                        if (face.Triangles[i].RawGeometry == geomIndex)
                        {
                            face.Triangles[i].RawGeometry = 0;
                            face.Triangles[i].RawVertex  += indexOffset;
                        }
                    }
                }
            }

            // changes in the mesh

            if (undo != null)
            {
                //add structure update to undo
                var property = (Metadata.Property)mesh.MetadataGetMemberBySignature("property:" + nameof(Component_Mesh.Structure));
                undo.AddAction(new UndoActionPropertiesChange(new UndoActionPropertiesChange.Item(mesh, property, mesh.Structure?.Clone())));
            }

            bool meshWasEnabled = mesh.Enabled;

            mesh.Enabled = false;
            try
            {
                var newGeometry = mesh.CreateComponent <Component_MeshGeometry>();
                newGeometry.Material = material;

                newGeometry.Vertices        = newVertices.ToArray();
                newGeometry.Indices         = newIndices.ToArray();
                newGeometry.VertexStructure = newVertexStructure;

                //add created geometry to undo
                undo?.AddAction(new UndoActionComponentCreateDelete(document, new Component[] { newGeometry }, create: true));

                mesh.Structure = extracted.Structure;

                //delete old mesh geometry
                undo?.AddAction(new UndoActionComponentCreateDelete(document, geometries, create: false));

                newGeometry.Name = CommonFunctions.GetUniqueFriendlyName(newGeometry);
            }
            finally
            {
                mesh.Enabled = meshWasEnabled;
            }
        }