/// <summary> /// 半球防空区域 /// </summary> /// <param name="pos"></param> /// <param name="radius"></param> /// <param name="angle">默认为半球,通过修改角度可以修改球的缺省</param> /// <param name="meshFilter"></param> public static void DrawHemisphere(Vector3 pos, float radius, MeshFilter meshFilter, int angle = 90) { meshFilter.mesh.vertices = PhysicsMath.GetVertices(pos, radius, angle); // 圆球形 meshFilter.mesh.triangles = PhysicsMath.Sort3(angle); meshFilter.mesh.RecalculateBounds(); // 重置范围 meshFilter.mesh.RecalculateNormals(); // 重置法线 meshFilter.mesh.RecalculateTangents(); // 重置切线 }
public EllipseGraphic(Vector2 center, Vector2 radius) { var points = PhysicsMath.GetEllipsePoints(radius.x, radius.y, center, 60); m_Poses = new List <Vector3>(); foreach (var item in points) { m_Poses.Add(item); } }
/// <summary> /// 创建通用多边形区域 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="list">下底面点链表</param> /// <param name="height">高度</param> public void CreatePolygon(List <Vector3> list, float height, Color color) { Vector3[] vector3s = PhysicsMath.CheckVector(list); // 使数组逆时针排序 Mesh mesh = GLDraw.CreatePolygon(vector3s, height, color.Int32()); // 画出图形 Game.GraphicsModule.AddGraphics(Camera.main, () => { ShapeMaterial.SetPass(0); Graphics.DrawMeshNow(mesh, Matrix4x4.identity); }); }
/// <summary> /// 创建扇形防空区 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="origin">起始点</param> /// <param name="tarPoint">水平最远距离点</param> /// <param name="alpha">横向张角</param> /// <param name="theta">纵向张角</param> public void CreateSector(Vector3 origin, Vector3 tarPoint, float alpha, float theta, Color color) { Vector3[] vertices = PhysicsMath.GetSectorPoints_2(origin, tarPoint, alpha, theta); Mesh mesh = GLDraw.CreatePolygon(vertices, color.Int32()); Game.GraphicsModule.AddGraphics(Camera.main, () => { ShapeMaterial.SetPass(0); Graphics.DrawMeshNow(mesh, Matrix4x4.identity); }); }
/// <summary> /// 创建通用多边形区域 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="list">下底面点链表</param> /// <param name="height">高度</param> public void CreatePolygon(int id, List <Vector3> list, float height, Color Fillcolor, Color BoradColor) { LineRenderer[] lineRenderers = new LineRenderer[4]; List <GameObject> meshList = GetMeshPrefab(lineRenderers, 1); // 获取mesh meshDic.Add(id, meshList); // 加入字典 MeshFilter meshFilter = meshList[0].GetComponent <MeshFilter>(); // 获取meshfilter meshList[0].GetComponent <MeshRenderer>().material.color = Fillcolor; Vector3[] vector3s = PhysicsMath.CheckVector(list); // 使数组逆时针排序 DrawTriangles.DrawPolygon(vector3s, height, meshFilter, lineRenderers, BoradColor); // 画出图形 }
/// <summary> /// 创建扇形防空区 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="origin">起始点</param> /// <param name="tarPoint">水平最远距离点</param> /// <param name="alpha">横向张角</param> /// <param name="theta">纵向张角</param> public void CreateSector(int id, Vector3 origin, Vector3 tarPoint, float alpha, float theta, Color Fillcolor, Color BoradColor) { LineRenderer[] lineRenderers = new LineRenderer[4]; List <GameObject> meshList = GetMeshPrefab(lineRenderers, 1); meshDic.Add(id, meshList); MeshFilter meshFilter = meshList[0].GetComponent <MeshFilter>(); meshList[0].GetComponent <MeshRenderer>().material.color = Fillcolor; Vector3[] vertices = PhysicsMath.GetSectorPoints_2(origin, tarPoint, alpha, theta); DrawTriangles.DrawPolygon(vertices, meshFilter, lineRenderers, BoradColor); }
public Dictionary <int, List <GameObject> > meshDic = new Dictionary <int, List <GameObject> >(); // 命令与mesh对应字典 /// <summary> /// 创建圆柱形区域 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="point"> 圆心点 </param> /// <param name="radius"> 半径 </param> /// <param name="height"> 高度 </param> public void CreateCylinder(int id, Vector3 point, float radius, float height, Color Fillcolor, Color BoradColor) { LineRenderer[] lineRenderers = new LineRenderer[4]; List <GameObject> meshList = GetMeshPrefab(lineRenderers, 1); // 获取mesh meshDic.Add(id, meshList); // 加入字典 MeshFilter meshFilter = meshList[0].GetComponent <MeshFilter>(); // 获取meshfilter meshList[0].GetComponent <MeshRenderer>().material.color = Fillcolor; Vector3[] vertices = PhysicsMath.GetCirclePoints(point, radius); // 获取点集 DrawTriangles.DrawCylinder(vertices, height, meshFilter, lineRenderers, BoradColor); // 画出图形 }
public BezierGraphic(Vector3[] originPoints, uint[] segTypes) { List <Vector3> points = new List <Vector3>(); int index = 0; for (int i = 0; i < segTypes.Length; i++) { switch (segTypes[i]) { case 0: // 直线,只取2个点 AddifNotContain(points, new List <Vector3>() { originPoints[index++], originPoints[index] }); break; case 1: // 二次贝塞尔, 取3个点 Vector3[] bezier2 = new Vector3[3]; bezier2[0] = originPoints[index++]; bezier2[1] = originPoints[index++]; bezier2[2] = originPoints[index]; AddifNotContain(points, PhysicsMath.GetBezierList(bezier2)); break; case 2: // 三次贝塞尔, 取4个点 Vector3[] bezier3 = new Vector3[4]; bezier3[0] = originPoints[index++]; bezier3[1] = originPoints[index++]; bezier3[2] = originPoints[index++]; bezier3[3] = originPoints[index]; AddifNotContain(points, PhysicsMath.GetBezierList(bezier3)); break; default: break; } } m_Poses = points; void AddifNotContain(List <Vector3> _drawPath, List <Vector3> _pointsAdd) { if (_drawPath.Count > 0 && _drawPath.End() == _pointsAdd[0]) { _pointsAdd.RemoveAt(0); } _drawPath.AddRange(_pointsAdd); } // 内部函数, 去重添加 }
/// <summary> /// 创建空中走廊 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="list">中心点链表</param> /// <param name="width">宽度</param> /// <param name="height">高度</param> public void CreateAirCorridorSpace(int id, List <Vector3> list, float width, float height, Color Fillcolor) { LineRenderer[] lineRenderers = new LineRenderer[4]; List <GameObject> meshList = GetMeshPrefab(lineRenderers, 1); // 获取mesh meshDic.Add(id, meshList); // 加入字典 MeshFilter meshFilter = meshList[0].GetComponent <MeshFilter>(); // 获取meshfilter meshList[0].GetComponent <MeshRenderer>().material.color = Fillcolor; //Vector3[] vertices = PhysicsMath.GetAirCorridorSpace(list, width, height); // 获取点集 //DrawTriangles.DrawAirCorridorSpace(vertices, meshFilter, lineRenderers); // 画出图形 Vector3[] bottomPoints = PhysicsMath.GetAirSpaceBottomPoints(list, width, height); Vector3[] vertices = PhysicsMath.GetAirBottomSpaceWithSector(bottomPoints.ToList(), width); DrawTriangles.GetAirSpaceWithSector(vertices.ToList(), width, height, list.Count - 1, meshFilter); }
/// <summary> /// 画数据折线 /// </summary> private void DrawLine(VertexHelper vh) { foreach (var data in datas) { Vector2[] pixelPoints = new Vector2[data.Length]; for (int i = 0; i < data.Length; i++) { pixelPoints[i].x = (data[i].x - axleMinValue.x) / axleMaxValue.x * width; pixelPoints[i].y = (data[i].y - axleMinValue.y) / axleMaxValue.y * height; pixelPoints[i] += offset; } UIVertex[] verts = new UIVertex[4]; for (int i = 0; i < verts.Length; i++) { verts[i].color = lineColor; } for (int i = 0; i < pixelPoints.Length - 1; i++) { SetVerts(pixelPoints[i], pixelPoints[i + 1], lineWidth, verts); vh.AddUIVertexQuad(verts); } // 点状数据 //foreach (var item in pixelPoints) //{ // verts[0].position = item; // verts[1].position = new Vector2(5, 0) + item; // verts[2].position = new Vector2(5, 5) + item; // verts[3].position = new Vector2(0, 5) + item; // vh.AddUIVertexQuad(verts); //} void SetVerts(Vector2 _start, Vector2 _end, float _width, UIVertex[] _verts) { Vector2[] tmp = PhysicsMath.GetRect(_start, _end, _width); _verts[0].position = tmp[0]; _verts[1].position = tmp[1]; _verts[2].position = tmp[3]; _verts[3].position = tmp[2]; } } }
protected override void OnUpdate() { Entities.ForEach((UnityEngine.BoxCollider2D collider) => { // Convert the collider if it's valid. if (ConversionUtilities.CanConvertCollider(collider)) { try { var lossyScale = new float3(collider.transform.lossyScale).xy; if (math.any(!math.isfinite(lossyScale)) || math.any(lossyScale <= 0.0f)) { throw new ArgumentException("Transform XY scale cannot be zero or Infinite/NaN.", "Transform XY scale."); } var localToWorld = ConversionUtilities.GetColliderLocalToWorld(collider); var size = collider.size; var geometry = new BoxGeometry { Center = new float3(localToWorld.MultiplyPoint(collider.offset)).xy, Size = new float2(size.x * lossyScale.x, size.y * lossyScale.y), Angle = PhysicsMath.ZRotationFromQuaternion(localToWorld.rotation), BevelRadius = math.max(collider.edgeRadius, PhysicsSettings.Constants.MinimumConvexRadius), }; geometry.Validate(); var colliderBlob = PhysicsBoxCollider.Create( geometry, ConversionUtilities.GetCollisionFilterFromCollider(collider), ConversionUtilities.GetPhysicsMaterialFromCollider(collider) ); // Submit the collider for conversion. m_ColliderConversionSystem.SubmitCollider(collider, ref colliderBlob); } catch (ArgumentException exception) { UnityEngine.Debug.LogWarning($"{collider.name}: {exception.Message}", collider); } } }); }
// Get collider local to world as defined relative to any attached Rigidbody2D. public static Matrix4x4 GetColliderLocalToWorld(Collider2D collider) { // If no attached rigidbody or we're attached to a rigidbody but it's on the same GameObject // then we simply use identity as the relative transform. var attachedRigidbody = collider.attachedRigidbody; if (attachedRigidbody == null || attachedRigidbody.gameObject == collider.gameObject) { return(Matrix4x4.identity); } // Calculate relative to the attached rigidbody. var rigidbodyTransform = attachedRigidbody.transform; var bodyInverseRotation = Quaternion.Inverse(PhysicsMath.ZQuaternionFromQuaternion(rigidbodyTransform.rotation)); var bodyInversePosition = bodyInverseRotation * -rigidbodyTransform.position; var localToWorld = collider.transform.localToWorldMatrix; return(Matrix4x4.TRS(bodyInversePosition, bodyInverseRotation, Vector3.one) * localToWorld); }
public override void GetVertexs(ref List <UIVertex> vertexs) { if (m_Poses.Count < 2) { return; } int count = m_Poses.Count; Vector2 dir = PhysicsMath.GetHorizontalDir((m_Poses[1] - m_Poses[0]).XY()); vertexs.Add(new UIVertex() { position = m_Poses[0].XY() - dir * width, color = color, }); vertexs.Add(new UIVertex() { position = m_Poses[0].XY() + dir * width, color = color, }); for (int i = 1; i < count - 1; i++) { dir = PhysicsMath.GetHorizontalDir((m_Poses[i + 1] - m_Poses[i - 1]).XY()); vertexs.Add(new UIVertex() { position = m_Poses[i].XY() - dir * width, color = color, }); vertexs.Add(new UIVertex() { position = m_Poses[i].XY() + dir * width, color = color }); } dir = PhysicsMath.GetHorizontalDir((m_Poses[count - 1] - m_Poses[count - 2]).XY()); vertexs.Add(new UIVertex() { position = m_Poses[count - 1].XY() - dir * width, color = color, }); vertexs.Add(new UIVertex() { position = m_Poses[count - 1].XY() + dir * width, color = color, }); }
protected Vector2 CollisionCheck(Vector3 position, Vector2 force) { if (security > 25) { return(force); } boxRaycast = Physics2D.BoxCast(position, collisionBox.bounds.size, 0.0f, force.normalized, Mathf.Infinity, collisionMask); security++; if (boxRaycast.collider != null) { if (boxRaycast.distance > force.magnitude * Time.deltaTime) { return(force); } if (boxRaycast.transform.tag == "MoveableObj") { force += boxRaycast.normal * Time.deltaTime; } Vector2 normalHit = boxRaycast.normal; float angle = Mathf.Abs((Vector2.Angle(normalHit, force.normalized) - 90) * Mathf.Deg2Rad); if (Mathf.Approximately(Mathf.Sin(angle), 0)) { return(force); } float range = skinWidth / Mathf.Sin(angle); if (boxRaycast.distance - range > 0) { Vector2 snap = force.normalized * (boxRaycast.distance - range); // snap = Vector2.ClampMagnitude(snap, force.magnitude * Time.deltaTime); position += (Vector3)snap; totalSnap += (Vector3)snap; } Vector2 normalForce = PhysicsMath.NormalizeForce2D(force, normalHit); force += normalForce; force = ApplicationOfFriction(normalForce.magnitude, force, staticFriction); force = CollisionCheck(position, force); } return(force); }
public unsafe void Draw() { if (VertexCount < 3) { return; } BeginLineStrip(Color); fixed(byte *array = Vertices) { float2 *vertexArray = (float2 *)array; for (var i = 0; i < VertexCount; ++i) { var vertex = PhysicsMath.mul(Transform, vertexArray[i]); DrawLineVertex(vertex); } DrawLineVertex(PhysicsMath.mul(Transform, vertexArray[0])); } EndDraw(); }
private static unsafe void DrawComposite( Collider *collider, ref PhysicsTransform worldTransform, ref PhysicsDebugStreamSystem.Context outputStream, Color colliderColor) { switch (collider->ColliderType) { case ColliderType.Compound: { var compoundCollider = (PhysicsCompoundCollider *)collider; var children = compoundCollider->Children; for (var i = 0; i < children.Length; ++i) { ref PhysicsCompoundCollider.Child child = ref children[i]; var colliderWorldTransform = PhysicsMath.mul(worldTransform, child.CompoundFromChild); DrawCollider(children[i].Collider, ref colliderWorldTransform, ref outputStream, colliderColor); } return; } }
/// <summary> /// 创建紫色杀伤盒 /// </summary> /// <param name="id"> 命令ID,用作字典key </param> /// <param name="list">底面四点链表</param> /// <param name="lower">下限高度</param> /// <param name="Ceiling">上限高度</param> public void CreateKillBox(List <Vector3> list, float lower, float Ceiling, Color color) { // 第一个杀伤盒 Vector3[] vector3s1 = PhysicsMath.CheckVector(list); // 使数组逆时针排序 Mesh mesh0 = GLDraw.CreatePolygon(vector3s1, lower, color.Int32()); // 画出图形 // 第二个杀伤盒 List <Vector3> CeilingList = new List <Vector3>(); // 中层顶点集合 foreach (var item in list) { CeilingList.Add(item + Vector3.up * lower); } Vector3[] vector3s2 = PhysicsMath.CheckVector(CeilingList); // 使数组逆时针排序 Mesh mesh1 = GLDraw.CreatePolygon(vector3s2, Ceiling - lower, color.Int32()); // 画出图形 Game.GraphicsModule.AddGraphics(Camera.main, () => { ShapeMaterial.SetPass(0); Graphics.DrawMeshNow(mesh0, Matrix4x4.identity); Graphics.DrawMeshNow(mesh1, Matrix4x4.identity); }); }
public void MassProperties_BuiltFromChildren_MatchesExpected() { void TestCompoundBox(PhysicsTransform transform) { // Create a unit box var boxCollider = PhysicsBoxCollider.Create(new BoxGeometry { Size = new float2(1f), Center = transform.Translation, Angle = 0f, BevelRadius = 0.0f }); // Create a compound of mini boxes, matching the volume of the single box var miniBox = PhysicsBoxCollider.Create(new BoxGeometry { Size = new float2(0.5f), Center = float2.zero, Angle = 0f, BevelRadius = 0.0f }); const uint UserData = 0xDEADBEEF; const int ChildrenCount = 4; var childrenTransforms = new NativeArray <PhysicsTransform>(ChildrenCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory) { [0] = new PhysicsTransform(new float2(-0.25f, -0.25f), float2x2.identity), [1] = new PhysicsTransform(new float2(0.25f, -0.25f), float2x2.identity), [2] = new PhysicsTransform(new float2(0.25f, 0.25f), float2x2.identity), [3] = new PhysicsTransform(new float2(-0.25f, 0.25f), float2x2.identity), }; var children = new NativeArray <PhysicsCompoundCollider.ColliderBlobInstance>(ChildrenCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory); for (var i = 0; i < ChildrenCount; ++i) { children[i] = new PhysicsCompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = PhysicsMath.mul(transform, childrenTransforms[i]) }; } var colliderBlob = PhysicsCompoundCollider.Create(children, UserData); childrenTransforms.Dispose(); children.Dispose(); ref var collider = ref colliderBlob.GetColliderRef <PhysicsCompoundCollider>(); Assert.AreEqual(ColliderType.Compound, collider.ColliderType); Assert.AreEqual(CollisionType.Composite, collider.CollisionType); Assert.AreEqual(UserData, collider.UserData); var boxMassProperties = boxCollider.Value.MassProperties; var compoundMassProperties = colliderBlob.Value.MassProperties; Assert.AreEqual(boxMassProperties.Area, compoundMassProperties.Area, 1e-3f, "Area incorrect."); Assert.AreEqual(boxMassProperties.AngularExpansionFactor, compoundMassProperties.AngularExpansionFactor, 1e-3f, "AngularExpansionFactor incorrect."); PhysicsAssert.AreEqual(boxMassProperties.MassDistribution.LocalCenterOfMass, compoundMassProperties.MassDistribution.LocalCenterOfMass, 1e-3f, "LocalCenterOfMass incorrect."); Assert.AreEqual(boxMassProperties.MassDistribution.InverseInertia, compoundMassProperties.MassDistribution.InverseInertia, 1e-3f, "InverseInertia incorrect."); boxCollider.Dispose(); colliderBlob.Dispose(); }
/// <summary> /// 根据传参 路径点信息 创建路面: /// 0 --- 2 /// | | /// 1 --- 3 /// </summary> /// <param name="meshFilter">路面网格</param> /// <param name="_roadPoints">路点</param> /// <param name="_width">路面宽度</param> public static void CreateRoads(Terrain terrain, MeshFilter meshFilter, List <Vector3> wayPoints, float _width = 5) { if (wayPoints.Count < 2) { return; // 路点数量不能低于2个 } List <Vector3> _roadPoints = wayPoints; // 取出路径点 List <Vector3> vertice = new List <Vector3>(); // 顶点 List <int> triangles = new List <int>(); // 三角形排序 List <Vector2> uv = new List <Vector2>(); // uv排序 Vector3 dir = PhysicsMath.GetHorizontalDir(_roadPoints[1], _roadPoints[0]); // 获取两点间的垂直向量 vertice.Add(_roadPoints[0] + dir * _width); // 添加初始顶点 vertice.Add(_roadPoints[0] - dir * _width); uv.Add(Vector2.zero); // 添加初始顶点对应uv uv.Add(Vector2.right); for (int i = 1, count = _roadPoints.Count; i < count; i++) { // 添加由 路径点 生成的路面点集 dir = PhysicsMath.GetHorizontalDir(_roadPoints[i], _roadPoints[i - 1]); vertice.Add(_roadPoints[i] + dir * _width); vertice.Add(_roadPoints[i] - dir * _width); // 添加三jio形排序 triangles.Add(2 * i - 2); triangles.Add(2 * i); triangles.Add(2 * i - 1); triangles.Add(2 * i); triangles.Add(2 * i + 1); triangles.Add(2 * i - 1); // 添加uv排序 if (i % 2 == 1) { uv.Add(Vector2.up); uv.Add(Vector2.one); } else { uv.Add(Vector2.zero); uv.Add(Vector2.right); } } List <float> roadHeights = PointsFitToTerrain(terrain, ref vertice); // 路面高度适配地形 //TerrainUtility.ChangeHeights(terrain, _roadPoints.ToArray(), roadHeights.ToArray()); // 将道路整平 meshFilter.mesh.Clear(); meshFilter.mesh.vertices = vertice.ToArray(); meshFilter.mesh.triangles = triangles.ToArray(); meshFilter.mesh.uv = uv.ToArray(); meshFilter.mesh.RecalculateBounds(); // 重置范围 meshFilter.mesh.RecalculateNormals(); // 重置法线 meshFilter.mesh.RecalculateTangents(); // 重置切线 }
/// <summary> /// 圆柱 /// </summary> public static Mesh CreateCylinder(Vector3 buttomOrigin, float radius, float height, int colorInt = ColorInt32.white) { Vector3[] buttomSurface = PhysicsMath.GetCirclePoints(buttomOrigin, radius); List <Vector3> verticesDown = new List <Vector3>(); List <Vector3> verticesUp = new List <Vector3>(); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); //上下面坐标赋值 数组转List for (int i = 0; i < buttomSurface.Length; i++) { verticesDown.Add(buttomSurface[i]); } for (int i = 0; i < buttomSurface.Length; i++) { verticesUp.Add(buttomSurface[i] + new Vector3(0, height, 0)); } //计算一个平面的点数量 int count = verticesDown.Count; //将上下平面点合并 for (int i = 0; i < verticesDown.Count; i++) { vertices.Add(verticesDown[i]); } for (int i = 0; i < verticesUp.Count; i++) { vertices.Add(verticesUp[i]); } //获取底面和顶面的三角形排序 List <int> trianglesDown = PhysicsMath.DrawPolygon(verticesDown, false); List <int> trianglesUp = PhysicsMath.DrawPolygon(verticesUp, true); for (int i = 0; i < trianglesDown.Count; i++) { trianglesUp[i] += count; } //合并底面顶面三角形排序 for (int i = 0; i < trianglesDown.Count; i++) { triangles.Add(trianglesDown[i]); } for (int i = 0; i < trianglesUp.Count; i++) { triangles.Add(trianglesUp[i]); } //侧面三角形排序 for (int i = 0; i < count - 1; i++) { // 加上侧面的点集 vertices.Add(vertices[i]); vertices.Add(vertices[i + 1]); vertices.Add(vertices[i + count + 1]); vertices.Add(vertices[i + count]); // 侧面三角形排序 triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 0 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 2 + i * 4); } // 加上最后一个侧面的点集 vertices.Add(vertices[count - 1]); vertices.Add(vertices[0]); vertices.Add(vertices[count]); vertices.Add(vertices[2 * count - 1]); // 加上最后一个侧面的三角形排序 triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 4); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 2); Color[] colors = new Color[vertices.Count]; Color color = colorInt.Color(); for (int i = 0; i < colors.Length; ++i) { colors[i] = color; } Mesh mesh = new Mesh { name = "Cylinder", vertices = vertices.ToArray(), triangles = triangles.ToArray(), colors = colors, }; mesh.RecalculateBounds(); // 重置范围 mesh.RecalculateNormals(); // 重置法线 mesh.RecalculateTangents(); // 重置切线 return(mesh); }
static unsafe bool CastCollider( Ray ray, ref float2x2 rotation, ref DistanceProxy proxySource, ref DistanceProxy proxyTarget, out ColliderCastHit hit) { hit = default; var transformSource = new PhysicsTransform { Translation = ray.Origin, Rotation = rotation }; // Check we're not initially overlapped. if ((proxySource.VertexCount < 3 || proxyTarget.VertexCount < 3) && OverlapQueries.OverlapConvexConvex(ref transformSource, ref proxySource, ref proxyTarget)) { return(false); } // B = Source // A = Target var radiusSource = proxySource.ConvexRadius; var radiusTarget = proxyTarget.ConvexRadius; var totalRadius = radiusSource + radiusTarget; var invRotation = math.inverse(rotation); var sweepDirection = ray.Displacement; var normal = float2.zero; var lambda = 0.0f; // Initialize the simplex. var simplex = new Simplex(); simplex.Count = 0; var vertices = &simplex.Vertex1; // Get a support point in the inverse direction. var indexTarget = proxyTarget.GetSupport(-sweepDirection); var supportTarget = proxyTarget.Vertices[indexTarget]; var indexSource = proxySource.GetSupport(PhysicsMath.mul(invRotation, sweepDirection)); var supportSource = PhysicsMath.mul(transformSource, proxySource.Vertices[indexSource]); var v = supportTarget - supportSource; // Sigma is the target distance between polygons var sigma = math.max(PhysicsSettings.Constants.MinimumConvexRadius, totalRadius - PhysicsSettings.Constants.MinimumConvexRadius); const float tolerance = PhysicsSettings.Constants.LinearSlop * 0.5f; var iteration = 0; while ( iteration++ < PhysicsSettings.Constants.MaxGJKInterations && math.abs(math.length(v) - sigma) > tolerance ) { if (simplex.Count >= 3) { SafetyChecks.ThrowInvalidOperationException("ColliderCast Simplex must have less than 3 vertex."); } // Support in direction -supportV (Target - Source) indexTarget = proxyTarget.GetSupport(-v); supportTarget = proxyTarget.Vertices[indexTarget]; indexSource = proxySource.GetSupport(PhysicsMath.mul(invRotation, v)); supportSource = PhysicsMath.mul(transformSource, proxySource.Vertices[indexSource]); var p = supportTarget - supportSource; v = math.normalizesafe(v); // Intersect ray with plane. var vp = math.dot(v, p); var vr = math.dot(v, sweepDirection); if (vp - sigma > lambda * vr) { if (vr <= 0.0f) { return(false); } lambda = (vp - sigma) / vr; if (lambda > 1.0f) { return(false); } normal = -v; simplex.Count = 0; } // Reverse simplex since it works with B - A. // Shift by lambda * r because we want the closest point to the current clip point. // Note that the support point p is not shifted because we want the plane equation // to be formed in un-shifted space. var vertex = vertices + simplex.Count; vertex->IndexA = indexSource; vertex->SupportA = supportSource + lambda * sweepDirection; vertex->IndexB = indexTarget; vertex->SupportB = supportTarget; vertex->W = vertex->SupportB - vertex->SupportA; vertex->A = 1.0f; simplex.Count += 1; switch (simplex.Count) { case 1: break; case 2: simplex.Solve2(); break; case 3: simplex.Solve3(); break; default: SafetyChecks.ThrowInvalidOperationException("Simplex has invalid count."); return(default); } // If we have 3 points, then the origin is in the corresponding triangle. if (simplex.Count == 3) { // Overlap. return(false); } // Get search direction. v = simplex.GetClosestPoint(); } // Ensure we don't process an empty simplex. if (simplex.Count == 0) { return(false); } // Prepare result. var pointSource = float2.zero; var pointTarget = float2.zero; simplex.GetWitnessPoints(ref pointSource, ref pointTarget); normal = math.normalizesafe(-v); hit = new ColliderCastHit { Position = pointTarget + (normal * radiusTarget), SurfaceNormal = normal, Fraction = lambda }; return(true); }
/// <summary> /// 立体线,可用于画空中走廊 /// </summary> /// <param name="positions">空中走廊所有顶点</param> public static Mesh CreateLineMesh_Old(Vector3[] vertexs, float width, float height, int colorInt = ColorInt32.white) { Vector3[] positions = PhysicsMath.GetAirCorridorSpace(vertexs.ToList(), width, height); // 获取点集 List <Vector3> vertices = new List <Vector3>(); List <int> trangles = new List <int>(); int count = positions.Length - 4; // 左侧面 vertices.Add(positions[0]); vertices.Add(positions[1]); vertices.Add(positions[2]); vertices.Add(positions[3]); trangles.Add(3); trangles.Add(1); trangles.Add(0); trangles.Add(3); trangles.Add(2); trangles.Add(1); // 走廊框体 for (int i = 0; i < count; i++) { if (i % 4 == 3) { vertices.Add(positions[i]); vertices.Add(positions[i - 3]); vertices.Add(positions[i + 1]); vertices.Add(positions[i + 4]); } else { vertices.Add(positions[i]); vertices.Add(positions[i + 1]); vertices.Add(positions[i + 5]); vertices.Add(positions[i + 4]); } trangles.Add((i + 1) * 4); trangles.Add((i + 1) * 4 + 2); trangles.Add((i + 1) * 4 + 3); trangles.Add((i + 1) * 4); trangles.Add((i + 1) * 4 + 1); trangles.Add((i + 1) * 4 + 2); } // 右侧面 vertices.Add(positions[count]); vertices.Add(positions[count + 1]); vertices.Add(positions[count + 2]); vertices.Add(positions[count + 3]); trangles.Add(vertices.Count - 4); trangles.Add(vertices.Count - 2); trangles.Add(vertices.Count - 1); trangles.Add(vertices.Count - 4); trangles.Add(vertices.Count - 3); trangles.Add(vertices.Count - 2); Color[] colors = new Color[vertices.Count]; Color color = colorInt.Color(); for (int i = 0; i < colors.Length; ++i) { colors[i] = color; } Mesh mesh = new Mesh { name = "Line", vertices = vertices.ToArray(), triangles = trangles.ToArray(), colors = colors, }; mesh.RecalculateBounds(); // 重置范围 mesh.RecalculateNormals(); // 重置法线 mesh.RecalculateTangents(); // 重置切线 return(mesh); }
/// <summary> /// 凹/凸多边形空域 每个点高度不一样时 可以用来画扇形区域 /// </summary> /// <param name="positions"></param> public static Mesh CreatePolygon(Vector3[] positions, int colorInt = ColorInt32.white) { List <Vector3> verticesDown = new List <Vector3>(); List <Vector3> verticesUp = new List <Vector3>(); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); //上下面坐标赋值 数组转List for (int i = 0; i < positions.Length / 2; i++) { verticesDown.Add(positions[i]); } for (int i = positions.Length / 2; i < positions.Length; i++) { verticesUp.Add(positions[i]); } //计算一个平面的点数量 int count = verticesDown.Count; //将上下平面点合并 for (int i = 0; i < verticesDown.Count; i++) { vertices.Add(verticesDown[i]); } for (int i = 0; i < verticesUp.Count; i++) { vertices.Add(verticesUp[i]); } //获取底面和顶面的三角形排序 List <int> trianglesDown = PhysicsMath.DrawPolygon(verticesDown, false); List <int> trianglesUp = PhysicsMath.DrawPolygon(verticesUp, true); for (int i = 0; i < trianglesDown.Count; i++) { trianglesUp[i] += count; } //合并底面顶面三角形排序 for (int i = 0; i < trianglesDown.Count; i++) { triangles.Add(trianglesDown[i]); } for (int i = 0; i < trianglesUp.Count; i++) { triangles.Add(trianglesUp[i]); } //侧面三角形排序 for (int i = 0; i < count - 1; i++) { // 加上侧面的点集 vertices.Add(vertices[i]); vertices.Add(vertices[i + 1]); vertices.Add(vertices[i + count + 1]); vertices.Add(vertices[i + count]); // 侧面三角形排序 triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 0 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 2 + i * 4); } // 加上最后一个侧面的点集 vertices.Add(vertices[count - 1]); vertices.Add(vertices[0]); vertices.Add(vertices[count]); vertices.Add(vertices[2 * count - 1]); // 加上最后一个侧面的三角形排序 triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 4); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 2); Color[] colors = new Color[vertices.Count]; Color color = colorInt.Color(); for (int i = 0; i < colors.Length; ++i) { colors[i] = color; } Mesh mesh = new Mesh { name = "Polygon", vertices = vertices.ToArray(), triangles = triangles.ToArray(), colors = colors, }; mesh.RecalculateBounds(); // 重置范围 mesh.RecalculateNormals(); // 重置法线 mesh.RecalculateTangents(); // 重置切线 return(mesh); }
/// <summary> /// 立体线,可用于画空中走廊 /// </summary> /// <param name="_bottomList">下底面排序</param> /// <param name="_width">宽度</param> /// <param name="_height">高度</param> /// <returns></returns> public static Mesh CreateLineMesh(List <Vector3> list, float _width, float _height, int colorInt = ColorInt32.white) { Vector3[] bottomPoints = PhysicsMath.GetAirSpaceBottomPoints(list, _width, _height); Vector3[] vertices = PhysicsMath.GetAirBottomSpaceWithSector(bottomPoints.ToList(), _width); // 计算Mesh int _squareCount = list.Count - 1; var _bottomList = vertices.ToList(); List <Vector3> outList = new List <Vector3>(); //输出点集合 List <Vector3> topList = new List <Vector3>(); //顶面点集合 List <Vector3> allSquareList = new List <Vector3>(); // 所有矩形点集 List <Vector3> allArcList = new List <Vector3>(); // 所有弧形点集 List <int> triangles = new List <int>(); // 存储三角形排序集合 foreach (var item in _bottomList) { topList.Add(item + Vector3.up * _height);// 添加顶面点集 } #region 矩形所有 //合并矩形上下底面点集 for (int i = 0; i < _squareCount * 4; i += 2) { allSquareList.Add(_bottomList[i]); allSquareList.Add(_bottomList[i + 1]); allSquareList.Add(topList[i + 1]); allSquareList.Add(topList[i]); } int bottomCount = _bottomList.Count; //画最左侧面 outList.Add(allSquareList[0]); outList.Add(allSquareList[1]); outList.Add(allSquareList[2]); outList.Add(allSquareList[3]); triangles.Add(3); triangles.Add(0); triangles.Add(1); triangles.Add(3); triangles.Add(1); triangles.Add(2); //获得矩形区域点集合 4是为了去除左侧四个点 for (int i = 0; i < _squareCount; i++) { for (int j = 0; j < 4; j++) { //取余对内层循环的最后一次做处理 (i * 8)是为了去除前面i个矩形的点 if (j % 4 == 3) { outList.Add(allSquareList[i * 8 + j]); outList.Add(allSquareList[i * 8 + (j - 3)]); outList.Add(allSquareList[i * 8 + (j + 1)]); outList.Add(allSquareList[i * 8 + (j + 4)]); } else { //以下四个点是组成了矩形的一个面 outList.Add(allSquareList[i * 8 + j]); outList.Add(allSquareList[i * 8 + j + 1]); outList.Add(allSquareList[i * 8 + j + 5]); outList.Add(allSquareList[i * 8 + j + 4]); } // 第一个4是为了去除左侧面的四个点,16是为了去除一个矩形四个面的16个点,第二个4是为了去除内层循环j个面的点 triangles.Add(4 + i * 16 + j * 4); triangles.Add(4 + i * 16 + j * 4 + 2); triangles.Add(4 + i * 16 + j * 4 + 1); triangles.Add(4 + i * 16 + j * 4); triangles.Add(4 + i * 16 + j * 4 + 3); triangles.Add(4 + i * 16 + j * 4 + 2); } } //画最右侧面 outList.Add(allSquareList[allSquareList.Count - 4]); outList.Add(allSquareList[allSquareList.Count - 3]); outList.Add(allSquareList[allSquareList.Count - 2]); outList.Add(allSquareList[allSquareList.Count - 1]); triangles.Add(outList.Count - 1); triangles.Add(outList.Count - 3); triangles.Add(outList.Count - 4); triangles.Add(outList.Count - 1); triangles.Add(outList.Count - 2); triangles.Add(outList.Count - 3); #endregion #region 弧形所有 int squarePointCount = outList.Count; // 记录用于画矩形的点的数量 int squareBottomCount = _squareCount * 4; // 记录底面矩形点的数量 // 添加弧形底面点 for (int i = squareBottomCount; i < _bottomList.Count; i++) { outList.Add(_bottomList[i]); } // 添加弧形顶面点 for (int i = squareBottomCount; i < _bottomList.Count; i++) { outList.Add(_bottomList[i] + Vector3.up * _height); } // 弧形顶面和底面三角形排序 for (int i = 0; i < _squareCount - 1; i++) { for (int j = 1; j < 11; j++) { triangles.Add(squarePointCount + i * 12); triangles.Add(squarePointCount + i * 12 + j + 1); triangles.Add(squarePointCount + i * 12 + j); } } for (int i = _squareCount - 1; i < (_squareCount - 1) * 2; i++) { for (int j = 1; j < 11; j++) { triangles.Add(squarePointCount + i * 12); triangles.Add(squarePointCount + i * 12 + j); triangles.Add(squarePointCount + i * 12 + j + 1); } } int prePointCount = outList.Count; // 记录当前输出集合的点的数量 // 添加弧形侧面点集 for (int i = squareBottomCount; i < _bottomList.Count; i++) { outList.Add(_bottomList[i]); outList.Add(_bottomList[i] + Vector3.up * _height); } // 弧形侧面三角形排序 for (int i = 0; i < _squareCount - 1; i++) { //j从2开始去除两个弧心点,i*24是为了去除每次内层循环后加入的22个点 for (int j = 2; j < 22; j += 2) { triangles.Add(prePointCount + i * 24 + j); triangles.Add(prePointCount + i * 24 + j + 3); triangles.Add(prePointCount + i * 24 + j + 1); triangles.Add(prePointCount + i * 24 + j); triangles.Add(prePointCount + i * 24 + j + 2); triangles.Add(prePointCount + i * 24 + j + 3); } } #endregion Color[] colors = new Color[outList.Count]; Color color = colorInt.Color(); for (int i = 0; i < colors.Length; ++i) { colors[i] = color; } Mesh mesh = new Mesh { name = "LineMesh", vertices = outList.ToArray(), triangles = triangles.ToArray(), colors = colors, }; mesh.RecalculateBounds(); // 重置范围 mesh.RecalculateNormals(); // 重置法线 mesh.RecalculateTangents(); // 重置切线 return(mesh); }
public override void OnUpdate() { MouseLeft(); // 路面创建测试 if (Input.GetKeyDown(KeyCode.K)) { List <Vector3> points_out = new List <Vector3>(); List <Vector3> points_in = new List <Vector3>(); Vector3 dirr; dirr = PhysicsMath.GetHorizontalDir(positions[1] - positions[0]); points_in.Add(positions[0] + dirr * 4); points_out.Add(positions[0] - dirr * 4); for (int i = 1; i < positions.Count - 1; i++) { dirr = PhysicsMath.GetHorizontalDir(positions[i + 1] - positions[i - 1]); points_in.Add(positions[i] + dirr * 4); points_out.Add(positions[i] - dirr * 4); } dirr = PhysicsMath.GetHorizontalDir(positions[positions.Count - 1] - positions[positions.Count - 2]); points_in.Add(positions[positions.Count - 1] + dirr * 4); points_out.Add(positions[positions.Count - 1] - dirr * 4); for (int i = 0; i < positions.Count; i++) { outCurve.AddNode(points_out[i], c); inCurve.AddNode(points_in[i], c); centerCurve.AddNode(positions[i], c); } outCurve.AddCatmull_RomControl(); inCurve.AddCatmull_RomControl(); centerCurve.AddCatmull_RomControl(); for (int i = 0; i < outCurve.segmentList.Count; i++) { float add = 1f / 20; for (float j = 0; j < 1; j += add) { Vector3 point = centerCurve.segmentList[i].GetPoint(j); path.Add(point); objs.Add(Utility.CreatPrimitiveType(PrimitiveType.Sphere, Color.red, point, 1)); //point = outCurve.segmentList[i].GetPoint(j); //path.Add(point); //objs.Add(Utility.CreatPrimitiveType(PrimitiveType.Sphere, point, 1, Color.red)); //point = inCurve.segmentList[i].GetPoint(j); //path.Add(point); //objs.Add(Utility.CreatPrimitiveType(PrimitiveType.Sphere, point, 1, Color.red)); } } CreateRoads(Terrain.activeTerrain, meshFilter, path, 6); } if (Input.GetKeyDown(KeyCode.C)) { meshFilter.mesh.Clear(); objs.ForEach((a) => { Object.Destroy(a); }); objs.Clear(); outCurve = new SplineCurve(); inCurve = new SplineCurve(); centerCurve = new SplineCurve(); positions.Clear(); path.Clear(); } if (Input.GetKeyDown(KeyCode.J)) { hit = Utility.SendRay(LayerMask.GetMask("Terrain")); } // 刷新地图 if (Input.GetKeyDown(KeyCode.L)) { //TerrainUtility.Refresh(); } }
/// <summary> /// 凹多边形空域 每个点高度不一样时 可以用来画扇形区域 /// </summary> /// <param name="positions"></param> /// <param name="meshFilter"></param> /// <param name="lineRenderers"></param> public static void DrawPolygon(Vector3[] positions, MeshFilter meshFilter, LineRenderer[] lineRenderers, Color BoradColor) { List <Vector3> verticesDown = new List <Vector3>(); List <Vector3> verticesUp = new List <Vector3>(); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); //上下面坐标赋值 数组转List for (int i = 0; i < positions.Length / 2; i++) { verticesDown.Add(positions[i]); } for (int i = positions.Length / 2; i < positions.Length; i++) { verticesUp.Add(positions[i]); } //计算一个平面的点数量 int count = verticesDown.Count; //将上下平面点合并 for (int i = 0; i < verticesDown.Count; i++) { vertices.Add(verticesDown[i]); } for (int i = 0; i < verticesUp.Count; i++) { vertices.Add(verticesUp[i]); } //获取底面和顶面的三角形排序 List <int> trianglesDown = PhysicsMath.DrawPolygon(verticesDown, false); List <int> trianglesUp = PhysicsMath.DrawPolygon(verticesUp, true); for (int i = 0; i < trianglesDown.Count; i++) { trianglesUp[i] += count; } //合并底面顶面三角形排序 for (int i = 0; i < trianglesDown.Count; i++) { triangles.Add(trianglesDown[i]); } for (int i = 0; i < trianglesUp.Count; i++) { triangles.Add(trianglesUp[i]); } //侧面三角形排序 for (int i = 0; i < count - 1; i++) { // 加上侧面的点集 vertices.Add(vertices[i]); vertices.Add(vertices[i + 1]); vertices.Add(vertices[i + count + 1]); vertices.Add(vertices[i + count]); // 侧面三角形排序 triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 0 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 2 + i * 4); } // 加上最后一个侧面的点集 vertices.Add(vertices[count - 1]); vertices.Add(vertices[0]); vertices.Add(vertices[count]); vertices.Add(vertices[2 * count - 1]); // 加上最后一个侧面的三角形排序 triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 4); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 2); meshFilter.mesh.vertices = vertices.ToArray(); meshFilter.mesh.triangles = triangles.ToArray(); meshFilter.mesh.RecalculateBounds(); // 重置范围 meshFilter.mesh.RecalculateNormals(); // 重置法线 meshFilter.mesh.RecalculateTangents(); // 重置切线 //设置LineRenderer属性 foreach (var item in lineRenderers) { item.startWidth = 5; item.endWidth = 5; item.positionCount = 2; item.startColor = BoradColor; item.endColor = BoradColor; } lineRenderers[0].positionCount = positions.Length + 1; //画两个弧面线及和圆心点的连接线 for (int i = 0; i < positions.Length; i++) { lineRenderers[0].SetPosition(i, positions[i]); } lineRenderers[0].SetPosition(positions.Length, positions[0]); lineRenderers[1].SetPosition(0, positions[1]); lineRenderers[1].SetPosition(1, positions[positions.Length / 2 + 1]); lineRenderers[2].SetPosition(0, positions[positions.Length / 2 - 1]); lineRenderers[2].SetPosition(1, positions[positions.Length - 1]); }
private void CreatSector_2() { Vector3[] points = PhysicsMath.GetSectorPoints_2(positions[0], new Vector3(positions[1].x, positions[0].y, positions[1].z), alpha, theta); MeshManager.Instance.CreateSector(positions[0], positions[1], alpha, theta, sectorColor); }
/// <summary> /// 凹多边形空域 每个点高度不一样时 可以用来画扇形区域 /// </summary> /// <param name="positions"></param> /// <param name="meshFilter"></param> /// <param name="lineRenderers"></param> public static void DrawPolygon(Vector3Extend[] positions, MeshFilter meshFilter) { List <Vector3> verticesDown = new List <Vector3>(); List <Vector3> verticesUp = new List <Vector3>(); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); //上下面坐标赋值 数组转List for (int i = 0; i < positions.Length; i++) { verticesDown.Add(positions[i].position); } for (int i = 0; i < positions.Length; i++) { verticesUp.Add(positions[i].position + new Vector3(0, positions[i].height, 0)); } //计算一个平面的点数量 int count = verticesDown.Count; //将上下平面点合并 for (int i = 0; i < verticesDown.Count; i++) { vertices.Add(verticesDown[i]); } for (int i = 0; i < verticesUp.Count; i++) { vertices.Add(verticesUp[i]); } //获取底面和顶面的三角形排序 List <int> trianglesDown = PhysicsMath.DrawPolygon(verticesDown, false); List <int> trianglesUp = PhysicsMath.DrawPolygon(verticesUp, true); for (int i = 0; i < trianglesDown.Count; i++) { trianglesUp[i] += count; } //合并底面顶面三角形排序 for (int i = 0; i < trianglesDown.Count; i++) { triangles.Add(trianglesDown[i]); } for (int i = 0; i < trianglesUp.Count; i++) { triangles.Add(trianglesUp[i]); } //侧面三角形排序 for (int i = 0; i < count - 1; i++) { // 加上侧面的点集 vertices.Add(vertices[i]); vertices.Add(vertices[i + 1]); vertices.Add(vertices[i + count + 1]); vertices.Add(vertices[i + count]); // 侧面三角形排序 triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 0 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 1 + i * 4); triangles.Add(2 * count + 3 + i * 4); triangles.Add(2 * count + 2 + i * 4); } // 加上最后一个侧面的点集 vertices.Add(vertices[count - 1]); vertices.Add(vertices[0]); vertices.Add(vertices[count]); vertices.Add(vertices[2 * count - 1]); // 加上最后一个侧面的三角形排序 triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 4); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 2); meshFilter.mesh.vertices = vertices.ToArray(); meshFilter.mesh.triangles = triangles.ToArray(); meshFilter.mesh.RecalculateBounds(); // 重置范围 meshFilter.mesh.RecalculateNormals(); // 重置法线 meshFilter.mesh.RecalculateTangents(); // 重置切线 }
/// <summary> /// 获取凹多边形平面排序 /// </summary> /// <param name="points"> 关键点集合 </param> /// <returns></returns> public static List <int> GetPolygonSort(List <Vector3> points, bool isUp) { List <int> indexs = new List <int>(); for (int i = 0; i < points.Count; i++) { indexs.Add(i); } List <int> triangles = new List <int>(); //创建一个除去自身前一点的 多边形,判断前一点是否为内点(凹点) int index = points.Count - 1; int next; int prev; int maxCount = indexs.Count + 1; int count = 0; // 切分到无法切割三角形为止 while (indexs.Count > 2) { if (maxCount > indexs.Count) // 正确 { maxCount = indexs.Count; count = 0; } else { if (count > maxCount) { throw new System.Exception("当前有" + (count - 1).ToString() + "个数据死在循环中"); } count++; } // 判断要判断是否切割的三角形的三个点是否在同一位置 next = (index == indexs.Count - 1) ? 0 : index + 1; prev = (index == 0) ? indexs.Count - 1 : index - 1; if (points[index] == points[prev] && points[index] == points[next]) { throw new System.Exception("[DrawPolygon data error]三个点的个位置两两相等"); } List <Vector3> polygon = new List <Vector3>(points.ToArray()); polygon.RemoveAt(index); //是否是凹点 if (!PhysicsMath.IsPointInsidePolygon(points[index], polygon)) { // 是否是可划分顶点:新的多边形没有顶点在被分割的三角形内 if (PhysicsMath.IsFragementIndex(points, index)) { //可划分,剖分三角形 next = (index == indexs.Count - 1) ? 0 : index + 1; prev = (index == 0) ? indexs.Count - 1 : index - 1; if (isUp) { triangles.Add(indexs[next]); triangles.Add(indexs[prev]); triangles.Add(indexs[index]); } else { triangles.Add(indexs[index]); triangles.Add(indexs[prev]); triangles.Add(indexs[next]); } indexs.RemoveAt(index); points.RemoveAt(index); index = (index + indexs.Count - 1) % indexs.Count; // 防止出现index超出值域,类似于i-- continue; } } index = (index + 1) % indexs.Count; } return(triangles); }