public void AddGeneratedMesh() { GeneratedMesh newMesh = new GeneratedMesh(); newMesh.name = string.Concat("Generated mesh ", generated.Count + 1); generated.Add(newMesh); }
void MergeGrass(GameObject[] _grassesToMerge) { GameObject mergedMesh = new GameObject("MergedGrassGroup"); Vector3 avgPos = GetAvgPosOfObjs(_grassesToMerge); mergedMesh.transform.position = avgPos; //Merge objects to one mesh int count = _grassesToMerge.Length; MeshFilter[] meshFilters = new MeshFilter[count]; for (int i = 0; i < count; i++) { meshFilters[i] = _grassesToMerge[i].transform.GetChild(0).GetComponent <MeshFilter>(); _grassesToMerge[i].transform.position -= avgPos; } GeneratedMesh.CombineMeshes(mergedMesh.transform, meshFilters); ///////////////////////// //AddLods mergedMesh.AddComponent <LODGroup>(); LOD[] lods = new LOD[1]; Renderer[] renderers = new Renderer[1]; renderers[0] = mergedMesh.transform.GetChild(0).GetComponent <Renderer>(); lods[0] = new LOD(0.07f, renderers); mergedMesh.GetComponent <LODGroup>().SetLODs(lods); mergedMesh.GetComponent <LODGroup>().RecalculateBounds(); }
//Generates a mesh along a spline. The mesh is defined in the settings at index i private void GenerateMesh(Transform splineParent, SplineSettings settings, int spline, int i) { GeneratedMesh meshSettings = settings.generated[i]; string name = meshSettings.name; if (name.Length == 0) { name = string.Concat("Generated Mesh ", i.ToString("D2")); } name = string.Concat(i.ToString("D2"), "-", name); Transform newGenerated = splineParent.Find(name); //Create a new GameObject if there is none in the current scene if (newGenerated == null) { newGenerated = new GameObject().transform; newGenerated.parent = splineParent; newGenerated.localPosition = Vector3.zero; newGenerated.localRotation = Quaternion.identity; newGenerated.localScale = Vector3.one; newGenerated.name = name; newGenerated.gameObject.AddComponent <MeshFilter>(); newGenerated.gameObject.AddComponent <MeshRenderer>(); } //Update mesh and material newGenerated.GetComponent <MeshFilter>().mesh = meshSettings.Generate(splines[spline]); newGenerated.GetComponent <MeshRenderer>().material = meshSettings.material; }
private static void MakeTriangles(Plane _plane, MeshTriangle _triangle, GeneratedMesh _currentSide, List <Vector3> _addedVertices, MeshTriangle currentMeshTriangle, MeshTriangle oppositeMeshTriangle, bool addVertices) { float normalizedDistance; float distance; // Get the distance from the vertex to the intersecting plane, in the direction of a vertex that we know exists on the other side of the intersection // From our original triangle _plane.Raycast(new Ray(currentMeshTriangle.Vertices[0], (oppositeMeshTriangle.Vertices[0] - currentMeshTriangle.Vertices[0]).normalized), out distance); normalizedDistance = distance / (oppositeMeshTriangle.Vertices[0] - currentMeshTriangle.Vertices[0]).magnitude; Vector3 vertLeft = Vector3.Lerp(currentMeshTriangle.Vertices[0], oppositeMeshTriangle.Vertices[0], normalizedDistance); Vector3 normalLeft = Vector3.Lerp(currentMeshTriangle.Normals[0], oppositeMeshTriangle.Normals[0], normalizedDistance); Vector2 uvLeft = Vector2.Lerp(currentMeshTriangle.UVs[0], oppositeMeshTriangle.UVs[0], normalizedDistance); _plane.Raycast(new Ray(currentMeshTriangle.Vertices[1], (oppositeMeshTriangle.Vertices[1] - currentMeshTriangle.Vertices[1]).normalized), out distance); normalizedDistance = distance / (oppositeMeshTriangle.Vertices[1] - currentMeshTriangle.Vertices[1]).magnitude; Vector3 vertRight = Vector3.Lerp(currentMeshTriangle.Vertices[1], oppositeMeshTriangle.Vertices[1], normalizedDistance); // Since we call this method twice, prevent adding new vertices twice if (addVertices) { _addedVertices.Add(vertLeft); _addedVertices.Add(vertRight); } Vector3 normalRight = Vector3.Lerp(currentMeshTriangle.Normals[1], oppositeMeshTriangle.Normals[1], normalizedDistance); Vector3 uvRight = Vector2.Lerp(currentMeshTriangle.UVs[1], oppositeMeshTriangle.UVs[1], normalizedDistance); MeshTriangle currentTriangle; Vector3[] updatedVertices = new Vector3[] { currentMeshTriangle.Vertices[0], vertLeft, vertRight }; Vector3[] updatedNormals = new Vector3[] { currentMeshTriangle.Normals[0], normalLeft, normalRight }; Vector2[] updatedUVs = new Vector2[] { currentMeshTriangle.UVs[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex); if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2]) { if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0) { FlipTriangle(currentTriangle); } _currentSide.AddTriangle(currentTriangle); } updatedVertices = new Vector3[] { currentMeshTriangle.Vertices[0], currentMeshTriangle.Vertices[1], vertRight }; updatedNormals = new Vector3[] { currentMeshTriangle.Normals[0], currentMeshTriangle.Normals[1], normalRight }; updatedUVs = new Vector2[] { currentMeshTriangle.UVs[0], currentMeshTriangle.UVs[1], uvRight }; currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex); if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2]) { if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0) { FlipTriangle(currentTriangle); } _currentSide.AddTriangle(currentTriangle); } }
public static void FillCut(List <Vector3> _addedVertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh, int submeshCount) { List <Vector3> vertices = new List <Vector3>(); List <Vector3> polygone = new List <Vector3>(); // find the needed polygons // the cut faces added new vertices by 2 each time to make an edge // if two edges contain the same Vector3 point, they are connected for (int i = 0; i < _addedVertices.Count; i++) { // check the edge if (!vertices.Contains(_addedVertices[i]))// if it has one, it has this edge { //new polygon started with this edge polygone.Clear(); polygone.Add(_addedVertices[i]); vertices.Add(_addedVertices[i]); if (i + 1 < _addedVertices.Count) { polygone.Add(_addedVertices[i + 1]); vertices.Add(_addedVertices[i + 1]); } EvaluatePairs(_addedVertices, vertices, polygone); Fill(polygone, _plane, _leftMesh, _rightMesh, submeshCount); } } }
//Copy constructor public GeneratedMesh(GeneratedMesh other) { name = other.name + " Clone"; length = other.length; sides = other.sides; smoothEdges = other.smoothEdges; rotation = other.rotation; scale = other.scale; offset = other.offset; cap = other.cap; material = other.material; }
// Draw the editor for a Generated Mesh private void DrawGeneratedMeshSettings(GeneratedMesh meshSettings) { meshSettings.name = EditorGUILayout.TextField("Name", meshSettings.name); meshSettings.length = EditorGUILayout.Slider("Length", meshSettings.length, 0.05f, 2f); meshSettings.sides = Mathf.FloorToInt(EditorGUILayout.Slider("Sides", meshSettings.sides, 3, 12)); meshSettings.smoothEdges = EditorGUILayout.Toggle("Smooth Edges", meshSettings.smoothEdges); meshSettings.rotation = EditorGUILayout.Slider("Rotation", meshSettings.rotation, 0f, 360f); meshSettings.scale = EditorGUILayout.Vector2Field("Scale", meshSettings.scale); meshSettings.offset = EditorGUILayout.Vector2Field("Offset", meshSettings.offset); meshSettings.cap = EditorGUILayout.Toggle("Cap", meshSettings.cap); meshSettings.material = (Material)EditorGUILayout.ObjectField("Material", meshSettings.material, typeof(Material), false); }
public static void Cut(GameObject oGO, Vector3 _contactPoint, Vector3 _direction, Material _cutMaterial = null, bool fill = true, bool _addRigidbody = false) { if (currentCut) { return; } currentCut = true; Plane plane = new Plane(oGO.transform.InverseTransformDirection(-_direction), oGO.transform.InverseTransformPoint(_contactPoint)); originalMesh = oGO.GetComponent <MeshFilter>().mesh; List <Vector3> addedVertices = new List <Vector3>(); GeneratedMesh leftMesh = new GeneratedMesh(); GeneratedMesh rightMesh = new GeneratedMesh(); int[] submeshIndices; int triangleIndexA, triangleIndexB, triangleIndexC; for (int i = 0; i < originalMesh.subMeshCount; i++) { submeshIndices = originalMesh.GetTriangles(i); for (int j = 0; j < originalMesh.subMeshCount; j += 3) { triangleIndexA = submeshIndices[j]; triangleIndexB = submeshIndices[j + 1]; triangleIndexC = submeshIndices[j + 2]; MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i); bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]); bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]); bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]); if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide) { leftMesh.AddTriangle(currentTriangle); } else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide) { rightMesh.AddTriangle(currentTriangle); } else { } } } }
void MergeGrass() { //Merge objects to one mesh int count = generatedBranches.Length; MeshFilter[] meshFilters = new MeshFilter[count]; for (int i = 0; i < count; i++) { meshFilters[i] = generatedBranches[i].GetComponent <MeshFilter>(); } mergedMesh = GeneratedMesh.CombineMeshes(transform, meshFilters); }
void MergeGrass() { //Merge objects to one mesh //MeshFilter[] meshFilters = new MeshFilter[2]; //meshFilters[0] = generatedBranch.GetComponent<MeshFilter>(); //meshFilters[1] = generatedLeaves.GetComponent<MeshFilter>(); //mergedMesh = GeneratedMesh.CombineMeshes(transform, meshFilters); MeshFilter[] meshFilters = new MeshFilter[2]; meshFilters[0] = generatedBranch.GetComponent <MeshFilter>(); meshFilters[1] = generatedLeaves.GetComponent <MeshFilter>(); mergedMesh = GeneratedMesh.CombineMeshesManyMats(transform, meshFilters); }
// Generate a GameObject with the mesh public static void GenerateGameObject(GeneratedMesh mesh) { GameObject newGameObject = new GameObject("Generated Slice"); newGameObject.transform.localScale = originalGameObject.transform.localScale; newGameObject.transform.position = originalGameObject.transform.position; newGameObject.AddComponent <MeshFilter>(); newGameObject.AddComponent <MeshRenderer>(); newGameObject.AddComponent <MeshCollider>(); newGameObject.GetComponent <MeshFilter>().mesh.vertices = mesh.Vertices.ToArray(); newGameObject.GetComponent <MeshFilter>().mesh.normals = mesh.Normals.ToArray(); newGameObject.GetComponent <MeshFilter>().mesh.SetUVs(0, mesh.UVs); Material[] originalMaterials = originalGameObject.GetComponent <MeshRenderer>().materials; Material[] materials = new Material[mesh.SubmeshIndices.Count]; for (int i = 0; i < mesh.SubmeshIndices.Count; i++) { if (i < originalMaterials.Length) { materials[i] = originalMaterials[i]; } else { materials[i] = originalMaterials[0]; } } newGameObject.GetComponent <MeshRenderer>().materials = materials; int submeshCount = mesh.SubmeshIndices.Count; newGameObject.GetComponent <MeshFilter>().mesh.subMeshCount = submeshCount; for (int i = 0; i < mesh.SubmeshIndices.Count; i++) { newGameObject.GetComponent <MeshFilter>().mesh.SetTriangles(mesh.SubmeshIndices[i], i); } newGameObject.AddComponent <Rigidbody>(); newGameObject.GetComponent <MeshCollider>().sharedMesh = newGameObject.GetComponent <MeshFilter>().mesh; newGameObject.GetComponent <MeshCollider>().convex = true; // Small force for a more subtle cutting effect newGameObject.GetComponent <Rigidbody>().AddExplosionForce(100.0f, originalGameObject.transform.position, 10f); }
private static void Fill(List <Vector3> _vertices, Plane plane, GeneratedMesh leftMesh, GeneratedMesh rightMesh) { Vector3 centerPosition = Vector3.zero; for (int i = 0; i < _vertices.Count; i++) { centerPosition += _vertices[i]; } centerPosition /= _vertices.Count; Vector3 up = plane.normal; Vector3 left = Vector3.Cross(plane.normal, plane.normal); Vector3 displacement = Vector3.zero; Vector2 uv1, uv2; for (int i = 0; i < _vertices.Count; i++) { displacement = _vertices[i] - centerPosition; uv1 = new Vector2(0.5f + Vector3.Dot(displacement, left), 0.5f + Vector3.Dot(displacement, up)); displacement = _vertices[(i + 1) % _vertices.Count] - centerPosition; uv2 = new Vector2(0.5f + Vector3.Dot(displacement, left), 0.5f + Vector3.Dot(displacement, up)); Vector3[] vertices = new Vector3[] { _vertices[i], _vertices[(i + 1) % _vertices.Count], centerPosition }; Vector3[] normals = new Vector3[] { -plane.normal, -plane.normal, -plane.normal }; Vector2[] uvs = new Vector2[] { uv1, uv2, new Vector2(0.5f, 0.5f) }; MeshTriangle currenTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount - 1); if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0) { FlipTriangle(currenTriangle); } leftMesh.AddTriangle(currenTriangle); normals = new Vector3[] { plane.normal, plane.normal, plane.normal }; currenTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount - 1); if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0) { FlipTriangle(currenTriangle); } rightMesh.AddTriangle(currenTriangle); } }
private static void FillCut(List <Vector3> addedVertices, Plane plane, GeneratedMesh leftMesh, GeneratedMesh rightMesh) { List <Vector3> vertices = new List <Vector3>(); List <Vector3> polygon = new List <Vector3>(); for (int i = 0; i < addedVertices.Count; i++) { if (!vertices.Contains(addedVertices[i])) { polygon.Clear(); polygon.Add(addedVertices[i]); polygon.Add(addedVertices[i + 1]); vertices.Add(addedVertices[i]); vertices.Add(addedVertices[i + 1]); EvaluatePairs(addedVertices, vertices, polygon); Fill(polygon, plane, leftMesh, rightMesh); } } }
/// <summary> /// Takes a triangle, splits it into two, and places it in the correct GeneratedMesh /// </summary> private static void CutTriangle(Plane _plane, MeshTriangle _triangle, bool _triangleALeftSide, bool _triangleBLeftSide, bool _triangleCLeftSide, GeneratedMesh _leftSide, GeneratedMesh _rightSide, List <Vector3> _addedVertices) { // Keep a list of where the triangle vertices lie left of the plane or below List <bool> leftSide = new List <bool>(); leftSide.Add(_triangleALeftSide); leftSide.Add(_triangleBLeftSide); leftSide.Add(_triangleCLeftSide); // We generate two fake triangles with vertex data from the intersecting triangle MeshTriangle leftMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex); MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex); // Place the vertices in either the left and right mesh, depending on which side the vertex lies in relation to the plane SortVerticesFromIntersectedTriangle(_triangle, leftSide, leftMeshTriangle, rightMeshTriangle); // Using the fake triangle, we generate either one or two triangles per side MakeTriangles(_plane, _triangle, _leftSide, _addedVertices, leftMeshTriangle, rightMeshTriangle, true); MakeTriangles(_plane, _triangle, _rightSide, _addedVertices, rightMeshTriangle, leftMeshTriangle, false); }
public static void FillCut(List <Vector3> _addedVertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh) { List <Vector3> vertices = new List <Vector3>(); List <Vector3> polygone = new List <Vector3>(); for (int i = 0; i < _addedVertices.Count; i++) { if (!vertices.Contains(_addedVertices[i])) { polygone.Clear(); polygone.Add(_addedVertices[i]); polygone.Add(_addedVertices[i + 1]); vertices.Add(_addedVertices[i]); vertices.Add(_addedVertices[i + 1]); EvaluatePairs(_addedVertices, vertices, polygone); Fill(polygone, _plane, _leftMesh, _rightMesh); } } }
private static void GenerateCutterGameobject(GameObject originalGameObject, GeneratedMesh mesh, bool addRigidbody, Vector3 direction) { if (mesh.Vertices.Count > 3) { GameObject gameObject = new GameObject(originalGameObject.name, typeof(MeshFilter), typeof(MeshRenderer)); gameObject.transform.localRotation = originalGameObject.transform.localRotation; gameObject.transform.localScale = originalGameObject.transform.localScale; gameObject.transform.position = originalGameObject.transform.position; gameObject.GetComponent <MeshFilter>().mesh = mesh.GenerateMesh(); gameObject.GetComponent <MeshRenderer>().material = originalGameObject.GetComponent <MeshRenderer>().material; if (addRigidbody) { gameObject.AddComponent <Rigidbody>(); gameObject.GetComponent <Rigidbody>().AddTorque(direction * 200f); } gameObject.AddComponent <MeshCollider>(); gameObject.GetComponent <MeshCollider>().convex = true; } }
private void GenerateFood() { int count = 5; GeneratedLeaves[] food = new GeneratedLeaves[count]; for (int i = 0; i < count; i++) { food[i] = Instantiate(VegetationGenerator.instance.generatedBushFoodPrefab, generatedLeaves.transform); food[i].transform.localPosition = generatedLeaves.GetComponent <MeshFilter>().mesh.vertices[Random.Range(0, generatedLeaves.GetComponent <MeshFilter>().mesh.vertexCount - 1)]; food[i].Generate(0); food[i].transform.localScale = new Vector3(0.15f, 0.15f, 0.15f); food[i].VerySlowlyConvertToFlatShading(); } //Merge food objects to one mesh count = food.Length; MeshFilter[] meshFilters = new MeshFilter[count]; for (int i = 0; i < count; i++) { meshFilters[i] = food[i].GetComponent <MeshFilter>(); } foodObject = GeneratedMesh.CombineMeshes(generatedLeaves.transform, meshFilters); }
void GenerateTile(GameObject tileGameObject) { BackgroundWorker backgroundWorker = new BackgroundWorker(); MeshRenderer renderer = tileGameObject.GetComponent <MeshRenderer>(); Mesh mesh = tileGameObject.GetComponent <MeshFilter>().mesh; mesh.Clear(); backgroundWorker.DoWork += (o, a) => { Arg aa = (Arg)a.Argument; a.Result = GenerateTileAsync(aa.t, aa.position); }; backgroundWorker.RunWorkerCompleted += (o, a) => { GeneratedMesh gm = (GeneratedMesh)a.Result; mesh.vertices = gm.vertices; mesh.uv = gm.uvs; mesh.triangles = gm.triangles; mesh.RecalculateNormals(); //renderer.material.color = RandomTextureGenerator.RandomColor(); //tileGameObject.GetComponent<MeshCollider>().sharedMesh = null; //tileGameObject.GetComponent<MeshCollider>().sharedMesh = mesh; }; Arg args = new Arg(); args.t = tileGameObject; args.position = tileGameObject.transform.position; workers.Add(backgroundWorker); backgroundWorker.RunWorkerAsync(args); }
GeneratedMesh GenerateTileAsync(GameObject tileGameObject, Vector3 position) { int verticesPerSegment = 6; int vertexCount = verticesPerSegment * ((int)cellsPerTile.x) * ((int)cellsPerTile.y); GeneratedMesh gm = new GeneratedMesh(); gm.vertices = new Vector3[vertexCount]; gm.normals = new Vector3[vertexCount]; gm.uvs = new Vector2[vertexCount]; gm.triangles = new int[vertexCount]; gm.colours = new Color[vertexCount]; int vertex = 0; // What cell is x and z for the bottom left of this tile in world space Vector3 tileBottomLeft = new Vector3(); tileBottomLeft.x = -(tileSize.x) / 2; tileBottomLeft.z = -(tileSize.y) / 2; for (int z = 0; z < cellsPerTile.y; z++) { for (int x = 0; x < cellsPerTile.x; x++) { int startVertex = vertex; // Calculate some stuff Vector3 cellBottomLeft = tileBottomLeft + new Vector3(x * cellSize.x, 0, z * cellSize.y); Vector3 cellTopLeft = tileBottomLeft + new Vector3(x * cellSize.x, 0, (z + 1) * cellSize.y); Vector3 cellTopRight = tileBottomLeft + new Vector3((x + 1) * cellSize.x, 0, (z + 1) * cellSize.y); Vector3 celBottomRight = tileBottomLeft + new Vector3((x + 1) * cellSize.x, 0, z * cellSize.y); // Add all the samplers together to make the height Vector3 cellWorldCoords = position + tileBottomLeft + new Vector3(x * cellSize.x, 0, z * cellSize.y); foreach (Sampler sampler in samplers) { cellBottomLeft.y += sampler.Sample(cellWorldCoords.x, cellWorldCoords.z); cellTopLeft.y += sampler.Sample(cellWorldCoords.x, cellWorldCoords.z + cellSize.y); cellTopRight.y += sampler.Sample(cellWorldCoords.x + cellSize.x, cellWorldCoords.z + cellSize.y); celBottomRight.y += sampler.Sample(cellWorldCoords.x + cellSize.x, cellWorldCoords.z); } // Make the vertices gm.vertices[vertex++] = cellBottomLeft; gm.vertices[vertex++] = cellTopLeft; gm.vertices[vertex++] = cellTopRight; gm.vertices[vertex++] = cellTopRight; gm.vertices[vertex++] = celBottomRight; gm.vertices[vertex++] = cellBottomLeft; // Make the normals, UV's and triangles for (int i = 0; i < 6; i++) { int vertexIndex = startVertex + i; gm.triangles[vertexIndex] = vertexIndex; gm.uvs[vertexIndex] = new Vector2(x / cellsPerTile.x, z / cellsPerTile.y); } } } return(gm); }
private static void Fill(List <Vector3> _vertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh) { Vector3 centerPosition = Vector3.zero; for (int i = 0; i < _vertices.Count; i++) { centerPosition += _vertices[i]; } centerPosition = centerPosition / _vertices.Count; Vector3 up = new Vector3() { x = _plane.normal.x, y = _plane.normal.y, z = _plane.normal.z }; Vector3 left = Vector3.zero; Vector3 displacement = Vector3.zero; Vector2 uv1 = Vector2.zero; Vector2 uv2 = Vector2.zero; for (int i = 0; i < _vertices.Count; i++) { displacement = _vertices[i] - centerPosition; uv1 = new Vector2() { x = .5f + Vector3.Dot(displacement, left), y = .5f + Vector3.Dot(displacement, up) }; displacement = _vertices[(i + 1) % _vertices.Count] - centerPosition; uv2 = new Vector2() { x = .5f + Vector3.Dot(displacement, left), y = .5f + Vector3.Dot(displacement, up) }; Vector3[] vertices = new Vector3[] { _vertices[i], _vertices[(i + 1) % _vertices.Count], centerPosition }; Vector3[] normals = new Vector3[] { -_plane.normal, -_plane.normal, -_plane.normal }; Vector2[] uvs = new Vector2[] { uv1, uv2, new Vector2(0.5f, 0.5f) }; MeshTriangle currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1); // Make sure triangle is facing the right way if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0) { FlipTriangle(currentTriangle); } _leftMesh.AddTriangle(currentTriangle); normals = new Vector3[] { _plane.normal, _plane.normal, _plane.normal }; currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1); if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0) { FlipTriangle(currentTriangle); } _rightMesh.AddTriangle(currentTriangle); } }
public void CloneGeneratedMesh(int index) { GeneratedMesh newMesh = new GeneratedMesh(generated[index]); generated.Insert(index + 1, newMesh); }
public static void CutGameobject(GameObject originalGameObject, Vector3 contactPoint, Vector3 direction, bool addRigidbody = false) { if (currentlyCutting) { return; } currentlyCutting = true; originalMesh = originalGameObject.GetComponent <MeshFilter>().mesh; var plane = new Plane(originalGameObject.transform.InverseTransformDirection(direction), originalGameObject.transform.InverseTransformPoint(contactPoint)); var addedVertices = new List <Vector3>(); var leftMesh = new GeneratedMesh(); var rightMesh = new GeneratedMesh(); int[] submeshIndices; int triangleIndexA, triangleIndexB, triangleIndexC; for (int i = 0; i < originalMesh.subMeshCount; i++) { submeshIndices = originalMesh.GetTriangles(i); for (int j = 0; j < submeshIndices.Length; j += 3) { triangleIndexA = submeshIndices[j]; triangleIndexB = submeshIndices[j + 1]; triangleIndexC = submeshIndices[j + 2]; MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i); bool[] pointsOnLeftSide = new bool [3]; pointsOnLeftSide[0] = plane.GetSide(originalMesh.vertices[triangleIndexA]); pointsOnLeftSide[1] = plane.GetSide(originalMesh.vertices[triangleIndexB]); pointsOnLeftSide[2] = plane.GetSide(originalMesh.vertices[triangleIndexC]); if (pointsOnLeftSide[0] && pointsOnLeftSide[1] && pointsOnLeftSide[2]) { leftMesh.AddTriangle(currentTriangle); } else if (!pointsOnLeftSide[0] && !pointsOnLeftSide[1] && !pointsOnLeftSide[2]) { rightMesh.AddTriangle(currentTriangle); } else { CutTriangle(plane, currentTriangle, pointsOnLeftSide, leftMesh, rightMesh, addedVertices); } } FillCut(addedVertices, plane, leftMesh, rightMesh); GenerateCutterGameobject(originalGameObject, leftMesh, addRigidbody, Vector3.up); GenerateCutterGameobject(originalGameObject, rightMesh, addRigidbody, Vector3.left); currentlyCutting = false; } }
protected IEnumerator MergeChildTrees(float LOD0_Distance, float LOD1_Distance) { yield return(new WaitForEndOfFrame()); List <Tree> treesToMerge = new List <Tree>(); if (transform.parent && !transform.parent.GetComponent <Tree>()) { treesToMerge.Add(this); for (int i = 0; i < transform.childCount; i++) { if (transform.GetChild(i).GetComponent <Tree>()) { treesToMerge.Add(transform.GetChild(i).GetComponent <Tree>()); } } //Merge int count = treesToMerge.Count; if (count > 0) { List <MeshFilter> meshFiltersBranches = new List <MeshFilter>(); List <MeshFilter> meshFiltersLeaves = new List <MeshFilter>(); List <MeshFilter> meshFiltersBranchesLOD = new List <MeshFilter>(); List <MeshFilter> meshFiltersLeavesLOD = new List <MeshFilter>(); for (int i = 0; i < count; i++) { meshFiltersBranches.Add(treesToMerge[i].generatedBranch.GetComponent <MeshFilter>()); meshFiltersBranches.AddRange(treesToMerge[i].generatedBranchesParent.GetComponentsInChildren <MeshFilter>()); meshFiltersLeaves.Add(treesToMerge[i].generatedLeaves.GetComponent <MeshFilter>()); meshFiltersBranchesLOD.Add(treesToMerge[i].generatedBranchLOD.GetComponent <MeshFilter>()); meshFiltersLeavesLOD.Add(treesToMerge[i].generatedLeavesLOD.GetComponent <MeshFilter>()); } GameObject mergedBranches = GeneratedMesh.CombineMeshes(transform, meshFiltersBranches.ToArray()); mergedBranches.AddComponent <GeneratedBranch>(); mergedBranches.name = "Newly merged branches"; generatedBranch = mergedBranches.GetComponent <GeneratedBranch>(); GameObject mergedLeaves = GeneratedMesh.CombineMeshes(transform, meshFiltersLeaves.ToArray()); mergedLeaves.AddComponent <GeneratedLeaves>(); mergedLeaves.name = "Newly merged leaves"; generatedLeaves = mergedLeaves.GetComponent <GeneratedLeaves>(); //LOD GameObject mergedBranchesLOD = GeneratedMesh.CombineMeshes(transform, meshFiltersBranchesLOD.ToArray()); mergedBranchesLOD.AddComponent <GeneratedBranch>(); mergedBranchesLOD.name = "Newly merged branches LOD"; generatedBranchLOD = mergedBranchesLOD.GetComponent <GeneratedBranch>(); GameObject mergedLeavesLOD = GeneratedMesh.CombineMeshes(transform, meshFiltersLeavesLOD.ToArray()); mergedLeavesLOD.AddComponent <GeneratedLeaves>(); mergedLeavesLOD.name = "Newly merged leaves LOD"; generatedLeavesLOD = mergedLeavesLOD.GetComponent <GeneratedLeaves>(); } AddLODsNew(LOD0_Distance, LOD1_Distance); } }
private static void CutTriangle(Plane _plane, MeshTriangle meshTri, bool tALS, bool TBLS, bool TCLS, GeneratedMesh lSide, GeneratedMesh rSide, List <Vector3> addedVert) { List <bool> leftSide = new List <bool>(); leftSide.Add(tALS); leftSide.Add(TBLS); leftSide.Add(TCLS); MeshTriangle leftMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], meshTri.SMIndex); MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], meshTri.SMIndex); bool left = false; bool right = false; for (int i = 0; i < 3; i++) { if (leftSide[i]) { if (!left) { left = true; leftMeshTriangle.Vert[0] = meshTri.Vert[i]; leftMeshTriangle.Vert[1] = leftMeshTriangle.Vert[0]; leftMeshTriangle.UV[0] = meshTri.UV[i]; leftMeshTriangle.UV[1] = leftMeshTriangle.UV[0]; leftMeshTriangle.Norm[0] = meshTri.Norm[i]; leftMeshTriangle.Norm[1] = leftMeshTriangle.Norm[0]; } else { leftMeshTriangle.Vert[1] = meshTri.Vert[i]; leftMeshTriangle.Norm[1] = meshTri.Vert[i]; leftMeshTriangle.UV[1] = meshTri.Vert[i]; } } else { if (!right) { right = true; rightMeshTriangle.Vert[0] = meshTri.Vert[i]; rightMeshTriangle.Vert[1] = rightMeshTriangle.Vert[0]; rightMeshTriangle.UV[0] = meshTri.UV[i]; rightMeshTriangle.UV[1] = rightMeshTriangle.UV[0]; rightMeshTriangle.Norm[0] = meshTri.Norm[i]; rightMeshTriangle.Norm[1] = rightMeshTriangle.Norm[0]; } else { rightMeshTriangle.Vert[1] = meshTri.Vert[i]; rightMeshTriangle.Norm[1] = meshTri.Vert[i]; rightMeshTriangle.UV[1] = meshTri.Vert[i]; } } } float normalizedDistance; float distance; _plane.Raycast(new Ray(leftMeshTriangle.Vert[0], (rightMeshTriangle.Vert[0] - leftMeshTriangle.Vert[0]).normalized), out distance); normalizedDistance = distance / (rightMeshTriangle.Vert[0] - leftMeshTriangle.Vert[0]).magnitude; Vector3 vertLeft = Vector3.Lerp(leftMeshTriangle.Vert[0], rightMeshTriangle.Vert[0], normalizedDistance); addedVert.Add(vertLeft); Vector3 normalLeft = Vector3.Lerp(leftMeshTriangle.Norm[0], rightMeshTriangle.Norm[0], normalizedDistance); Vector2 uvLeft = Vector2.Lerp(leftMeshTriangle.UV[0], rightMeshTriangle.UV[0], normalizedDistance); _plane.Raycast(new Ray(leftMeshTriangle.Vert[1], (rightMeshTriangle.Vert[1] - leftMeshTriangle.Vert[1]).normalized), out distance); normalizedDistance = distance / (rightMeshTriangle.Vert[1] - leftMeshTriangle.Vert[1]).magnitude; Vector3 vertRight = Vector3.Lerp(leftMeshTriangle.Vert[1], rightMeshTriangle.Vert[1], normalizedDistance); addedVert.Add(vertLeft); Vector3 normalRight = Vector3.Lerp(leftMeshTriangle.Norm[1], rightMeshTriangle.Norm[1], normalizedDistance); Vector2 uvRight = Vector2.Lerp(leftMeshTriangle.UV[1], rightMeshTriangle.UV[1], normalizedDistance); MeshTriangle currentTriangle; Vector3[] updatedVert = new Vector3[] { leftMeshTriangle.Vert[0], vertLeft, vertRight }; Vector3[] updatedNorm = new Vector3[] { leftMeshTriangle.Norm[0], normalLeft, normalRight }; Vector2[] updatedUV = new Vector2[] { leftMeshTriangle.UV[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex); if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2]) { if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0) { FlipTriangle(currentTriangle); } lSide.AddTriangle(currentTriangle); } updatedVert = new Vector3[] { leftMeshTriangle.Vert[0], leftMeshTriangle.Vert[1], vertRight }; updatedNorm = new Vector3[] { leftMeshTriangle.Norm[0], leftMeshTriangle.Norm[1], normalRight }; updatedUV = new Vector2[] { leftMeshTriangle.UV[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex); if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2]) { if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0) { FlipTriangle(currentTriangle); } lSide.AddTriangle(currentTriangle); } updatedVert = new Vector3[] { rightMeshTriangle.Vert[0], vertLeft, vertRight }; updatedNorm = new Vector3[] { rightMeshTriangle.Norm[0], normalLeft, normalRight }; updatedUV = new Vector2[] { rightMeshTriangle.UV[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex); if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2]) { if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0) { FlipTriangle(currentTriangle); } rSide.AddTriangle(currentTriangle); } updatedVert = new Vector3[] { rightMeshTriangle.Vert[0], rightMeshTriangle.Vert[1], vertRight }; updatedNorm = new Vector3[] { rightMeshTriangle.Norm[0], rightMeshTriangle.Norm[1], normalRight }; updatedUV = new Vector2[] { rightMeshTriangle.UV[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex); if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2]) { if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0) { FlipTriangle(currentTriangle); } rSide.AddTriangle(currentTriangle); } }
public static void Cut(GameObject _originalGameObject, Vector3 _contactPoint, Vector3 _direction, Material _cutMaterial = null, bool fill = true, bool _addRigidbody = false) { if (currentlyCutting) { return; } currentlyCutting = true; //We are instantiating a plane through our initial object to seperate the left and right side from each other Plane plane = new Plane(_originalGameObject.transform.InverseTransformDirection(-_direction), _originalGameObject.transform.InverseTransformPoint(_contactPoint)); originalMesh = _originalGameObject.GetComponent <MeshFilter>().mesh; List <Vector3> addedVertices = new List <Vector3>(); //We are getting two new generated meshes for our left and right side GeneratedMesh leftMesh = new GeneratedMesh(); GeneratedMesh rightMesh = new GeneratedMesh(); //Some meshes use different submeshes to have multiple materials attached to them //in an early iteration I had an extra script to turn everything into one mesh to make my life a little easier //however the result was not great because I could only slice objects that had one single material int[] submeshIndices; int triangleIndexA, triangleIndexB, triangleIndexC; for (int i = 0; i < originalMesh.subMeshCount; i++) { submeshIndices = originalMesh.GetTriangles(i); //We are now going through the submesh indices as triangles to determine on what side of the mesh they are. for (int j = 0; j < submeshIndices.Length; j += 3) { triangleIndexA = submeshIndices[j]; triangleIndexB = submeshIndices[j + 1]; triangleIndexC = submeshIndices[j + 2]; MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i); //We are now using the plane.getside function to see on which side of the cut our trianle is situated //or if it might be cut through bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]); bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]); bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]); //All three vertices are on the left side of the plane, so they need to be added to the left //mesh if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide) { leftMesh.AddTriangle(currentTriangle); } //All three vertices are on the right side of the mesh. else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide) { rightMesh.AddTriangle(currentTriangle); } else { CutTriangle(plane, currentTriangle, triangleALeftSide, triangleBLeftSide, triangleCLeftSide, leftMesh, rightMesh, addedVertices); } } } //Filling our cut if (fill == true) { FillCut(addedVertices, plane, leftMesh, rightMesh); } // Generer de to nye meshes Mesh finishedLeftMesh = leftMesh.GetGeneratedMesh(); Mesh finishedRightMesh = rightMesh.GetGeneratedMesh(); Debug.Log(finishedLeftMesh); Destroy(_originalGameObject.GetComponent <MeshCollider>()); MeshCollider newCollider = _originalGameObject.AddComponent <MeshCollider>(); newCollider.sharedMesh = finishedLeftMesh; newCollider.convex = true; // Materials Material[] mats = new Material[finishedLeftMesh.subMeshCount]; for (int i = 0; i < finishedLeftMesh.subMeshCount; i++) { mats[i] = _originalGameObject.GetComponent <MeshRenderer>().material; } _originalGameObject.GetComponent <MeshRenderer>().materials = mats; // Tildel mesh _originalGameObject.GetComponent <MeshFilter>().mesh = finishedLeftMesh; // Når meshet er tillagt, beregner vi den nye masse. _originalGameObject.GetComponent <Rigidbody>().mass = VolumeAndMass.MassOfMesh(finishedLeftMesh, _originalGameObject.GetComponent <Food>().density); // Opdater center of mass _originalGameObject.GetComponent <Rigidbody>().centerOfMass = _originalGameObject.GetComponent <MeshFilter>().mesh.bounds.center; GameObject rightGO = new GameObject(); rightGO.transform.position = _originalGameObject.transform.position + (_direction * .007f); rightGO.transform.rotation = _originalGameObject.transform.rotation; rightGO.transform.localScale = _originalGameObject.transform.localScale; rightGO.AddComponent <MeshRenderer>(); // Materials mats = new Material[finishedRightMesh.subMeshCount]; for (int i = 0; i < finishedRightMesh.subMeshCount; i++) { mats[i] = _originalGameObject.GetComponent <MeshRenderer>().material; } rightGO.GetComponent <MeshRenderer>().materials = mats; // Tildel mesh rightGO.AddComponent <MeshFilter>().mesh = finishedRightMesh; // Tildel rigidbody if (rightGO.GetComponent <Rigidbody>() == null) { rightGO.AddComponent <Rigidbody>(); } // Når meshet er tillagt, beregner vi den nye masse med samme densitet som det originale objekt (selvfølgelig). rightGO.GetComponent <Rigidbody>().mass = VolumeAndMass.MassOfMesh(finishedRightMesh, _originalGameObject.GetComponent <Food>().density); // Opdater center of mass rightGO.GetComponent <Rigidbody>().centerOfMass = rightGO.GetComponent <MeshFilter>().mesh.bounds.center; rightGO.AddComponent <MeshCollider>().sharedMesh = finishedRightMesh; rightGO.GetComponent <MeshCollider>().convex = true; rightGO.tag = _originalGameObject.tag; // Opdater scripts Food newFoodScript = rightGO.AddComponent <Food>(); Food originFoodScript = _originalGameObject.GetComponent <Food>(); UpdateFoodScript(newFoodScript, originFoodScript); rightGO.AddComponent <Throwable>(); currentlyCutting = false; }
private static void CutTriangle(Plane _plane, MeshTriangle _triangle, bool _triangleALeftSide, bool _triangleBLeftSide, bool _triangleCLeftSide, GeneratedMesh _leftSide, GeneratedMesh _rightSide, List <Vector3> _addedVertices) { List <bool> leftSide = new List <bool>(); leftSide.Add(_triangleALeftSide); leftSide.Add(_triangleBLeftSide); leftSide.Add(_triangleCLeftSide); MeshTriangle leftMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex); MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex); bool left = false; bool right = false; for (int i = 0; i < 3; i++) { if (leftSide[i]) { if (!left) { left = true; leftMeshTriangle.Vertices[0] = _triangle.Vertices[i]; leftMeshTriangle.Vertices[1] = leftMeshTriangle.Vertices[0]; leftMeshTriangle.UVs[0] = _triangle.UVs[i]; leftMeshTriangle.UVs[1] = leftMeshTriangle.UVs[0]; leftMeshTriangle.Normals[0] = _triangle.Normals[i]; leftMeshTriangle.Normals[1] = leftMeshTriangle.Normals[0]; } else { leftMeshTriangle.Vertices[1] = _triangle.Vertices[i]; leftMeshTriangle.Normals[1] = _triangle.Normals[i]; leftMeshTriangle.UVs[1] = _triangle.UVs[i]; } } else { if (!right) { right = true; rightMeshTriangle.Vertices[0] = _triangle.Vertices[i]; rightMeshTriangle.Vertices[1] = rightMeshTriangle.Vertices[0]; rightMeshTriangle.UVs[0] = _triangle.UVs[i]; rightMeshTriangle.UVs[1] = rightMeshTriangle.UVs[0]; rightMeshTriangle.Normals[0] = _triangle.Normals[i]; rightMeshTriangle.Normals[1] = rightMeshTriangle.Normals[0]; } else { rightMeshTriangle.Vertices[1] = _triangle.Vertices[i]; rightMeshTriangle.Normals[1] = _triangle.Normals[i]; rightMeshTriangle.UVs[1] = _triangle.UVs[i]; } } } float normalizedDistance; float distance; _plane.Raycast(new Ray(leftMeshTriangle.Vertices[0], (rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0]).normalized), out distance); normalizedDistance = distance / (rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0]).magnitude; Vector3 vertLeft = Vector3.Lerp(leftMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[0], normalizedDistance); _addedVertices.Add(vertLeft); Vector3 normalLeft = Vector3.Lerp(leftMeshTriangle.Normals[0], rightMeshTriangle.Normals[0], normalizedDistance); Vector2 uvLeft = Vector2.Lerp(leftMeshTriangle.UVs[0], rightMeshTriangle.UVs[0], normalizedDistance); _plane.Raycast(new Ray(leftMeshTriangle.Vertices[1], (rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1]).normalized), out distance); normalizedDistance = distance / (rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1]).magnitude; Vector3 vertRight = Vector3.Lerp(leftMeshTriangle.Vertices[1], rightMeshTriangle.Vertices[1], normalizedDistance); _addedVertices.Add(vertRight); Vector3 normalRight = Vector3.Lerp(leftMeshTriangle.Normals[1], rightMeshTriangle.Normals[1], normalizedDistance); Vector2 uvRight = Vector2.Lerp(leftMeshTriangle.UVs[1], rightMeshTriangle.UVs[1], normalizedDistance); //TESTING OUR FIRST TRIANGLE MeshTriangle currentTriangle; Vector3[] updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], vertLeft, vertRight }; Vector3[] updatedNormals = new Vector3[] { leftMeshTriangle.Normals[0], normalLeft, normalRight }; Vector2[] updatedUVs = new Vector2[] { leftMeshTriangle.UVs[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex); //If our vertices arent the same if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2]) { if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0) { FlipTriangel(currentTriangle); } _leftSide.AddTriangle(currentTriangle); } //SECOND TRIANGLE updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], leftMeshTriangle.Vertices[1], vertRight }; updatedNormals = new Vector3[] { leftMeshTriangle.Normals[0], leftMeshTriangle.Normals[1], normalRight }; updatedUVs = new Vector2[] { leftMeshTriangle.UVs[0], leftMeshTriangle.UVs[1], uvRight }; currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex); //If our vertices arent the same if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2]) { if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0) { FlipTriangel(currentTriangle); } _leftSide.AddTriangle(currentTriangle); } //THIRD TRIANGLE updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], vertLeft, vertRight }; updatedNormals = new Vector3[] { rightMeshTriangle.Normals[0], normalLeft, normalRight }; updatedUVs = new Vector2[] { rightMeshTriangle.UVs[0], uvLeft, uvRight }; currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex); //If our vertices arent the same if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2]) { if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0) { FlipTriangel(currentTriangle); } _rightSide.AddTriangle(currentTriangle); } //FOURTH TRIANGLE updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[1], vertRight }; updatedNormals = new Vector3[] { rightMeshTriangle.Normals[0], rightMeshTriangle.Normals[1], normalRight }; updatedUVs = new Vector2[] { rightMeshTriangle.UVs[0], rightMeshTriangle.UVs[1], uvRight }; currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex); //If our vertices arent the same if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2]) { if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0) { FlipTriangel(currentTriangle); } _rightSide.AddTriangle(currentTriangle); } }
public static void Cut(GameObject _originalGameObject, Vector3 _contactPoint, Vector3 _direction, Material _cutMaterial = null, bool _fill = true, bool _addRigidbody = false) { if (currentlyCutting) { return; } currentlyCutting = true; Plane plane = new Plane(_originalGameObject.transform.InverseTransformDirection(-_direction), _originalGameObject.transform.InverseTransformDirection(_contactPoint)); originalMesh = _originalGameObject.GetComponent <MeshFilter>().mesh; List <Vector3> addedVertices = new List <Vector3>(); GeneratedMesh leftMesh = new GeneratedMesh(); GeneratedMesh rightMesh = new GeneratedMesh(); int[] submeshIndices; int triangleIndexA, triangleIndexB, triangleIndexC; for (int i = 0; i < originalMesh.subMeshCount; ++i) { submeshIndices = originalMesh.GetTriangles(i); for (int j = 0; j < submeshIndices.Length; j += 3) { triangleIndexA = submeshIndices[j]; triangleIndexB = submeshIndices[j + 1]; triangleIndexC = submeshIndices[j + 2]; MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i); bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]); bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]); bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]); if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide) { leftMesh.AddTriangle(currentTriangle); } else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide) { rightMesh.AddTriangle(currentTriangle); } else { CutTriangle(plane, currentTriangle, triangleALeftSide, triangleBLeftSide, triangleCLeftSide, leftMesh, rightMesh, addedVertices); } } } if (_fill) { FillCut(addedVertices, plane, leftMesh, rightMesh); } originalMesh.Clear(); originalMesh.vertices = leftMesh.Vertices.ToArray(); originalMesh.normals = leftMesh.Normals.ToArray(); originalMesh.uv = leftMesh.UVs.ToArray(); originalMesh.triangles = leftMesh.Indices(0); GameObject secondGameObject = GameObject.Instantiate(_originalGameObject); Mesh secondMesh = secondGameObject.GetComponent <MeshFilter>().mesh; secondMesh.vertices = rightMesh.Vertices.ToArray(); secondMesh.normals = rightMesh.Normals.ToArray(); secondMesh.uv = rightMesh.UVs.ToArray(); secondMesh.triangles = rightMesh.Indices(0); Component.Destroy(_originalGameObject.GetComponent <SphereCollider>()); Component.Destroy(secondGameObject.GetComponent <SphereCollider>()); _originalGameObject.AddComponent <MeshCollider>(); secondGameObject.AddComponent <MeshCollider>(); _originalGameObject.GetComponent <MeshCollider>().convex = true; secondGameObject.GetComponent <MeshCollider>().convex = true; currentlyCutting = false; }
public static void Fill(List <Vector3> _vertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh) { //Firstly we need the center we do this by adding up all the vertices and then calculating the average Vector3 centerPosition = Vector3.zero; for (int i = 0; i < _vertices.Count; i++) { centerPosition += _vertices[i]; } centerPosition = centerPosition / _vertices.Count; //We now need an Upward Axis we use the plane we cut the mesh with for that Vector3 up = new Vector3() { x = _plane.normal.x, y = _plane.normal.y, z = _plane.normal.z }; Vector3 left = Vector3.Cross(_plane.normal, up); Vector3 displacement = Vector3.zero; Vector2 uv1 = Vector2.zero; Vector2 uv2 = Vector2.zero; for (int i = 0; i < _vertices.Count; i++) { displacement = _vertices[i] - centerPosition; uv1 = new Vector2() { x = .5f + Vector3.Dot(displacement, left), y = .5f + Vector3.Dot(displacement, up) }; displacement = _vertices[(i + 1) % _vertices.Count] - centerPosition; uv2 = new Vector2() { x = .5f + Vector3.Dot(displacement, left), y = .5f + Vector3.Dot(displacement, up) }; Vector3[] vertices = new Vector3[] { _vertices[i], _vertices[(i + 1) % _vertices.Count], centerPosition }; Vector3[] normals = new Vector3[] { -_plane.normal, -_plane.normal, -_plane.normal }; Vector2[] uvs = new Vector2[] { uv1, uv2, new Vector2(0.5f, 0.5f) }; MeshTriangle currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1); if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0) { FlipTriangel(currentTriangle); } _leftMesh.AddTriangle(currentTriangle); normals = new Vector3[] { _plane.normal, _plane.normal, _plane.normal }; currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1); if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0) { FlipTriangel(currentTriangle); } _rightMesh.AddTriangle(currentTriangle); } }
Mesh GenerateMesh(Vector3 position) { int verticesPerSegment = 6; int vertexCount = verticesPerSegment * ((int)cellsPerTile) * ((int)cellsPerTile); int vertex = 0; // What cell is x and z for the bottom left of this tile in world space Vector3 tileBottomLeft = new Vector3(); tileBottomLeft.x = -(cellsPerTile) / 2; tileBottomLeft.z = -(cellsPerTile) / 2; GeneratedMesh gm = new GeneratedMesh(); gm.vertices = new Vector3[vertexCount]; gm.normals = new Vector3[vertexCount]; gm.uv = new Vector2[vertexCount]; gm.triangles = new int[vertexCount]; gm.colors = new Color[vertexCount]; Vector2 texOrigin = position / cellSize; texOrigin.x = texOrigin.x % textureGenerator.size; texOrigin.y = texOrigin.y % textureGenerator.size; float tilesPerTexture = textureGenerator.size / cellsPerTile; for (int z = 0; z < cellsPerTile; z++) { for (int x = 0; x < cellsPerTile; x++) { int startVertex = vertex; Vector3 cellBottomLeft = tileBottomLeft + new Vector3(x * cellSize, 0, z * cellSize); Vector3 cellTopLeft = tileBottomLeft + new Vector3(x * cellSize, 0, ((z + 1) * cellSize)); Vector3 cellTopRight = tileBottomLeft + new Vector3((x + 1) * cellSize, 0, (z + 1) * cellSize); Vector3 cellBottomRight = tileBottomLeft + new Vector3((x + 1) * cellSize, 0, z * cellSize); // Add all the samplers together to make the height Vector3 cell = (position / cellSize) + tileBottomLeft + new Vector3(x, 0, z); foreach (Sampler sampler in samplers) { cellBottomLeft.y = sampler.Operate(cellBottomLeft.y, cell.x, cell.z); cellTopLeft.y = sampler.Operate(cellTopLeft.y, cell.x, cell.z + 1); cellTopRight.y = sampler.Operate(cellTopRight.y, cell.x + 1, cell.z + 1); cellBottomRight.y = sampler.Operate(cellBottomRight.y, cell.x + 1, cell.z); } // Make the vertices gm.vertices[vertex++] = cellBottomLeft; gm.vertices[vertex++] = cellTopLeft; gm.vertices[vertex++] = cellTopRight; gm.vertices[vertex++] = cellTopRight; gm.vertices[vertex++] = cellBottomRight; gm.vertices[vertex++] = cellBottomLeft; vertex = startVertex; gm.uv[vertex++] = MakeUV(position, x, z); gm.uv[vertex++] = MakeUV(position, x, z + 1); gm.uv[vertex++] = MakeUV(position, x + 1, z + 1); gm.uv[vertex++] = MakeUV(position, x + 1, z + 1); gm.uv[vertex++] = MakeUV(position, x + 1, z); gm.uv[vertex++] = MakeUV(position, x, z); // Make the triangles for (int i = 0; i < 6; i++) { int vertexIndex = startVertex + i; gm.triangles[vertexIndex] = vertexIndex; gm.colors[vertexIndex] = color; } } } Mesh mesh = new Mesh(); mesh.vertices = gm.vertices; mesh.uv = gm.uv; mesh.triangles = gm.triangles; mesh.colors = gm.colors; mesh.RecalculateNormals(); return(mesh); }
GeneratedMesh GenerateTileAsync(GameObject tileGameObject, Vector3 position, bool lod) { int verticesPerSegment = 6; //adjusting these values for LOD if necessary Vector2 cellsPerTile; Vector2 tileSize; Vector2 cellSize; if (lod) { cellsPerTile = new Vector2(this.cellsPerTile.x / lodFactor, this.cellsPerTile.y / lodFactor); tileSize = new Vector2(this.tileSize.x * lodFactor, this.tileSize.y * lodFactor); cellSize = new Vector2(this.cellSize.x * lodFactor, this.cellSize.y * lodFactor); } else { cellsPerTile = this.cellsPerTile; tileSize = this.tileSize; cellSize = this.cellSize; } int vertexCount = verticesPerSegment * ((int)cellsPerTile.x) * ((int)cellsPerTile.y); GeneratedMesh gm = new GeneratedMesh(); gm.vertices = new Vector3[vertexCount]; gm.normals = new Vector3[vertexCount]; gm.uvs = new Vector2[vertexCount]; gm.triangles = new int[vertexCount]; gm.colours = new Color[vertexCount]; int vertex = 0; // What cell is x and z for the bottom left of this tile in world space Vector3 tileBottomLeft = new Vector3(); tileBottomLeft.x = - (tileSize.x) / 2; tileBottomLeft.z = - (tileSize.y) / 2; for (int z = 0; z < cellsPerTile.y; z++) { for (int x = 0; x < cellsPerTile.x; x++) { int startVertex = vertex; // Calculate some stuff Vector3 cellBottomLeft = tileBottomLeft + new Vector3(x * cellSize.x, 0, z * cellSize.y); Vector3 cellTopLeft = tileBottomLeft + new Vector3(x * cellSize.x, 0, (z + 1) * cellSize.y); Vector3 cellTopRight = tileBottomLeft + new Vector3((x + 1) * cellSize.x, 0 , (z + 1) * cellSize.y); Vector3 celBottomRight = tileBottomLeft + new Vector3((x + 1) * cellSize.x, 0, z * cellSize.y); // Add all the samplers together to make the height Vector3 cellWorldCoords = position + tileBottomLeft + new Vector3(x * cellSize.x, 0, z * cellSize.y); foreach(Sampler sampler in samplers) { cellBottomLeft.y += sampler.Sample(cellWorldCoords.x, cellWorldCoords.z); cellTopLeft.y += sampler.Sample(cellWorldCoords.x, cellWorldCoords.z + cellSize.y); cellTopRight.y += sampler.Sample(cellWorldCoords.x + cellSize.x, cellWorldCoords.z + cellSize.y); celBottomRight.y += sampler.Sample(cellWorldCoords.x + cellSize.x, cellWorldCoords.z); } // Make the vertices gm.vertices[vertex++] = cellBottomLeft; gm.vertices[vertex++] = cellTopLeft; gm.vertices[vertex++] = cellTopRight; gm.vertices[vertex++] = cellTopRight; gm.vertices[vertex++] = celBottomRight; gm.vertices[vertex++] = cellBottomLeft; // Make the normals, UV's and triangles for (int i = 0; i < 6; i++) { int vertexIndex = startVertex + i; gm.triangles[vertexIndex] = vertexIndex; gm.uvs[vertexIndex] = new Vector2(x / cellsPerTile.x, z / cellsPerTile.y); } } } return gm; }
public static void Cut(GameObject _originalGameObject, Vector3 _contactPoint, Vector3 _direction, Material _cutMaterial = null, bool fill = true, bool _addRigidBody = false) { if (currentlyCutting) { return; } currentlyCutting = true; Plane plane = new Plane(_originalGameObject.transform.InverseTransformDirection(-_direction), _originalGameObject.transform.InverseTransformPoint(_contactPoint)); originalGameObject = _originalGameObject; originalMesh = _originalGameObject.GetComponent <MeshFilter>().mesh; List <Vector3> addedVertices = new List <Vector3>(); GeneratedMesh leftMesh = new GeneratedMesh(); GeneratedMesh rightMesh = new GeneratedMesh(); int[] submeshIndices; int triangleIndexA, triangleIndexB, triangleIndexC; for (int i = 0; i < originalMesh.subMeshCount; i++) { submeshIndices = originalMesh.GetTriangles(i); for (int j = 0; j < submeshIndices.Length; j += 3) { triangleIndexA = submeshIndices[j]; triangleIndexB = submeshIndices[j + 1]; triangleIndexC = submeshIndices[j + 2]; MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i); bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]); bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]); bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]); /* * Three different cases: * - The triangle is either above the plane * - The triangle is below the plane * - The place intersects the triangle */ if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide) { leftMesh.AddTriangle(currentTriangle); } else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide) { rightMesh.AddTriangle(currentTriangle); } else { CutTriangle(plane, currentTriangle, triangleALeftSide, triangleBLeftSide, triangleCLeftSide, leftMesh, rightMesh, addedVertices); } } } // if either mesh has no vertices, return if (leftMesh.Vertices.Count == 0 || rightMesh.Vertices.Count == 0 || addedVertices.Count == 0) { currentlyCutting = false; return; } FillCut(addedVertices, plane, leftMesh, rightMesh); GenerateGameObject(leftMesh); GenerateGameObject(rightMesh); Object.Destroy(_originalGameObject); currentlyCutting = false; }