static unsafe void TransformVertices(byte[] vertices, MeshData.MeshGeometryFormat format, Matrix4 matrix, Quaternion rotation) { fixed(byte *ptr = vertices) { int count = vertices.Length / format.vertexSize; for (int i = 0; i < count; i++) { byte * vertexStart = ptr + i * format.vertexSize; Vector3F *posPtr = (Vector3F *)(vertexStart + format.positionOffset); * posPtr = (*posPtr * matrix).ToVector3F(); Vector3F *normalPtr = (Vector3F *)(vertexStart + format.normalOffset); * normalPtr = (*normalPtr * rotation).ToVector3F(); Vector4F *tangentPtr = (Vector4F *)(vertexStart + format.tangentOffset); * tangentPtr = new Vector4F(((*tangentPtr).ToVector3F() * rotation).ToVector3F(), (*tangentPtr).W); } } }
//static byte[] ToVertices( Net3dBool.Vector3[] vertices, MeshData.MeshGeometryFormat vs ) //{ // byte[] ret = new byte[ vertices.Length * vs.vertexSize ]; // unsafe // { // fixed ( byte* ptr = ret ) // { // for( int i = 0; i < vertices.Length; i++ ) // { // var v = vertices[ i ]; // var pos = (Vector3F*)( ptr + i * vs.vertexSize + vs.positionOffset ); // ( *pos ) = new Vector3F( (float)v.x, (float)v.y, (float)v.z ); // } // } // } // return ret; //} //The data are extracted from Component_Mesh.ExtractedStructure. //Хотя можно взять из MeshGeometry.Vertices,Indices, но там проиндексировано вместе с другими элементами(normals,...). static List <(Vector3F[] positions, int[] indices)> GetData(Component_MeshInSpace ms) { Component_Mesh.ExtractedStructure structure = ms.Mesh.Value.ExtractStructure(); var ret = new List <(Vector3F[] positions, int[] indices)>(); //extract old positions var oldPositions = new Vector3F[structure.MeshGeometries.Length][]; for (int geomIndex = 0; geomIndex < structure.MeshGeometries.Length; geomIndex++) { var vs = new MeshData.MeshGeometryFormat(structure.MeshGeometries[geomIndex].VertexStructure); oldPositions[geomIndex] = new Vector3F[structure.MeshGeometries[geomIndex].Vertices.Length / vs.vertexSize]; unsafe { fixed(byte *ptr = structure.MeshGeometries[geomIndex].Vertices) { for (int i = 0; i < oldPositions[geomIndex].Length; i++) { oldPositions[geomIndex][i] = *(Vector3F *)(ptr + i * vs.vertexSize + vs.positionOffset); } } } } //------------ var geomTriangles = new List <Component_Mesh.StructureClass.FaceVertex> [structure.MeshGeometries.Length]; for (int i = 0; i < structure.MeshGeometries.Length; i++) { geomTriangles[i] = new List <Component_Mesh.StructureClass.FaceVertex>(); } for (int faceIndex = 0; faceIndex < structure.Structure.Faces.Length; faceIndex++) { var face = structure.Structure.Faces[faceIndex]; for (int i = 0; i < face.Triangles.Length; i++) { geomTriangles[face.Triangles[i].RawGeometry].Add(face.Triangles[i]); } } for (int i = 0; i < geomTriangles.Length; i++) { var g = geomTriangles[i]; int[] oldVertexToNewMapping = new int[structure.Structure.Vertices.Length]; for (int j = 0; j < oldVertexToNewMapping.Length; j++) { oldVertexToNewMapping[j] = -1; } int nextIndex = 0; var newPositions = new List <Vector3F>(); var newIndices = new int[g.Count]; for (int j = 0; j < g.Count; j++) { var tv = g[j]; int newIndex = oldVertexToNewMapping[tv.Vertex]; if (newIndex == -1) { newIndex = nextIndex++; oldVertexToNewMapping[tv.Vertex] = newIndex; newPositions.Add(oldPositions[tv.RawGeometry][tv.RawVertex]); } newIndices[j] = newIndex; } ret.Add((newPositions.ToArray(), newIndices)); } return(ret); }
//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; } }