public static ColliderPrefab CreateColliderPrefab(ColliderData data) { CBaseShape collider = null; if (LMath.Abs(data.deg - 45) < 1) { } //warning data.deg is unity deg //changed unity deg to ccw deg var collisionDeg = -data.deg + 90; if (data.radius > 0) { //circle collider = new CCircle(data.radius); } else { //obb collider = new COBB(data.size, collisionDeg); } collider.high = data.high; var colFab = new ColliderPrefab(); colFab.parts.Add(new ColliderPart() { transform = new CTransform2D(data.pos, data.y, data.deg), collider = collider }); return(colFab); }
public bool ContainsCircle(LVector2 circleCenter, LFloat radius) { var center = _bounds.center; var dx = LMath.Abs(circleCenter.x - center.x); var dy = LMath.Abs(circleCenter.y - center.y); if (dx > (_bounds.width / 2 + radius)) { return(false); } if (dy > (_bounds.height / 2 + radius)) { return(false); } if (dx <= (_bounds.width / 2)) { return(true); } if (dy <= (_bounds.height / 2)) { return(true); } var dsx = (dx - _bounds.width / 2); var dsy = (dy - _bounds.height / 2); var cornerDist = dsx * dsx + dsy * dsy; return(cornerDist <= (radius * radius)); }
public static bool TestAABBAABB(LVector2 posA, LFloat rA, LVector2 sizeA, LVector2 posB, LFloat rB, LVector2 sizeB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var absX = LMath.Abs(diff.x); var absY = LMath.Abs(diff.y); //AABB and AABB var allSize = sizeA + sizeB; if (absX > allSize.x) { return(false); } if (absY > allSize.y) { return(false); } return(true); }
/// <summary> /// /// </summary> /// <param name="o">射线起点</param> /// <param name="d">射线终点</param> /// <param name="min">矩形的左下角坐标</param> /// <param name="max">矩形的右上角坐标</param> /// <param name="tmin">返回距离</param> /// <returns></returns> public static bool TestRayAABB(LVector2 o, LVector2 d, LVector2 min, LVector2 max, out LFloat tmin) { tmin = LFloat.zero; LFloat tmax = LFloat.FLT_MAX; for (int i = 0; i < 2; i++) { if (LMath.Abs(d[i]) < LFloat.EPSILON) { if (o[i] < min[i] || o[i] > max[i]) { return(false); } } else { LFloat ood = LFloat.one / d[i]; LFloat t1 = (min[i] - o[i]) * ood; LFloat t2 = (max[i] - o[i]) * ood; if (t1 > t2) { var temp = t1; t1 = t2; t2 = temp; } tmin = LMath.Max(tmin, t1); tmax = LMath.Min(tmax, t2); if (tmin > tmax) { return(false); } } } return(true); }
public static bool TestAABBOBB(LVector2 posA, LFloat rA, LVector2 sizeA, LVector2 posB, LFloat rB, LVector2 sizeB, LVector2 upB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var absUPX = LMath.Abs(upB.x); //abs(up dot aabb.right) var absUPY = LMath.Abs(upB.y); //abs(right dot aabb.right) { //轴 投影 AABBx var distX = absUPX * sizeB.y + absUPY * sizeB.x; if (LMath.Abs(diff.x) > distX + sizeA.x) { return(false); } //轴 投影 AABBy //absUPX is abs(right dot aabb.up) //absUPY is abs(up dot aabb.up) var distY = absUPY * sizeB.y + absUPX * sizeB.x; if (LMath.Abs(diff.y) > distY + sizeA.y) { return(false); } } { var right = new LVector2(upB.y, -upB.x); var diffPObbX = LVector2.Dot(diff, right); var diffPObbY = LVector2.Dot(diff, upB); //absUPX is abs(aabb.up dot right ) //absUPY is abs(aabb.right dot right) //轴 投影 OBBx var distX = absUPX * sizeA.y + absUPY * sizeA.x; if (LMath.Abs(diffPObbX) > distX + sizeB.x) { return(false); } //absUPX is abs(aabb.right dot up ) //absUPY is abs(aabb.up dot up) //轴 投影 OBBy var distY = absUPY * sizeA.y + absUPX * sizeA.x; if (LMath.Abs(diffPObbY) > distY + sizeB.y) { return(false); } } return(true); }
public LFloat height; // 高 /** * 数据检测,客户端的顶点坐标和三角形数据有可能是重复的ç∂ * TODO 小三角形合并成大三角形或多边形;判断顶点是否在寻路层中,寻路层中的顶点不能作为路径点;两点所连线段是否穿过阻挡区,不穿过,直接获取坐标点 */ public void check(int scale) { amendmentSameVector(pathTriangles, pathVertices); scaleVector(pathVertices, scale); this.width = LMath.Abs(this.getEndX() - this.getStartX()); this.height = LMath.Abs(this.getEndZ() - this.getStartZ()); }
public static LFloat RoundIfNear(LFloat val, LFloat roundDist) { var roundVal = LMath.Round(val); var diff = LMath.Abs(val - roundVal); if (diff < roundDist) { return(roundVal); } return(val); }
public static bool CheckCollision(LVector2 posA, LFloat rA, LVector2 sizeA, LVector2 posB, LFloat rB, LVector2 sizeB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var isBoxA = sizeA != LVector2.zero; var isBoxB = sizeB != LVector2.zero; if (!isBoxA && !isBoxB) { return(true); } var absX = LMath.Abs(diff.x); var absY = LMath.Abs(diff.y); if (isBoxA && isBoxB) { //AABB and AABB var allSize = sizeA + sizeB; if (absX > allSize.x) { return(false); } if (absY > allSize.y) { return(false); } return(true); } else { //AABB & circle var size = sizeB; var radius = rA; if (isBoxA) { size = sizeA; radius = rB; } var x = LMath.Max(absX - size.x, LFloat.zero); var y = LMath.Max(absY - size.y, LFloat.zero); return(x * x + y * y < radius * radius); } }
public static LVector2 GetIntersectPoint(LVector2 p0, LVector2 p1, LVector2 p2, LVector2 p3) { var diff = p2 - p0; var d1 = p1 - p0; var d2 = p3 - p2; var demo = LMath.Cross2D(d1, d2); //det if (LMath.Abs(demo) < LFloat.EPSILON) //parallel { return(p0); } var t1 = LMath.Cross2D(diff, d2) / demo; // Cross2D(diff,-d2) return(p0 + (p1 - p0) * t1); }
private void _OnTriggerEnter(ColliderProxy other) { if (_curPart.collider.IsCircle && _curPart.collider.deg > 0) { var deg = (other.Transform2D.pos - owner.transform.pos).ToDeg(); var degDiff = owner.transform.deg.Abs() - deg; if (LMath.Abs(degDiff) <= _curPart.collider.deg) { _tempTargets.Add(other); } } else { _tempTargets.Add(other); } }
//private static readonly HashSet<Entity> _tempEntities = new HashSet<Entity>(); private void _OnTriggerEnter(ColliderProxy other) { if (CurPart.collider.IsCircle && CurPart.collider.deg > 0) { var deg = (other.Transform2D.pos - entity.transform.pos).ToDeg(); var degDiff = entity.transform.deg.Abs() - deg; if (LMath.Abs(degDiff) <= CurPart.collider.deg) { _tempEntities.Add(other.Entity); } } else { _tempEntities.Add(other.Entity); } }
public void DoUpdate(LFloat deltaTime) { var curPos = Transform2D.pos; if (_prePos != curPos) { _prePos = curPos; IsMoved = true; } var curDeg = Transform2D.deg; if (LMath.Abs(curDeg - _preDeg) > DegGap) { _preDeg = curDeg; IsMoved = true; } }
/// <summary> /// sqrt(a^2 + b^2) without under/overflow. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static LFloat Hypot(LFloat a, LFloat b) { LFloat r; if (LMath.Abs(a) > LMath.Abs(b)) { r = b / a; r = LMath.Abs(a) * LMath.Sqrt(1 + r * r); } else if (b != 0) { r = a / b; r = LMath.Abs(b) * LMath.Sqrt(1 + r * r); } else { r = 0d; } return(r); }
/// <summary> /// /// </summary> /// <param name="o">射线的起点</param> /// <param name="d1">射线的终点</param> /// <param name="p2">多边形的顶点</param> /// <param name="p3">多边形相邻的顶点(和p2 组成线段)</param> /// <returns>返回大于等于0时 说明相交</returns> public static LFloat TestRaySegment(LVector2 o, LVector2 d1, LVector2 p2, LVector2 p3) { LVector2 diff = p2 - o; LVector2 d2 = p3 - p2; // 叉乘的结果如过为0 说明平行 LFloat dome = LMath.Cross2D(d1, d2); if (LMath.Abs(dome) < LFloat.EPSILON) { return(LFloat.negOne); } LFloat t1 = LMath.Cross2D(d2, diff); LFloat t2 = LMath.Cross2D(d1, diff); if (t1 >= 0 && (t2 >= 0 && t2 <= 1)) { return(t1); } return(LFloat.negOne); }
public static LFloat TestRaySegment(LVector2 o, LVector2 d1, LVector2 p2, LVector2 p3) { var diff = p2 - o; var d2 = p3 - p2; var demo = Cross2D(d1, d2); //det if (LMath.Abs(demo) < LFloat.EPSILON) //parallel { return(LFloat.negOne); } var t1 = Cross2D(d2, diff) / demo; // Cross2D(diff,-d2) var t2 = Cross2D(d1, diff) / demo; //Dot(v1,pd0) == cross(d0,d1) if (t1 >= 0 && (t2 >= 0 && t2 <= 1)) { return(t1); } return(LFloat.negOne); }
public static bool TestCircleAABB(LVector2 posA, LFloat rA, LVector2 posB, LFloat rB, LVector2 sizeB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var absX = LMath.Abs(diff.x); var absY = LMath.Abs(diff.y); //AABB & circle var size = sizeB; var radius = rA; var x = LMath.Max(absX - size.x, LFloat.zero); var y = LMath.Max(absY - size.y, LFloat.zero); return(x * x + y * y < radius * radius); }
public static bool TestCircleOBB(LVector2 posA, LFloat rA, LVector2 posB, LFloat rB, LVector2 sizeB, LVector2 up) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定CollisionHelper if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } //空间转换 var absX = LMath.Abs(LVector2.Dot(diff, new LVector2(up.y, -up.x))); var absY = LMath.Abs(LVector2.Dot(diff, up)); var size = sizeB; var radius = rA; var x = LMath.Max(absX - size.x, LFloat.zero); var y = LMath.Max(absY - size.y, LFloat.zero); return(x * x + y * y < radius * radius); }
public static LFloat TestSegmentSegment(LVector2 p0, LVector2 p1, LVector2 p2, LVector2 p3) { LVector2 diff = p2 - p0; LVector2 d1 = p1 - p0; LVector2 d2 = p3 - p2; var demo = LMath.Cross2D(d1, d2); if (LMath.Abs(demo) < LFloat.EPSILON) //parallel { return(LFloat.negOne); } var t1 = LMath.Cross2D(d2, diff) / demo; // Cross2D(diff,-d2) var t2 = LMath.Cross2D(d1, diff) / demo; //Dot(v1,pd0) == cross(d0,d1) if ((t1 >= 0 && t1 <= 1) && (t2 >= 0 && t2 <= 1)) { return(t1); // return p0 + (p1-p0) * t1 } return(LFloat.negOne); }
public static bool TestOBBOBB(LVector2 posA, LFloat rA, LVector2 sizeA, LVector2 upA, LVector2 posB, LFloat rB, LVector2 sizeB, LVector2 upB) { var diff = posA - posB; var allRadius = rA + rB; //circle 判定 if (diff.sqrMagnitude > allRadius * allRadius) { return(false); } var rightA = new LVector2(upA.y, -upA.x); var rightB = new LVector2(upB.y, -upB.x); { //轴投影到 A.right var BuProjAr = LMath.Abs(LVector2.Dot(upB, rightA)); var BrProjAr = LMath.Abs(LVector2.Dot(rightB, rightA)); var DiffProjAr = LMath.Abs(LVector2.Dot(diff, rightA)); var distX = BuProjAr * sizeB.y + BrProjAr * sizeB.x; if (DiffProjAr > distX + sizeA.x) { return(false); } //轴投影到 A.up var BuProjAu = LMath.Abs(LVector2.Dot(upB, upA)); var BrProjAu = LMath.Abs(LVector2.Dot(rightB, upA)); var DiffProjAu = LMath.Abs(LVector2.Dot(diff, upA)); var distY = BuProjAu * sizeB.y + BrProjAu * sizeB.x; if (DiffProjAu > distY + sizeA.y) { return(false); } } { //轴投影到 B.right var AuProjBr = LMath.Abs(LVector2.Dot(upA, rightB)); var ArProjBr = LMath.Abs(LVector2.Dot(rightA, rightB)); var DiffProjBr = LMath.Abs(LVector2.Dot(diff, rightB)); var distX = AuProjBr * sizeA.y + ArProjBr * sizeA.x; if (DiffProjBr > distX + sizeB.x) { return(false); } //轴投影到 B.right var AuProjBu = LMath.Abs(LVector2.Dot(upA, upB)); var ArProjBu = LMath.Abs(LVector2.Dot(rightA, upB)); var DiffProjBu = LMath.Abs(LVector2.Dot(diff, upB)); var distY = AuProjBu * sizeA.y + ArProjBu * sizeA.x; if (DiffProjBu > distY + sizeB.x) { return(false); } } return(true); }
public static bool IsZero(LFloat value) { return(LMath.Abs(value) <= GeometryUtil.FLOAT_ROUNDING_ERROR); }
/// <summary> /// 夹角大小 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static LFloat Angle(LQuaternion a, LQuaternion b) { LFloat single = Dot(a, b); return(LMath.Acos(LMath.Min(LMath.Abs(single), LFloat.one)) * 2 * (180 / LMath.PI)); }