public static GameObject CreateGameObject(string name, VoxData data, Texture2D texture, Color32[] colors, float scale) { var cruncher = VOXPolygonCruncher.CalcVoxelCruncher(data, colors, VOXCruncherMode.Greedy); var entities = new Dictionary <string, int>(); if (CalcFaceCountAsAllocate(cruncher, colors, ref entities) == 0) { throw new System.Exception(name + ": There is no voxel for this file"); } var model = new GameObject(name); foreach (var entity in entities) { if (entity.Value == 0) { continue; } var index = 0; var allocSize = entity.Value; var vertices = new Vector3[allocSize * 4]; var normals = new Vector3[allocSize * 4]; var uv = new Vector2[allocSize * 4]; var triangles = new int[allocSize * 6]; bool isTransparent = false; foreach (var it in cruncher.voxels) { VOXModel.CreateCubeMesh16x16(it, ref vertices, ref normals, ref uv, ref triangles, ref index, scale); isTransparent |= (colors[it.material].a < 255) ? true : false; } if (triangles.Length > 0) { Mesh mesh = new Mesh(); mesh.name = "mesh"; mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.triangles = triangles; var meshFilter = model.AddComponent <MeshFilter>(); var meshRenderer = model.AddComponent <MeshRenderer>(); #if UNITY_EDITOR MeshUtility.Optimize(mesh); meshFilter.sharedMesh = mesh; meshRenderer.sharedMaterial = new Material(Shader.Find("Mobile/Diffuse")); meshRenderer.sharedMaterial.name = "material"; meshRenderer.sharedMaterial.mainTexture = texture; #else meshFilter.mesh = mesh; meshRenderer.material = new Material(Shader.Find("Mobile/Diffuse")); meshRenderer.material.mainTexture = texture; #endif } } return(model); }
/// <summary> /// 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. /// </summary> /// <param name="pb"></param> /// <param name="preserveFaces"></param> /// <returns></returns> public static bool ResetPbObjectWithMeshFilter(ProBuilderMesh pb, bool preserveFaces) { MeshFilter mf = pb.gameObject.GetComponent <MeshFilter>(); if (mf == null || mf.sharedMesh == null) { Log.Error(pb.name + " does not have a mesh or Mesh Filter component."); return(false); } Mesh m = mf.sharedMesh; int vertexCount = m.vertexCount; Vector3[] m_positions = MeshUtility.GetMeshChannel <Vector3[]>(pb.gameObject, x => x.vertices); Color[] m_colors = MeshUtility.GetMeshChannel <Color[]>(pb.gameObject, x => x.colors); Vector2[] m_uvs = MeshUtility.GetMeshChannel <Vector2[]>(pb.gameObject, x => x.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 <Face> faces = new List <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].distinctIndexesInternal.Contains(tris[i + 0]) || faces[j].distinctIndexesInternal.Contains(tris[i + 1]) || faces[j].distinctIndexesInternal.Contains(tris[i + 2])) { index = j; break; } } } if (index > -1 && preserveFaces) { int len = faces[index].indexesInternal.Length; int[] arr = new int[len + 3]; System.Array.Copy(faces[index].indexesInternal, 0, arr, 0, len); arr[len + 0] = tris[i + 0]; arr[len + 1] = tris[i + 1]; arr[len + 2] = tris[i + 2]; faces[index].indexesInternal = arr; } else { int[] faceTris; if (preserveFaces) { faceTris = new int[3] { tris[i + 0], tris[i + 1], tris[i + 2] }; } else { verts.Add(m_positions[tris[i + 0]]); verts.Add(m_positions[tris[i + 1]]); verts.Add(m_positions[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 Face( faceTris, Math.Clamp(n, 0, mat_length - 1), AutoUnwrapSettings.tile, 0, // smoothing group -1, // texture group -1, // element group true // manualUV )); } } } pb.positionsInternal = verts.ToArray(); pb.texturesInternal = uvs.ToArray(); pb.facesInternal = faces.ToArray(); pb.sharedVerticesInternal = SharedVertex.GetSharedVerticesWithPositions(verts.ToArray()); pb.colorsInternal = cols.ToArray(); return(true); }
private void GenerateDefault() { int vertexCount = clippedSamples.Length * (_slices + 1); if (tsMesh.vertexCount != vertexCount) { tsMesh.vertices = new Vector3[vertexCount]; tsMesh.normals = new Vector3[vertexCount]; tsMesh.uv = new Vector2[vertexCount]; tsMesh.colors = new Color[vertexCount]; } int vertIndex = 0; float avgTop = 0f; float avgBottom = 0f; float totalLength = 0f; for (int i = 0; i < clippedSamples.Length; i++) { Vector3 top = clippedSamples[i].position; Vector3 bottom = top; Vector3 normal = Vector3.right; float heightPercent = 1f; if (_uvWrapMode == UVWrapMode.UniformX || _uvWrapMode == UVWrapMode.Uniform) { if (i > 0) { totalLength += Vector3.Distance(clippedSamples[i].position, clippedSamples[i - 1].position); } } switch (_axis) { case Axis.X: avgBottom = bottom.x = computer.position.x; heightPercent = uvScale.y * Mathf.Abs(top.x - bottom.x); avgTop += top.x; break; case Axis.Y: avgBottom = bottom.y = computer.position.y; heightPercent = uvScale.y * Mathf.Abs(top.y - bottom.y); normal = Vector3.up; avgTop += top.y; break; case Axis.Z: avgBottom = bottom.z = computer.position.z; heightPercent = uvScale.y * Mathf.Abs(top.z - bottom.z); normal = Vector3.forward; avgTop += top.z; break; } Vector3 right = Vector3.Cross(normal, clippedSamples[i].direction).normalized; Vector3 offsetRight = Vector3.Cross(clippedSamples[i].normal, clippedSamples[i].direction); for (int n = 0; n < _slices + 1; n++) { float slicePercent = ((float)n / _slices); tsMesh.vertices[vertIndex] = Vector3.Lerp(bottom, top, slicePercent) + normal * offset.y + offsetRight * offset.x; tsMesh.normals[vertIndex] = right; switch (_uvWrapMode) { case UVWrapMode.Clamp: tsMesh.uv[vertIndex] = new Vector2((float)clippedSamples[i].percent * uvScale.x + uvOffset.x, slicePercent * uvScale.y + uvOffset.y); break; case UVWrapMode.UniformX: tsMesh.uv[vertIndex] = new Vector2(totalLength * uvScale.x + uvOffset.x, slicePercent * uvScale.y + uvOffset.y); break; case UVWrapMode.UniformY: tsMesh.uv[vertIndex] = new Vector2((float)clippedSamples[i].percent * uvScale.x + uvOffset.x, heightPercent * slicePercent * uvScale.y + uvOffset.y); break; case UVWrapMode.Uniform: tsMesh.uv[vertIndex] = new Vector2(totalLength * uvScale.x + uvOffset.x, heightPercent * slicePercent * uvScale.y + uvOffset.y); break; } tsMesh.colors[vertIndex] = clippedSamples[i].color * color; vertIndex++; } } if (clippedSamples.Length > 0) { avgTop /= clippedSamples.Length; } tsMesh.triangles = MeshUtility.GeneratePlaneTriangles(_slices, clippedSamples.Length, avgTop < avgBottom); }
private void Generate() { int vertexCount = sampleCount * (_slices + 1); AllocateMesh(vertexCount, _slices * (sampleCount - 1) * 6); int vertIndex = 0; float avgTop = 0f; float totalLength = 0f; Vector3 computerPosition = spline.position; Vector3 normal = spline.TransformDirection(Vector3.right); switch (_axis) { case Axis.Y: normal = spline.TransformDirection(Vector3.up); break; case Axis.Z: normal = spline.TransformDirection(Vector3.forward); break; } for (int i = 0; i < sampleCount; i++) { evalResult = GetSampleRaw(i); float resultSize = GetBaseSize(evalResult); Vector3 samplePosition = evalResult.position; Vector3 localSamplePosition = spline.InverseTransformPoint(samplePosition); Vector3 bottomPosition = localSamplePosition; Vector3 sampleDirection = evalResult.forward; Vector3 sampleNormal = evalResult.up; float heightPercent = 1f; if (_uvWrapMode == UVWrapMode.UniformX || _uvWrapMode == UVWrapMode.Uniform) { if (i > 0) { totalLength += Vector3.Distance(evalResult.position, GetSampleRaw(i - 1).position); } } switch (_axis) { case Axis.X: bottomPosition.x = _symmetry ? -localSamplePosition.x : 0f; heightPercent = uvScale.y * Mathf.Abs(localSamplePosition.x); avgTop += localSamplePosition.x; break; case Axis.Y: bottomPosition.y = _symmetry ? -localSamplePosition.y : 0f; heightPercent = uvScale.y * Mathf.Abs(localSamplePosition.y); avgTop += localSamplePosition.y; break; case Axis.Z: bottomPosition.z = _symmetry ? -localSamplePosition.z : 0f; heightPercent = uvScale.y * Mathf.Abs(localSamplePosition.z); avgTop += localSamplePosition.z; break; } bottomPosition = spline.TransformPoint(bottomPosition); Vector3 right = Vector3.Cross(normal, sampleDirection).normalized; Vector3 offsetRight = Vector3.Cross(sampleNormal, sampleDirection); for (int n = 0; n < _slices + 1; n++) { float slicePercent = ((float)n / _slices); tsMesh.vertices[vertIndex] = Vector3.Lerp(bottomPosition, samplePosition, slicePercent) + normal * (offset.y * resultSize) + offsetRight * (offset.x * resultSize); tsMesh.normals[vertIndex] = right; switch (_uvWrapMode) { case UVWrapMode.Clamp: tsMesh.uv[vertIndex] = new Vector2((float)evalResult.percent * uvScale.x + uvOffset.x, slicePercent * uvScale.y + uvOffset.y); break; case UVWrapMode.UniformX: tsMesh.uv[vertIndex] = new Vector2(totalLength * uvScale.x + uvOffset.x, slicePercent * uvScale.y + uvOffset.y); break; case UVWrapMode.UniformY: tsMesh.uv[vertIndex] = new Vector2((float)evalResult.percent * uvScale.x + uvOffset.x, heightPercent * slicePercent * uvScale.y + uvOffset.y); break; case UVWrapMode.Uniform: tsMesh.uv[vertIndex] = new Vector2(totalLength * uvScale.x + uvOffset.x, heightPercent * slicePercent * uvScale.y + uvOffset.y); break; } tsMesh.colors[vertIndex] = GetBaseColor(evalResult) * color; vertIndex++; } } if (sampleCount > 0) { avgTop /= sampleCount; } MeshUtility.GeneratePlaneTriangles(ref tsMesh.triangles, _slices, sampleCount, avgTop < 0f); }
void OnGUI() { string bakeText = "Bake"; EditorGUILayout.BeginHorizontal(); GUIContent saveMeshText = new GUIContent("Save as OBJ [?]", "Saves the mesh as an OBJ file which can then be used in other scenes and prefabs. OBJ files do not support vertex colors and secondary UV sets."); saveMesh = EditorGUILayout.Toggle(saveMeshText, saveMesh); if (saveMesh) { copy = EditorGUILayout.Toggle("Save as copy", copy); if (copy) { bakeText = "Save Copy"; } } EditorGUILayout.EndHorizontal(); bool hold = false; if (saveMesh) { EditorGUILayout.LabelField("Save Path: " + savePath); if (GUILayout.Button("Browse Path")) { string meshName = "mesh"; if (filter != null) { meshName = filter.sharedMesh.name; } savePath = EditorUtility.SaveFilePanel("Save " + meshName + ".obj", Application.dataPath, meshName + ".obj", "obj"); } } EditorGUILayout.Space(); bool isCopy = saveMesh && copy; if (!isCopy) { isStatic = EditorGUILayout.Toggle("Make Static", isStatic); } if (!saveMesh) { lightmapUV = EditorGUILayout.Toggle("Generate Lightmap UVs", lightmapUV); } SplineUser[] users = meshGen.GetComponents <SplineUser>(); if (users.Length == 1 && !isCopy) { removeComputer = EditorGUILayout.Toggle("Remove SplineComputer", removeComputer); } if (!isCopy) { permanent = EditorGUILayout.Toggle("Permanent", permanent); } bool _removeComputer = removeComputer; if (users.Length != 1) { _removeComputer = false; } if (_removeComputer && meshGen.computer.subscriberCount > 1 && !isCopy) { EditorGUILayout.HelpBox("WARNING: Removing the SplineComputer from this object may cause other SplineUsers to malfunction!", MessageType.Warning); } if (saveMesh) { if (savePath == "") { hold = true; } else if (!Directory.Exists(Path.GetDirectoryName(savePath))) { hold = true; } } if (hold) { GUI.color = new Color(1f, 1f, 1f, 0.5f); } if (GUILayout.Button(bakeText)) { Undo.RecordObject(meshGen.gameObject, "Bake mesh"); if (hold) { return; } if (!isCopy) { meshGen.Bake(isStatic, lightmapUV); } else if (lightmapUV) { Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh); } MeshRenderer renderer = meshGen.GetComponent <MeshRenderer>(); if (saveMesh) { string relativepath = "Assets" + savePath.Substring(Application.dataPath.Length); string objString = MeshUtility.ToOBJString(filter.sharedMesh, renderer.sharedMaterials); File.WriteAllText(savePath, objString); AssetDatabase.ImportAsset(relativepath, ImportAssetOptions.ForceSynchronousImport); #if UNITY_5_0 if (!isCopy) { filter.sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(relativepath, typeof(Mesh)); } #else if (!isCopy) { filter.sharedMesh = AssetDatabase.LoadAssetAtPath <Mesh>(relativepath); } #endif } if (removeComputer && !isCopy) { DestroyImmediate(meshGen.computer); } if (permanent && !isCopy) { DestroyImmediate(meshGen); } Close(); } string add = ""; if (removeComputer) { add += "It will also remove the SplineComputer component from the object."; } EditorGUILayout.HelpBox("This operation will remove the mesh generator component and will make the mesh uneditable." + add, MessageType.Info); }
public static void Generate(int subdivisionsCount, float radius, Vector3 viewCenter, float viewAngle, out List <Vector3> outVerts, out List <int> outIndices) { SphereGenerator.middlePointsCache.Clear(); outVerts = new List <Vector3>(); IcosahedronGenerator.GenerateIcosahedron(outVerts, SphereGenerator.tris, radius, viewCenter, viewAngle); for (int i = 0; i < subdivisionsCount; i++) { SphereGenerator.newTris.Clear(); int j = 0; int count = SphereGenerator.tris.Count; while (j < count) { TriangleIndices triangleIndices = SphereGenerator.tris[j]; int middlePoint = SphereGenerator.GetMiddlePoint(triangleIndices.v1, triangleIndices.v2, outVerts, radius); int middlePoint2 = SphereGenerator.GetMiddlePoint(triangleIndices.v2, triangleIndices.v3, outVerts, radius); int middlePoint3 = SphereGenerator.GetMiddlePoint(triangleIndices.v3, triangleIndices.v1, outVerts, radius); SphereGenerator.newTris.Add(new TriangleIndices(triangleIndices.v1, middlePoint, middlePoint3)); SphereGenerator.newTris.Add(new TriangleIndices(triangleIndices.v2, middlePoint2, middlePoint)); SphereGenerator.newTris.Add(new TriangleIndices(triangleIndices.v3, middlePoint3, middlePoint2)); SphereGenerator.newTris.Add(new TriangleIndices(middlePoint, middlePoint2, middlePoint3)); j++; } SphereGenerator.tris.Clear(); SphereGenerator.tris.AddRange(SphereGenerator.newTris); } MeshUtility.RemoveVertices(outVerts, SphereGenerator.tris, (Vector3 x) => !MeshUtility.Visible(x, radius, viewCenter, viewAngle)); outIndices = new List <int>(); int k = 0; int count2 = SphereGenerator.tris.Count; while (k < count2) { TriangleIndices triangleIndices2 = SphereGenerator.tris[k]; outIndices.Add(triangleIndices2.v1); outIndices.Add(triangleIndices2.v2); outIndices.Add(triangleIndices2.v3); k++; } }
void OnWizardCreate() { GameObject sphere = new GameObject(); if (!string.IsNullOrEmpty(optionalName)) { sphere.name = optionalName; } else { sphere.name = "IcoSphere"; } if (!createAtOrigin && cam) { sphere.transform.position = cam.transform.position + cam.transform.forward * 5.0f; } else { sphere.transform.position = Vector3.zero; } MeshFilter filter = (MeshFilter)sphere.AddComponent(typeof(MeshFilter)); sphere.AddComponent(typeof(MeshRenderer)); string anchorId; switch (anchor) { case AnchorPoint.Center: default: anchorId = "C"; break; } string sphereAssetName = sphere.name + recursionLevel + anchorId + ".asset"; Mesh mesh = (Mesh)AssetDatabase.LoadAssetAtPath("Assets/Editor/" + sphereAssetName, typeof(Mesh)); if (mesh == null) { mesh = new Mesh(); mesh.name = sphere.name; List <Vector3> vertList = new List <Vector3>(); Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>(); // create 12 vertices of a icosahedron float t = (1f + Mathf.Sqrt(5f)) / 2f; vertList.Add(new Vector3(-1f, t, 0f).normalized *radius); vertList.Add(new Vector3(1f, t, 0f).normalized *radius); vertList.Add(new Vector3(-1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(0f, -1f, t).normalized *radius); vertList.Add(new Vector3(0f, 1f, t).normalized *radius); vertList.Add(new Vector3(0f, -1f, -t).normalized *radius); vertList.Add(new Vector3(0f, 1f, -t).normalized *radius); vertList.Add(new Vector3(t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(t, 0f, 1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, 1f).normalized *radius); // create 20 triangles of the icosahedron List <TriangleIndices> faces = new List <TriangleIndices>(); // 5 faces around point 0 faces.Add(new TriangleIndices(0, 11, 5)); faces.Add(new TriangleIndices(0, 5, 1)); faces.Add(new TriangleIndices(0, 1, 7)); faces.Add(new TriangleIndices(0, 7, 10)); faces.Add(new TriangleIndices(0, 10, 11)); // 5 adjacent faces faces.Add(new TriangleIndices(1, 5, 9)); faces.Add(new TriangleIndices(5, 11, 4)); faces.Add(new TriangleIndices(11, 10, 2)); faces.Add(new TriangleIndices(10, 7, 6)); faces.Add(new TriangleIndices(7, 1, 8)); // 5 faces around point 3 faces.Add(new TriangleIndices(3, 9, 4)); faces.Add(new TriangleIndices(3, 4, 2)); faces.Add(new TriangleIndices(3, 2, 6)); faces.Add(new TriangleIndices(3, 6, 8)); faces.Add(new TriangleIndices(3, 8, 9)); // 5 adjacent faces faces.Add(new TriangleIndices(4, 9, 5)); faces.Add(new TriangleIndices(2, 4, 11)); faces.Add(new TriangleIndices(6, 2, 10)); faces.Add(new TriangleIndices(8, 6, 7)); faces.Add(new TriangleIndices(9, 8, 1)); // refine triangles for (int i = 0; i < recursionLevel; i++) { List <TriangleIndices> faces2 = new List <TriangleIndices>(); foreach (var tri in faces) { // replace triangle by 4 triangles int a = getMiddlePoint(tri.v1, tri.v2, ref vertList, ref middlePointIndexCache, radius); int b = getMiddlePoint(tri.v2, tri.v3, ref vertList, ref middlePointIndexCache, radius); int c = getMiddlePoint(tri.v3, tri.v1, ref vertList, ref middlePointIndexCache, radius); faces2.Add(new TriangleIndices(tri.v1, a, c)); faces2.Add(new TriangleIndices(tri.v2, b, a)); faces2.Add(new TriangleIndices(tri.v3, c, b)); faces2.Add(new TriangleIndices(a, b, c)); } faces = faces2; } mesh.vertices = vertList.ToArray(); List <int> triList = new List <int>(); for (int i = 0; i < faces.Count; i++) { triList.Add(faces[i].v1); triList.Add(faces[i].v2); triList.Add(faces[i].v3); } mesh.triangles = triList.ToArray(); var nVertices = mesh.vertices; Vector2[] UVs = new Vector2[nVertices.Length]; for (var i = 0; i < nVertices.Length; i++) { var unitVector = nVertices[i].normalized; Vector2 ICOuv = new Vector2(0, 0); ICOuv.x = (Mathf.Atan2(unitVector.x, unitVector.z) + Mathf.PI) / Mathf.PI / 2; ICOuv.y = (Mathf.Acos(unitVector.y) + Mathf.PI) / Mathf.PI - 1; UVs[i] = new Vector2(ICOuv.x, ICOuv.y); } mesh.uv = UVs; Vector3[] normales = new Vector3[vertList.Count]; for (int i = 0; i < normales.Length; i++) { normales[i] = vertList[i].normalized; } mesh.normals = normales; mesh.RecalculateBounds(); MeshUtility.Optimize(mesh); AssetDatabase.CreateAsset(mesh, "Assets/Editor/" + sphereAssetName); AssetDatabase.SaveAssets(); } filter.sharedMesh = mesh; mesh.RecalculateBounds(); if (addCollider) { sphere.AddComponent(typeof(BoxCollider)); } Selection.activeObject = sphere; }
private void Bake(MeshGenerator gen) { MeshFilter filter = gen.GetComponent <MeshFilter>(); if (filter == null) { EditorUtility.DisplayDialog("Save error", "No mesh present in " + gen.name, "OK"); return; } if (copy) { #if UNITY_5_5_OR_NEWER UnityEditor.MeshUtility.Optimize(filter.sharedMesh); #else filter.sharedMesh.Optimize(); #endif Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh); } else { gen.Bake(isStatic, true); } if (format == BakeMeshWindow.SaveFormat.OBJ) { MeshRenderer renderer = gen.GetComponent <MeshRenderer>(); dirInfo = new DirectoryInfo(savePath); FileInfo[] files = dirInfo.GetFiles(filter.sharedMesh.name + "*.obj"); string meshName = filter.sharedMesh.name; if (files.Length > 0) { meshName += "_" + files.Length; } string path = savePath + "/" + meshName + ".obj"; string objString = MeshUtility.ToOBJString(filter.sharedMesh, renderer.sharedMaterials); File.WriteAllText(path, objString); if (copy) { string relativepath = "Assets" + path.Substring(Application.dataPath.Length); AssetDatabase.ImportAsset(relativepath, ImportAssetOptions.ForceSynchronousImport); #if UNITY_5_0 filter.sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(relativepath, typeof(Mesh)); #else filter.sharedMesh = AssetDatabase.LoadAssetAtPath <Mesh>(relativepath); #endif } } if (format == BakeMeshWindow.SaveFormat.MeshAsset) { dirInfo = new DirectoryInfo(savePath); FileInfo[] files = dirInfo.GetFiles(filter.sharedMesh.name + "*.asset"); string meshName = filter.sharedMesh.name; if (files.Length > 0) { meshName += "_" + files.Length; } string path = savePath + "/" + meshName + ".asset"; string relativepath = "Assets" + path.Substring(Application.dataPath.Length); if (copy) { Mesh assetMesh = MeshUtility.Copy(filter.sharedMesh); AssetDatabase.CreateAsset(assetMesh, relativepath); } else { AssetDatabase.CreateAsset(filter.sharedMesh, relativepath); } } if (permanent && !copy) { SplineComputer meshGenComputer = gen.computer; if (permanent) { meshGenComputer.Unsubscribe(gen); Object.DestroyImmediate(gen); } if (removeComputer) { if (meshGenComputer.GetComponents <Component>().Length == 2) { Object.DestroyImmediate(meshGenComputer.gameObject); } else { Object.DestroyImmediate(meshGenComputer); } } } }
private void GenerateAndSaveDecalInstance() { // thisPath: Assets/BigMarch/OoSimpleDecalExample/Decal_ii-example.asset string thisPath = AssetDatabase.GetAssetPath(_decalApply.Set); // folderPath: Assets/BigMarch/OoSimpleDecalExample/Decal_ii-example/ string saveFolderPath = thisPath.Replace(".asset", "/"); if (!Directory.Exists(saveFolderPath)) { Debug.LogError("无法存储,找不到同名的文件夹 " + saveFolderPath); return; } DecalItemSet dis = _decalApply.Set; dis.DecalItemList.Clear(); Transform root = _decalApply.transform; List <GameObject> decalList = FindAllChild(root, DecalName); for (var i = 0; i < decalList.Count; i++) { EditorUtility.DisplayProgressBar("", "saving", i * 1f / decalList.Count); GameObject decalObj = decalList[i]; OoSimpleDecal decal = decalObj.GetComponent <OoSimpleDecal>(); // 创建 instance GameObject decalInstance = decal.CreateDecalInstance(); // 储存 mesh Mesh meshToSave = decalInstance.GetComponent <MeshFilter>().sharedMesh; MeshUtility.Optimize(meshToSave); string meshName = dis.name + "-DecalMesh-" + i; AssetDatabase.CreateAsset(meshToSave, saveFolderPath + meshName + ".asset"); // 重新关联 mesh Mesh loadMesh = AssetDatabase.LoadAssetAtPath <Mesh>(saveFolderPath + meshName + ".asset"); decalInstance.GetComponent <MeshFilter>().sharedMesh = loadMesh; // 存储 prefab string prefabName = dis.name + "-DecalInstance-" + i; GameObject decalInstancePrefab = PrefabUtility.CreatePrefab(saveFolderPath + prefabName + ".prefab", decalInstance); // 删除 instance DestroyImmediate(decalInstance); // 记录本次循环的 decal item。 DecalItemSet.DecalItem di = new DecalItemSet.DecalItem(); di.DecalInstancePrefab = decalInstancePrefab; // parent 的 local 值 di.ParentPath = GetTransformPath(root, decal.transform.parent); // 放到 root 下面记录 local 值。 Transform cacheParent = decalObj.transform.parent; decalObj.transform.parent = root; di.LocalPositionInRoot = decalObj.transform.localPosition; di.LocalEulerAngleInRoot = decalObj.transform.localEulerAngles; di.LocalScaleInRoot = decalObj.transform.localScale; // 放到原本的 parent 下面。 decalObj.transform.parent = cacheParent; di.TargetObjPath = GetTransformPath(root, decal.TargetObjects[0].transform); di.UvArea = decal.UvArea; di.PushDistance = decal.PushDistance; dis.DecalItemList.Add(di); } EditorUtility.ClearProgressBar(); EditorUtility.SetDirty(dis); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Repaint(); }
// Start is called before the first frame update void Awake() { filter = GetComponent <MeshFilter>(); util = new MeshUtility(filter.sharedMesh); DebugGraph.meshUtility = util; }
public void Step() { MeshUtility temp = new MeshUtility(); setCoef(util.Vertices.Count); List <Vertex> vs = new List <Vertex>(); //Centers foreach (Triangle t in util.Triangles) { Vertex vert = new Vertex(((t.GetVertices()[0].Position + t.GetVertices()[1].Position + t.GetVertices()[2].Position) / 3)); temp.FindOrCreateVertex(vert); vs.Add(vert); } foreach (Vertex v in vs) { foreach (Vertex v2 in vs) { if (v != v2) { temp.FindOrCreateEdge(v, v2); } } } List <Edge> edges = new List <Edge>(); foreach (Edge e in temp.Edges) { edges.Add(e); } foreach (Edge e in edges) { foreach (Vertex v in vs) { if (v != e.Vertices[0] && v != e.Vertices[1] && e.Vertices[0] != e.Vertices[1]) { temp.CreateTriangle(v, e.Vertices[0], e.Vertices[1]); } } } foreach (Triangle t in util.Triangles) { Vector3 vt = getVertexPoint(t); temp.FindOrCreateVertex(vt); } //foreach (Vertex v in util.Vertices) //{ // for (int j = 0; j < v.GetTriangles().Length; j++) // { // Triangle t = v.GetTriangles()[j]; // Triangle tnext = null; // int i = 0; // do // { // if (i > v.GetTriangles().Length) // tnext = null; // else // tnext = v.GetTriangles()[i]; // temp.CreateTriangle(tnext.GetVertices()[0], tnext.GetVertices()[1], tnext.GetVertices()[2]); // t = tnext; // i++; // } while (t != v.GetTriangles()[j] && t != null); // } //} Debug.Log(temp.Vertices.Count); Debug.Log(temp.Edges.Count); Debug.Log(temp.Triangles.Count); util = temp; DebugGraph.meshUtility = util; filter.sharedMesh = util.ToMesh(); }
private static bool IcosahedronFaceNeeded(int v1, int v2, int v3, List <Vector3> verts, float radius, Vector3 viewCenter, float viewAngle) { viewAngle += 18f; return(MeshUtility.Visible(verts[v1], radius, viewCenter, viewAngle) || MeshUtility.Visible(verts[v2], radius, viewCenter, viewAngle) || MeshUtility.Visible(verts[v3], radius, viewCenter, viewAngle)); }
// Use this for initialization void Start() { MeshFilter mf = GetComponent <MeshFilter>(); Mesh mesh = mf.mesh; //Vertices Vector3[] vertices = new Vector3[] { //Vorderseite vertLeftFront, //linke vordere Front,0 vertRightFront, //rechte vordere Front,1 new Vector3(-1, -1, 1), //linke hintere front,2 new Vector3(1, -1, 1), //rechte hintere front,3 //Rückseite vertRightBack, vertLeftBack, new Vector3(1, -1, -1), new Vector3(-1, -1, -1), //Linkeseite vertLeftBack, vertLeftFront, new Vector3(-1, -1, -1), new Vector3(-1, -1, 1), //Rechteseite vertRightFront, vertRightBack, new Vector3(1, -1, 1), new Vector3(1, -1, -1), //Obereseite (Deckel) vertLeftBack, vertRightBack, vertLeftFront, vertRightFront, //Untereseite (Grund) new Vector3(-1, -1, 1), new Vector3(1, -1, 1), new Vector3(-1, -1, -1), new Vector3(1, -1, -1), }; // Dreieck int[] triangles = new int[] { //Vorderseite 0, 2, 3, //erstes triangles 3, 1, 0, //zweites triangles //Rückseite 4, 6, 7, //drittes triangles 7, 5, 4, //viertes triangles //Linkeseite 8, 10, 11, //fünftes triangles 11, 9, 8, //sechstes triangles //Rechteseite 12, 14, 15, //siebtes triangles 15, 13, 12, //achtes triangles //Obereseite (Deckel) 16, 18, 19, //neuntes triangles 19, 17, 16, //zehntes triangles //Untereseite (Grund) 20, 22, 23, //elftes triangles 23, 21, 20 //zwelftes triangles }; //UVs Vector2[] uvs = new Vector2[] { //Vorderseite new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0), //Rückseite new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0), //Linkeseite new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0), //Rechteseite new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0), //Obereseite (Deckel) new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0), //Untereseite (Grund) new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0) }; mesh.Clear(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = uvs; MeshUtility.Optimize(mesh); mesh.RecalculateNormals(); }
protected override void BuildMesh() { base.BuildMesh(); GenerateVertices(vertexDirection, orthographic); MeshUtility.GeneratePlaneTriangles(ref tsMesh.triangles, _slices, base.clippedSamples.Length, flip: false); }
public static void AutoWeld(Mesh mesh, float threshold, float bucketStep) { Vector3[] oldVertices = mesh.vertices; Vector3[] newVertices = new Vector3[oldVertices.Length]; int[] old2new = new int[oldVertices.Length]; int newSize = 0; // Find AABB Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue); for (int i = 0; i < oldVertices.Length; i++) { if (oldVertices[i].x < min.x) { min.x = oldVertices[i].x; } if (oldVertices[i].y < min.y) { min.y = oldVertices[i].y; } if (oldVertices[i].z < min.z) { min.z = oldVertices[i].z; } if (oldVertices[i].x > max.x) { max.x = oldVertices[i].x; } if (oldVertices[i].y > max.y) { max.y = oldVertices[i].y; } if (oldVertices[i].z > max.z) { max.z = oldVertices[i].z; } } // Make cubic buckets, each with dimensions "bucketStep" int bucketSizeX = Mathf.FloorToInt((max.x - min.x) / bucketStep) + 1; int bucketSizeY = Mathf.FloorToInt((max.y - min.y) / bucketStep) + 1; int bucketSizeZ = Mathf.FloorToInt((max.z - min.z) / bucketStep) + 1; List <int>[,,] buckets = new List <int> [bucketSizeX, bucketSizeY, bucketSizeZ]; // Make new vertices for (int i = 0; i < oldVertices.Length; i++) { // Determine which bucket it belongs to int x = Mathf.FloorToInt((oldVertices[i].x - min.x) / bucketStep); int y = Mathf.FloorToInt((oldVertices[i].y - min.y) / bucketStep); int z = Mathf.FloorToInt((oldVertices[i].z - min.z) / bucketStep); // Check to see if it's already been added if (buckets[x, y, z] == null) { buckets[x, y, z] = new List <int> (); // Make buckets lazily } for (int j = 0; j < buckets[x, y, z].Count; j++) { Vector3 to = newVertices[buckets[x, y, z][j]] - oldVertices[i]; if (Vector3.SqrMagnitude(to) < threshold) { old2new[i] = buckets[x, y, z][j]; goto skip; // Skip to next old vertex if this one is already there } } // Add new vertex newVertices[newSize] = oldVertices[i]; buckets[x, y, z].Add(newSize); old2new[i] = newSize; newSize++; skip :; } // Make new triangles int[] oldTris = mesh.triangles; int[] newTris = new int[oldTris.Length]; for (int i = 0; i < oldTris.Length; i++) { newTris[i] = old2new[oldTris[i]]; } Vector3[] finalVertices = new Vector3[newSize]; for (int i = 0; i < newSize; i++) { finalVertices[i] = newVertices[i]; } mesh.Clear(); mesh.vertices = finalVertices; mesh.triangles = newTris; mesh.RecalculateNormals(); MeshUtility.Optimize(mesh); }
public void Update() { savedMesh = MeshUtility.CreateCubeSidedTextureOptimized(1, Position, new Vector2(7, 0), new Vector2(7, 0), new Vector2(7, 0), new Vector2(7, 0), new Vector2(7, 0), new Vector2(7, 0), this); }
protected override void BuildMesh() { base.BuildMesh(); GenerateVertices(); MeshUtility.GeneratePlaneTriangles(ref tsMesh.triangles, _slices, sampleCount, false); }
public void CreateMesh() { //get component MeshFilter filter = GetComponent <MeshFilter>(); MeshRenderer renderer = GetComponent <MeshRenderer>(); //create mesh Mesh mesh = new Mesh(); mesh.name = "PlanetMesh"; //create material Material material = new Material(Shader.Find("Standard")); renderer.sharedMaterial = material; List <Vector3> vertList = new List <Vector3>(); Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>(); // create 12 vertices of a icosahedron float t = (1f + Mathf.Sqrt(5f)) / 2f; vertList.Add(new Vector3(-1f, t, 0f).normalized *radius); vertList.Add(new Vector3(1f, t, 0f).normalized *radius); vertList.Add(new Vector3(-1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(0f, -1f, t).normalized *radius); vertList.Add(new Vector3(0f, 1f, t).normalized *radius); vertList.Add(new Vector3(0f, -1f, -t).normalized *radius); vertList.Add(new Vector3(0f, 1f, -t).normalized *radius); vertList.Add(new Vector3(t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(t, 0f, 1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, 1f).normalized *radius); // create 20 triangles of the icosahedron List <TriangleIndices> faces = new List <TriangleIndices>(); // 5 faces around point 0 faces.Add(new TriangleIndices(0, 11, 5)); faces.Add(new TriangleIndices(0, 5, 1)); faces.Add(new TriangleIndices(0, 1, 7)); faces.Add(new TriangleIndices(0, 7, 10)); faces.Add(new TriangleIndices(0, 10, 11)); // 5 adjacent faces faces.Add(new TriangleIndices(1, 5, 9)); faces.Add(new TriangleIndices(5, 11, 4)); faces.Add(new TriangleIndices(11, 10, 2)); faces.Add(new TriangleIndices(10, 7, 6)); faces.Add(new TriangleIndices(7, 1, 8)); // 5 faces around point 3 faces.Add(new TriangleIndices(3, 9, 4)); faces.Add(new TriangleIndices(3, 4, 2)); faces.Add(new TriangleIndices(3, 2, 6)); faces.Add(new TriangleIndices(3, 6, 8)); faces.Add(new TriangleIndices(3, 8, 9)); // 5 adjacent faces faces.Add(new TriangleIndices(4, 9, 5)); faces.Add(new TriangleIndices(2, 4, 11)); faces.Add(new TriangleIndices(6, 2, 10)); faces.Add(new TriangleIndices(8, 6, 7)); faces.Add(new TriangleIndices(9, 8, 1)); // refine triangles for (int i = 0; i < resolution; i++) { List <TriangleIndices> faces2 = new List <TriangleIndices>(); foreach (var tri in faces) { // replace triangle by 4 triangles int a = getMiddlePoint(tri.v1, tri.v2, ref vertList, ref middlePointIndexCache, radius); int b = getMiddlePoint(tri.v2, tri.v3, ref vertList, ref middlePointIndexCache, radius); int c = getMiddlePoint(tri.v3, tri.v1, ref vertList, ref middlePointIndexCache, radius); faces2.Add(new TriangleIndices(tri.v1, a, c)); faces2.Add(new TriangleIndices(tri.v2, b, a)); faces2.Add(new TriangleIndices(tri.v3, c, b)); faces2.Add(new TriangleIndices(a, b, c)); } faces = faces2; } mesh.vertices = vertList.ToArray(); List <int> triList = new List <int>(); for (int i = 0; i < faces.Count; i++) { triList.Add(faces[i].v1); triList.Add(faces[i].v2); triList.Add(faces[i].v3); } mesh.triangles = triList.ToArray(); var nVertices = mesh.vertices; Vector2[] UVs = new Vector2[nVertices.Length]; for (var i = 0; i < nVertices.Length; i++) { var unitVector = nVertices[i].normalized; Vector2 ICOuv = new Vector2(0, 0); ICOuv.x = (Mathf.Atan2(unitVector.x, unitVector.z) + Mathf.PI) / Mathf.PI / 2; ICOuv.y = (Mathf.Acos(unitVector.y) + Mathf.PI) / Mathf.PI - 1; UVs[i] = new Vector2(ICOuv.x, ICOuv.y); } mesh.uv = UVs; Vector3[] normales = new Vector3[vertList.Count]; for (int i = 0; i < normales.Length; i++) { normales[i] = vertList[i].normalized; } mesh.normals = normales; mesh.RecalculateBounds(); MeshUtility.Optimize(mesh); filter.sharedMesh = mesh; }
internal bool <> m__0(Vector3 x) { return(!MeshUtility.Visible(x, this.radius, this.viewCenter, this.viewAngle)); }
public void Generate() { if (_extrudeComputer != null) { _extrudeComputer.Evaluate(ref extrudeResults, _extrudeFrom, _extrudeTo); } int capVertexCount = clippedSamples.Length; int wallVertexCount = 0; int totalVertexCount = 0; if (computer.isClosed) { capVertexCount--; } bool pathExtrude = _extrudeComputer != null && extrudeResults.Length > 0; bool simpleExtrude = !pathExtrude && _extrude != 0f; totalVertexCount = capVertexCount; if (pathExtrude) { wallVertexCount = clippedSamples.Length * extrudeResults.Length; totalVertexCount = capVertexCount * 2 + wallVertexCount; } else if (simpleExtrude) { wallVertexCount = clippedSamples.Length * 2; totalVertexCount = capVertexCount * 2 + wallVertexCount; } AllocateMesh(totalVertexCount, tsMesh.triangles.Length); Vector3 avgPos = Vector3.zero; Vector3 avgNormal = Vector3.zero; Vector3 off = transform.right * offset.x + transform.up * offset.y + transform.forward * offset.z; for (int i = 0; i < capVertexCount; i++) { tsMesh.vertices[i] = clippedSamples[i].position + off; tsMesh.normals[i] = clippedSamples[i].normal; tsMesh.colors[i] = clippedSamples[i].color; tsMesh.colors[i] *= color; avgPos += tsMesh.vertices[i]; avgNormal += tsMesh.normals[i]; } avgNormal.Normalize(); avgPos /= capVertexCount; GetProjectedVertices(tsMesh.vertices, avgNormal, avgPos, capVertexCount); Vector2 min = projectedVerts[0]; Vector2 max = projectedVerts[0]; for (int i = 1; i < projectedVerts.Length; i++) { if (min.x < projectedVerts[i].x) { min.x = projectedVerts[i].x; } if (min.y < projectedVerts[i].y) { min.y = projectedVerts[i].y; } if (max.x > projectedVerts[i].x) { max.x = projectedVerts[i].x; } if (max.y > projectedVerts[i].y) { max.y = projectedVerts[i].y; } } for (int i = 0; i < projectedVerts.Length; i++) { tsMesh.uv[i].x = Mathf.InverseLerp(max.x, min.x, projectedVerts[i].x) * uvScale.x - uvScale.x * 0.5f + uvOffset.x + 0.5f; tsMesh.uv[i].y = Mathf.InverseLerp(min.y, max.y, projectedVerts[i].y) * uvScale.y - uvScale.y * 0.5f + uvOffset.y + 0.5f; } bool clockwise = IsClockwise(projectedVerts); bool flipCap = false; bool flipSide = false; if (!clockwise) { flipSide = !flipSide; } if (simpleExtrude && _extrude < 0f) { flipCap = !flipCap; flipSide = !flipSide; } GenerateCapTris(flipCap); if (flipCap) { for (int i = 0; i < capVertexCount; i++) { tsMesh.normals[i] *= -1f; } } if (pathExtrude) { GetIdentityVerts(avgPos, avgNormal, clockwise); //Generate cap vertices with flipped normals for (int i = 0; i < capVertexCount; i++) { tsMesh.vertices[i + capVertexCount] = extrudeResults[0].position + extrudeResults[0].rotation * identityVertices[i] + off; tsMesh.normals[i + capVertexCount] = -extrudeResults[0].direction; tsMesh.colors[i + capVertexCount] = tsMesh.colors[i] * extrudeResults[0].color; tsMesh.uv[i + capVertexCount] = new Vector2(1f - tsMesh.uv[i].x, tsMesh.uv[i].y); tsMesh.vertices[i] = extrudeResults[extrudeResults.Length - 1].position + extrudeResults[extrudeResults.Length - 1].rotation * identityVertices[i] + off; tsMesh.normals[i] = extrudeResults[extrudeResults.Length - 1].direction; tsMesh.colors[i] *= extrudeResults[extrudeResults.Length - 1].color; } //Add wall vertices float totalLength = 0f; for (int i = 0; i < extrudeResults.Length; i++) { if (_uniformUvs && i > 0) { totalLength += Vector3.Distance(extrudeResults[i].position, extrudeResults[i - 1].position); } int startIndex = capVertexCount * 2 + i * clippedSamples.Length; for (int n = 0; n < identityVertices.Length; n++) { tsMesh.vertices[startIndex + n] = extrudeResults[i].position + extrudeResults[i].rotation * identityVertices[n] + off; tsMesh.normals[startIndex + n] = extrudeResults[i].rotation * identityNormals[n]; if (_uniformUvs) { tsMesh.uv[startIndex + n] = new Vector2((float)n / (identityVertices.Length - 1) * _sideUvScale.x + _sideUvOffset.x, totalLength * _sideUvScale.y + _sideUvOffset.y); } else { tsMesh.uv[startIndex + n] = new Vector2((float)n / (identityVertices.Length - 1) * _sideUvScale.x + _sideUvOffset.x, (float)i / (extrudeResults.Length - 1) * _sideUvScale.y + _sideUvOffset.y); } if (clockwise) { tsMesh.uv[startIndex + n].x = 1f - tsMesh.uv[startIndex + n].x; } } } MeshUtility.GeneratePlaneTriangles(ref wallTris, clippedSamples.Length - 1, extrudeResults.Length, flipSide, 0, 0, true); tsMesh.triangles = new int[capTris.Length * 2 + wallTris.Length]; int written = WriteTris(ref capTris, ref tsMesh.triangles, 0, 0, false); written = WriteTris(ref capTris, ref tsMesh.triangles, capVertexCount, written, true); written = WriteTris(ref wallTris, ref tsMesh.triangles, capVertexCount * 2, written, false); } else if (simpleExtrude) { //Duplicate cap vertices with flipped normals for (int i = 0; i < capVertexCount; i++) { tsMesh.vertices[i + capVertexCount] = tsMesh.vertices[i]; if (_expand != 0f) { tsMesh.vertices[i + capVertexCount] += (clockwise ? -clippedSamples[i].right : clippedSamples[i].right) * _expand; } tsMesh.normals[i + capVertexCount] = -tsMesh.normals[i]; tsMesh.colors[i + capVertexCount] = tsMesh.colors[i]; tsMesh.uv[i + capVertexCount] = new Vector2(1f - tsMesh.uv[i].x, tsMesh.uv[i].y); tsMesh.vertices[i] += avgNormal * _extrude; if (_expand != 0f) { tsMesh.vertices[i] += (clockwise ? -clippedSamples[i].right : clippedSamples[i].right) * _expand; } } //Add wall vertices for (int i = 0; i < clippedSamples.Length; i++) { tsMesh.vertices[i + capVertexCount * 2] = clippedSamples[i].position + off; if (_expand != 0f) { tsMesh.vertices[i + capVertexCount * 2] += (clockwise ? -clippedSamples[i].right : clippedSamples[i].right) * _expand; } tsMesh.normals[i + capVertexCount * 2] = clockwise ? -clippedSamples[i].right : clippedSamples[i].right; tsMesh.colors[i + capVertexCount * 2] = clippedSamples[i].color; tsMesh.uv[i + capVertexCount * 2] = new Vector2((float)i / (capVertexCount - 1) * _sideUvScale.x + _sideUvOffset.x, 0f + _sideUvOffset.y); if (clockwise) { tsMesh.uv[i + capVertexCount * 2].x = 1f - tsMesh.uv[i + capVertexCount * 2].x; } tsMesh.vertices[i + capVertexCount * 2 + clippedSamples.Length] = tsMesh.vertices[i + capVertexCount * 2] + avgNormal * _extrude; tsMesh.normals[i + capVertexCount * 2 + clippedSamples.Length] = clockwise ? -clippedSamples[i].right : clippedSamples[i].right; tsMesh.colors[i + capVertexCount * 2 + clippedSamples.Length] = clippedSamples[i].color; if (_uniformUvs) { tsMesh.uv[i + capVertexCount * 2 + clippedSamples.Length] = new Vector2((float)i / (capVertexCount - 1) * _sideUvScale.x + _sideUvOffset.x, _extrude * _sideUvScale.y + _sideUvOffset.y); } else { tsMesh.uv[i + capVertexCount * 2 + clippedSamples.Length] = new Vector2((float)i / (capVertexCount - 1) * _sideUvScale.x + _sideUvOffset.x, 1f * _sideUvScale.y + _sideUvOffset.y); } if (clockwise) { tsMesh.uv[i + capVertexCount * 2 + clippedSamples.Length].x = 1f - tsMesh.uv[i + capVertexCount * 2 + clippedSamples.Length].x; } } MeshUtility.GeneratePlaneTriangles(ref wallTris, clippedSamples.Length - 1, 2, flipSide, 0, 0, true); int trisCount = capTris.Length * 2 + wallTris.Length; if (doubleSided) { trisCount *= 2; } if (tsMesh.triangles.Length != trisCount) { tsMesh.triangles = new int[trisCount]; } int written = WriteTris(ref capTris, ref tsMesh.triangles, 0, 0, false); written = WriteTris(ref capTris, ref tsMesh.triangles, capVertexCount, written, true); written = WriteTris(ref wallTris, ref tsMesh.triangles, capVertexCount * 2, written, false); } else { //for (int i = 0; i < tsMesh.vertices.Length; i++) tsMesh.vertices[i] += clockwise ? -clippedSamples[i].right : clippedSamples[i].right; int trisCount = capTris.Length; if (doubleSided) { trisCount *= 2; } if (tsMesh.triangles.Length != trisCount) { tsMesh.triangles = new int[trisCount]; } WriteTris(ref capTris, ref tsMesh.triangles, 0, 0, false); } }
private static void ExportModel(TrackBuildR track) { GameObject baseObject = new GameObject(track.exportFilename); baseObject.transform.position = CURRENT_TRANSFORM.position; baseObject.transform.rotation = CURRENT_TRANSFORM.rotation; EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f); track.ForceFullRecalculation(); EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.1f); try { TrackBuildRTrack trackData = track.track; //check overwrites... string newDirectory = ROOT_FOLDER + track.exportFilename; if (!CreateFolder(newDirectory)) { EditorUtility.ClearProgressBar(); return; } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.15f); int numberOfCurves = trackData.numberOfCurves; float exportProgress = 0.75f / (numberOfCurves * 6.0f); ExportMaterial[] exportMaterials = new ExportMaterial[1]; ExportMaterial exportTexture = new ExportMaterial(); string[] dynNames = new [] { "track", "bumper", "boundary", "bottom", "offread", "trackCollider" }; for (int c = 0; c < numberOfCurves; c++) { TrackBuildRPoint curve = trackData[c]; int numberOfDynMeshes = 6; DynamicMeshGenericMultiMaterialMesh[] dynMeshes = new DynamicMeshGenericMultiMaterialMesh[6]; dynMeshes[0] = curve.dynamicTrackMesh; dynMeshes[1] = curve.dynamicBumperMesh; dynMeshes[2] = curve.dynamicBoundaryMesh; dynMeshes[3] = curve.dynamicBottomMesh; dynMeshes[4] = curve.dynamicOffroadMesh; dynMeshes[5] = curve.dynamicColliderMesh; int[] textureIndeices = new int[] { curve.trackTextureStyleIndex, curve.bumperTextureStyleIndex, curve.boundaryTextureStyleIndex, curve.bottomTextureStyleIndex, curve.offroadTextureStyleIndex, 0 }; for (int d = 0; d < numberOfDynMeshes; d++) { if (EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "Exporting Track Curve " + c + " " + dynNames[d], 0.15f + exportProgress * (c * 6 + d))) { EditorUtility.ClearProgressBar(); return; } DynamicMeshGenericMultiMaterialMesh exportDynMesh = dynMeshes[d]; if (track.includeTangents || exportDynMesh.isEmpty) { exportDynMesh.Build(track.includeTangents);//rebuild with tangents } TrackBuildRTexture texture = trackData.Texture(textureIndeices[d]); exportTexture.name = texture.customName; exportTexture.material = texture.material; exportTexture.generated = false; exportTexture.filepath = texture.filePath; exportMaterials[0] = exportTexture; int meshCount = exportDynMesh.meshCount; for (int i = 0; i < meshCount; i++) { Mesh exportMesh = exportDynMesh[i].mesh; MeshUtility.Optimize(exportMesh); string filenameSuffix = trackModelName(dynNames[d], c, (meshCount > 1) ? i : -1);// "trackCurve" + c + ((meshCount > 1) ? "_" + i.ToString() : ""); string filename = track.exportFilename + filenameSuffix; Export(filename, ROOT_FOLDER + track.exportFilename + "/", track, exportMesh, exportMaterials); if (track.createPrefabOnExport) { AssetDatabase.Refresh();//ensure the database is up to date... string modelFilePath = ROOT_FOLDER + track.exportFilename + "/" + filename + FILE_EXTENTION; if (d < numberOfDynMeshes - 1) { GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath)); newModel.name = filename; newModel.transform.parent = baseObject.transform; newModel.transform.localPosition = Vector3.zero; newModel.transform.localRotation = Quaternion.identity; } else { GameObject colliderObject = new GameObject("trackCollider"); colliderObject.AddComponent <MeshCollider>().sharedMesh = (Mesh)AssetDatabase.LoadAssetAtPath(modelFilePath, typeof(Mesh)); colliderObject.transform.parent = baseObject.transform; colliderObject.transform.localPosition = Vector3.zero; colliderObject.transform.localRotation = Quaternion.identity; } } } } } if (track.createPrefabOnExport) { string prefabPath = ROOT_FOLDER + track.exportFilename + "/" + track.exportFilename + ".prefab"; Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if (prefab == null) { prefab = PrefabUtility.CreateEmptyPrefab(prefabPath); } PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab); } EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f); AssetDatabase.Refresh();//ensure the database is up to date... } catch (System.Exception e) { Debug.LogError("BuildR Export Error: " + e); EditorUtility.ClearProgressBar(); } Object.DestroyImmediate(baseObject); EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssets(); AssetDatabase.Refresh(); }
public static GameObject CombineAllMeshesInGameObject(List <Material> matsInCombine, MeshFilter[] sourceMeshFilters, MeshRenderer[] sourceMeshRenderers) { // --------------------------------------------------------------------------- // Extract Meshes into Separate CombineInstances based on Material // --------------------------------------------------------------------------- // Create a MeshCombine Class Array the size of the uniqueMats List and initialize MeshCombine[] uniqueMatMeshCombine = new MeshCombine[matsInCombine.Count]; for (int i = 0; i < matsInCombine.Count; i++) { uniqueMatMeshCombine[i] = new MeshCombine(); uniqueMatMeshCombine[i].combineList = new List <CombineInstance>(); } // Prepare variables CombineInstance combineInstance; // Loop through each MeshRenderer in sourceMeshRenderers for (int i = 0; i < sourceMeshRenderers.Length; i++) { // Loop through each Material in each MeshRenderer for (int j = 0; j < sourceMeshRenderers[i].sharedMaterials.Length; j++) { // Loop through each Material in the uniqueMats List for (int k = 0; k < matsInCombine.Count; k++) { // If this Material matches the Material in the uniqueMats List if (sourceMeshRenderers[i].sharedMaterials[j] == matsInCombine[k]) { // Initialize a Combine Instance combineInstance = new CombineInstance(); // Copy this mesh to the Combine Instance combineInstance.mesh = sourceMeshFilters[i].sharedMesh; // Set it to only include the Mesh with the specified material combineInstance.subMeshIndex = j; // Transform to world matrix combineInstance.transform = sourceMeshFilters[i].transform.localToWorldMatrix; // Add this CombineInstance to the appropriate CombineInstance List (by Material) uniqueMatMeshCombine[k].combineList.Add(combineInstance); } } } } // --------------------------------------------------------------------------- // Combine all Mesh Instances into a single GameObject // --------------------------------------------------------------------------- // Disable all Source GameObjects for (int i = 0; i < sourceMeshFilters.Length; i++) { sourceMeshFilters[i].gameObject.SetActive(false); } // Create the final GameObject that will hold all the other GameObjects GameObject finalGameObject = new GameObject("Merged Meshes"); // Create a new GameObject Array the size of the All Materials List GameObject[] singleMatGameObject = new GameObject[matsInCombine.Count]; // Combine meshes for each singleMatGameObject into one mesh CombineInstance[] finalCombineInstance = new CombineInstance[matsInCombine.Count]; // Enable all Source GameObjects for (int i = 0; i < sourceMeshFilters.Length; i++) { sourceMeshFilters[i].gameObject.SetActive(true); } // Prepare mesh filter and mesh renderer arrays for the final combine MeshFilter[] meshFilter = new MeshFilter[matsInCombine.Count]; MeshRenderer[] meshRenderer = new MeshRenderer[matsInCombine.Count]; // Loop through each Material in the uniqueMats List for (int i = 0; i < matsInCombine.Count; i++) { // Initialize GameObject singleMatGameObject[i] = new GameObject(); singleMatGameObject[i].name = matsInCombine[i].name; // Add a MeshRender and set the Material meshRenderer[i] = singleMatGameObject[i].AddComponent <MeshRenderer>(); meshRenderer[i].sharedMaterial = matsInCombine[i]; // Add a MeshFilter and add the Combined Meshes with this Material meshFilter[i] = singleMatGameObject[i].AddComponent <MeshFilter>(); meshFilter[i].sharedMesh = new Mesh(); meshFilter[i].sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; meshFilter[i].sharedMesh.CombineMeshes(uniqueMatMeshCombine[i].combineList.ToArray()); // Weld duplicate vertices //meshFilter[i].sharedMesh = WeldVertices(meshFilter[i].sharedMesh, 0.001f); // Add this Mesh to the final Mesh Combine finalCombineInstance[i].mesh = meshFilter[i].sharedMesh; finalCombineInstance[i].transform = meshFilter[i].transform.localToWorldMatrix; // Hide the GameObject meshFilter[i].gameObject.SetActive(false); GameObject.DestroyImmediate(singleMatGameObject[i]); } // Combine the Mesh, optimize it, and recalculate the bounds Mesh mesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; mesh.CombineMeshes(finalCombineInstance, false, false); MeshUtility.Optimize(mesh); mesh.RecalculateBounds(); // Add MeshFilter to final GameObject and Combine all Meshes MeshFilter finalMeshFilter = finalGameObject.AddComponent <MeshFilter>(); finalMeshFilter.sharedMesh = new Mesh(); finalMeshFilter.sharedMesh = mesh; // Add MeshRenderer to final GameObject Attach Materials MeshRenderer finalMeshRenderer = finalGameObject.AddComponent <MeshRenderer>(); finalMeshRenderer.sharedMaterials = matsInCombine.ToArray(); return(finalGameObject); }
public void Generate() { int surfaceVertexCount = sampleCount; if (spline.isClosed) { surfaceVertexCount--; } int vertexCount = surfaceVertexCount; if (_extrudeSpline) { _extrudeSpline.Evaluate(ref extrudeResults, _extrudeFrom, _extrudeTo); } bool pathExtrude = _extrudeSpline && extrudeResults.Length > 0; bool simpleExtrude = !pathExtrude && _extrude != 0f; if (pathExtrude) { vertexCount *= 2; vertexCount += sampleCount * extrudeResults.Length; } else if (simpleExtrude) { vertexCount *= 4; vertexCount += 2; } Vector3 center, normal; GetProjectedVertices(surfaceVertexCount, out center, out normal); bool clockwise = IsClockwise(projectedVerts); bool flipCap = false; bool flipSide = false; if (!clockwise) { flipSide = !flipSide; } if (simpleExtrude && _extrude < 0f) { flipCap = !flipCap; flipSide = !flipSide; } GenerateSurfaceTris(flipCap); int totalTrisCount = surfaceTris.Length; if (simpleExtrude) { totalTrisCount *= 2; totalTrisCount += 2 * sampleCount * 2 * 3; } else { totalTrisCount *= 2; totalTrisCount += extrudeResults.Length * sampleCount * 2 * 3; } AllocateMesh(vertexCount, totalTrisCount); Vector3 off = trs.right * offset.x + trs.up * offset.y + trs.forward * offset.z; for (int i = 0; i < surfaceVertexCount; i++) { GetSample(i, evalResult); tsMesh.vertices[i] = evalResult.position + off; tsMesh.normals[i] = evalResult.up; tsMesh.colors[i] = evalResult.color * color; } #region UVs Vector2 min = projectedVerts[0]; Vector2 max = projectedVerts[0]; for (int i = 1; i < projectedVerts.Length; i++) { if (min.x < projectedVerts[i].x) { min.x = projectedVerts[i].x; } if (min.y < projectedVerts[i].y) { min.y = projectedVerts[i].y; } if (max.x > projectedVerts[i].x) { max.x = projectedVerts[i].x; } if (max.y > projectedVerts[i].y) { max.y = projectedVerts[i].y; } } for (int i = 0; i < projectedVerts.Length; i++) { tsMesh.uv[i].x = Mathf.InverseLerp(max.x, min.x, projectedVerts[i].x) * uvScale.x - uvScale.x * 0.5f + uvOffset.x + 0.5f; tsMesh.uv[i].y = Mathf.InverseLerp(min.y, max.y, projectedVerts[i].y) * uvScale.y - uvScale.y * 0.5f + uvOffset.y + 0.5f; } #endregion if (flipCap) { for (int i = 0; i < surfaceVertexCount; i++) { tsMesh.normals[i] *= -1f; } } if (_expand != 0f) { for (int i = 0; i < surfaceVertexCount; i++) { GetSample(i, evalResult); tsMesh.vertices[i] += (clockwise ? -evalResult.right : evalResult.right) * _expand; } } if (pathExtrude) { GetIdentityVerts(center, normal, clockwise); //Generate cap vertices with flipped normals for (int i = 0; i < surfaceVertexCount; i++) { tsMesh.vertices[i + surfaceVertexCount] = extrudeResults[0].position + extrudeResults[0].rotation * identityVertices[i] + off; tsMesh.normals[i + surfaceVertexCount] = -extrudeResults[0].forward; tsMesh.colors[i + surfaceVertexCount] = tsMesh.colors[i] * extrudeResults[0].color; tsMesh.uv[i + surfaceVertexCount] = new Vector2(1f - tsMesh.uv[i].x, tsMesh.uv[i].y); tsMesh.vertices[i] = extrudeResults[extrudeResults.Length - 1].position + extrudeResults[extrudeResults.Length - 1].rotation * identityVertices[i] + off; tsMesh.normals[i] = extrudeResults[extrudeResults.Length - 1].forward; tsMesh.colors[i] *= extrudeResults[extrudeResults.Length - 1].color; } //Add wall vertices float totalLength = 0f; for (int i = 0; i < extrudeResults.Length; i++) { if (_uniformUvs && i > 0) { totalLength += Vector3.Distance(extrudeResults[i].position, extrudeResults[i - 1].position); } int startIndex = surfaceVertexCount * 2 + i * sampleCount; for (int n = 0; n < identityVertices.Length; n++) { tsMesh.vertices[startIndex + n] = extrudeResults[i].position + extrudeResults[i].rotation * identityVertices[n] + off; tsMesh.normals[startIndex + n] = extrudeResults[i].rotation * identityNormals[n]; if (_uniformUvs) { tsMesh.uv[startIndex + n] = new Vector2((float)n / (identityVertices.Length - 1) * _sideUvScale.x + _sideUvOffset.x, totalLength * _sideUvScale.y + _sideUvOffset.y); } else { tsMesh.uv[startIndex + n] = new Vector2((float)n / (identityVertices.Length - 1) * _sideUvScale.x + _sideUvOffset.x, (float)i / (extrudeResults.Length - 1) * _sideUvScale.y + _sideUvOffset.y); } if (clockwise) { tsMesh.uv[startIndex + n].x = 1f - tsMesh.uv[startIndex + n].x; } } } int written = WriteTris(ref surfaceTris, ref tsMesh.triangles, 0, 0, false); written = WriteTris(ref surfaceTris, ref tsMesh.triangles, surfaceVertexCount, written, true); MeshUtility.GeneratePlaneTriangles(ref wallTris, sampleCount - 1, extrudeResults.Length, flipSide, 0, 0, true); WriteTris(ref wallTris, ref tsMesh.triangles, surfaceVertexCount * 2, written, false); } else if (simpleExtrude) { //Duplicate cap vertices with flipped normals for (int i = 0; i < surfaceVertexCount; i++) { tsMesh.vertices[i + surfaceVertexCount] = tsMesh.vertices[i]; tsMesh.normals[i + surfaceVertexCount] = -tsMesh.normals[i]; tsMesh.colors[i + surfaceVertexCount] = tsMesh.colors[i]; tsMesh.uv[i + surfaceVertexCount] = new Vector2(1f - tsMesh.uv[i].x, tsMesh.uv[i].y); tsMesh.vertices[i] += normal * _extrude; } //Add wall vertices for (int i = 0; i < surfaceVertexCount + 1; i++) { int index = i; if (i >= surfaceVertexCount) { index = i - surfaceVertexCount; } GetSample(index, evalResult); tsMesh.vertices[i + surfaceVertexCount * 2] = tsMesh.vertices[index] - normal * _extrude; tsMesh.normals[i + surfaceVertexCount * 2] = clockwise ? -evalResult.right : evalResult.right; tsMesh.colors[i + surfaceVertexCount * 2] = tsMesh.colors[index]; tsMesh.uv[i + surfaceVertexCount * 2] = new Vector2((float)i / (surfaceVertexCount - 1) * _sideUvScale.x + _sideUvOffset.x, 0f + _sideUvOffset.y); if (clockwise) { tsMesh.uv[i + surfaceVertexCount * 2].x = 1f - tsMesh.uv[i + surfaceVertexCount * 2].x; } int offsetIndex = i + surfaceVertexCount * 3 + 1; tsMesh.vertices[offsetIndex] = tsMesh.vertices[index]; tsMesh.normals[offsetIndex] = tsMesh.normals[i + surfaceVertexCount * 2]; tsMesh.colors[offsetIndex] = tsMesh.colors[index]; if (_uniformUvs) { tsMesh.uv[offsetIndex] = new Vector2((float)i / surfaceVertexCount * _sideUvScale.x + _sideUvOffset.x, _extrude * _sideUvScale.y + _sideUvOffset.y); } else { tsMesh.uv[offsetIndex] = new Vector2((float)i / surfaceVertexCount * _sideUvScale.x + _sideUvOffset.x, 1f * _sideUvScale.y + _sideUvOffset.y); } if (clockwise) { tsMesh.uv[offsetIndex].x = 1f - tsMesh.uv[offsetIndex].x; } } int written = WriteTris(ref surfaceTris, ref tsMesh.triangles, 0, 0, false); written = WriteTris(ref surfaceTris, ref tsMesh.triangles, surfaceVertexCount, written, true); MeshUtility.GeneratePlaneTriangles(ref wallTris, sampleCount - 1, 2, flipSide, 0, 0, true); WriteTris(ref wallTris, ref tsMesh.triangles, surfaceVertexCount * 2, written, false); } else { WriteTris(ref surfaceTris, ref tsMesh.triangles, 0, 0, false); } }
protected override void BuildMesh() { if (_sides <= 2) { return; } base.BuildMesh(); bodyVertexCount = (_sides + 1) * clippedSamples.Length; CapMethod _capModeFinal = _capMode; if (!useCap) { _capModeFinal = CapMethod.None; } switch (_capModeFinal) { case CapMethod.Flat: capVertexCount = _sides + 1; break; case CapMethod.Round: capVertexCount = _roundCapLatitude * (sides + 1); break; default: capVertexCount = 0; break; } int vertexCount = bodyVertexCount + capVertexCount * 2; if (tsMesh.vertexCount != vertexCount) { tsMesh.vertices = new Vector3[vertexCount]; tsMesh.normals = new Vector3[vertexCount]; tsMesh.colors = new Color[vertexCount]; tsMesh.uv = new Vector2[vertexCount]; bodyTrisCount = _sides * (clippedSamples.Length - 1) * 2 * 3; switch (_capModeFinal) { case CapMethod.Flat: capTrisCount = (_sides - 1) * 3 * 2; break; case CapMethod.Round: capTrisCount = _sides * _roundCapLatitude * 6; break; default: capTrisCount = 0; break; } if (tsMesh.triangles.Length != bodyTrisCount + capTrisCount * 2) { tsMesh.triangles = new int[bodyTrisCount + capTrisCount * 2]; } } Generate(); switch (_capModeFinal) { case CapMethod.Flat: GenerateFlatCaps(); break; case CapMethod.Round: GenerateRoundCaps(); break; } if (doubleSided) { MeshUtility.MakeDoublesided(tsMesh); } if (calculateTangents) { MeshUtility.CalculateTangents(tsMesh); } }
/// <summary> /// "ProBuilder-ize" function /// </summary> /// <param name="t"></param> /// <param name="preserveFaces"></param> /// <returns></returns> public static ProBuilderMesh CreateMeshWithTransform(Transform t, bool preserveFaces) { Mesh m = t.GetComponent <MeshFilter>().sharedMesh; Vector3[] m_vertices = MeshUtility.GetMeshChannel <Vector3[]>(t.gameObject, x => x.vertices); Color[] m_colors = MeshUtility.GetMeshChannel <Color[]>(t.gameObject, x => x.colors); Vector2[] m_uvs = MeshUtility.GetMeshChannel <Vector2[]>(t.gameObject, x => x.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 <Face> faces = new List <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].distinctIndexesInternal.Contains(tris[i + 0]) || faces[j].distinctIndexesInternal.Contains(tris[i + 1]) || faces[j].distinctIndexesInternal.Contains(tris[i + 2])) { index = j; break; } } } if (index > -1 && preserveFaces) { int len = faces[index].indexesInternal.Length; int[] arr = new int[len + 3]; System.Array.Copy(faces[index].indexesInternal, 0, arr, 0, len); arr[len + 0] = tris[i + 0]; arr[len + 1] = tris[i + 1]; arr[len + 2] = tris[i + 2]; faces[index].indexesInternal = arr; } 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 Face( faceTris, n, AutoUnwrapSettings.tile, 0, // smoothing group -1, // texture group -1, // element group true // manualUV )); } } } GameObject go = (GameObject)Object.Instantiate(t.gameObject); go.GetComponent <MeshFilter>().sharedMesh = null; ProBuilderMesh pb = go.AddComponent <ProBuilderMesh>(); pb.RebuildWithPositionsAndFaces(verts.ToArray(), faces.ToArray()); pb.colorsInternal = cols.ToArray(); pb.textures = uvs; pb.gameObject.name = t.name; go.transform.position = t.position; go.transform.localRotation = t.localRotation; go.transform.localScale = t.localScale; pb.CenterPivot(null); return(pb); }
protected override void BuildMesh() { base.BuildMesh(); GenerateVertices(vertexDirection, orthographic); MeshUtility.GeneratePlaneTriangles(ref tsMesh.triangles, _slices, sampleCount, false, 0, 0); }
/// <summary> /// Generates a mesh object which is then passed to the Mesh component of this monobehaviour. /// </summary> public void GenerateMesh() { // Creation of temporary mesh variables which we will use to create the unity mesh object. List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uvs = new List <Vector2>(); int NumFaces = 0; // For each block in this chunk for (int x = 0; x < ConfigurationManager.Instance.Chunk_Diameter; x++) { for (int z = 0; z < ConfigurationManager.Instance.Chunk_Diameter; z++) { for (int y = 0; y < ConfigurationManager.Instance.Chunk_Diameter; y++) { // If the block is visible, display all faces which are adjacent to invisible blocks AbstractBlock ours = GetBlock(x, y, z); if (ours.isVisible()) { if (!GetBlock(x + 1, y, z).isVisible()) { AddPosXFace(x, y, z, ours, vertices, triangles, uvs, ref NumFaces); } if (!GetBlock(x - 1, y, z).isVisible()) { AddNegXFace(x, y, z, ours, vertices, triangles, uvs, ref NumFaces); } if (!GetBlock(x, y + 1, z).isVisible()) { AddPosYFace(x, y, z, ours, vertices, triangles, uvs, ref NumFaces); } if (!GetBlock(x, y - 1, z).isVisible()) { AddNegYFace(x, y, z, ours, vertices, triangles, uvs, ref NumFaces); } if (!GetBlock(x, y, z + 1).isVisible()) { AddPosZFace(x, y, z, ours, vertices, triangles, uvs, ref NumFaces); } if (!GetBlock(x, y, z - 1).isVisible()) { AddNegZFace(x, y, z, ours, vertices, triangles, uvs, ref NumFaces); } } } } } // Clear whatever data was in the mesh previously mesh.Clear(); // Add in newly calculated values mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uvs.ToArray(); // Optimize, and normal calculation MeshUtility.Optimize(mesh); mesh.RecalculateNormals(); collider.sharedMesh = mesh; }
void WeldMeshes() { Dictionary <Material, List <MeshFilter> > usedMaterials = new Dictionary <Material, List <MeshFilter> >(); combined = new Mesh(); CombineInstance[] combine = new CombineInstance[selectedObjects.Length]; if (intelligentMergeSubmeshes) { List <Mesh> CombinedMeshes = new List <Mesh>(); for (int i = 0; i < selectedObjects.Length; i++) { Material mat = selectedObjects[i].GetComponent <MeshRenderer>().sharedMaterial; if (!usedMaterials.ContainsKey(mat)) { usedMaterials.Add(mat, new List <MeshFilter>()); } usedMaterials[mat].Add(selectedObjects[i].GetComponent <MeshFilter>()); } foreach (Material mat in usedMaterials.Keys) { MeshFilter[] meshes = usedMaterials[mat].ToArray(); CombineInstance[] comb = new CombineInstance[meshes.Length]; for (int i = 0; i < comb.Length; i++) { comb[i].mesh = meshes[i].sharedMesh; comb[i].transform = meshes[i].transform.localToWorldMatrix; } Mesh curmesh = new Mesh(); curmesh.CombineMeshes(comb); CombinedMeshes.Add(curmesh); } Matrix4x4 refPoint = LocalSpacePoint.worldToLocalMatrix; refPoint.SetTRS(new Vector3(refPoint.m03, refPoint.m13, refPoint.m23), Quaternion.identity, Vector3.one); combine = new CombineInstance[CombinedMeshes.Count]; for (int i = 0; i < CombinedMeshes.Count; i++) { combine[i].mesh = CombinedMeshes[i]; combine[i].transform = refPoint; } combined.CombineMeshes(combine, false); if (spawnInstance) { GameObject go = new GameObject("CombinedMesh", typeof(MeshFilter), typeof(MeshRenderer)); go.GetComponent <MeshFilter>().sharedMesh = combined; MeshRenderer mr = go.GetComponent <MeshRenderer>(); Material[] mats = new Material[usedMaterials.Keys.Count]; int i = 0; foreach (Material mat in usedMaterials.Keys) { mats[i] = mat; i++; } mr.sharedMaterials = mats; } } else { for (int i = 0; i < selectedObjects.Length; i++) { combine[i].mesh = selectedObjects[i].GetComponent <MeshFilter>().sharedMesh; combine[i].transform = selectedObjects[i].GetComponent <MeshFilter>().transform.localToWorldMatrix; } combined.CombineMeshes(combine, mergeSubmeshes); if (spawnInstance) { GameObject go = new GameObject("CombinedMesh", typeof(MeshFilter), typeof(MeshRenderer)); go.GetComponent <MeshFilter>().sharedMesh = combined; MeshRenderer mr = go.GetComponent <MeshRenderer>(); if (mergeSubmeshes) { mr.sharedMaterial = selectedObjects[0].GetComponent <MeshRenderer>().sharedMaterial; } else { Material[] mats = new Material[selectedObjects.Length]; for (int i = 0; i < selectedObjects.Length; i++) { if (selectedObjects[i].GetComponent <MeshRenderer>()) { mats[i] = selectedObjects[i].GetComponent <MeshRenderer>().sharedMaterial; } } mr.sharedMaterials = mats; } } } string path = EditorUtility.SaveFilePanel("Save Welded Mesh Asset", "Assets/", name, "asset"); if (string.IsNullOrEmpty(path)) { return; } path = FileUtil.GetProjectRelativePath(path); Mesh meshToSave = combined; if (optimizeMesh) { MeshUtility.Optimize(meshToSave); } AssetDatabase.CreateAsset(meshToSave, path); AssetDatabase.SaveAssets(); meshCombined = true; }
void RecalculateMesh() { if (m_Anchors.Length < 2 || m_SourceMeshRenderer == null) { return; } var sourceMesh = m_SourceMeshRenderer.GetComponent <MeshFilter>().sharedMesh; if (sourceMesh == null) { return; } using (var so = new SerializedObject(this)) using (var sp = so.FindProperty(nameof(m_MeshObjects))) { DestroyAllCurves(); var bounds = sourceMesh.bounds; var unitLength = 0f; switch (m_Axis) { case Axis.X: unitLength = bounds.size.x; break; case Axis.Y: unitLength = bounds.size.y; break; case Axis.Z: unitLength = bounds.size.z; break; default: throw new System.ArgumentOutOfRangeException(nameof(m_Axis)); } sp.ClearArray(); for (var i = 0; i < m_Anchors.Length - 1; ++i) { if (m_Anchors[i] == null || m_Anchors[i + 1] == null) { continue; } var startPos = m_Anchors[i].position; var endPos = m_Anchors[i + 1].position; var curve = new CatenaryCurve(startPos, endPos, m_Catenary, unitLength); var combines = new List <CombineInstance>(); foreach (var line in curve) { var scale = (line.to - line.from).magnitude / unitLength; var matrix = Matrix4x4.LookAt((line.from + line.to) * 0.5f, line.to, Vector3.up) * Matrix4x4.Scale(Vector3.one + Vector3.forward * (scale - 1f)); switch (m_Axis) { case Axis.X: matrix *= Matrix4x4.Rotate(Quaternion.Euler(0, 90f, 0)); break; case Axis.Y: matrix *= Matrix4x4.Rotate(Quaternion.Euler(90f, 0, 0)); break; } combines.Add(new CombineInstance() { mesh = sourceMesh, transform = matrix }); } var mesh = new Mesh(); mesh.CombineMeshes(combines.ToArray(), true, true, true); MeshUtility.Optimize(mesh); mesh.UploadMeshData(true); var go = new GameObject($"ProcedualMesh{i}") { hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable }; ++sp.arraySize; using (var element = sp.GetArrayElementAtIndex(sp.arraySize - 1)) element.objectReferenceValue = go; var meshFilter = go.AddComponent <MeshFilter>(); var renderer = go.AddComponent <MeshRenderer>(); meshFilter.sharedMesh = mesh; renderer.sharedMaterials = m_SourceMeshRenderer.sharedMaterials; Undo.RegisterCreatedObjectUndo(mesh, "Create Mesh"); Undo.RegisterCreatedObjectUndo(go, "Create GameObject"); } so.ApplyModifiedProperties(); } }
public void DrawFromGama() { // 1. Generate the game object hierarchy in the scene graph if (groupOptions == SceneGroupType.Nothing) { // Merge every game object created to the 'root' element being the map region foreach (var featureMesh in features) { MergeMeshData(regionMap, featureMesh); } } else { GameObject currentGroup; // Generate all game object with the appropriate hiarchy foreach (var featureMesh in features) { currentGroup = regionMap; foreach (SceneGroupType group in Enum.GetValues(typeof(SceneGroupType))) { // Exclude 'nothing' and 'everything' group if (group == SceneGroupType.Nothing || group == SceneGroupType.Everything) { continue; } if (groupOptions.Includes(group)) { // Use currentGroup as the parentGroup for the current generation var parentGroup = currentGroup; var newGroup = AddGameObjectGroup(group, parentGroup, featureMesh); // Top down of the hierarchy, merge the game objects if (group == leafGroup) { MergeMeshData(newGroup, featureMesh); } currentGroup = newGroup; } } } } // 2. Initialize game objects and associate their components (physics, rendering) foreach (var pair in gameObjectMeshData) { var meshData = pair.Value; var root = pair.Key; // Create one game object per mesh object 'bucket', each bucket is ensured to // have less that 65535 vertices (valid under Unity mesh max vertex count). for (int i = 0; i < meshData.Meshes.Count; ++i) { var meshBucket = meshData.Meshes[i]; GameObject gameObject; if (meshData.Meshes.Count > 1) { gameObject = new GameObject(root.name + "_Part" + i); gameObject.transform.parent = root.transform; } else { gameObject = root.gameObject; } gameObject.isStatic = gameObjectOptions.IsStatic; var mesh = new Mesh(); mesh.Clear(); //meshBucket.meshGeometry = "LineString"; //----------------------------------- Debug.Log("Geometry ++------> " + meshBucket.gamaAgent.geometry); Debug.Log("game Object Name > " + gameObject.name); if (meshBucket.gamaAgent.geometry.Equals("LineString")) { gameObject.AddComponent <LineRenderer>(); LineRenderer line = (LineRenderer)gameObject.GetComponent(typeof(LineRenderer)); line.positionCount = meshBucket.Vertices.Count; line.SetPositions(meshBucket.Vertices.ToArray()); line.positionCount = meshBucket.Vertices.Count / 2; Material mat = Utils.getMaterialByName("Green"); if (mat != null) { line.material = mat; } line.material = new Material(Shader.Find("Particles/Additive")); Color c1 = Color.green; Color c2 = new Color(1, 1, 1, 0); line.startColor = c1; line.endColor = c1; line.startWidth = 5.0f; line.endWidth = 5.0f; } else if (meshBucket.gamaAgent.geometry.Equals("Point")) { Transform tr = gameObject.transform.parent; string name = gameObject.name; gameObject.name = gameObject.name + "Old"; gameObject = GameObject.CreatePrimitive(PrimitiveType.Sphere); gameObject.name = name; gameObject.transform.parent = tr; gameObject.transform.position = meshBucket.Vertices[0]; gameObject.transform.localScale = new Vector3(10, 10, 10); //gameObject.AddComponent<LineRenderer>(); Color col = Utils.getColorFromGamaColor(meshBucket.gamaAgent.color); Renderer rend = gameObject.GetComponent <Renderer>(); rend.material.color = UnityEngine.Random.ColorHSV();// Color.green; //("green");//col; //col.a = 0.5f; //rend.material.color = col; Debug.Log(" =========>>>>>> the color is : " + col); } else if (meshBucket.gamaAgent.geometry.Equals("Polygon")) { mesh.SetVertices(meshBucket.Vertices); mesh.SetUVs(0, meshBucket.UVs); mesh.subMeshCount = meshBucket.Submeshes.Count; for (int s = 0; s < meshBucket.Submeshes.Count; s++) { mesh.SetTriangles(meshBucket.Submeshes[s].Indices, s); } // Automatic Uvs Calculator // meshBucket.setUvs(); Unwrapping.GenerateSecondaryUVSet(mesh); mesh.RecalculateNormals(); mesh.RecalculateBounds(); MeshUtility.Optimize(mesh); // Associate the mesh filter and mesh renderer components with this game object var materials = meshBucket.Submeshes.Select(s => s.Material).ToArray(); var meshFilterComponent = gameObject.AddComponent <MeshFilter>(); var meshRendererComponent = gameObject.AddComponent <MeshRenderer>(); if (meshFilterComponent == null) { meshFilterComponent = gameObject.GetComponent <MeshFilter>(); } if (meshRendererComponent == null) { meshRendererComponent = gameObject.GetComponent <MeshRenderer>(); } meshRendererComponent.materials = materials; meshFilterComponent.mesh = mesh; if (gameObjectOptions.GeneratePhysicMeshCollider) { var meshColliderComponent = gameObject.AddComponent <MeshCollider>(); meshColliderComponent.material = gameObjectOptions.PhysicMaterial; meshColliderComponent.sharedMesh = mesh; } Renderer rend = gameObject.GetComponent <Renderer>(); //Set the main Color of the Material to green rend.material.shader = Shader.Find("_Color"); rend.material.SetColor("_Color", Color.green); //Find the Specular shader and change its Color to red rend.material.shader = Shader.Find("Specular"); rend.material.SetColor("_SpecColor", Color.red); Material material = new Material(Shader.Find("Standard")); material.color = Color.blue; material.color = UnityEngine.Random.ColorHSV(); // assign the material to the renderer gameObject.GetComponent <Renderer>().material = material; } } } }