/// <summary> /// 从edges开始检查, 获取将半径为radius的物体, 从from移动到to, 可达的最远位置. /// </summary> Vector3 RaycastWithEdges(IEnumerable<HalfEdge> edges, Vector3 from, Vector3 to, float radius) { if (from.equals2(to)) { return to; } Vector2 segCrossAnswer = Vector2.zero; foreach (HalfEdge edge in edges) { // 检查相交. CrossState crossState = MathUtility.SegmentCross(out segCrossAnswer, from, to, edge.Src.Position, edge.Dest.Position); Utility.Verify(crossState == CrossState.CrossOnSegment || crossState == CrossState.CrossOnExtLine); // 交点不在线段上. if (segCrossAnswer.x < 0 || segCrossAnswer.x > 1) { continue; } // 如果交点在线段上, 那么表示该交点为当前最远位置. 再继续从这条边开始检查. if (crossState == CrossState.CrossOnSegment) { Vector3 cross = from + segCrossAnswer.x * (to - from); to = RaycastFromEdge(edge, cross, to, radius); break; } } return to; }
/// <summary> /// 查找ray的环中, 与src->dest的边相交的边. /// </summary> bool FindCrossedEdge(out Tuple2<HalfEdge, CrossState> answer, HalfEdge ray, Vector3 src, Vector3 dest) { List<HalfEdge> cycle = ray.Cycle; answer = new Tuple2<HalfEdge, CrossState>(); foreach (HalfEdge edge in cycle) { Vector3 point; CrossState crossState = MathUtility.GetLineCrossPoint(out point, edge.Src.Position, edge.Dest.Position, src, dest ); if (crossState == CrossState.FullyOverlaps || (crossState == CrossState.CrossOnSegment && !point.equals2(edge.Src.Position) && !point.equals2(edge.Dest.Position))) { answer.Second = crossState; answer.First = edge; if (crossState == CrossState.FullyOverlaps && (dest.equals2(edge.Src.Position) || src.equals2(edge.Dest.Position))) { answer.First = answer.First.Pair; } return true; } } return false; }
/// <summary> /// from在edge上, 查找半径为radius的物体从from到to可达的最远位置. /// </summary> Vector3 RaycastFromEdge(HalfEdge edge, Vector3 from, Vector3 to, float radius) { // 起点==终点, 或者edge为约束边. if (from.equals2(to) || edge.Constrained || edge.Pair.Constrained) { return from; } // from位置无效. if (!IsValidPosition(from, radius)) { return from; } // 根据from->to的方向, 确定下一个要访问的三角形是edge.Face还是edge.Pair.Face. if ((to - from).cross2(edge.Dest.Position - edge.Src.Position) > 0) { edge = edge.Pair; } // 不存在另一边的三角形. if (edge.Face == null) { return from; } // 检查另外两条边. return RaycastWithEdges(new HalfEdge[] { edge.Next, edge.Next.Next }, from, to, radius); }