// Start is called before the first frame update void Start() { addPointButton.onClick.AddListener(SetAddPointState); themesh = GetComponent <MeshFilter>().sharedMesh; triangles = themesh.triangles; meshvertices = themesh.vertices; arapTris = new ARAPTriangle[triangles.Length / 3]; reorderVerID = new int[meshvertices.Length]; mvConstraint = new List <int>(); mvDeformed = meshvertices; ///precompute variables for (int i = 0; i < triangles.Length / 3; i++) { ARAPTriangle t = new ARAPTriangle(); Vector3 v0 = meshvertices[triangles[i * 3]]; Vector3 v1 = meshvertices[triangles[i * 3 + 1]]; Vector3 v2 = meshvertices[triangles[i * 3 + 2]]; var v2local = ARAPOperation.FindLocalCoordinator(v0, v1, v2); var v0local = ARAPOperation.FindLocalCoordinator(v1, v2, v0); var v1local = ARAPOperation.FindLocalCoordinator(v2, v0, v1); t.SetLocalXY(v0local, v1local, v2local); t.SetVertexID(triangles[i * 3], triangles[i * 3 + 1], triangles[i * 3 + 2]); t.scale_factor_divisor = Vector3.Dot(v1 - v0, v1 - v0); t.PreComputeScaleAdjustmentMatrixFC(); arapTris[i] = t; } drawTris = new List <Vector3>(); for (int i = 0; i < triangles.Length / 3; i++) { drawTris.Add(mvDeformed[triangles[i * 3]]); drawTris.Add(mvDeformed[triangles[i * 3 + 1]]); drawTris.Add(mvDeformed[triangles[i * 3 + 2]]); } }
public static Vector3[] AdjustScaleToTriangle(ARAPTriangle thetriangle, Vector3[] mDrformedVertex) { Matrix triangle_points_coords = Matrix.ZeroMatrix(6, 1); for (int i = 0; i < 3; i++) { int vid = thetriangle.vertex_id[i]; triangle_points_coords[i * 2, 0] = mDrformedVertex[vid].x; triangle_points_coords[i * 2 + 1, 0] = mDrformedVertex[vid].y; } Matrix theF = thetriangle.mF; Matrix theC = thetriangle.mC; Matrix vfittedcoords = -1 * theF * theC * triangle_points_coords; Vector3 v0f = new Vector3((float)vfittedcoords[0, 0], (float)vfittedcoords[1, 0], 0); Vector3 v1f = new Vector3((float)vfittedcoords[2, 0], (float)vfittedcoords[3, 0], 0); float x01 = thetriangle.local_xy[2].x; float y01 = thetriangle.local_xy[2].y; Vector3 v01 = v1f - v0f; Vector3 v01R90 = Quaternion.AngleAxis(90, Vector3.forward) * (v01); Vector3 v2f = v0f + x01 * (v01) + y01 * v01R90; Vector3[] updateTriPoints = new Vector3[3]; updateTriPoints[0] = v0f; updateTriPoints[1] = v1f; updateTriPoints[2] = v2f; Vector3 centermass = (v0f + v1f + v2f) / 3; float sf = Mathf.Sqrt(thetriangle.scale_factor_divisor / Vector3.Dot(v01, v01)); for (int i = 0; i < 3; i++) { updateTriPoints[i] -= centermass; updateTriPoints[i] *= sf; updateTriPoints[i] += centermass; } return(updateTriPoints); }
void MeshDeform() { int nConstaint = mvConstraint.Count; if (mvConstraint.Count > 1) { Matrix vq = new Matrix(2 * nConstaint, 1); for (int i = 0; i < nConstaint; i++) { vq[2 * i, 0] = mvDeformed[mvConstraint[i]].x; vq[2 * i + 1, 0] = mvDeformed[mvConstraint[i]].y; } //step1 deform var vu = scaleFreeMatrix * vq; int nVerts = meshvertices.Length; for (int i = 0; i < nVerts; i++) { if (mvConstraint.IndexOf(i) != -1) { continue; } int nRow = reorderVerID[i]; double fx = vu[2 * nRow, 0]; double fy = vu[2 * nRow + 1, 0]; mvDeformed[i] = new Vector3((float)fx, (float)fy, 0); } //step 2.1 float[] f = new float[2 * meshvertices.Length]; for (int i = 0; i < triangles.Length / 3; i++) { ARAPTriangle thetri = arapTris[i]; Vector3[] updatedTris = ARAPOperation.AdjustScaleToTriangle(thetri, mvDeformed); for (int j = 0; j < 3; j++) { var v0f = updatedTris[j]; var v1f = updatedTris[(j + 1) % 3]; int v0f_id = reorderVerID[thetri.vertex_id[j]]; int v1f_id = reorderVerID[thetri.vertex_id[(j + 1) % 3]]; f[2 * v0f_id] += -2 * v0f.x + 2 * v1f.x; f[2 * v0f_id + 1] += -2 * v0f.y + 2 * v1f.y; f[2 * v1f_id] += 2 * v0f.x - 2 * v1f.x; f[2 * v1f_id + 1] += 2 * v0f.y - 2 * v1f.y; } } //step2.2 int nFreeVerts = nVerts - nConstaint; Debug.Log(f[2 * nFreeVerts - 1]); Debug.Log(f[2 * nFreeVerts]); Matrix f0 = Matrix.ZeroMatrix(2 * nFreeVerts, 1); for (int i = 0; i < 2 * nFreeVerts; i++) { f0[i, 0] = f[i]; } for (int i = 0; i < nConstaint; i++) { vq[2 * i, 0] = mvDeformed[mvConstraint[i]].x; vq[2 * i + 1, 0] = mvDeformed[mvConstraint[i]].y; } Matrix mb = -1 * (mHandmD[1] * vq + f0); Matrix mu = mHandmD[0].SolveWith(mb); for (int i = 0; i < nVerts; i++) { if (mvConstraint.IndexOf(i) != -1) { continue; } int nRow = reorderVerID[i]; double fx = mu[2 * nRow, 0]; double fy = mu[2 * nRow + 1, 0]; mvDeformed[i] = new Vector3((float)fx, (float)fy, 0); } drawTris = new List <Vector3>(); for (int i = 0; i < triangles.Length / 3; i++) { drawTris.Add(mvDeformed[triangles[i * 3]]); drawTris.Add(mvDeformed[triangles[i * 3 + 1]]); drawTris.Add(mvDeformed[triangles[i * 3 + 2]]); } } }
//call every time add constraint point public static Matrix UpdateConstraint(int ninitialVer, int nContraint, int[] mVertexMap, ARAPTriangle[] triangles) { Matrix mFirstMatrix = Matrix.ZeroMatrix(1, 1); //matrix computation int nfreeVec = ninitialVer - nContraint; if (nContraint > 1) { Matrix mG = Matrix.ZeroMatrix(2 * ninitialVer, 2 * ninitialVer); for (int i = 0; i < triangles.Length; i++) { ARAPTriangle tris = triangles[i]; for (int j = 0; j < 3; j++) { int v0_id = mVertexMap[tris.vertex_id[j]]; int v1_id = mVertexMap[tris.vertex_id[(j + 1) % 3]]; int v2_id = mVertexMap[tris.vertex_id[(j + 2) % 3]]; float x01 = tris.local_xy[(j + 2) % 3].x; float y01 = tris.local_xy[(j + 2) % 3].y; mG[2 * v0_id, 2 * v0_id] += Mathf.Pow(x01, 2) - 2 * x01 + Mathf.Pow(y01, 2) + 1; mG[2 * v0_id, 2 * v0_id + 1] = 0 / 2; mG[2 * v0_id + 1, 2 * v0_id] += 0; mG[2 * v0_id, 2 * v1_id] += (1 - x01) * x01 - Mathf.Pow(y01, 2); mG[2 * v1_id, 2 * v0_id] += (1 - x01) * x01 - Mathf.Pow(y01, 2); mG[2 * v0_id, 2 * v1_id + 1] += -y01; mG[2 * v1_id + 1, 2 * v0_id] += -y01; mG[2 * v0_id, 2 * v2_id] += -(1 - x01); mG[2 * v2_id, 2 * v0_id] += -(1 - x01); mG[2 * v0_id, 2 * v2_id + 1] += y01; mG[2 * v2_id + 1, 2 * v0_id] += y01; mG[2 * v0_id + 1, 2 * v0_id + 1] += Mathf.Pow(x01, 2) - 2 * x01 + Mathf.Pow(y01, 2) + 1; mG[2 * v0_id + 1, 2 * v1_id] += y01; mG[2 * v1_id, 2 * v0_id + 1] += y01; mG[2 * v0_id + 1, 2 * v1_id + 1] += x01 - x01 * x01 - y01 * y01; mG[2 * v1_id + 1, 2 * v0_id + 1] += x01 - x01 * x01 - y01 * y01; mG[2 * v0_id + 1, 2 * v2_id] += -y01; mG[2 * v2_id, 2 * v0_id + 1] += -y01; mG[2 * v0_id + 1, 2 * v2_id + 1] += -1 + x01; mG[2 * v2_id + 1, 2 * v0_id + 1] += -1 + x01; mG[2 * v1_id, 2 * v1_id] += Mathf.Pow(x01, 2) + Mathf.Pow(y01, 2); mG[2 * v1_id, 2 * v1_id + 1] += 0 / 2; mG[2 * v1_id + 1, 2 * v1_id] += 0 / 2; mG[2 * v1_id, 2 * v2_id] += -x01; mG[2 * v2_id, 2 * v1_id] += -x01; mG[2 * v1_id, 2 * v2_id + 1] += -y01; mG[2 * v2_id + 1, 2 * v1_id] += -y01; mG[2 * v1_id + 1, 2 * v1_id + 1] += Mathf.Pow(x01, 2) + Mathf.Pow(y01, 2); mG[2 * v1_id + 1, 2 * v2_id] += y01; mG[2 * v2_id, 2 * v1_id + 1] += y01; mG[2 * v1_id + 1, 2 * v2_id + 1] += -x01; mG[2 * v2_id + 1, 2 * v1_id + 1] += -x01; mG[2 * v2_id, 2 * v2_id] += 1; mG[2 * v2_id, 2 * v2_id + 1] += 0; mG[2 * v2_id + 1, 2 * v2_id] += 0; mG[2 * v2_id + 1, 2 * v2_id + 1] += 1; } } Matrix mG00 = mG.SubMatrix(0, 0, 2 * nfreeVec, 2 * nfreeVec); Matrix mG01 = mG.SubMatrix(0, 2 * nfreeVec, 2 * nfreeVec, 2 * nContraint); Matrix mG10 = mG.SubMatrix(2 * nfreeVec, 0, 2 * nContraint, 2 * nfreeVec); Matrix mGprime = mG00 + Matrix.Transpose(mG00); Matrix mB = mG01 + Matrix.Transpose(mG10); Matrix mGprimeInverse = mGprime.Invert(); mFirstMatrix = -1 * mGprimeInverse * mB; } return(mFirstMatrix); }