public void Transform(MeshPartType type, List<Vector2> points, Vector2 center) { var movedPoints = new List<int>(); var linkedIndices = new Dictionary<int, int>(); var rects = Rects.Where(r => r.Type == type).ToList(); foreach (var rect in rects) { for (var i = 0; i < rect.Points.Length; i++) { var idx = rect.ShapeIndices[i]; if (movedPoints.Contains(idx)) continue; movedPoints.Add(idx); } if (rect.LinkedShapeRect != null) { linkedIndices.Add(rect.ShapeIndices.First(), rect.LinkedShapeRect.ShapeIndices.First()); linkedIndices.Add(rect.ShapeIndices.Last(), rect.LinkedShapeRect.ShapeIndices.Last()); } } switch (type) { case MeshPartType.LEye: case MeshPartType.REye: case MeshPartType.Head: foreach (var key in movedPoints) { var p = ShapeInfo.Points[key].Value; float ua, ub; Vector2 p0, p1, target; for (int i = 0, j = points.Count - 1; i < points.Count; j = i, i++) { p0 = points[j]; p1 = points[i]; if (GetUaUb(ref center, ref p, ref p0, ref p1, out ua, out ub) && ub > 0.0f && ub < 1.0f && ua > 0.0f) { target = center + (p - center) * ua; ShapeInfo.Points[key].Value = target; break; } } } break; case MeshPartType.Nose: if ((points[points.Count - 1] - points[0]).X < 0.0f) points.Reverse(); var plist = movedPoints.Select(i => ShapeInfo.Points[i].Value).ToList(); plist = TransformLine(plist, points); for (var i = 0; i < movedPoints.Count; i++) { var key = movedPoints[i]; var p = plist[i]; ShapeInfo.Points[key].Value = p; } break; case MeshPartType.Lip: #region Lip { if (points.Count < 5) return; var lipPoints = new List<Vector2>(); var indices = new List<int>(); var pointnsDict = new Dictionary<Vector2, int>(new VectorEqualityComparer()); var centerLine = false; for (var i = 0; i < points.Count; i++) { var p = points[i]; if (i > 0 && !centerLine && p.Equals(points[0])) { centerLine = true; continue; } int index; if (!pointnsDict.TryGetValue(p, out index)) { index = lipPoints.Count; pointnsDict.Add(p, index); lipPoints.Add(p); } indices.Add(index); } var lipLists = new List<Vector2>[3]; for (var i = 0; i < 3; i++) lipLists[i] = new List<Vector2>(); for (var i = 0; i < indices.Count; i++) if (indices[i] < i) { var first = indices[i]; var last = indices[indices.Count - 1]; for (var j = first; j <= last; j++) lipLists[0].Add(lipPoints[indices[j]]); for (var j = last; j < i; j++) lipLists[1].Add(lipPoints[indices[j]]); for (var j = 0; j <= first; j++) lipLists[1].Add(lipPoints[indices[j]]); for (var j = i; j < indices.Count; j++) lipLists[2].Add(lipPoints[indices[j]]); break; } for (var i = 0; i < 3; i++) if (lipLists[i].Count == 0) return; var lipCenter = lipLists[2]; var c = (lipCenter[0] + lipPoints[lipCenter.Count - 1]) * 0.5f; var c0 = new Vector2(c.X, c.Y + 1000.0f); var c1 = new Vector2(c.X, c.Y - 1000.0f); for (var i = 2; i > 0; i--) { var list = lipLists[i]; for (var j = 0; j < list.Count - 1; j++) { var p0 = list[j]; var p1 = list[j + 1]; float ua, ub; if (GetUaUb(ref p0, ref p1, ref c0, ref c1, out ua, out ub) && ua > 0.0f && ua < 1.0f && ub > 0.0f && ub < 1.0f) { var p = p0 + (p1 - p0) * ua; if (i == 2) c = p; else if (p.Y >= c.Y) { lipLists[1] = lipLists[0]; lipLists[0] = list; } break; } } } var tmpIndices = new[] { 3, 4, 2 }; var idx = 0; var sourcePoints = new List<Vector2>(); var sourceIndices = new List<int>(); for (var i = 0; i < 3; i++) { sourcePoints.Clear(); sourceIndices.Clear(); for (var j = 0; j < tmpIndices[i]; j++, idx++) { var rect = rects[idx]; sourcePoints.AddRange(rect.Points); sourceIndices.AddRange(rect.ShapeIndices); } var list = lipLists[i]; if ((sourcePoints[sourcePoints.Count - 1].X - sourcePoints[0].X) * (list[list.Count - 1].X - list[0].X) < 0.0f) list.Reverse(); sourcePoints = TransformLine(sourcePoints, list); for (var j = 0; j < sourcePoints.Count; j++) { var id = sourceIndices[j]; if (movedPoints.Contains(id)) { var p = sourcePoints[j]; ShapeInfo.Points[id].Value = p; movedPoints.Remove(id); } } } } #endregion break; case MeshPartType.ProfileBottom: case MeshPartType.ProfileTop: #region Profile { var index = 0; var isFirst = true; movedPoints.Clear(); foreach (var rect in ProfileRects) { if (rect.LinkedShapeRect == null || rect.Type != type) continue; //Подгоняем основные точки по Y Vector2 a = rect.Points[0], b = rect.Points.Last(); var v = new Vector2(1.0f, 0.0f); var a1 = a + v; var b1 = b + v; //Подгоняем точки по Z float? az = null, bz = null; var tmpPoints = new List<Vector2>(); if (isFirst) { az = a.X; tmpPoints.Add(a); } if (rect.IsLast) bz = b.X; //Идем от index и ищем пересечение линии [i, i + 1] с прямой, парралельной oX проходящей через a.Y и b.Y //Если дошли до конца и не нашли - что-то пошло не так, прекращаем все for (var i = index; i < points.Count - 1; i++) { float ua, ub; var p0 = points[i]; var p1 = points[i + 1]; if (az == null && GetUaUb(ref p0, ref p1, ref a, ref a1, out ua, out ub) && ua > 0.0f && ua < 1.0f) { var tmp = p0 + (p1 - p0) * ua; tmpPoints.Add(tmp); az = tmp.X; } if (az != null) { if (rect.IsLast) { for (var j = i + 1; j < points.Count - 1; j++) tmpPoints.Add(points[j]); tmpPoints.Add(b); break; } if (i != index && p0.Y < a.Y) tmpPoints.Add(points[i]); if (GetUaUb(ref p0, ref p1, ref b, ref b1, out ua, out ub) && ua > 0.0f && ua < 1.0f) { var tmp = p0 + (p1 - p0) * ua; tmpPoints.Add(tmp); bz = tmp.X; index = i; break; } } } if (az == null || bz == null) return; a.X = az.Value; b.X = bz.Value; rect.Transform(ref a, ref b); //Строим линию rect.Points = TransformLine(rect.Points.ToList(), tmpPoints).ToArray(); //Обновляем точки для шейпа var count = rect.IsLast ? rect.Points.Length - 1 : rect.Points.Length; var start = isFirst ? 1 : 0; for (var i = start; i < count; i++) { var idx = rect.ShapeIndices[i]; if (movedPoints.Contains(idx)) continue; movedPoints.Add(idx); ShapeProfileInfo.Points[idx].Value = rect.Points[i]; } isFirst = false; } headMeshesController.UpdateProfileShape(ref ShapeProfileInfo); headMeshesController.UpdateNormals(); //headMeshesController.UpdateShape(ref ShapeInfo); return; } #endregion } foreach (var rect in rects) { if (rect.LinkedShapeRect != null) { Vector2 a = ShapeInfo.Points[rect.ShapeIndices.First()].Value, b = ShapeInfo.Points[rect.ShapeIndices.Last()].Value; a = rect.LinkedShapeRect.Points.First() + a - rect.Points.First(); b = rect.LinkedShapeRect.Points.Last() + b - rect.Points.Last(); rect.LinkedShapeRect.Transform(ref a, ref b, false); for (var i = 0; i < rect.LinkedShapeRect.Points.Length; i++) { var pos = rect.LinkedShapeRect.Points[i]; var idx = rect.LinkedShapeRect.ShapeIndices[i]; ShapeInfo.Points[idx].Value = pos; } } for (var i = 0; i < rect.Points.Length; i++) { var idx = rect.ShapeIndices[i]; rect.Points[i] = ShapeInfo.Points[idx].Value; } rect.Points = rect.Points; } headMeshesController.UpdateShape(ref ShapeInfo); }
public void ResetPoints(MeshPartType type) { if (type == MeshPartType.None) return; var movedPoints = new Dictionary<int, Vector2>(); var rects = Rects.Where(r => r.Type == type).ToList(); var linked = rects.Where(r => r.LinkedShapeRect != null).Select(r => r.LinkedShapeRect).ToList(); rects.AddRange(linked); foreach (var rect in rects) { for (var i = 0; i < rect.Points.Length; i++) { var idx = rect.ShapeIndices[i]; if (movedPoints.ContainsKey(idx)) { rect.Points[i] = movedPoints[idx]; continue; } movedPoints.Add(idx, rect.OriginalPoints[i]); var dv = rect.OriginalPoints[i] - rect.Points[i]; if (Math.Abs(dv.LengthSquared) < 0.000001f) continue; rect.Points[i] = rect.OriginalPoints[i]; ShapeInfo.Points[idx].Value = rect.OriginalPoints[i]; } rect.Points = rect.Points; } headMeshesController.UpdateShape(ref ShapeInfo); headMeshesController.UpdateNormals(); }