public void ChangeBackgroundColor(Color newColor) { Color color = newColor; // Cycle through each unique vertex in the cube (8 total), and assign a color to the index in the sharedIndices array. int si_len = backgroundPlane.sharedIndices.Length; Color[] vertexColors = new Color[si_len]; for (int i = 0; i < si_len; i++) { vertexColors[i] = color; } // Now go through each face (vertex colors are stored the pb_Face class) and assign the pre-calculated index color to each index in the triangles array. Color[] colors = backgroundPlane.colors; for (int CurSharedIndex = 0; CurSharedIndex < backgroundPlane.sharedIndices.Length; CurSharedIndex++) { foreach (int CurIndex in backgroundPlane.sharedIndices[CurSharedIndex].array) { colors[CurIndex] = vertexColors[CurSharedIndex]; } } backgroundPlane.SetColors(colors); // In order for these changes to take effect, you must refresh the mesh object. backgroundPlane.Refresh(); }
void Start() { // Create a new ProBuilder cube to work with. pb = pb_ShapeGenerator.CubeGenerator(Vector3.one); // Cycle through each unique vertex in the cube (8 total), and assign a color // to the index in the sharedIndices array. int si_len = pb.sharedIndices.Length; Color[] vertexColors = new Color[si_len]; for(int i = 0; i < si_len; i++) { vertexColors[i] = HSVtoRGB( (i/(float)si_len) * 360f, 1f, 1f); } // Now go through each face (vertex colors are stored the pb_Face class) and // assign the pre-calculated index color to each index in the triangles array. Color[] colors = pb.colors; for(int CurSharedIndex = 0; CurSharedIndex < pb.sharedIndices.Length; CurSharedIndex++) { foreach(int CurIndex in pb.sharedIndices[CurSharedIndex].array) { colors[CurIndex] = vertexColors[CurSharedIndex]; } } pb.SetColors(colors); // In order for these changes to take effect, you must refresh the mesh // object. pb.Refresh(); }
void ColorizeObject(pb_Object obj) { int randomColorsLength = randomColors.Length; int randomInt = Random.Range(0, randomColorsLength); // Random.seed = GameController.current.randomGeneratorSeed; Color color = randomColors[randomInt]; // Cycle through each unique vertex in the cube (8 total), and assign a color to the index in the sharedIndices array. int si_len = obj.sharedIndices.Length; Color[] vertexColors = new Color[si_len]; for (int i = 0; i < si_len; i++) { vertexColors[i] = color; } // Now go through each face (vertex colors are stored the pb_Face class) and assign the pre-calculated index color to each index in the triangles array. Color[] colors = obj.colors; for (int CurSharedIndex = 0; CurSharedIndex < obj.sharedIndices.Length; CurSharedIndex++) { foreach (int CurIndex in obj.sharedIndices[CurSharedIndex].array) { colors[CurIndex] = vertexColors[CurSharedIndex]; } } obj.SetColors(colors); // In order for these changes to take effect, you must refresh the mesh object. obj.Refresh(); }
void Start() { // Create a new ProBuilder cube to work with. pb = pb_ShapeGenerator.CubeGenerator(Vector3.one); // Cycle through each unique vertex in the cube (8 total), and assign a color // to the index in the sharedIndices array. int si_len = pb.sharedIndices.Length; Color[] vertexColors = new Color[si_len]; for (int i = 0; i < si_len; i++) { vertexColors[i] = HSVtoRGB((i / (float)si_len) * 360f, 1f, 1f); } // Now go through each face (vertex colors are stored the pb_Face class) and // assign the pre-calculated index color to each index in the triangles array. Color[] colors = pb.colors; for (int CurSharedIndex = 0; CurSharedIndex < pb.sharedIndices.Length; CurSharedIndex++) { foreach (int CurIndex in pb.sharedIndices[CurSharedIndex].array) { colors[CurIndex] = vertexColors[CurSharedIndex]; } } pb.SetColors(colors); // In order for these changes to take effect, you must refresh the mesh // object. pb.Refresh(); }
/** * Append a group of new faces to the pb_Object. Significantly faster than calling AppendFace multiple times. */ public static pb_Face[] AppendFaces(this pb_Object pb, Vector3[][] new_Vertices, Color[][] new_Colors, Vector2[][] new_uvs, pb_Face[] new_Faces, int[][] new_SharedIndices) { List <Vector3> _verts = new List <Vector3>(pb.vertices); List <Color> _colors = new List <Color>(pb.colors); List <Vector2> _uv = new List <Vector2>(pb.uv); List <pb_Face> _faces = new List <pb_Face>(pb.faces); pb_IntArray[] sharedIndices = pb.sharedIndices; int vc = pb.vertexCount; for (int i = 0; i < new_Faces.Length; i++) { _verts.AddRange(new_Vertices[i]); _colors.AddRange(new_Colors[i]); _uv.AddRange(new_uvs[i]); new_Faces[i].ShiftIndicesToZero(); new_Faces[i].ShiftIndices(vc); new_Faces[i].RebuildCaches(); _faces.Add(new_Faces[i]); if (new_SharedIndices != null && new_Vertices[i].Length != new_SharedIndices[i].Length) { Debug.LogError("Append Face failed because sharedIndex array does not match new vertex array."); return(null); } if (new_SharedIndices != null) { for (int j = 0; j < new_SharedIndices[i].Length; j++) { pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, new_SharedIndices[i][j], j + vc); } } else { for (int j = 0; j < new_Vertices[i].Length; j++) { pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, -1, j + vc); } } vc = _verts.Count; } pb.SetSharedIndices(sharedIndices); pb.SetVertices(_verts.ToArray()); pb.SetColors(_colors.ToArray()); pb.SetUV(_uv.ToArray()); pb.SetFaces(_faces.ToArray()); return(new_Faces); }
/** * Removes faces from a pb_Object. Overrides available for pb_Face[] and int[] faceIndices. handles * all the sharedIndices moving stuff for you. */ public static void DeleteFaces(this pb_Object pb, int[] faceIndices) { pb_Face[] faces = new pb_Face[faceIndices.Length]; for (int i = 0; i < faces.Length; i++) { faces[i] = pb.faces[faceIndices[i]]; } int[] distInd = pb_Face.AllTrianglesDistinct(faces); Vector3[] verts = pb.vertices.RemoveAt(distInd); Color[] cols = pb.colors.RemoveAt(distInd); Vector2[] uvs = pb.uv.RemoveAt(distInd); pb_Face[] nFaces = pb.faces.RemoveAt(faceIndices); // shift all other face indices down to account for moved vertex positions for (int i = 0; i < nFaces.Length; i++) { int[] tris = nFaces[i].indices; for (int n = 0; n < tris.Length; n++) { int sub = 0; for (int d = 0; d < distInd.Length; d++) { if (tris[n] > distInd[d]) { sub++; } } tris[n] -= sub; } nFaces[i].SetIndices(tris); } // shift all other face indices in the shared index array down to account for moved vertex positions pb_IntArray[] si = pb.sharedIndices; pb_IntArray[] si_uv = pb.sharedIndicesUV; pb_IntArrayUtility.RemoveValuesAndShift(ref si, distInd); pb_IntArrayUtility.RemoveValuesAndShift(ref si_uv, distInd); pb.SetSharedIndices(si); pb.SetSharedIndicesUV(si_uv); pb.SetVertices(verts); pb.SetColors(cols); pb.SetUV(uvs); pb.SetFaces(nFaces); pb.RebuildFaceCaches(); }
/** * Removes faces from a pb_Object. Overrides available for pb_Face[] and int[] faceIndices. handles * all the sharedIndices moving stuff for you. */ public static void DeleteFaces(this pb_Object pb, pb_Face[] faces) { int[] f_ind = new int[faces.Length]; // test for triangle array equality, not reference equality for (int i = 0; i < faces.Length; i++) { f_ind[i] = System.Array.IndexOf(pb.faces, faces[i]); } List <int> indices_to_remove = new List <int>(pb_Face.AllTrianglesDistinct(faces)); indices_to_remove.Sort(); Vector3[] verts = pb.vertices.SortedRemoveAt(indices_to_remove); Color[] cols = pb.colors.SortedRemoveAt(indices_to_remove); Vector2[] uvs = pb.uv.SortedRemoveAt(indices_to_remove); pb_Face[] nFaces = pb.faces.RemoveAt(f_ind); // shift all other face indices down to account for moved vertex positions for (int i = 0; i < nFaces.Length; i++) { int[] tris = nFaces[i].indices; for (int n = 0; n < tris.Length; n++) { int index = pbUtil.NearestIndexPriorToValue(indices_to_remove, tris[n]); // add 1 because index is zero based tris[n] -= index + 1; } nFaces[i].SetIndices(tris); } // shift all other face indices in the shared index array down to account for moved vertex positions pb_IntArray[] si = pb.sharedIndices; pb_IntArray[] si_uv = pb.sharedIndicesUV; pb_IntArrayUtility.RemoveValuesAndShift(ref si, indices_to_remove); pb_IntArrayUtility.RemoveValuesAndShift(ref si_uv, indices_to_remove); pb.SetSharedIndices(si); pb.SetSharedIndicesUV(si_uv); pb.SetVertices(verts); pb.SetColors(cols); pb.SetUV(uvs); pb.SetFaces(nFaces); pb.RebuildFaceCaches(); }
/** * Deletes the vertices from the passed index array. Handles rebuilding the sharedIndices array. */ public static void DeleteVerticesWithIndices(this pb_Object pb, int[] distInd) { Vector3[] verts = pb.vertices; Color[] cols = pb.colors; Vector2[] uvs = pb.uv; verts = verts.RemoveAt(distInd); cols = cols.RemoveAt(distInd); uvs = uvs.RemoveAt(distInd); pb_Face[] nFaces = pb.faces; // shift all other face indices down to account for moved vertex positions for (int i = 0; i < nFaces.Length; i++) { int[] tris = nFaces[i].indices; for (int n = 0; n < tris.Length; n++) { int sub = 0; for (int d = 0; d < distInd.Length; d++) { if (tris[n] > distInd[d]) { sub++; } } tris[n] -= sub; } nFaces[i].SetIndices(tris); } // shift all other face indices in the shared index array down to account for moved vertex positions pb_IntArray[] si = pb.sharedIndices; pb_IntArrayUtility.RemoveValuesAndShift(ref si, distInd); pb.SetSharedIndices(si); pb.SetVertices(verts); pb.SetColors(cols); pb.SetUV(uvs); pb.SetFaces(nFaces); pb.RebuildFaceCaches(); pb.ToMesh(); }
/** * Append a new face to the pb_Object using sharedIndex array to set the face indices to sharedIndex groups. */ public static pb_Face AppendFace(this pb_Object pb, Vector3[] v, Color[] c, Vector2[] u, pb_Face face, int[] sharedIndex) { int vertexCount = pb.vertexCount; Vector3[] _verts = new Vector3[vertexCount + v.Length]; Color[] _colors = new Color[vertexCount + c.Length]; Vector2[] _uvs = new Vector2[pb.uv.Length + u.Length]; List <pb_Face> _faces = new List <pb_Face>(pb.faces); pb_IntArray[] sharedIndices = pb.sharedIndices; // copy new vertices System.Array.Copy(pb.vertices, 0, _verts, 0, vertexCount); System.Array.Copy(v, 0, _verts, vertexCount, v.Length); // copy new colors System.Array.Copy(pb.colors, 0, _colors, 0, vertexCount); System.Array.Copy(c, 0, _colors, vertexCount, c.Length); // copy new uvs System.Array.Copy(pb.uv, 0, _uvs, 0, pb.uv.Length); System.Array.Copy(u, 0, _uvs, pb.uv.Length, u.Length); face.ShiftIndicesToZero(); face.ShiftIndices(vertexCount); face.RebuildCaches(); _faces.Add(face); for (int i = 0; i < sharedIndex.Length; i++) { pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, sharedIndex[i], i + vertexCount); } pb.SetVertices(_verts); pb.SetColors(_colors); pb.SetUV(_uvs); pb.SetSharedIndices(sharedIndices); pb.SetFaces(_faces.ToArray()); return(face); }
private void Start() { pb = pb_ShapeGenerator.CubeGenerator(Vector3.one); int num = pb.sharedIndices.Length; Color[] array = new Color[num]; for (int i = 0; i < num; i++) { array[i] = HSVtoRGB((float)i / (float)num * 360f, 1f, 1f); } Color[] colors = pb.colors; for (int j = 0; j < pb.sharedIndices.Length; j++) { int[] array2 = pb.sharedIndices[j].array; foreach (int num2 in array2) { colors[num2] = array[j]; } } pb.SetColors(colors); pb.Refresh(); }
/** * Creates a new pb_Object instance with the provided vertices, faces, and sharedIndex information. */ public static pb_Object CreateInstanceWithElements(Vector3[] v, Vector2[] u, Color[] c, pb_Face[] f, pb_IntArray[] si, pb_IntArray[] si_uv) { GameObject _gameObject = new GameObject(); pb_Object pb = _gameObject.AddComponent <pb_Object>(); pb.SetVertices(v); pb.SetUV(u); pb.SetColors(c); pb.SetSharedIndices(si ?? pb_IntArrayUtility.ExtractSharedIndices(v)); pb.SetSharedIndicesUV(si_uv ?? new pb_IntArray[0] { }); pb.SetFaces(f); pb.ToMesh(); pb.Refresh(); pb.GetComponent <pb_Entity>().SetEntity(EntityType.Detail); return(pb); }
/** * ProBuilderize in-place function. You must call ToMesh() and Refresh() after * returning from this function, as this only creates the pb_Object and sets its * fields. This allows you to record the mesh and gameObject for Undo operations. */ public static bool ResetPbObjectWithMeshFilter(pb_Object pb, bool preserveFaces) { MeshFilter mf = pb.gameObject.GetComponent <MeshFilter>(); if (mf == null || mf.sharedMesh == null) { Debug.Log(pb.name + " does not have a mesh or Mesh Filter component."); return(false); } Mesh m = mf.sharedMesh; int vertexCount = m.vertexCount; Vector3[] m_vertices = m.vertices; Color[] m_colors = m.colors != null && m.colors.Length == vertexCount ? m.colors : new Color[vertexCount]; Vector2[] m_uvs = m.uv; List <Vector3> verts = preserveFaces ? new List <Vector3>(m.vertices) : new List <Vector3>(); List <Color> cols = preserveFaces ? new List <Color>(m.colors) : new List <Color>(); List <Vector2> uvs = preserveFaces ? new List <Vector2>(m.uv) : new List <Vector2>(); List <pb_Face> faces = new List <pb_Face>(); MeshRenderer mr = pb.gameObject.GetComponent <MeshRenderer>(); if (mr == null) { mr = pb.gameObject.AddComponent <MeshRenderer>(); } Material[] sharedMaterials = mr.sharedMaterials; int mat_length = sharedMaterials.Length; for (int n = 0; n < m.subMeshCount; n++) { int[] tris = m.GetTriangles(n); for (int i = 0; i < tris.Length; i += 3) { int index = -1; if (preserveFaces) { for (int j = 0; j < faces.Count; j++) { if (faces[j].distinctIndices.Contains(tris[i + 0]) || faces[j].distinctIndices.Contains(tris[i + 1]) || faces[j].distinctIndices.Contains(tris[i + 2])) { index = j; break; } } } if (index > -1 && preserveFaces) { int len = faces[index].indices.Length; int[] arr = new int[len + 3]; System.Array.Copy(faces[index].indices, 0, arr, 0, len); arr[len + 0] = tris[i + 0]; arr[len + 1] = tris[i + 1]; arr[len + 2] = tris[i + 2]; faces[index].SetIndices(arr); faces[index].RebuildCaches(); } else { int[] faceTris; if (preserveFaces) { faceTris = new int[3] { tris[i + 0], tris[i + 1], tris[i + 2] }; } else { verts.Add(m_vertices[tris[i + 0]]); verts.Add(m_vertices[tris[i + 1]]); verts.Add(m_vertices[tris[i + 2]]); cols.Add(m_colors != null && m_colors.Length == vertexCount ? m_colors[tris[i + 0]] : Color.white); cols.Add(m_colors != null && m_colors.Length == vertexCount ? m_colors[tris[i + 1]] : Color.white); cols.Add(m_colors != null && m_colors.Length == vertexCount ? m_colors[tris[i + 2]] : Color.white); uvs.Add(m_uvs[tris[i + 0]]); uvs.Add(m_uvs[tris[i + 1]]); uvs.Add(m_uvs[tris[i + 2]]); faceTris = new int[3] { i + 0, i + 1, i + 2 }; } faces.Add( new pb_Face( faceTris, sharedMaterials[n >= mat_length ? mat_length - 1 : n], new pb_UV(), 0, // smoothing group -1, // texture group -1, // element group true // manualUV )); } } } pb.SetVertices(verts.ToArray()); pb.SetUV(uvs.ToArray()); pb.SetFaces(faces.ToArray()); pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(verts.ToArray())); pb.SetColors(cols.ToArray()); return(true); }
static void Triangulate(pb_Object pb) { Vector3[] v = pb.vertices; Color[] c = pb.colors; Vector2[] u = pb.uv; int triangleCount = pb.TriangleCount(); // int triangleCount = pb_Face.AllTriangles(pb.faces).Length; // pb.msh.triangles.Length; if (triangleCount == v.Length) { Debug.LogWarning("We can't pull over any further!\npb_Object: " + pb.name + " is already triangulated."); } int vertexCount = triangleCount; int faceCount = vertexCount / 3; Vector3[] tri_vertices = new Vector3[vertexCount]; Color[] tri_colors = new Color[vertexCount]; Vector2[] tri_uvs = new Vector2[vertexCount]; pb_Face[] tri_faces = new pb_Face[faceCount]; int n = 0, f = 0; foreach (pb_Face face in pb.faces) { int[] indices = face.indices; for (int i = 0; i < indices.Length; i += 3) { tri_vertices[n + 0] = v[indices[i + 0]]; tri_vertices[n + 1] = v[indices[i + 1]]; tri_vertices[n + 2] = v[indices[i + 2]]; tri_colors[n + 0] = c[indices[i + 0]]; tri_colors[n + 1] = c[indices[i + 1]]; tri_colors[n + 2] = c[indices[i + 2]]; tri_uvs[n + 0] = u[indices[i + 0]]; tri_uvs[n + 1] = u[indices[i + 1]]; tri_uvs[n + 2] = u[indices[i + 2]]; tri_faces[f++] = new pb_Face(new int[] { n + 0, n + 1, n + 2 }, face.material, face.uv, face.smoothingGroup, face.textureGroup, // textureGroup -> force to manual uv mode face.elementGroup, face.manualUV ); n += 3; } } pb.SetVertices(tri_vertices); pb.SetColors(tri_colors); pb.SetUV(tri_uvs); pb.SetFaces(tri_faces); pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(tri_vertices)); pb.SetSharedIndicesUV(new pb_IntArray[0]); }
/** * Triangulate an entire pb_Object. */ public static void Triangulate(pb_Object pb) { Vector3[] v = pb.vertices; Color[] c = pb.colors; Vector2[] u = pb.uv; int triangleCount = pb.TriangleCount(); // int triangleCount = pb_Face.AllTriangles(pb.faces).Length; // pb.msh.triangles.Length; if(triangleCount == v.Length) { Debug.LogWarning("We can't pull over any further!\npb_Object: " + pb.name + " is already triangulated."); } int vertexCount = triangleCount; int faceCount = vertexCount / 3; Vector3[] tri_vertices = new Vector3[vertexCount]; Color[] tri_colors = new Color[vertexCount]; Vector2[] tri_uvs = new Vector2[vertexCount]; pb_Face[] tri_faces = new pb_Face[faceCount]; int n = 0, f = 0; foreach(pb_Face face in pb.faces) { int[] indices = face.indices; for(int i = 0; i < indices.Length; i+=3) { tri_vertices[n+0] = v[indices[i+0]]; tri_vertices[n+1] = v[indices[i+1]]; tri_vertices[n+2] = v[indices[i+2]]; tri_colors[n+0] = c[indices[i+0]]; tri_colors[n+1] = c[indices[i+1]]; tri_colors[n+2] = c[indices[i+2]]; tri_uvs[n+0] = u[indices[i+0]]; tri_uvs[n+1] = u[indices[i+1]]; tri_uvs[n+2] = u[indices[i+2]]; tri_faces[f++] = new pb_Face( new int[] { n+0, n+1, n+2 }, face.material, face.uv, face.smoothingGroup, face.textureGroup, // textureGroup -> force to manual uv mode face.elementGroup, face.manualUV ); n += 3; } } pb.SetVertices(tri_vertices); pb.SetColors(tri_colors); pb.SetUV(tri_uvs); pb.SetFaces(tri_faces); pb.SetSharedIndices( pb_IntArrayUtility.ExtractSharedIndices(tri_vertices) ); pb.SetSharedIndicesUV( new pb_IntArray[0] ); }
/** * \brief Given an array of "donors", this method returns a merged #pb_Object. */ public static bool CombineObjects(pb_Object[] pbs, out pb_Object combined) { combined = null; if (pbs.Length < 1) { return(false); } List <Vector3> v = new List <Vector3>(); List <Vector2> u = new List <Vector2>(); List <Color> c = new List <Color>(); List <pb_Face> f = new List <pb_Face>(); List <pb_IntArray> s = new List <pb_IntArray>(); List <pb_IntArray> suv = new List <pb_IntArray>(); foreach (pb_Object pb in pbs) { int vertexCount = v.Count; // Vertices v.AddRange(pb.VerticesInWorldSpace()); // UVs u.AddRange(pb.uv); // Colors c.AddRange(pb.colors); // Faces pb_Face[] faces = new pb_Face[pb.faces.Length]; for (int i = 0; i < faces.Length; i++) { faces[i] = new pb_Face(pb.faces[i]); faces[i].manualUV = true; faces[i].ShiftIndices(vertexCount); faces[i].RebuildCaches(); } f.AddRange(faces); // Shared Indices pb_IntArray[] si = pb.GetSharedIndices(); for (int i = 0; i < si.Length; i++) { for (int n = 0; n < si[i].Length; n++) { si[i][n] += vertexCount; } } s.AddRange(si); // Shared Indices UV { pb_IntArray[] si_uv = pb.GetSharedIndicesUV(); for (int i = 0; i < si_uv.Length; i++) { for (int n = 0; n < si_uv[i].Length; n++) { si_uv[i][n] += vertexCount; } } suv.AddRange(si_uv); } } GameObject go = (GameObject)GameObject.Instantiate(pbs[0].gameObject); go.transform.position = Vector3.zero; go.transform.localRotation = Quaternion.identity; go.transform.localScale = Vector3.one; // Destroy the children foreach (Transform t in go.transform) { GameObject.DestroyImmediate(t.gameObject); } if (go.GetComponent <pb_Object>()) { GameObject.DestroyImmediate(go.GetComponent <pb_Object>()); } if (go.GetComponent <pb_Entity>()) { GameObject.DestroyImmediate(go.GetComponent <pb_Entity>()); } combined = go.AddComponent <pb_Object>(); combined.SetVertices(v.ToArray()); combined.SetUV(u.ToArray()); combined.SetColors(c.ToArray()); combined.SetFaces(f.ToArray()); combined.SetSharedIndices(s.ToArray() ?? pb_IntArrayUtility.ExtractSharedIndices(v.ToArray())); combined.SetSharedIndicesUV(suv.ToArray() ?? new pb_IntArray[0] { }); combined.ToMesh(); combined.GetComponent <pb_Entity>().SetEntity(pbs[0].GetComponent <pb_Entity>().entityType); combined.CenterPivot(pbs[0].transform.position); combined.Refresh(); // refresh donors since deleting the children of the instantiated object could cause them to lose references foreach (pb_Object pb in pbs) { pb.Verify(); } return(true); }
/** * "ProBuilder-ize function" */ public static pb_Object CreatePbObjectWithTransform(Transform t, bool preserveFaces) { Mesh m = t.GetComponent <MeshFilter>().sharedMesh; Vector3[] m_vertices = m.vertices; Color[] m_colors = m.colors ?? new Color[m_vertices.Length]; Vector2[] m_uvs = m.uv; List <Vector3> verts = preserveFaces ? new List <Vector3>(m.vertices) : new List <Vector3>(); List <Color> cols = preserveFaces ? new List <Color>(m.colors) : new List <Color>(); List <Vector2> uvs = preserveFaces ? new List <Vector2>(m.uv) : new List <Vector2>(); List <pb_Face> faces = new List <pb_Face>(); for (int n = 0; n < m.subMeshCount; n++) { int[] tris = m.GetTriangles(n); for (int i = 0; i < tris.Length; i += 3) { int index = -1; if (preserveFaces) { for (int j = 0; j < faces.Count; j++) { if (faces[j].distinctIndices.Contains(tris[i + 0]) || faces[j].distinctIndices.Contains(tris[i + 1]) || faces[j].distinctIndices.Contains(tris[i + 2])) { index = j; break; } } } if (index > -1 && preserveFaces) { int len = faces[index].indices.Length; int[] arr = new int[len + 3]; System.Array.Copy(faces[index].indices, 0, arr, 0, len); arr[len + 0] = tris[i + 0]; arr[len + 1] = tris[i + 1]; arr[len + 2] = tris[i + 2]; faces[index].SetIndices(arr); faces[index].RebuildCaches(); } else { int[] faceTris; if (preserveFaces) { faceTris = new int[3] { tris[i + 0], tris[i + 1], tris[i + 2] }; } else { verts.Add(m_vertices[tris[i + 0]]); verts.Add(m_vertices[tris[i + 1]]); verts.Add(m_vertices[tris[i + 2]]); cols.Add(m_colors != null ? m_colors[tris[i + 0]] : Color.white); cols.Add(m_colors != null ? m_colors[tris[i + 1]] : Color.white); cols.Add(m_colors != null ? m_colors[tris[i + 2]] : Color.white); uvs.Add(m_uvs[tris[i + 0]]); uvs.Add(m_uvs[tris[i + 1]]); uvs.Add(m_uvs[tris[i + 2]]); faceTris = new int[3] { i + 0, i + 1, i + 2 }; } faces.Add( new pb_Face( faceTris, t.GetComponent <MeshRenderer>().sharedMaterials[n], new pb_UV(), 0, // smoothing group -1, // texture group -1, // element group true // manualUV )); } } } GameObject go = (GameObject)GameObject.Instantiate(t.gameObject); go.GetComponent <MeshFilter>().sharedMesh = null; pb_Object pb = go.AddComponent <pb_Object>(); pb.GeometryWithVerticesFaces(verts.ToArray(), faces.ToArray()); pb.SetColors(cols.ToArray()); pb.SetUV(uvs.ToArray()); pb.SetName(t.name); go.transform.position = t.position; go.transform.localRotation = t.localRotation; go.transform.localScale = t.localScale; pb.CenterPivot(null); return(pb); }
/** * ProBuilderize in-place function. You must call ToMesh() and Refresh() after * returning from this function, as this only creates the pb_Object and sets its * fields. This allows you to record the mesh and gameObject for Undo operations. */ public static bool ResetPbObjectWithMeshFilter(pb_Object pb, bool preserveFaces) { MeshFilter mf = pb.gameObject.GetComponent<MeshFilter>(); if(mf == null || mf.sharedMesh == null) { Debug.Log(pb.name + " does not have a mesh or Mesh Filter component."); return false; } Mesh m = mf.sharedMesh; int vertexCount = m.vertexCount; Vector3[] m_vertices = m.vertices; Color[] m_colors = m.colors != null && m.colors.Length == vertexCount ? m.colors : new Color[vertexCount]; Vector2[] m_uvs = m.uv; List<Vector3> verts = preserveFaces ? new List<Vector3>(m.vertices) : new List<Vector3>(); List<Color> cols = preserveFaces ? new List<Color>(m.colors) : new List<Color>(); List<Vector2> uvs = preserveFaces ? new List<Vector2>(m.uv) : new List<Vector2>(); List<pb_Face> faces = new List<pb_Face>(); MeshRenderer mr = pb.gameObject.GetComponent<MeshRenderer>(); if(mr == null) mr = pb.gameObject.AddComponent<MeshRenderer>(); Material[] sharedMaterials = mr.sharedMaterials; int mat_length = sharedMaterials.Length; for(int n = 0; n < m.subMeshCount; n++) { int[] tris = m.GetTriangles(n); for(int i = 0; i < tris.Length; i+=3) { int index = -1; if(preserveFaces) { for(int j = 0; j < faces.Count; j++) { if( faces[j].distinctIndices.Contains(tris[i+0]) || faces[j].distinctIndices.Contains(tris[i+1]) || faces[j].distinctIndices.Contains(tris[i+2])) { index = j; break; } } } if(index > -1 && preserveFaces) { int len = faces[index].indices.Length; int[] arr = new int[len + 3]; System.Array.Copy(faces[index].indices, 0, arr, 0, len); arr[len+0] = tris[i+0]; arr[len+1] = tris[i+1]; arr[len+2] = tris[i+2]; faces[index].SetIndices(arr); faces[index].RebuildCaches(); } else { int[] faceTris; if(preserveFaces) { faceTris = new int[3] { tris[i+0], tris[i+1], tris[i+2] }; } else { verts.Add(m_vertices[tris[i+0]]); verts.Add(m_vertices[tris[i+1]]); verts.Add(m_vertices[tris[i+2]]); cols.Add(m_colors != null && m_colors.Length == vertexCount ? m_colors[tris[i+0]] : Color.white); cols.Add(m_colors != null && m_colors.Length == vertexCount ? m_colors[tris[i+1]] : Color.white); cols.Add(m_colors != null && m_colors.Length == vertexCount ? m_colors[tris[i+2]] : Color.white); uvs.Add(m_uvs[tris[i+0]]); uvs.Add(m_uvs[tris[i+1]]); uvs.Add(m_uvs[tris[i+2]]); faceTris = new int[3] { i+0, i+1, i+2 }; } faces.Add( new pb_Face( faceTris, sharedMaterials[n >= mat_length ? mat_length - 1 : n], new pb_UV(), 0, // smoothing group -1, // texture group -1, // element group true // manualUV )); } } } pb.SetVertices(verts.ToArray()); pb.SetUV(uvs.ToArray()); pb.SetFaces(faces.ToArray()); pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(verts.ToArray())); pb.SetColors(cols.ToArray()); return true; }
/** * \brief Given an array of "donors", this method returns a merged #pb_Object. */ public static bool CombineObjects(pb_Object[] pbs, out pb_Object combined) { combined = null; if(pbs.Length < 1) return false; List<Vector3> v = new List<Vector3>(); List<Vector2> u = new List<Vector2>(); List<Color> c = new List<Color>(); List<pb_Face> f = new List<pb_Face>(); List<pb_IntArray> s = new List<pb_IntArray>(); List<pb_IntArray> suv = new List<pb_IntArray>(); foreach(pb_Object pb in pbs) { int vertexCount = v.Count; // Vertices v.AddRange(pb.VerticesInWorldSpace()); // UVs u.AddRange(pb.uv); // Colors c.AddRange(pb.colors); // Faces pb_Face[] faces = new pb_Face[pb.faces.Length]; for(int i = 0; i < faces.Length; i++) { faces[i] = new pb_Face(pb.faces[i]); faces[i].manualUV = true; faces[i].ShiftIndices(vertexCount); faces[i].RebuildCaches(); } f.AddRange(faces); // Shared Indices pb_IntArray[] si = pb.GetSharedIndices(); for(int i = 0; i < si.Length; i++) { for(int n = 0; n < si[i].Length; n++) si[i][n] += vertexCount; } s.AddRange(si); // Shared Indices UV { pb_IntArray[] si_uv = pb.GetSharedIndicesUV(); for(int i = 0; i < si_uv.Length; i++) { for(int n = 0; n < si_uv[i].Length; n++) si_uv[i][n] += vertexCount; } suv.AddRange(si_uv); } } GameObject go = (GameObject)GameObject.Instantiate(pbs[0].gameObject); go.transform.position = Vector3.zero; go.transform.localRotation = Quaternion.identity; go.transform.localScale = Vector3.one; // Destroy the children foreach(Transform t in go.transform) GameObject.DestroyImmediate(t.gameObject); if(go.GetComponent<pb_Object>()) GameObject.DestroyImmediate(go.GetComponent<pb_Object>()); if(go.GetComponent<pb_Entity>()) GameObject.DestroyImmediate(go.GetComponent<pb_Entity>()); combined = go.AddComponent<pb_Object>(); combined.SetVertices(v.ToArray()); combined.SetUV(u.ToArray()); combined.SetColors(c.ToArray()); combined.SetFaces(f.ToArray()); combined.SetSharedIndices( s.ToArray() ?? pb_IntArrayUtility.ExtractSharedIndices(v.ToArray()) ); combined.SetSharedIndicesUV( suv.ToArray() ?? new pb_IntArray[0] {}); combined.ToMesh(); combined.GetComponent<pb_Entity>().SetEntity( pbs[0].GetComponent<pb_Entity>().entityType ); combined.CenterPivot( pbs[0].transform.position ); combined.Refresh(); // refresh donors since deleting the children of the instantiated object could cause them to lose references foreach(pb_Object pb in pbs) pb.Verify(); return true; }