//ホモグラフィの変換行列を取得 public int CreateHomographyMatrix(out Matrix4x4 matrix) { matrix = Matrix4x4.identity; //標本点の数 int count = mPositionList.Count / 2; if (count < 4) { return(2); } //最小二乗法を利用してホモグラフィ変換行列を取得 MatrixNxM a = MatrixNxM.ZeroMatrix(count * 2, 8); MatrixNxM b = MatrixNxM.ZeroMatrix(count * 2, 1); for (int i = 0; i < count; i++) { int index0 = i * 2; int index1 = i * 2 + 1; Vector2 posBefore = mPositionList [i * 2]; Vector2 posAfter = mPositionList [i * 2 + 1]; a.Mat [index0, 0] = posBefore.x; a.Mat [index0, 1] = posBefore.y; a.Mat [index0, 2] = 1.0f; a.Mat [index0, 3] = 0.0f; a.Mat [index0, 4] = 0.0f; a.Mat [index0, 5] = 0.0f; a.Mat [index0, 6] = -posBefore.x * posAfter.x; a.Mat [index0, 7] = -posBefore.y * posAfter.x; a.Mat [index1, 0] = 0.0f; a.Mat [index1, 1] = 0.0f; a.Mat [index1, 2] = 0.0f; a.Mat [index1, 3] = posBefore.x; a.Mat [index1, 4] = posBefore.y; a.Mat [index1, 5] = 1.0f; a.Mat [index1, 6] = -posBefore.x * posAfter.y; a.Mat [index1, 7] = -posBefore.y * posAfter.y; b.Mat [index0, 0] = posAfter.x; b.Mat [index1, 0] = posAfter.y; } MatrixNxM a_inv = a.InverseMatrix(); if (a_inv != null) { MatrixNxM h = a_inv * b; Matrix4x4 homoMat = Matrix4x4.identity; homoMat.m00 = (float)h.Mat [0, 0]; homoMat.m01 = (float)h.Mat [1, 0]; homoMat.m03 = (float)h.Mat [2, 0]; homoMat.m10 = (float)h.Mat [3, 0]; homoMat.m11 = (float)h.Mat [4, 0]; homoMat.m13 = (float)h.Mat [5, 0]; homoMat.m30 = (float)h.Mat [6, 0]; homoMat.m31 = (float)h.Mat [7, 0]; homoMat.m33 = 1.0f; matrix = homoMat; return(0); } else { return(1); } }
//面に貼る三角形のインデックス配列を作成(同一平面上に存在していることが前提) // vertices :頂点の配列 public static int[] CreateIndexTriangles(Vector3[] vertices) { //インデックスを初期化 List <int> sortedIndex = new List <int> (); for (int i = 0; i < vertices.Length; i++) { sortedIndex.Add(i); } //頂点数が規定に達したら終了 List <int> triangles = new List <int> (); while (triangles.Count < (vertices.Length - 2) * 3) { int index0 = 0, index1 = 1, index2 = 2; int count = sortedIndex.Count; for (int i = 0; i < count; i++) { //2辺に接する三角形を選択 index0 = (i - 1 + count) % count; index1 = (i + count) % count; index2 = (i + 1 + count) % count; Vector3 o = vertices [sortedIndex [index1]]; Vector3 oa = vertices [sortedIndex [index0]] - o; Vector3 ob = vertices [sortedIndex [index2]] - o; Vector3 oc = (oa + ob) / 2; { //この三角形が面内部に内包されているものか調べる // 重心と注目した頂点でできる直線上の、交点の数によって判定 // op + s(oq-op) = toc + uN (0f<=s<1f, Nは法線) // op = s(op-oq) + toc + uN // で調べられる int ocount = 0, ccount = 0; for (int j = 0; j < count; j++) { int j0, j1, j2; j0 = (j + count - 1) % count; j1 = (j + count) % count; j2 = (j + count + 1) % count; Vector3 op = vertices [sortedIndex [j1]] - o; Vector3 oq = vertices [sortedIndex [j2]] - o; Vector3 qp = op - oq; Vector3 n = Vector3.Cross(oc, qp); MatrixNxM m = new MatrixNxM(3, 3); m.Mat [0, 0] = qp.x; m.Mat [0, 1] = oc.x; m.Mat [0, 2] = n.x; m.Mat [1, 0] = qp.y; m.Mat [1, 1] = oc.y; m.Mat [1, 2] = n.y; m.Mat [2, 0] = qp.z; m.Mat [2, 1] = oc.z; m.Mat [2, 2] = n.z; MatrixNxM v = new MatrixNxM(3, 1); v.Mat [0, 0] = op.x; v.Mat [1, 0] = op.y; v.Mat [2, 0] = op.z; MatrixNxM m_inv = m.InverseMatrix(); if (m_inv == null) { continue; } MatrixNxM x = m_inv * v; int addCount = 0; float s = (float)x.Mat [0, 0], t = (float)x.Mat [1, 0]; if (s == 0f) { Vector3 d, e; d = vertices [sortedIndex [j0]] - vertices [sortedIndex [j1]]; e = vertices [sortedIndex [j2]] - vertices [sortedIndex [j1]]; if (Vector3.Dot(Vector3.Cross(oc, d), Vector3.Cross(oc, e)) < 0f) { addCount = 1; } else { addCount = 2; } } else if (0f < s && s < 1f) { addCount = 1; } if (t <= 0f) { ocount += addCount; } else { ccount += addCount; } } if ((ocount % 2) * (ccount % 2) == 0) { continue; } } { //三角形内部に他の頂点が存在しないか判定 // soa + tob + uN = op を解く (Nは法線) //三角形の法線ベクトルを作成 Vector3 n = Vector3.Cross(oa, ob); MatrixNxM m = new MatrixNxM(3, 3); m.Mat [0, 0] = oa.x; m.Mat [0, 1] = ob.x; m.Mat [0, 2] = n.x; m.Mat [1, 0] = oa.y; m.Mat [1, 1] = ob.y; m.Mat [1, 2] = n.y; m.Mat [2, 0] = oa.z; m.Mat [2, 1] = ob.z; m.Mat [2, 2] = n.z; MatrixNxM m_inv = m.InverseMatrix(); if (m_inv == null) { continue; } bool isValidTriangle = true; for (int j = 0; j < count; j++) { Vector3 op = vertices [sortedIndex [j]] - o; MatrixNxM v = new MatrixNxM(3, 1); v.Mat [0, 0] = op.x; v.Mat [1, 0] = op.y; v.Mat [2, 0] = op.z; MatrixNxM x = m_inv * v; float s = (float)x.Mat [0, 0], t = (float)x.Mat [1, 0]; if (0f < s && s < 1f) { if (0f < t && t < 1f) { if (0f < s + t && s + t < 1f) { isValidTriangle = false; break; } } } } if (!isValidTriangle) { continue; } } break; } triangles.Add(sortedIndex [index0]); triangles.Add(sortedIndex [index1]); triangles.Add(sortedIndex [index2]); sortedIndex.RemoveAt(index1); } return(triangles.ToArray()); }