public void BuildData(ref List <Model3D.MeshData> meshes) { finalMesh = newFinalMesh(); for (int t = 0; t < TempMeshes.Count; t++) { uint indexCount = 0; Model3D.MeshData md = new Model3D.MeshData(); Bitmap bmp = textureImages[t]; md.texture = ContentPipe.LoadTexture(ref bmp); md.texture.TextureParamS = textureInfo[t].wrapS; md.texture.TextureParamT = textureInfo[t].wrapT; TempMesh temp = TempMeshes[t]; for (int i = 0; i < temp.vertices.Count; i++) { int vExists = doesVertexAlreadyExist(t, temp.vertices[i], temp.texCoords[i], temp.colors[i]); if (vExists < 0) { Vector2 texCoord = temp.texCoords[i]; texCoord.X /= (float)bmp.Width * 32.0f; texCoord.Y /= (float)bmp.Height * 32.0f; temp.final.vertices.Add(temp.vertices[i]); temp.final.texCoords.Add(texCoord); temp.final.colors.Add(temp.colors[i]); temp.final.indices.Add(indexCount); indexCount++; } else { temp.final.indices.Add((uint)vExists); } } meshes.Add(md); } }
static private void FillBoundaryFace(TempMesh tempMesh, List <Vector3> added, ref Vector3[] tempTriangle) { // 1. Reorder added so in order ot their occurence along the perimeter. MeshUtils.ReorderList(added); // 2. Find actual face vertices var face = FindRealPolygon(added); // 3. Create triangle fans int t_fwd = 0, t_bwd = face.Count - 1, t_new = 1; bool incr_fwd = true; while (t_new != t_fwd && t_new != t_bwd) { MeshTools.AddTriangle(tempMesh, ref tempTriangle, face, t_bwd, t_fwd, t_new); if (incr_fwd) { t_fwd = t_new; } else { t_bwd = t_new; } incr_fwd = !incr_fwd; t_new = incr_fwd ? t_fwd + 1 : t_bwd - 1; } }
/// <summary> /// Begins creating a new mesh object with given attributes /// </summary> /// <param name="name">The name of the Mesh Object</param> /// <param name="indices">The vertex indices as triangles</param> /// <paramref name="positions"/> /// <param name="parentBoneName"></param> /// <param name="generateBounding"></param> public void StartMeshObject(string name, uint[] indices, SsbhVertexAttribute[] positions, string parentBoneName = "", bool generateBounding = false) { currentMesh = new TempMesh { Name = name, ParentBone = parentBoneName }; currentMesh.Indices.AddRange(indices); currentMesh.VertexCount = positions.Length; meshes.Add(currentMesh); AddAttributeToMeshObject(UltimateVertexAttribute.Position0, positions); if (generateBounding) { //TODO: sphere generation BoundingBoxGenerator.GenerateAabb(positions, out SsbhVertexAttribute max, out SsbhVertexAttribute min); SetAaBoundingBox(min, max); SetOrientedBoundingBox( new SsbhVertexAttribute((max.X + min.X / 2), (max.Y + min.Y / 2), (max.Y + min.Y / 2)), new SsbhVertexAttribute((max.X - min.X), (max.Y - min.Y), (max.Z - min.Z)), new float[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 }); } }
void Face(TempMesh mesh, int material, int side, Vector3 q1, Vector3 q2, Vector3 q3, Vector3 q4) { int a = mesh.vertex.Count; mesh.vertex.Add(q1); mesh.vertex.Add(q2); mesh.vertex.Add(q3); mesh.vertex.Add(q4); mesh.face.Add(a); mesh.face.Add(a + 2); mesh.face.Add(a + 1); mesh.face.Add(a + 2); mesh.face.Add(a + 3); mesh.face.Add(a + 1); mesh.uv.Add(new Vector2((float)(material - 1) / textureCount + 0.1f, 0)); mesh.uv.Add(new Vector2((float)(material) / textureCount - 0.1f, 0)); mesh.uv.Add(new Vector2((float)(material - 1) / textureCount + 0.1f, 1)); mesh.uv.Add(new Vector2((float)(material) / textureCount - 0.1f, 1)); /* * mesh.uv.Add(Main.main.GetMapTextures(material,0)); * mesh.uv.Add(Main.main.GetMapTextures(material, 1)); * mesh.uv.Add(Main.main.GetMapTextures(material, 2)); * mesh.uv.Add(Main.main.GetMapTextures(material, 3)); */ }
private TempMesh newTempMesh() { TempMesh m = new TempMesh(); m.vertices = new List <Vector3>(); m.texCoords = new List <Vector2>(); m.colors = new List <Vector4>(); m.final = newFinalMesh(); return(m); }
static private void AddTriangle(TempMesh PositiveMesh, ref Vector3[] tempTriangle, List <Vector3> face, int t1, int t2, int t3) { tempTriangle[0] = face[t1]; tempTriangle[1] = face[t2]; tempTriangle[2] = face[t3]; PositiveMesh.AddTriangle(tempTriangle); tempTriangle[1] = face[t3]; tempTriangle[2] = face[t2]; // NegativeMesh.AddTriangle(tempTriangle); }
/// <summary> /// Replace the mesh with tempMesh. /// </summary> public static void ReplaceMesh(Mesh mesh, TempMesh tempMesh) { mesh.Clear(); mesh.SetVertices(tempMesh.vertices); mesh.SetTriangles(tempMesh.triangles, 0); mesh.SetNormals(tempMesh.normals); mesh.SetUVs(0, tempMesh.uvs); //mesh.RecalculateNormals(); mesh.RecalculateTangents(); }
void SliceObject(ref Plane slicePlane, GameObject obj) { var mesh = obj.GetComponent <MeshFilter>().mesh; if (!meshCutter.SliceMesh(mesh, ref slicePlane)) { // If we didn't slice the object then no need to separate it into 2 objects // Debug.Log("Didn't slice"); return; } // TODO: Update center of mass bool posBigger = meshCutter.PositiveMesh.surfacearea > meshCutter.NegativeMesh.surfacearea; if (posBigger) { biggerMesh = meshCutter.PositiveMesh; smallerMesh = meshCutter.NegativeMesh; } else { biggerMesh = meshCutter.NegativeMesh; smallerMesh = meshCutter.PositiveMesh; } // Put the bigger mesh in the original object // Ignore colliders for now ReplaceMesh(mesh, biggerMesh); // Create new Sliced object with the other mesh GameObject newObject = Instantiate(SlicedPrefab, ObjectContainer); newObject.transform.SetPositionAndRotation(obj.transform.position, obj.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; ReplaceMesh(newObjMesh, smallerMesh); Transform posTransform, negTransform; if (posBigger) { posTransform = obj.transform; negTransform = newObject.transform; } else { posTransform = newObject.transform; negTransform = obj.transform; } // Separate meshes SeparateMeshes(posTransform, negTransform, slicePlane.normal); }
private bool SliceObject(ref Plane slicePlane, GameObject obj, List <Transform> positiveObjects, List <Transform> negativeObjects, bool isPlayer) { var mesh = obj.GetComponent <MeshFilter>().mesh; if (!_meshCutter.SliceMesh(mesh, ref slicePlane)) { if (slicePlane.GetDistanceToPoint(_meshCutter.GetFirstVertex()) >= 0) { positiveObjects.Add(obj.transform); } else { negativeObjects.Add(obj.transform); } return(false); } bool posBigger = _meshCutter.PositiveMesh.surfacearea > _meshCutter.NegativeMesh.surfacearea; if (posBigger) { _biggerMesh = _meshCutter.PositiveMesh; _smallerMesh = _meshCutter.NegativeMesh; } else { _biggerMesh = _meshCutter.NegativeMesh; _smallerMesh = _meshCutter.PositiveMesh; } GameObject newObject = Instantiate(obj, objectContainer); newObject.transform.SetPositionAndRotation(obj.transform.position, obj.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; obj.GetComponent <Rigidbody>().useGravity = true; obj.GetComponent <Rigidbody>().isKinematic = false; newObject.layer = 18; obj.layer = 18; // Destroy(obj.GetComponent<BoxCollider>()); // // obj.AddComponent<SphereCollider>(); obj.GetComponent <Rigidbody>().AddForce(isPlayer ? 10f : 0f, 10f, 0f); ReplaceMesh(mesh, _biggerMesh); ReplaceMesh(newObjMesh, _smallerMesh); (posBigger ? positiveObjects : negativeObjects).Add(obj.transform); (posBigger ? negativeObjects : positiveObjects).Add(newObject.transform); return(true); }
bool SliceObject(ref Plane slicePlane, GameObject obj, List <Transform> positiveObjects, List <Transform> negativeObjects) { var mesh = obj.GetComponent <MeshFilter>().mesh; if (!meshCutter.SliceMesh(mesh, ref slicePlane)) { // Put object in the respective list if (slicePlane.GetDistanceToPoint(meshCutter.GetFirstVertex()) >= 0) { positiveObjects.Add(obj.transform); } else { negativeObjects.Add(obj.transform); } return(false); } // TODO: Update center of mass // Silly condition that labels which mesh is bigger to keep the bigger mesh in the original gameobject bool posBigger = meshCutter.PositiveMesh.surfacearea > meshCutter.NegativeMesh.surfacearea; if (posBigger) { biggerMesh = meshCutter.PositiveMesh; smallerMesh = meshCutter.NegativeMesh; } else { biggerMesh = meshCutter.NegativeMesh; smallerMesh = meshCutter.PositiveMesh; } // Create new Sliced object with the other mesh GameObject newObject = Instantiate(obj, ObjectContainer); newObject.transform.SetPositionAndRotation(obj.transform.position, obj.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; // Put the bigger mesh in the original object // TODO: Enable collider generation (either the exact mesh or compute smallest enclosing sphere) ReplaceMesh(mesh, biggerMesh); ReplaceMesh(newObjMesh, smallerMesh); (posBigger ? positiveObjects : negativeObjects).Add(obj.transform); (posBigger ? negativeObjects : positiveObjects).Add(newObject.transform); return(true); }
private bool SliceObject(ref Plane slicePlane, GameObject sliceObject, List <Transform> positiveObjects, List <Transform> negativeObjects) { var meshFilter = sliceObject.GetComponent <MeshFilter>(); var mesh = meshFilter.sharedMesh; if (!meshCutter.SliceMesh(mesh, ref slicePlane)) { // Распределяем куски объекта в соответствующие списки if (slicePlane.GetDistanceToPoint(meshCutter.GetFirstVertex()) >= 0) { positiveObjects.Add(sliceObject.transform); } else { negativeObjects.Add(sliceObject.transform); } return(false); } // Определяем больший меш для исходного объекта bool posBigger = meshCutter.PositiveMesh.surfaceArea > meshCutter.NegativeMesh.surfaceArea; if (posBigger) { biggerMesh = meshCutter.PositiveMesh; smallerMesh = meshCutter.NegativeMesh; } else { biggerMesh = meshCutter.NegativeMesh; smallerMesh = meshCutter.PositiveMesh; } //Новый меньший отрезанный объект GameObject newObject = Instantiate(sliceObject, ObjectContainer); newObject.transform.SetPositionAndRotation(sliceObject.transform.position, sliceObject.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; //Распределение мешей и переопределение MeshCollider'ов ReplaceMesh(mesh, biggerMesh, sliceObject.GetComponent <MeshCollider>()); ReplaceMesh(newObjMesh, smallerMesh, newObject.GetComponent <MeshCollider>()); (posBigger ? positiveObjects : negativeObjects).Add(sliceObject.transform); (posBigger ? negativeObjects : positiveObjects).Add(newObject.transform); return(true); }
public MeshCutter(int initialArraySize) { PositiveMesh = new TempMesh(initialArraySize); NegativeMesh = new TempMesh(initialArraySize); addedPairs = new List <Vector3>(initialArraySize); ogVertices = new List <Vector3>(initialArraySize); ogTriangles = new List <int>(initialArraySize * 3); ogNormals = new List <Vector3>(initialArraySize); intersectPair = new Vector3[2]; tempTriangle = new Vector3[3]; intersect = new Intersections(); }
/// <summary> /// Replace the mesh with tempMesh. /// </summary> void ReplaceMesh(Mesh mesh, TempMesh tempMesh, MeshCollider collider = null) { mesh.Clear(); mesh.SetVertices(tempMesh.vertices); mesh.SetTriangles(tempMesh.triangles, 0); mesh.SetNormals(tempMesh.normals); //mesh.RecalculateNormals(); mesh.RecalculateTangents(); if (collider != null && collider.enabled) { collider.sharedMesh = mesh; collider.convex = true; } }
bool SliceObject(ref Plane slicePlane, GameObject obj, List <Transform> positiveObjects, List <Transform> negativeObjects) { var mesh = obj.GetComponent <MeshFilter>().mesh; if (!meshCutter.SliceMesh(mesh, ref slicePlane)) { if (slicePlane.GetDistanceToPoint(meshCutter.GetFirstVertex()) >= 0) { positiveObjects.Add(obj.transform); } else { negativeObjects.Add(obj.transform); } return(false); } bool posBigger = meshCutter.PositiveMesh.surfacearea > meshCutter.NegativeMesh.surfacearea; if (posBigger) { biggerMesh = meshCutter.PositiveMesh; smallerMesh = meshCutter.NegativeMesh; } else { biggerMesh = meshCutter.NegativeMesh; smallerMesh = meshCutter.PositiveMesh; } // Create new Sliced object with the other mesh GameObject newObject = Instantiate(obj, ObjectContainer); newObject.transform.SetPositionAndRotation(obj.transform.position, obj.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; ReplaceMesh(mesh, biggerMesh); ReplaceMesh(newObjMesh, smallerMesh); (posBigger ? positiveObjects : negativeObjects).Add(obj.transform); (posBigger ? negativeObjects : positiveObjects).Add(newObject.transform); return(true); }
public void AddTexture(TextureFormats.Raw bmp, TextureInfo info, uint segmentAddress, TempMaterial material) { TempMeshData data; data.info = info; data.segmentAddress = segmentAddress; if (null != (object)material) { data.wr_material = material.weakref; } else { data.wr_material = null; } TempMesh.Add(ref TempMeshes, ref data, new TempMeshReferences { bmp = bmp, }); currentMaterial = TempMeshes.last; }
/* * public Vector3[] getVertices(int i) { * return TempMeshes[i].final.vertices.ToArray(); * } * * public Vector2[] getTexCoords(int i) * { * return TempMeshes[i].final.texCoords.ToArray(); * } * * public Vector4[] getColors(int i) * { * return TempMeshes[i].final.colors.ToArray(); * } * * public Vector3[] getNormals(int i) * { * return TempMeshes[i].final.normals.ToArray(); * } * * public uint[] getIndices(int i) * { * return TempMeshes[i].final.indices.ToArray(); * } */ public bool hasTexture(uint segmentAddress, TempMaterial register) { TempMesh mesh_iter; uint mesh_iter_pos; if (null == (object)register) { for (mesh_iter = TempMeshes.first, mesh_iter_pos = TempMeshes.count; 0 != mesh_iter_pos; mesh_iter = mesh_iter.next, --mesh_iter_pos) { if (mesh_iter.value.segmentAddress == segmentAddress && mesh_iter.value.wr_material == null) { break; } } } else { for (mesh_iter = TempMeshes.first, mesh_iter_pos = TempMeshes.count; 0 != mesh_iter_pos; mesh_iter = mesh_iter.next, --mesh_iter_pos) { if (mesh_iter.value.segmentAddress == segmentAddress && mesh_iter.value.wr_material == register.weakref) { break; } } } if (mesh_iter_pos != 0) { currentMaterial = mesh_iter; return(true); } else { return(false); } }
/* * private void AddFinalVertex(Vector3 pos, Vector2 uv, Vector4 color) * { * finalMesh.vertices.Add(pos); * finalMesh.texCoords.Add(uv); * finalMesh.colors.Add(color); * }*/ private int doesVertexAlreadyExist(int index, Vector3 pos, Vector2 uv, Vector4 col) { TempMesh tmp = TempMeshes[index]; for (int i = 0; i < tmp.final.vertices.Count; i++) { Vector3 v = tmp.final.vertices[i]; if (pos.X == v.X && pos.Y == v.Y && pos.Z == v.Z) { Vector2 t = tmp.final.texCoords[i]; if (uv.X == t.X && uv.Y == t.Y) { Vector4 c = tmp.final.colors[i]; if (col.X == c.X && col.Y == c.Y && col.Z == c.Z && col.W == c.W) { return(i); } } } } return(-1); }
public void BuildData(List <Model3D.MeshData> meshes) { //TextureAtlasBuilder.TextureAtlas atlas = new TextureAtlasBuilder.TextureAtlas(textureImages); //atlas.outputToPNG("TestAtlas.png"); finalMesh = newFinalMesh(); for (int t = 0; t < TempMeshes.Count; t++) { uint indexCount = 0; meshes.Add(new Model3D.MeshData()); //if (t != 0) continue; //TextureAtlasBuilder.TextureAtlas.AtlasEntry atlasEntry = atlas.getEntryFromID((uint)t); Model3D.MeshData md = meshes[t]; md.texture = ContentPipe.LoadTexture(textureImages[t]); md.texture.TextureParamS = textureInfo[t].wrapS; md.texture.TextureParamT = textureInfo[t].wrapT; //Console.WriteLine("[Building]: " + (OpenTK.Graphics.OpenGL.All)md.texture.TextureParamS + "," +(OpenTK.Graphics.OpenGL.All)md.texture.TextureParamT); TempMesh temp = TempMeshes[t]; for (int i = 0; i < temp.vertices.Count; i++) { int vExists = doesVertexAlreadyExist(t, temp.vertices[i], temp.texCoords[i], temp.colors[i]); if (vExists < 0) { Vector2 texCoord = temp.texCoords[i]; texCoord.X /= (float)textureImages[t].Width * 32.0f; texCoord.Y /= (float)textureImages[t].Height * 32.0f; temp.final.vertices.Add(temp.vertices[i]); temp.final.texCoords.Add(texCoord); temp.final.colors.Add(temp.colors[i]); temp.final.indices.Add(indexCount); indexCount++; } else { temp.final.indices.Add((uint)vExists); } } } }
/// <summary> /// Replace the mesh with tempMesh. /// </summary> void ReplaceMesh(Mesh mesh, TempMesh tempMesh, MeshCollider collider = null) { //var colors = new Color32[tempMesh.vertices.Count]; //var color = mesh.colors32[0]; //for (int i = 0; i < colors.Length; i++) { // colors[i] = color; //} mesh.Clear(); mesh.SetVertices(tempMesh.vertices); mesh.SetTriangles(tempMesh.triangles, 0); mesh.SetNormals(tempMesh.normals); mesh.SetUVs(0, tempMesh.uvs); //mesh.SetColors(); //mesh.colors32 = colors; //mesh.RecalculateNormals(); mesh.RecalculateTangents(); if (collider != null && collider.enabled) { collider.sharedMesh = mesh; collider.convex = true; } }
/// <summary> Save the Mesh as a new GameObject</summary> public static GameObject Export(TempMesh tempMesh, string name) { var g = new GameObject(name); var meshFilter = g.AddComponent <MeshFilter>(); meshFilter.mesh.Clear(); meshFilter.mesh.SetVertices(tempMesh.vertices); meshFilter.mesh.SetTriangles(tempMesh.triangles, 0); meshFilter.mesh.SetNormals(tempMesh.normals); meshFilter.mesh.SetUVs(0, tempMesh.uvs); //mesh.RecalculateNormals(); meshFilter.mesh.RecalculateTangents(); // var rigidbody = g.AddComponent<Rigidbody>(); // rigidbody.useGravity = false; // var collider = g.AddComponent<MeshCollider>(); // collider.convex = true; // collider.sharedMesh = mesh; return(g); }
public void Render() { TempMesh terrain = new TempMesh(); TempMesh water = new TempMesh(); for (int y = (int)(Main.main.chunkSize.y * chunkNumber.y); y < (int)(Main.main.chunkSize.y * (chunkNumber.y + 1)); y++) { TempMesh terrainCover = new TempMesh(); TempMesh waterCover = new TempMesh(); for (int x = (int)(Main.main.chunkSize.x * chunkNumber.x); x < (int)(Main.main.chunkSize.x * (chunkNumber.x + 1)); x++) { for (int z = (int)(Main.main.chunkSize.z * chunkNumber.z); z < (int)(Main.main.chunkSize.z * (chunkNumber.z + 1)); z++) { if (Main.main.GetBlock(x, y, z) > 0) { if (Main.main.GetBlock(x, y, z) != (int)Material.water) { if (Avaible(x, y + 1, z)) { Face(terrain, Main.main.GetBlock(x, y, z), 0, new Vector3(x, y + 1, z), new Vector3(x + 1, y + 1, z), new Vector3(x, y + 1, z + 1), new Vector3(x + 1, y + 1, z + 1)); } else { Face(terrainCover, Main.main.GetBlock(x, y, z), 0, new Vector3(x, y + 1, z), new Vector3(x + 1, y + 1, z), new Vector3(x, y + 1, z + 1), new Vector3(x + 1, y + 1, z + 1)); } } else { if (Avaible(x, y + 1, z)) { Face(water, Main.main.GetBlock(x, y, z), 0, new Vector3(x, y + 1, z), new Vector3(x + 1, y + 1, z), new Vector3(x, y + 1, z + 1), new Vector3(x + 1, y + 1, z + 1)); } else { Face(waterCover, Main.main.GetBlock(x, y, z), 0, new Vector3(x, y + 1, z), new Vector3(x + 1, y + 1, z), new Vector3(x, y + 1, z + 1), new Vector3(x + 1, y + 1, z + 1)); } } if (Main.main.GetBlock(x, y, z) != (int)Material.water) { if (Avaible(x, y - 1, z)) { Face(terrain, Main.main.GetBlock(x, y, z), 1, new Vector3(x + 1, y, z + 1), new Vector3(x + 1, y, z), new Vector3(x, y, z + 1), new Vector3(x, y, z)); } if (Avaible(x + 1, y, z)) { Face(terrain, Main.main.GetBlock(x, y, z), 2, new Vector3(x + 1, y, z), new Vector3(x + 1, y, z + 1), new Vector3(x + 1, y + 1, z), new Vector3(x + 1, y + 1, z + 1)); } if (Avaible(x - 1, y, z)) { Face(terrain, Main.main.GetBlock(x, y, z), 2, new Vector3(x, y, z + 1), new Vector3(x, y, z), new Vector3(x, y + 1, z + 1), new Vector3(x, y + 1, z)); } if (Avaible(x, y, z - 1)) { Face(terrain, Main.main.GetBlock(x, y, z), 2, new Vector3(x, y, z), new Vector3(x + 1, y, z), new Vector3(x, y + 1, z), new Vector3(x + 1, y + 1, z)); } if (Avaible(x, y, z + 1)) { Face(terrain, Main.main.GetBlock(x, y, z), 2, new Vector3(x + 1, y, z + 1), new Vector3(x, y, z + 1), new Vector3(x + 1, y + 1, z + 1), new Vector3(x, y + 1, z + 1)); } } } } } Mesh temp = new Mesh(); temp.vertices = terrainCover.vertex.ToArray(); temp.uv = terrainCover.uv.ToArray(); temp.triangles = terrainCover.face.ToArray(); Mesh temp2 = new Mesh(); temp2.vertices = waterCover.vertex.ToArray(); temp2.uv = waterCover.uv.ToArray(); temp2.triangles = waterCover.face.ToArray(); levels[y] = new Level(terrain.face.Count, water.face.Count, temp, temp2); } allTerrain = new Mesh(); allTerrain.vertices = terrain.vertex.ToArray(); allTerrain.uv = terrain.uv.ToArray(); allTerrain.triangles = terrain.face.ToArray(); allTerrain.RecalculateNormals(); GetComponent <MeshFilter>().mesh = allTerrain; GetComponent <MeshCollider>().sharedMesh = allTerrain; allWater = new Mesh(); allWater.vertices = water.vertex.ToArray(); allWater.uv = water.uv.ToArray(); allWater.triangles = water.face.ToArray(); allWater.RecalculateNormals(); waterPrefab.GetComponent <MeshFilter>().mesh = allWater; }
public bool TrianglePlaneIntersect(List <Vector3> vertices, List <Vector2> uvs, List <int> triangles, int startIdx, ref Plane plane, TempMesh posMesh, TempMesh negMesh, Vector3[] intersectVectors) { int i; for (i = 0; i < 3; ++i) { t[i] = triangles[startIdx + i]; v[i] = vertices[t[i]]; u[i] = uvs[t[i]]; } // Находится ли вершина на положительной сетке posMesh.ContainsKeys(triangles, startIdx, positive); // Если они все на одной стороне, не пересечения нет if (positive[0] == positive[1] && positive[1] == positive[2]) { // Все точки на одной стороне, пересечения нет // Добавляем их в положительный или отрицательный меш (positive[0] ? posMesh : negMesh).AddOriginalTriangle(t); return(false); } // Поиск одиноой точки int lonelyPoint = 0; if (positive[0] != positive[1]) { lonelyPoint = positive[0] != positive[2] ? 0 : 1; } else { lonelyPoint = 2; } // Устанавливаем предыдущую точку относительно порядка передней грани int prevPoint = lonelyPoint - 1; if (prevPoint == -1) { prevPoint = 2; } // Устанавливаем следующую точку int nextPoint = lonelyPoint + 1; if (nextPoint == 3) { nextPoint = 0; } // Получаем 2 точки пересечения ValueTuple <Vector3, Vector2> newPointPrev = Intersect(plane, v[lonelyPoint], v[prevPoint], u[lonelyPoint], u[prevPoint]); ValueTuple <Vector3, Vector2> newPointNext = Intersect(plane, v[lonelyPoint], v[nextPoint], u[lonelyPoint], u[nextPoint]); // Добавляем новые треугольники и сохраните их в соответствующих буферных мешах (positive[lonelyPoint] ? posMesh : negMesh).AddSlicedTriangle(t[lonelyPoint], newPointNext.Item1, newPointPrev.Item1, newPointNext.Item2, newPointPrev.Item2); (positive[prevPoint] ? posMesh : negMesh).AddSlicedTriangle(t[prevPoint], newPointPrev.Item1, newPointPrev.Item2, t[nextPoint]); (positive[prevPoint] ? posMesh : negMesh).AddSlicedTriangle(t[nextPoint], newPointPrev.Item1, newPointNext.Item1, newPointPrev.Item2, newPointNext.Item2); // Возвращаем ребро, которое будет в правильной ориентации для положительного меша if (positive[lonelyPoint]) { intersectVectors[0] = newPointPrev.Item1; intersectVectors[1] = newPointNext.Item1; } else { intersectVectors[0] = newPointNext.Item1; intersectVectors[1] = newPointPrev.Item1; } return(true); }
bool SliceObject(ref Plane slicePlane, GameObject obj, List <Transform> positiveObjects, List <Transform> negativeObjects) { var mesh = obj.GetComponent <MeshFilter>().mesh; if (!meshCutter.SliceMesh(mesh, ref slicePlane)) { // Put object in the respective list if (slicePlane.GetDistanceToPoint(meshCutter.GetFirstVertex()) >= 0) { positiveObjects.Add(obj.transform); } else { negativeObjects.Add(obj.transform); } return(false); } // TODO: Update center of mass // Silly condition that labels which mesh is bigger to keep the bigger mesh in the original gameobject bool posBigger = meshCutter.PositiveMesh.surfacearea > meshCutter.NegativeMesh.surfacearea; if (posBigger) { biggerMesh = meshCutter.PositiveMesh; smallerMesh = meshCutter.NegativeMesh; } else { biggerMesh = meshCutter.NegativeMesh; smallerMesh = meshCutter.PositiveMesh; } // Create new Sliced object with the other mesh var newObject = Instantiate(obj, objectContainer); spawner.NewFruitCut(newObject); newObject.transform.SetPositionAndRotation(obj.transform.position, obj.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; // Put the bigger mesh in the original object // TODO: Enable collider generation (either the exact mesh or compute smallest enclosing sphere) ReplaceMesh(mesh, biggerMesh); ReplaceMesh(newObjMesh, smallerMesh); (posBigger ? positiveObjects : negativeObjects).Add(obj.transform); (posBigger ? negativeObjects : positiveObjects).Add(newObject.transform); if (obj.layer != /*UI*/ 5) { sController?.AddScore(); } else { uiSliceCount += 1; if (uiSliceCount == 5) { gameStarter.GoToGameMode(); for (int i = 0; i < fruitsChild.transform.childCount; i++) { fruitsChild.transform.GetChild(i).gameObject.SetActive(false); } } } //audio sliceSample.Play(); //slice effect if (fruitSliceEffect != null) { Instantiate(fruitSliceEffect, obj.transform); } obj.tag = "nonSlisable"; newObject.tag = "nonSlisable"; return(true); }
/* * Small diagram for reference :) * | | /| * | | / |P1 * | |/ | * | I1| | * | /| | * y| / | | * | P0/__|___|P2 * | |I2 * | | * |___________________ */ public bool TrianglePlaneIntersect(List <Vector3> vertices, List <Vector2> uvs, List <int> triangles, int startIdx, ref Plane plane, TempMesh posMesh, TempMesh negMesh, Vector3[] intersectVectors) { int i; // Store triangle, vertex and uv from indices for (i = 0; i < 3; ++i) { t[i] = triangles[startIdx + i]; v[i] = vertices[t[i]]; u[i] = uvs[t[i]]; } // Store wether the vertex is on positive mesh posMesh.ContainsKeys(triangles, startIdx, positive); // If they're all on the same side, don't do intersection if (positive[0] == positive[1] && positive[1] == positive[2]) { // All points are on the same side. No intersection // Add them to either positive or negative mesh (positive[0] ? posMesh : negMesh).AddOgTriangle(t); return(false); } // Find lonely point int lonelyPoint = 0; if (positive[0] != positive[1]) { lonelyPoint = positive[0] != positive[2] ? 0 : 1; } else { lonelyPoint = 2; } // Set previous point in relation to front face order int prevPoint = lonelyPoint - 1; if (prevPoint == -1) { prevPoint = 2; } // Set next point in relation to front face order int nextPoint = lonelyPoint + 1; if (nextPoint == 3) { nextPoint = 0; } // Get the 2 intersection points ValueTuple <Vector3, Vector2> newPointPrev = Intersect(plane, v[lonelyPoint], v[prevPoint], u[lonelyPoint], u[prevPoint]); ValueTuple <Vector3, Vector2> newPointNext = Intersect(plane, v[lonelyPoint], v[nextPoint], u[lonelyPoint], u[nextPoint]); //Set the new triangles and store them in respective tempmeshes (positive[lonelyPoint] ? posMesh : negMesh).AddSlicedTriangle(t[lonelyPoint], newPointNext.Item1, newPointPrev.Item1, newPointNext.Item2, newPointPrev.Item2); (positive[prevPoint] ? posMesh : negMesh).AddSlicedTriangle(t[prevPoint], newPointPrev.Item1, newPointPrev.Item2, t[nextPoint]); (positive[prevPoint] ? posMesh : negMesh).AddSlicedTriangle(t[nextPoint], newPointPrev.Item1, newPointNext.Item1, newPointPrev.Item2, newPointNext.Item2); // We return the edge that will be in the correct orientation for the positive side mesh if (positive[lonelyPoint]) { intersectVectors[0] = newPointPrev.Item1; intersectVectors[1] = newPointNext.Item1; } else { intersectVectors[0] = newPointNext.Item1; intersectVectors[1] = newPointPrev.Item1; } return(true); }
void Fracture(Vector2 center) { vec3center = new Vector3(center.x, center.y); print("Generating sites around " + center.ToString("F3")); var sites = VoronoiHelpers.GenerateSites(canvasSize, 30, center); drawSites(sites); var points = new List <VoronoiLib.Structures.FortuneSite>(); foreach (var site in sites) { // move all input points to Quadrant 1 var offsetSite = site; points.Add(new VoronoiLib.Structures.FortuneSite(offsetSite.x, offsetSite.y)); } //FortunesAlgorithm.Run(points, min x, min y, max x, max y) LinkedList <VoronoiLib.Structures.VEdge> cuttingEdges = VoronoiLib.FortunesAlgorithm.Run(points, 0, 0, 800, 800); // HERE !@!@$@!%$@!% var delaunay = VoronoiHelpers.GenerateDelaunay(points); StartCoroutine(DrawVoronoiCoroutine(cuttingEdges)); // StartCoroutine(DrawDelaunayCoroutine(delaunay)); // Make a copy of the original mesh var workingMesh = MeshTools.Clone(mesh); // Disable the orginal mesh // mesh.Clear(); // this.GetComponent<Renderer>().enabled = false; int i = 0; // Sutherland–Hodgman algorithm for slicing concave shapes foreach (var point in points) { // Duplicate the working mesh var piece = MeshTools.Clone(workingMesh); print("Cutting piece " + i + ", " + point.Neighbors.Count + " neighbors."); foreach (var neighbor in point.Neighbors) { // Find the perpendicular bisector and slice var a = new Vector2((float)point.X, (float)point.Y); var b = new Vector2((float)neighbor.X, (float)neighbor.Y); var bisector = VoronoiHelpers.PerpendicularBisector(a, b); // Keep vertices from this side of the bisector line try { TempMesh temp = MeshTools.Cut(piece, bisector, center); MeshTools.ReplaceMesh(mesh, temp); print("SUCCESS"); } catch (UnityException e) { print(e.ToString()); } // Fill the hole // MeshTools.FillHoles(piece); // Now we have the final chunk, save it to a new GameObject // var g = MeshTools.Export(temp, "Piece " + i); // MeshTools.ReplaceMesh(mesh, temp); // break; } // Instantiate(g, g.transform.position, Quaternion.identity); i++; break; } mesh = workingMesh; print("length: " + points.Count); }
/// <summary>Cut mesh along bisector line and keep only the half containing the center point.</summary> public static TempMesh Cut(Mesh mesh, Line bisector, Vector2 center) { var initialArraySize = 256; TempMesh tempMesh = new TempMesh(initialArraySize); TempMesh trashMesh = new TempMesh(initialArraySize); var intersect = new Intersections(); var addedPairs = new List <Vector3>(initialArraySize); var ogVertices = new List <Vector3>(initialArraySize); var ogNormals = new List <Vector3>(initialArraySize); var ogUvs = new List <Vector2>(initialArraySize); var ogTriangles = new List <int>(initialArraySize * 3); var intersectPair = new Vector3[2]; var tempTriangle = new Vector3[3]; // Let's always fill the vertices array so that we can access it even if the mesh didn't intersect mesh.GetVertices(ogVertices); mesh.GetTriangles(ogTriangles, 0); mesh.GetNormals(ogNormals); mesh.GetUVs(0, ogUvs); tempMesh.Clear(); trashMesh.Clear(); for (int i = 0; i < ogVertices.Count; ++i) { var test = bisector.isLeft(ogVertices[i]); // Debug.Log(test); if (test) { tempMesh.AddVertex(ogVertices, ogNormals, ogUvs, i); } else { trashMesh.AddVertex(ogVertices, ogNormals, ogUvs, i); } } Plane slice = bisector.GetPlane(); // 3. Separate triangles and cut those that intersect the plane for (int i = 0; i < ogTriangles.Count; i += 3) { if (intersect.TrianglePlaneIntersect(ogVertices, ogUvs, ogTriangles, i, ref slice, tempMesh, trashMesh, intersectPair)) { addedPairs.AddRange(intersectPair); } } if (addedPairs.Count > 0) { //FillBoundaryGeneral(addedPairs); MeshTools.FillBoundaryFace(tempMesh, addedPairs, ref tempTriangle); return(tempMesh); } else { throw new UnityException("Error: if added pairs is empty, we should have returned false earlier"); } return(tempMesh); }
bool SliceObject(ref Plane slicePlane, GameObject obj, List <Transform> positiveObjects, List <Transform> negativeObjects, bool isPlayer) { var mesh = obj.GetComponent <MeshFilter>().mesh; if (!meshCutter.SliceMesh(mesh, ref slicePlane)) { // Put object in the respective list if (slicePlane.GetDistanceToPoint(meshCutter.GetFirstVertex()) >= 0) { positiveObjects.Add(obj.transform); } else { negativeObjects.Add(obj.transform); } return(false); } // TODO: Update center of mass // Silly condition that labels which mesh is bigger to keep the bigger mesh in the original gameobject bool posBigger = meshCutter.PositiveMesh.surfacearea > meshCutter.NegativeMesh.surfacearea; if (posBigger) { biggerMesh = meshCutter.PositiveMesh; smallerMesh = meshCutter.NegativeMesh; } else { biggerMesh = meshCutter.NegativeMesh; smallerMesh = meshCutter.PositiveMesh; } // Create new Sliced object with the other mesh GameObject newObject = Instantiate(obj, ObjectContainer); newObject.transform.SetPositionAndRotation(obj.transform.position, obj.transform.rotation); var newObjMesh = newObject.GetComponent <MeshFilter>().mesh; //add gravity and disable kinematic to new game object obj.GetComponent <Rigidbody>().useGravity = true; obj.GetComponent <Rigidbody>().isKinematic = false; newObject.layer = 13; obj.layer = 13; //Recalculate box collider Destroy(obj.GetComponent <BoxCollider>()); // obj.AddComponent<MeshCollider>(); // obj.GetComponent<MeshCollider>().convex = true; obj.AddComponent <SphereCollider>(); obj.GetComponent <Rigidbody>().AddForce(isPlayer ? 10f : 0f, gm.cutObjGravityCoefficient * 10f, 0f); //obj.GetComponent<SphereCollider>().isTrigger = true; // obj.GetComponent<SphereCollider>().radius = 0.5f; // obj.GetComponent<SphereCollider>().center = new Vector3(0f,1f,0f); // Put the bigger mesh in the original object // TODO: Enable collider generation (either the exact mesh or compute smallest enclosing sphere) ReplaceMesh(mesh, biggerMesh); ReplaceMesh(newObjMesh, smallerMesh); (posBigger ? positiveObjects : negativeObjects).Add(obj.transform); (posBigger ? negativeObjects : positiveObjects).Add(newObject.transform); return(true); }
public void Dispose() { TempMesh.Free(ref TempMeshes); }