/// <summary> /// Places the torn object. /// /// To do this, touch a torn piece from the inventory. /// This should set the inventory state to "PLACING". /// After placing, inventory state should be set to "ROTATING". /// </summary> public void PlaceTornObject(TornObject pickedTornObject, TouchInfo tapInfo) { /*if(tapInfo.touchPos == pickedTornObject.TearableGameObject.rigidbody.position) { //holy shit I don't actually know what this does, good luck }*/ ///TODO: Learn how to get Touch Controller to give me a point ///corresponding to a certain box in the inventory }
/// <summary> /// Cutts the paper object along cutt verts ('tearLine'). /// </summary> private void FindNewCutPieces() { //The following initialize the storages holding the new vertices and faces for the two new citt paper objects CuttPieceOneVerts = Clone.GetComponent<MeshFilter>().mesh.vertices; CuttPieceTwoVerts = Clone_2.GetComponent<MeshFilter>().mesh.vertices; CuttPieceOneFaces = Clone.GetComponent<MeshFilter>().mesh.triangles; CuttPieceTwoFaces = Clone_2.GetComponent<MeshFilter>().mesh.triangles; //First, we update the paperGrid_1 DICT for determining whether a vertex has been hit be the user input for(int itor = 0; itor < CuttPieceOneVerts.Length; itor++) { if(tearLine.ContainsKey(CuttPieceOneVerts[itor])) { paperGrid_1[new Vector2(CuttPieceOneVerts[itor].y, CuttPieceOneVerts[itor].x)] = true; } else { paperGrid_1[new Vector2(CuttPieceOneVerts[itor].y, CuttPieceOneVerts[itor].x)] = false; } } /* // //Now we know which verticies are selected and how to distinguish both islands thanks to // the organized paper vert grid found previously // */ //Now, we create two lists of verticies to determine which vertices belong to which 'island' island1 = new List<Vector2>(); island2 = new List<Vector2>(); //The following is used to switch in between both new meshes for data transfer after cutt/tear addingToPieceOne = true; //This flags is we are currently at a tear vertice to add to both islands bool currentlyInTransition = false; //This is used for testing, printing the number of torn vertices being created int numEdgeTearVerts = 0; //This points to the vertex in the current row where the tear section begins int startingVertIndice = 0; //We looop through the sorted paperGrid to create two new mesh based of tearLine for(int iterator = 0; iterator < paperGrid.Values.Count; iterator++)//each(List<Vector3> tempList in paperGrid.Values) { //This is used for correctly assigning the beginning and ending tear sections of a tear region within //the currect row being raversed. bool haveHitTearLine = false; //This represents the tear vertex's position at the beginning of the current row's tear region //This is the first one hit Vector3 startTearPos = Vector3.zero; //This represents the tear vertex's position at the end of the current row's tear region //This is the last one hit ebfore another non-torn vertex is reached in the current row Vector3 endTearPos = Vector3.zero; //This is triggered true once we reach the end of one of the current row's tear regions, // this is when the critical decision is made, deciding which island to add to next for the next // non- torn vertex within the current row bool readyToDeterminShape = false; /* // //First we see if the begginning of the current row is a NON torn vertex and the beggginning //of the last row IS a torn vertex // */ //We make sure we are already past the first row because the following logic //is dependent upon the last row looked at if(iterator - 1 >= 0) { //If the current row's first vertex is not torn and the last row's first vertex is torn if (!tearLine.ContainsKey(paperGrid.Values.ElementAt(iterator)[0]) && tearLine.ContainsKey(paperGrid.Values.ElementAt(iterator - 1)[0])) { //We increase the numEdgeTearVerts to keep track of which island we are adding to when //the first row's veretex IS NOT a torn vertex numEdgeTearVerts++; } } //Now we change which island we are adding to, rotating between each one if(numEdgeTearVerts % 2 == 0) { addingToPieceOne = true; } else if(numEdgeTearVerts % 2 == 1) { addingToPieceOne = false; } //Iterate through every single value in the current row being observed for(int jtor = 0; jtor < paperGrid.Values.ElementAt(iterator).Count; jtor++) { /* // //Now, we need to remember the starting and ending vertices // in each of the current row's torn regions, this allows us // to accuratly find the incoming and outgoing directions of // the tear curve to then determine if we are rotating which // island we are adding to in the current row // */ //if the current vertex being looked at is a tear vertex and we have not hit one of the tear // region within the current row yet. if(tearLine.ContainsKey(paperGrid.Values.ElementAt(iterator)[jtor]) && !haveHitTearLine) { //Set flag to true, for proper assignment of ending poisiton in the current row's tear region haveHitTearLine = true; //Assign the starting position of the current row's tear region being traversed. startTearPos = paperGrid.Values.ElementAt(iterator)[jtor]; //This is a pointer to the row's list stored within the dictionary for proper direction of curve calculation startingVertIndice = jtor; //This is flagged to false because we are not yet ready to make the decision of which island to transition to readyToDeterminShape = false; //Testing printing //Debug.LogWarning("Current vert = " + paperGrid.Values.ElementAt(iterator)[jtor].ToString() + " has hit tearvert in row = " + iterator.ToString()); } //If we have started a tear region if(haveHitTearLine) { //If we are not at the last position in the row AND //If the next vertex in row in not torn, then we know // we have finally hit the end of one of the current row's // tear regions if((jtor + 1) < paperGrid.Values.ElementAt(iterator).Count && !tearLine.ContainsKey(paperGrid.Values.ElementAt(iterator)[jtor + 1])) { //This is set to false for triggering true for the possibility of the current //row containing another torn vertice region haveHitTearLine = false; //Flag we are now ready to make a decision based on incoming and outgoing direction //of curve about this tear region readyToDeterminShape = true; } //Assign the end position in the current row's tear region to be the current vertex //because we know that the next vertex in the row is not torn endTearPos = paperGrid.Values.ElementAt(iterator)[jtor]; } /* // //Now, at this point, we are ready to determine the incoming and outgoing //directions of the curve about one of the current row's tear regions // */ //In the following, the x==y and y==x already, these components have already been switched TraverseGridAddToNewPiece(paperGrid.Values.ElementAt(iterator)[jtor], new Vector2(paperGrid.Values.ElementAt(iterator)[jtor].y, paperGrid.Values.ElementAt(iterator)[jtor].x), currentlyInTransition, jtor, paperGrid.Values.ElementAt(iterator), startTearPos, endTearPos, readyToDeterminShape, startingVertIndice); } } //Make the second clone visible Clone_2.GetComponent<MeshRenderer>().enabled = true; //Initialize the length of each new triangle storage for the new objects faces island1Indicies = new int[CuttPieceOneFaces.Length]; island2Indicies = new int[CuttPieceTwoFaces.Length]; //This is used to properly index the above new triangle face data for the // two new objects after tear indexor1 = 0; indexor2 = 0; /* // //Now we have the associates vertices stored within island1 and island 2 //We can now determine the new faces for each mesh by FIRST finding the indices for each vertice // */ //Loop through every single face in the originial object to determine // which new faces belong on which island based of the vertex seperation // logic performed above for(int itor = 0; itor < CuttPieceOneFaces.Length; itor += 3) { //The following is used to add a specific face to one island or the other CreatNewCuttPaperMeshPieces(itor); } /* Vector3[] newIsland1 = new Vector3[island1.Count()]; Vector3[] newIsland2 = new Vector3[island2.Count()]; int indexIsland1 = 0; int indexIsland2 = 0; for(int itor = 0; itor < Clone.GetComponent<MeshFilter>().mesh.vertices.Count(); ++itor) { if(island1.Contains(new Vector2(Clone.GetComponent<MeshFilter>().mesh.vertices[itor].x, Clone.GetComponent<MeshFilter>().mesh.vertices[itor].y))) { Debug.LogError("test 1"); newIsland1[indexIsland1] = Clone.GetComponent<MeshFilter>().mesh.vertices[itor]; ++indexIsland1; } if(island2.Contains(new Vector2(Clone.GetComponent<MeshFilter>().mesh.vertices[itor].x, Clone.GetComponent<MeshFilter>().mesh.vertices[itor].y))) { Debug.LogError("test 2"); newIsland2[indexIsland2] = Clone.GetComponent<MeshFilter>().mesh.vertices[itor];//new Vector3(island1.ElementAt(itor1).y, island2.ElementAt(itor1).x, 0); ++indexIsland2; } } int[] newIsland1indicies = island1Indicies; int inderIsland1 = 0; int[] newIsland2indicies = island2Indicies; int inderIsland2 = 0; for(int finder = 0; finder < island1Indicies.Length; finder += 1) { for(int finder2 = 0; finder2 < newIsland1.Length; finder2++) { if(Clone.GetComponent<MeshFilter>().mesh.vertices[island1Indicies[finder]] == newIsland1[finder2]) { newIsland1indicies[inderIsland1] = finder; ++inderIsland1; } } } island1Indicies = newIsland1indicies; Mesh newMesh1 = Clone.GetComponent<MeshFilter>().mesh; Mesh newMesh2 = Clone_2.GetComponent<MeshFilter>().mesh; newMesh1.Clear(); newMesh2.Clear(); newMesh1.vertices = newIsland1; newMesh2.vertices = newIsland2; newMesh1.triangles = island1Indicies; newMesh2.triangles = island2Indicies; newMesh1.RecalculateBounds(); newMesh1.RecalculateNormals(); newMesh2.RecalculateBounds(); newMesh2.RecalculateNormals(); Clone.GetComponent<MeshFilter>().mesh = newMesh1; Clone_2.GetComponent<MeshFilter>().mesh = newMesh2; */ //Reassign new mesh triangles, defining the new faces for the cloned object List<int> newIsland1indTempList = new List<int>(); int numOfvertsIsland1 = 0; bool haveStarted = false; for(int itor = island1Indicies.Count() - 1; itor > -1; --itor) { if(island1Indicies[itor] != 0 || haveStarted) { haveStarted = true; newIsland1indTempList.Add(island1Indicies[itor]); ++numOfvertsIsland1; } } int[] newIsland1Ind = new int[numOfvertsIsland1]; int indexer = 0; for(int itor = newIsland1indTempList.Count() - 1; itor > -1; --itor) { newIsland1Ind[indexer] = newIsland1indTempList[itor]; ++indexer; } island1Indicies = newIsland1Ind; List<int> newIsland2indTempList = new List<int>(); int numOfvertsIsland2 = 0; bool haveStarted2 = false; for(int itor = island2Indicies.Count() - 1; itor > -1; --itor) { if(island2Indicies[itor] != 0 || haveStarted2) { haveStarted2 = true; newIsland2indTempList.Add(island2Indicies[itor]); ++numOfvertsIsland2; } } int[] newIsland2Ind = new int[numOfvertsIsland2]; int indexer2 = 0; for(int itor = newIsland2indTempList.Count() - 1; itor > -1; --itor) { newIsland2Ind[indexer2] = newIsland2indTempList[itor]; ++indexer2; } island2Indicies = newIsland2Ind; Clone.GetComponent<MeshFilter>().mesh.triangles = island1Indicies; Clone_2.GetComponent<MeshFilter>().mesh.triangles = island2Indicies; /* Clone.GetComponent<MeshFilter>().mesh.RecalculateBounds(); Clone.GetComponent<MeshFilter>().mesh.RecalculateNormals(); Clone_2.GetComponent<MeshFilter>().mesh.RecalculateBounds(); Clone_2.GetComponent<MeshFilter>().mesh.RecalculateNormals(); */ /* Clone.GetComponent<MeshFilter>().mesh.vertices = newIsland2; Clone.GetComponent<MeshFilter>().mesh.RecalculateBounds(); Clone.GetComponent<MeshFilter>().mesh.RecalculateNormals(); Clone_2.GetComponent<MeshFilter>().mesh.vertices = newIsland1; Clone_2.GetComponent<MeshFilter>().mesh.RecalculateBounds(); Clone_2.GetComponent<MeshFilter>().mesh.RecalculateNormals(); Clone.GetComponent<MeshFilter>().mesh.triangles = island1Indicies; Clone_2.GetComponent<MeshFilter>().mesh.triangles = island2Indicies; */ //Update the clone's mesh collider Clone.GetComponent<MeshCollider>().sharedMesh = Clone.GetComponent<MeshFilter>().mesh; Clone_2.GetComponent<MeshCollider>().sharedMesh = Clone_2.GetComponent<MeshFilter>().mesh; //Rename the object based on the number of faces in each of the new meshs if(island2.Count > island1.Count) { //Assign pointer towards object currently being moved and rotated by player CurrentCuttPiece = Clone_2; //Now move the piece being moved up a layer Clone_2.transform.position = new Vector3(Clone_2.transform.position.x, Clone_2.transform.position.y, Clone_2.transform.position.z + 0.001f); //Now we add the new clones to list of tearbleObjects TornObject newTornPiece = new TornObject(Clone_2, Clone_2.GetComponent<MeshFilter>().mesh, MESH_VERT_OFFSET, false); //GameObject.FindGameObjectWithTag("TearManager").GetComponent<TearObject>(). TearableObjects.Add (newTornPiece); TornObject newTornPiece2 = new TornObject(Clone, Clone.GetComponent<MeshFilter>().mesh, MESH_VERT_OFFSET, true); TearableObjects.Add (newTornPiece2); Clone_2.name = "paper_CuttPieceOfPaper"; Clone.name = "paper_LargerPiece"; Clone_2.GetComponent<MeshRenderer>().material.color = Color.green; } else { //Assign pointer towards object currently being moved and rotated by player CurrentCuttPiece = Clone; //Now move the piece being moved up a layer Clone.transform.position = new Vector3(Clone.transform.position.x, Clone.transform.position.y, Clone.transform.position.z + 0.001f); //Now we add the new clones to list of tearbleObjects TornObject newTornPiece = new TornObject(Clone, Clone.GetComponent<MeshFilter>().mesh, MESH_VERT_OFFSET, false); //GameObject.FindGameObjectWithTag("TearManager").GetComponent<TearObject>(). TearableObjects.Add (newTornPiece); TornObject newTornPiece2 = new TornObject(Clone_2, Clone_2.GetComponent<MeshFilter>().mesh, MESH_VERT_OFFSET, true); TearableObjects.Add (newTornPiece2); Clone.name = "paper_CuttPieceOfPaper"; Clone_2.name = "paper_LargerPiece"; Clone.GetComponent<MeshRenderer>().material.color = Color.green; } //Turn true to flag that we are now done calculating the cut line doneCalculatingCuttLine = false; }
/// <summary> /// Updates the piece of paper original piece of paper /// </summary> private void Update_PieceOfPaper(TornObject to) { if(doneCalculatingCuttLine) { Debug.LogError("done calculating tear original"); //This flag is for testing purposes only, //this flag is intented to be enabled from within unity to visuall debug and test tear line if(DrawTearLineONLY) { DrawTearLineOnly(); } else { //This is used to parse through the mesh to determine which vertices and faces //belong to which cut piece FindNewCutPieces(); //Assign flag for moving cutt piece currentlyMovingCuttPiece = true; //Assign varaibles for moving piece screenPoint = Camera.main.WorldToScreenPoint(CurrentCuttPiece.transform.position); offset = CurrentCuttPiece.transform.position - Camera.main.ScreenToWorldPoint( new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)); //Now we set the center of the cuttObject, used for rotation centerOfCuttPieceRotOffset = FindCenterOfCuttPiece(); } } else if (currentlyMovingCuttPiece) { //Here the cuttPiece needs to be translated where ever the player desires MoveCuttPiceToDesiredLocation(); } //The OnMouse functions are only called when mouse collides with an objects collider, //The following if(Input.GetMouseButtonDown(0) && PlayerTouchingDeadSpace() && !cuttInProgress)//PlayerTouchingDeadSpace() PlayerTouchingOffPaper() { //Debug.LogWarning("Updateing, Left Mouse DRAG"); cuttInProgress = true; playerHasTouchedPaperThisTear = false; forceStopTear = false; OnMouseDown(); } if(Input.GetMouseButton(0) && !forceStopTear && cuttInProgress)// && !PlayerTouchingDeadSpace()) { //Debug.LogWarning("Updateing, Left Mouse DOWN"); OnMouseDrag(); if(PlayerTouchingPaper()) { playerHasTouchedPaperThisTear = true; } if(playerHasTouchedPaperThisTear && PlayerTouchingDeadSpace())//PlayerTouchingDeadSpace() PlayerTouchingOffPaper() { playerHasTouchedPaperThisTear = false; forceStopTear = true; } } if((Input.GetMouseButtonUp(0)&& PlayerTouchingDeadSpace() && cuttInProgress) || forceStopTear)//PlayerTouchingDeadSpace() PlayerTouchingOffPaper() { //The following prevents mouseUp from being called if the player just cutts the dead space if(forceStopTear || playerHasTouchedPaperThisTear) { OnMouseUp(); } } else if(Input.GetMouseButtonUp(0)&& !PlayerTouchingDeadSpace()&& cuttInProgress) { Debug.LogError("REFRESHING MOUSE TEAR POSITIONS"); mouseTearPositions = new List<Vector3>(); mousePrevPos = Input.mousePosition; //Flag we are done finding cutt/tear line doneCalculatingCuttLine = false; cuttInProgress = false; gapPosiitons = null; } }
/// <summary> /// Creates the new paper world clone and hides the original mesh renderer /// This function also sets flags handling which object is being manipulated /// </summary> private void CreateNewPaperWorld() { //Assign the clone to be the new instance Clone = (GameObject) Instantiate(newPaper, newPaper.transform.position, newPaper.transform.rotation); Clone_2 = (GameObject) Instantiate(newPaper, newPaper.transform.position, newPaper.transform.rotation); Clone_2.GetComponent<TearPaper>().CloneObject = true; Clone_2.GetComponent<MeshRenderer>().enabled = false; //Turn off the original object's meshRenderer to hide newPaper.GetComponent<MeshRenderer>().enabled = false; //Set flag true to start deformations Clone.GetComponent<TearPaper>().CloneObject = true; //Loop through list storing any gameobject that can be torn foreach(GameObject go in ObjectsThatCanBeTorn) { //Create and determine mesh offset float newMeshOffset = 0; if(go.GetComponent<MeshFilter>().mesh.vertices.ElementAt(0).x != go.GetComponent<MeshFilter>().mesh.vertices.ElementAt(1).x) { newMeshOffset = go.GetComponent<MeshFilter>().mesh.vertices.ElementAt(0).x - go.GetComponent<MeshFilter>().mesh.vertices.ElementAt(1).x; if(newMeshOffset < 0) newMeshOffset *= -1; } else { newMeshOffset = go.GetComponent<MeshFilter>().mesh.vertices.ElementAt(0).y - go.GetComponent<MeshFilter>().mesh.vertices.ElementAt(1).y; if(newMeshOffset < 0) newMeshOffset *= -1; } //Now create new tearableObject TornObject newTearableObject = new TornObject(go, go.GetComponent<MeshFilter>().mesh, newMeshOffset, false); //Now add the object to tearableObjetsList for correctly updating tear TearableObjects.Add (newTearableObject); } }
/// <summary> /// Turns the input into torn vert curve on tear object, not dependent upon /// the player touching the deadSpace first /// </summary> private void TurnInputIntoTornVertCurveOnTearObject(TornObject tornPiece) { Vector3 screenDepth = Camera.main.WorldToScreenPoint(mesh.vertices[0]);//Clone.GetComponent<MeshFilter>() List<Vector3> newMouseTearWorldPos = new List<Vector3>(); //First the mouseTearPositions needs to be translated into world positions for(int indexr = 0; indexr < mouseTearPositions.Count - 1; indexr++) { Vector3 curPosition = Camera.main.ScreenToWorldPoint( new Vector3(mouseTearPositions[indexr].x, mouseTearPositions[indexr].y, screenDepth.z)); newMouseTearWorldPos.Add (curPosition); } mouseTearPositions = newMouseTearWorldPos; Vector3 previousTornVert = Clone.GetComponent<MeshFilter>().mesh.vertices[0];//Clone.GetComponent<MeshFilter>(). int numberOfVerts = 0; Vector3 previousMousePos = mouseTearPositions.ElementAt(0); //foreach(Vector3 mousePos in mouseTearPositions) for(int jtor = 0; jtor < mouseTearPositions.Count - 1; jtor++) { //Find change in position of the mouse float mouseMoveDistX = mouseTearPositions[jtor].x - previousMousePos.x; float mouseMoveDistY = mouseTearPositions[jtor].y - previousMousePos.y; if(mouseMoveDistX < 0) mouseMoveDistX *= -1; if(mouseMoveDistY < 0) mouseMoveDistY *= -1; //for(int jtor = 0; jtor < //If jtor == 0, we are at an edge, so we forsure add, else we only add every time // the mouse has moved the distance inbetween any two adjacent vertices on paper mesh if(jtor == 0 || mouseMoveDistX > (MESH_VERT_OFFSET * 1/3) || mouseMoveDistY > (MESH_VERT_OFFSET * 1/3)) { //Debug.LogWarning("Mouse Has Moved the offset amount to add new vert"); //Now, we know here we need to find the vert closest to the mouse position to add to the // tearLine float distToClosestRow = MESH_VERT_OFFSET * 20; int rowNum = 0; //First, loop through grid to find row with closest y-component for(int itor = 0; itor < paperGrid.Keys.Count; itor++) { float tempDist = paperGrid.Keys.ElementAt(itor) - mouseTearPositions[jtor].y; if(tempDist < 0) tempDist *= -1; if(tempDist < distToClosestRow) { distToClosestRow = tempDist; rowNum = itor; } } float distToClosestCol = MESH_VERT_OFFSET * 20; int colomnNum = 0; //Now, we loop through grid to find vert in colomn with closest x-component //Debug.LogWarning("Row Number = " + rowNum.ToString()); for(int ktor = 0; ktor < paperGrid[paperGrid.Keys.ElementAt(rowNum)].Count; ktor++)//paperGrid[paperGrid.Keys.ElementAt(rowNum)] { float tempDist2 = paperGrid[paperGrid.Keys.ElementAt(rowNum)][ktor].x - mouseTearPositions.ElementAt(jtor).x; if(tempDist2 < 0) tempDist2 *= -1; if(tempDist2 < distToClosestCol) { distToClosestCol = tempDist2; colomnNum = ktor; } } //Now rowNum and Colomn Num point to the new tornVert, so we add to tearLine list if(!tearLine.ContainsKey(paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum])) { tearLineTimer++; numberOfVerts++; //THE FOLLOWING NEEDS OPTIMIZATION, here we need to add the indice of the new torn vertice into tearline, // therefore the quickest, but slowest solution is to iterate through all mesh verts.... int meshIndex = -1; for(int gtor = 0; gtor < mesh.vertices.Length; gtor++) { if(mesh.vertices.ElementAt(gtor) == paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum]) { meshIndex = gtor; break; } } tearLine.Add(paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum], meshIndex); paperGrid_1[paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum]] = true; //This maps a 'time' to the tear vertice tearLineTime.Add (paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum], (float)tearLineTimer); tearLinePositionTime.Add ((float)tearLineTimer, paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum]); previousTornVert = paperGrid[paperGrid.Keys.ElementAt(rowNum)][colomnNum]; } //Set previous the the position we just looked at previousMousePos = mouseTearPositions.ElementAt(jtor); } } }