public static void DrawSceneGUIMouseOver(SkinAttachmentTarget driver) { var mouseScreen = Event.current.mousePosition; var mouseWorldRay = HandleUtility.GUIPointToWorldRay(mouseScreen); var objectRayPos = driver.transform.InverseTransformPoint(mouseWorldRay.origin); var objectRayDir = driver.transform.InverseTransformDirection(mouseWorldRay.direction); var meshInfo = driver.GetCachedMeshInfo(); if (meshInfo.valid == false) { return; } var vertex = meshInfo.meshVertexBSP.RaycastApprox(ref objectRayPos, ref objectRayDir, 10); if (vertex == -1) { return; } using (var scope = new Handles.DrawingScope(Color.blue, driver.transform.localToWorldMatrix)) { const int maxDepth = 3; var triangleColor = Handles.color; var triangleDepth = 0; using (var triangleBFS = new UnsafeBFS(meshInfo.meshAdjacency.triangleCount)) { foreach (var triangle in meshInfo.meshAdjacency.vertexTriangles[vertex]) { triangleBFS.Insert(triangle); } while (triangleBFS.MoveNext() && triangleBFS.depth < maxDepth) { if (triangleDepth < triangleBFS.depth) { triangleDepth = triangleBFS.depth; Handles.color = Color.Lerp(triangleColor, Color.clear, Mathf.InverseLerp(0, maxDepth, triangleDepth)); } var _e = meshInfo.meshAdjacency.triangleVertices[triangleBFS.position].GetEnumerator(); int v0 = _e.ReadNext(); int v1 = _e.ReadNext(); int v2 = _e.ReadNext(); Handles.DrawLine(meshInfo.meshBuffers.vertexPositions[v0], meshInfo.meshBuffers.vertexPositions[v1]); Handles.DrawLine(meshInfo.meshBuffers.vertexPositions[v1], meshInfo.meshBuffers.vertexPositions[v2]); Handles.DrawLine(meshInfo.meshBuffers.vertexPositions[v2], meshInfo.meshBuffers.vertexPositions[v0]); foreach (var triangle in meshInfo.meshAdjacency.triangleTriangles[triangleBFS.position]) { triangleBFS.Insert(triangle); } } } } }
public void BuildFrom(MeshAdjacency meshAdjacency, int[] roiIndices, int roiBoundaryLevels, int[] roiConstraintIndices = null) { unsafe { using (var visited = new UnsafeArrayBool(meshAdjacency.vertexCount)) using (var visitedBoundary = new UnsafeArrayBool(meshAdjacency.vertexCount)) using (var visitor = new UnsafeBFS(meshAdjacency.vertexCount)) { // find boundary visited.Clear(false); visitedBoundary.Clear(false); visitor.Clear(); int visitedCount = 0; int visitedBoundaryCount = 0; foreach (int i in roiIndices) { visited.val[i] = true; visitedCount++; visitor.Ignore(i); } foreach (int i in roiIndices) { foreach (var j in meshAdjacency.vertexVertices[i]) { visitor.Insert(j); } } // step boundary while (visitor.MoveNext()) { int i = visitor.position; visited.val[i] = true; visitedCount++; visitedBoundary.val[i] = true; visitedBoundaryCount++; if (visitor.depth < roiBoundaryLevels) { foreach (var j in meshAdjacency.vertexVertices[i]) { visitor.Insert(j); } } } // add constraints if (roiConstraintIndices != null) { foreach (int i in roiConstraintIndices) { if (visited.val[i]) { if (visitedBoundary.val[i] == false) { visitedBoundary.val[i] = true; visitedBoundaryCount++; } } else { Debug.LogWarning("ignoring user constraint outside ROI: vertex " + i); } } } // build translations internalCount = 0; externalCount = meshAdjacency.vertexCount; internalFromExternal = new int[externalCount]; externalFromInternal = new int[visitedCount]; for (int i = 0; i != meshAdjacency.vertexCount; i++) { if (visited.val[i]) { int internalIndex = internalCount++; externalFromInternal[internalIndex] = i; internalFromExternal[i] = internalIndex; } else { internalFromExternal[i] = -1; } } // find constraint indices constraintIndices = new int[visitedBoundaryCount]; constraintWeight = 1.0; int constraintCount = 0; for (int i = 0; i != internalCount; i++) { if (visitedBoundary.val[externalFromInternal[i]]) { constraintIndices[constraintCount++] = i; } } // count unconstrained laplacian non-zero fields int nzmax = internalCount; for (int i = 0; i != internalCount; i++) { nzmax += InternalValence(meshAdjacency, i); } // build Ls EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build Ls", 0.0f); var Ls_storage = new CoordinateStorage <double>(internalCount, internalCount, nzmax); for (int i = 0; i != internalCount; i++) // D { //TODO proper fix //Ls_storage.At(i, i, InternalValence(meshAdjacency, i)); Ls_storage.At(i, i, Mathf.Max(1, InternalValence(meshAdjacency, i))); } for (int i = 0; i != internalCount; i++) // A { foreach (var k in meshAdjacency.vertexVertices[externalFromInternal[i]]) { int j = internalFromExternal[k]; if (j != -1) { Ls_storage.At(i, j, -1.0); } } } Ls = Converter.ToCompressedColumnStorage(Ls_storage) as SparseMatrix; // build Lc EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build Lc", 0.0f); var Lc_storage = new CoordinateStorage <double>(internalCount + constraintCount, internalCount, nzmax + constraintCount); for (int i = 0; i != internalCount; i++) { //TODO proper fix //Lc_storage.At(i, i, InternalValence(meshAdjacency, i)); Lc_storage.At(i, i, Mathf.Max(1, InternalValence(meshAdjacency, i))); } for (int i = 0; i != internalCount; i++) { foreach (var k in meshAdjacency.vertexVertices[externalFromInternal[i]]) { int j = internalFromExternal[k]; if (j != -1) { Lc_storage.At(i, j, -1.0); } } } for (int i = 0; i != constraintIndices.Length; i++) { Lc_storage.At(internalCount + i, constraintIndices[i], constraintWeight); } Lc = Converter.ToCompressedColumnStorage(Lc_storage) as SparseMatrix; // build LcT EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT", 0.0f); LcT = Lc.Transpose() as SparseMatrix; // build LcT_Lc EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT_Lc", 0.0f); LcT_Lc = LcT.Multiply(Lc) as SparseMatrix; // build LcT_Lc_chol EditorUtilityProxy.DisplayProgressBar("MeshLaplacian", "build LcT_Lc_chol", 0.0f); LcT_Lc_chol = SparseCholesky.Create(LcT_Lc, ColumnOrdering.MinimumDegreeAtPlusA); // done EditorUtilityProxy.ClearProgressBar(); } } }