float ComputeEdgeCollapseCost(Vertex u, Vertex v, float fRelevanceBias) { bool bUseEdgeLength = _useEdgeLength; bool bUseCurvature = _useCurvature; float fBorderCurvature = _borderCurvature; int i; float fEdgeLength = bUseEdgeLength ? (Vector3.Magnitude(v.Position - u.Position) / _originalMeshSize) : 1.0f; float fCurvature = 0.001f; if (fEdgeLength < float.Epsilon) { return(fBorderCurvature * (1 - Vector3.Dot(u.Normal, v.Normal) + 2 * Vector3.Distance(u.UV, v.UV))); } else { List <Triangle> sides = new List <Triangle>(); for (i = 0; i < u.ListFaces.Count; i++) { if (u.ListFaces[i].HasVertex(v)) { sides.Add(u.ListFaces[i]); } } if (bUseCurvature) { for (i = 0; i < u.ListFaces.Count; i++) { float fMinCurv = 1.0f; for (int j = 0; j < sides.Count; j++) { float dotprod = Vector3.Dot(u.ListFaces[i].Normal, sides[j].Normal); fMinCurv = Mathf.Min(fMinCurv, (1.0f - dotprod) / 2.0f); } fCurvature = Mathf.Max(fCurvature, fMinCurv); } } bool isBorder = u.IsBorder(); if (isBorder && sides.Count > 1) { fCurvature = 1.0f; } if (fBorderCurvature > 1 && isBorder) { fCurvature = fBorderCurvature; } } fCurvature += fRelevanceBias; return(fEdgeLength * fCurvature); }
float ComputeEdgeCollapseCost(Vertex u, Vertex v, float fRelevanceBias) { bool bUseEdgeLength = m_bUseEdgeLength; bool bUseCurvature = m_bUseCurvature; bool bLockBorder = m_bLockBorder; int i; float fEdgeLength = bUseEdgeLength ? (Vector3.Magnitude(v.m_v3Position - u.m_v3Position) / m_fOriginalMeshSize) : 1.0f; float fCurvature = 0.001f; List <Triangle> sides = new List <Triangle>(); for (i = 0; i < u.m_listFaces.Count; i++) { if (u.m_listFaces[i].HasVertex(v)) { sides.Add(u.m_listFaces[i]); } } if (bUseCurvature) { for (i = 0; i < u.m_listFaces.Count; i++) { float fMinCurv = 1.0f; for (int j = 0; j < sides.Count; j++) { float dotprod = Vector3.Dot(u.m_listFaces[i].Normal, sides[j].Normal); fMinCurv = Mathf.Min(fMinCurv, (1.0f - dotprod) / 2.0f); } fCurvature = Mathf.Max(fCurvature, fMinCurv); } } bool isBorder = u.IsBorder(); if (isBorder && sides.Count > 1) { fCurvature = 1.0f; } if (bLockBorder && isBorder) { fCurvature = MAX_VERTEX_COLLAPSE_COST; } fCurvature += fRelevanceBias; return(fEdgeLength * fCurvature); }
public unsafe static void Compute(List <Vertex> vertices, TriangleList[] triangleLists, RelevanceSphere[] aRelevanceSpheres, bool bUseEdgeLength, bool bUseCurvature, bool bLockBorder, float fOriginalMeshSize, float[] costs, int[] collapses) { ComputeCostJob job = new ComputeCostJob(); job.UseEdgeLength = bUseEdgeLength; job.UseCurvature = bUseCurvature; job.LockBorder = bLockBorder; job.OriginalMeshSize = fOriginalMeshSize; List <StructTriangle> structTriangles = new List <StructTriangle>(); int intAlignment = UnsafeUtility.SizeOf <int>(); for (int n = 0; n < triangleLists.Length; n++) { List <Triangle> triangles = triangleLists[n].m_listTriangles; for (int i = 0; i < triangles.Count; i++) { Triangle t = triangles[i]; StructTriangle st = new StructTriangle() { Index = t.Index, Indices = (int *)UnsafeUtility.Malloc(t.Indices.Length * intAlignment, intAlignment, Allocator.TempJob), Normal = t.Normal, }; for (int j = 0; j < t.Indices.Length; j++) { st.Indices[j] = t.Indices[j]; } structTriangles.Add(st); } } job.Triangles = new NativeArray <StructTriangle>(structTriangles.ToArray(), Allocator.Temp); job.Vertices = new NativeArray <StructVertex>(vertices.Count, Allocator.TempJob); for (int i = 0; i < vertices.Count; i++) { Vertex v = vertices[i]; StructVertex sv = new StructVertex() { Position = v.m_v3Position, PositionWorld = v.m_v3PositionWorld, ID = v.m_nID, Neighbors = v.m_listNeighbors.Count == 0 ? null : (int *)UnsafeUtility.Malloc(v.m_listNeighbors.Count * intAlignment, intAlignment, Allocator.TempJob), NeighborCount = v.m_listNeighbors.Count, Faces = (int *)UnsafeUtility.Malloc(v.m_listFaces.Count * intAlignment, intAlignment, Allocator.TempJob), FaceCount = v.m_listFaces.Count, IsBorder = v.IsBorder() ? 1 : 0, }; for (int j = 0; j < v.m_listNeighbors.Count; j++) { sv.Neighbors[j] = v.m_listNeighbors[j].m_nID; } for (int j = 0; j < v.m_listFaces.Count; j++) { sv.Faces[j] = v.m_listFaces[j].Index; } job.Vertices[i] = sv; } job.Spheres = new NativeArray <StructRelevanceSphere>(aRelevanceSpheres.Length, Allocator.TempJob); for (int i = 0; i < aRelevanceSpheres.Length; i++) { RelevanceSphere rs = aRelevanceSpheres[i]; StructRelevanceSphere srs = new StructRelevanceSphere() { Transformation = Matrix4x4.TRS(rs.m_v3Position, rs.m_q4Rotation, rs.m_v3Scale), Relevance = rs.m_fRelevance, }; job.Spheres[i] = srs; } job.Result = new NativeArray <float>(costs, Allocator.TempJob); job.Collapse = new NativeArray <int>(collapses, Allocator.TempJob); #if !JOB_DEBUG JobHandle handle = job.Schedule(costs.Length, 1); handle.Complete(); #else for (int i = 0; i < costs.Length; i++) { job.Execute(i); } #endif job.Result.CopyTo(costs); job.Collapse.CopyTo(collapses); for (int i = 0; i < job.Triangles.Length; i++) { UnsafeUtility.Free(job.Triangles[i].Indices, Allocator.TempJob); } for (int i = 0; i < job.Vertices.Length; i++) { UnsafeUtility.Free(job.Vertices[i].Neighbors, Allocator.TempJob); UnsafeUtility.Free(job.Vertices[i].Faces, Allocator.TempJob); } job.Vertices.Dispose(); job.Triangles.Dispose(); job.Spheres.Dispose(); job.Result.Dispose(); job.Collapse.Dispose(); }