public override void OnInspectorGUI() { base.OnInspectorGUI(); CustomPolygonCollider col = target as CustomPolygonCollider; col.mEdit = GUILayout.Toggle(col.mEdit, "Edit"); }
/// <summary> /// 检查凸多边形和圆是否重合 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool CheckPolygonAndCircle(CustomPolygonCollider a, CustomCircleCollider b) { //障碍物之间的碰撞不处理 if (a.mIsobstacle && b.mIsobstacle) { return(false); } List <CustomVector3> a_worldBound = a.LocalToWorldBound; bool mInit = false; //a在左 bool a_at_left = true; //偏移向量 CustomVector2 offsetvec = new CustomVector2(0, 0); //偏移值 FixedPointF offsetfac = new FixedPointF(0); //顶点连线 //斜率k List <CustomVector2> a_edges = new List <CustomVector2>(); for (int i = 0; i < a_worldBound.Count; i++) { int point1_index = i; int point2_index = (i + 1) % a_worldBound.Count; CustomVector3 offset = a_worldBound[point2_index] - a_worldBound[point1_index]; a_edges.Add(new CustomVector2(offset.x, offset.z)); } for (int i = 0; i < a_edges.Count; i++) { CustomVector2 axis = a_edges[i]; axis = Vec_normal(axis); FixedPointF x = axis.x; FixedPointF y = axis.y; FixedPointF temp = x * x + y * y; FixedPointF z = FixedPointF.Sqrt(temp); axis.x = x / z; axis.y = y / z; //求圆在法线上的投影边界 CustomVector3 vec3 = b.mTrans.Position; CustomVector2 point = new CustomVector2(vec3.x, vec3.z); FixedPointF mapPoint = CustomVector2.Dot(point, axis); FixedPointF min = mapPoint - b.mRadius; FixedPointF max = mapPoint + b.mRadius; CustomVector2 proj_b = new CustomVector2(min, max); CustomVector2 proj_a = GetMapPointMinMaxDis(a_worldBound, axis); if (!Check_Overlap(proj_a, proj_b)) { return(false); } else { bool a_at_left_temp = false; FixedPointF offsetfac_temp = new FixedPointF(0); Set_PushVec(proj_a, proj_b, ref a_at_left_temp, ref offsetfac_temp); if (!mInit) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; mInit = true; } else { if (offsetfac_temp < offsetfac) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; } } } } Push(a, b, offsetfac, offsetvec, a_at_left); return(true); }
public override void OnSceneGUI() { base.OnSceneGUI(); CustomPolygonCollider col = target as CustomPolygonCollider; if (!col.mEdit) { return; } Camera camera = Camera.current; //获取鼠标的位置 Vector2 mousePos = Event.current.mousePosition; //scene视图中原点是左上角,但相机的原点是左下角,所以要转换下y值 mousePos.y = camera.pixelHeight - mousePos.y; int index = -1; float length = 0; float percentage = 0; for (int i = 0; i < col.Bound.Count; i++) { Vector3 startViewPos = camera.WorldToScreenPoint(col.LocalToWorld(col.Bound[i]).value); Vector3 endViewPos = camera.WorldToScreenPoint(col.LocalToWorld(col.Bound[(i + 1) % col.Bound.Count]).value); //平行于X轴 if (LineAndXParallel(startViewPos, endViewPos)) { //平行于Y轴 if (LineAndYParallel(startViewPos, endViewPos)) { continue; } else { float len = Mathf.Abs(mousePos.y - startViewPos.y); float percent = (mousePos.x - startViewPos.x) / (endViewPos.x - startViewPos.x); bool first = index == -1; bool replace = len < length; index = first ? i : replace ? i : index; length = first ? len : replace ? len : length; percentage = first ? percent : replace ? percent : percentage; } } //平行于Y轴 else if (LineAndYParallel(startViewPos, endViewPos)) { float len = Mathf.Abs(mousePos.x - startViewPos.x); float percent = (mousePos.y - startViewPos.y) / (endViewPos.y - startViewPos.y); bool first = index == -1; bool replace = len < length; index = first ? i : replace ? i : index; length = first ? len : replace ? len : length; percentage = first ? percent : replace ? percent : percentage; } else { float k = (endViewPos.y - startViewPos.y) / (endViewPos.x - startViewPos.x);//y = kx+b;kx - y + b = 0 float b = startViewPos.y - k * startViewPos.x; float len = Mathf.Abs((k * mousePos.x - mousePos.y + b)) / Mathf.Sqrt(1 + Mathf.Pow(k, 2)); float percent = (mousePos.y - startViewPos.y) / (endViewPos.y - startViewPos.y); bool first = index == -1; bool replace = len < length; index = first ? i : replace ? i : index; length = first ? len : replace ? len : length; percentage = first ? percent : replace ? percent : percentage; } } //点击右键 bool mRightMouseDown = Event.current.button == 1 && Event.current.type == EventType.MouseDown; //按下shift bool mShiftDown = Event.current.shift; //按下alt bool mAlt = Event.current.alt; if (index != -1 && percentage > 0) { Vector3 start = col.LocalToWorld(col.Bound[index]).value; Vector3 end = col.LocalToWorld(col.Bound[(index + 1) % col.Bound.Count]).value; Vector3 pos = start + (end - start) * percentage; //添加节点 if (mShiftDown && !mAlt) { Handles.color = Color.green; Handles.CircleHandleCap(0, pos, Quaternion.Euler(90, 0, 0), 0.5f, EventType.Repaint); if (mRightMouseDown) { CustomVector3 mCustomPos = CustomVector3.GetCustomVector3ByVector3(pos); mCustomPos = col.WorldToLocal(mCustomPos); if (index + 1 < col.Bound.Count) { col.Bound.Insert((index + 1), mCustomPos); } else { col.Bound.Add(mCustomPos); } } } } //移除节点 if (!mShiftDown && mAlt) { index = -1; length = 0; for (int i = 0; i < col.Bound.Count; i++) { bool first = index == -1; Vector3 viewPos = camera.WorldToScreenPoint(col.LocalToWorld(col.Bound[i]).value); float len = Vector3.Distance(viewPos, mousePos); bool replace = len < length; index = first ? i : replace ? i : index; length = first ? len : replace ? len : length; } if (index != -1) { Handles.color = Color.red; Vector3 pos = col.LocalToWorld(col.Bound[index]).value; Handles.CircleHandleCap(0, pos, Quaternion.Euler(90, 0, 0), 0.5f, EventType.Repaint); if (mRightMouseDown) { if (col.Bound.Count > 3) { col.Bound.RemoveAt(index); } else { Debug.Log("多变形顶点数目不能小于3个"); } } } } //节点拖拽并且限制节点 for (int i = 0; i < col.Bound.Count; i++) { CustomVector3 customPos = CustomVector3.GetCustomVector3ByVector3(Handles.PositionHandle(col.LocalToWorld(col.Bound[i]).value, Quaternion.identity)); customPos = col.WorldToLocal(customPos); customPos.y = new FixedPointF(0); col.Bound[i] = customPos; } }
/// <summary> /// 检查两个凸多边形是否重合 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool CheckPolygonAndPolygon(CustomPolygonCollider a, CustomPolygonCollider b) { //障碍物之间的碰撞不处理 if (a.mIsobstacle && b.mIsobstacle) { return(false); } List <CustomVector3> a_worldBound = a.LocalToWorldBound; List <CustomVector3> b_worldBound = b.LocalToWorldBound; bool mInit = false; //a在左 bool a_at_left = true; //偏移向量 CustomVector2 offsetvec = new CustomVector2(0, 0); //偏移值 FixedPointF offsetfac = new FixedPointF(0); //顶点连线, //斜率k List <CustomVector2> a_edges = new List <CustomVector2>(); for (int i = 0; i < a_worldBound.Count; i++) { int point1_index = i; int point2_index = (i + 1) % a_worldBound.Count; CustomVector3 offset = a_worldBound[point2_index] - a_worldBound[point1_index]; a_edges.Add(new CustomVector2(offset.x, offset.z)); } for (int i = 0; i < a_edges.Count; i++) { CustomVector2 axis = a_edges[i]; //获得法向量 axis = Vec_normal(axis); FixedPointF x = axis.x; FixedPointF y = axis.y; FixedPointF temp = x * x + y * y; FixedPointF z = FixedPointF.Sqrt(temp); axis.x = x / z; axis.y = y / z; CustomVector2 proj_a = GetMapPointMinMaxDis(a_worldBound, axis), proj_b = GetMapPointMinMaxDis(b_worldBound, axis); if (!Check_Overlap(proj_a, proj_b)) { return(false); } else { bool a_at_left_temp = false; FixedPointF offsetfac_temp = new FixedPointF(0); Set_PushVec(proj_a, proj_b, ref a_at_left_temp, ref offsetfac_temp); if (!mInit) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; mInit = true; } else { if (offsetfac_temp < offsetfac) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; } } } } //顶点连线 //斜率k List <CustomVector2> b_edges = new List <CustomVector2>(); for (int i = 0; i < b_worldBound.Count; i++) { int point1_index = i; int point2_index = (i + 1) % b_worldBound.Count; CustomVector3 offset = b_worldBound[point2_index] - b_worldBound[point1_index]; b_edges.Add(new CustomVector2(offset.x, offset.z)); } for (int i = 0; i < b_edges.Count; i++) { CustomVector2 axis = b_edges[i]; axis = Vec_normal(axis); FixedPointF x = axis.x; FixedPointF y = axis.y; FixedPointF temp = x * x + y * y; FixedPointF z = FixedPointF.Sqrt(temp); axis.x = x / z; axis.y = y / z; CustomVector2 proj_a = GetMapPointMinMaxDis(a_worldBound, axis), proj_b = GetMapPointMinMaxDis(b_worldBound, axis); if (!Check_Overlap(proj_a, proj_b)) { return(false); } { bool a_at_left_temp = false; FixedPointF offsetfac_temp = new FixedPointF(0); Set_PushVec(proj_a, proj_b, ref a_at_left_temp, ref offsetfac_temp); if (offsetfac_temp < offsetfac) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; } } } Push(a, b, offsetfac, offsetvec, a_at_left); return(true); }