public static void Equal() { bool result = true; for (int i = 0; i < NUM_TESTS; i++) { bool3 x = TestData_LHS[i] == TestData_RHS[i]; result &= x.Equals(new bool3(TestData_LHS[i].x == TestData_RHS[i].x, TestData_LHS[i].y == TestData_RHS[i].y, TestData_LHS[i].z == TestData_RHS[i].z)); } Assert.AreEqual(true, result); }
public static void GreaterThanOrEqual() { bool result = true; for (int i = 0; i < NUM_TESTS; i++) { bool3 x = TestData_LHS[i] >= TestData_RHS[i]; result &= x.Equals(new bool3(TestData_LHS[i].x >= TestData_RHS[i].x, TestData_LHS[i].y >= TestData_RHS[i].y, TestData_LHS[i].z >= TestData_RHS[i].z)); } Assert.AreEqual(true, result); }
private JobHandle BuildRadarLayer(FactionMember factionMember, out CollisionLayer layer, JobHandle inputDeps) { m_radars.SetSharedComponentFilter(factionMember); int count = m_radars.CalculateEntityCount(); var bodies = new NativeArray <ColliderBody>(count, Allocator.TempJob); var aabbs = new NativeArray <Aabb>(count, Allocator.TempJob); var jh = Entities.WithAll <AiRadarTag>().WithSharedComponentFilter(factionMember).WithStoreEntityQueryInField(ref m_radars) .ForEach((Entity e, int entityInQueryIndex, in AiShipRadar radar, in LocalToWorld ltw) => { var transform = new RigidTransform(quaternion.LookRotationSafe(ltw.Forward, ltw.Up), ltw.Position); var sphere = new SphereCollider(0f, radar.distance); if (radar.cosFov < 0f) { //Todo: Create tighter bounds here too. aabbs[entityInQueryIndex] = Physics.CalculateAabb(sphere, transform); } else { //Compute aabb of vertex and spherical cap points which are extreme points float3 forward = math.forward(transform.rot); bool3 positiveOnSphereCap = forward > radar.cosFov; bool3 negativeOnSphereCap = -forward > radar.cosFov; float3 min = math.select(0f, -radar.distance, negativeOnSphereCap); float3 max = math.select(0f, radar.distance, positiveOnSphereCap); Aabb aabb = new Aabb(min, max); //Compute aabb of circle base float4 cos = new float4(forward, radar.cosFov); float4 sinSq = 1f - (cos * cos); float4 sin = math.sqrt(sinSq); float3 center = forward * radar.distance * radar.cosFov; float radius = radar.distance * sin.w; float3 extents = sin.xyz * radius; min = center - extents; max = center + extents; aabb.min = math.min(aabb.min, min) + transform.pos; aabb.max = math.max(aabb.max, max) + transform.pos; aabbs[entityInQueryIndex] = aabb; } bodies[entityInQueryIndex] = new ColliderBody { collider = sphere, entity = e, transform = transform }; }).ScheduleParallel(inputDeps);
public static long3 negate(long3 x, bool3 p) { Assert.IsSafeBoolean(p.x); Assert.IsSafeBoolean(p.y); Assert.IsSafeBoolean(p.z); if (Avx2.IsAvx2Supported) { long3 mask = (sbyte3)Sse2.cmpgt_epi8(*(v128 *)&p, default(v128)); return((x ^ mask) - mask); } else { return(new long3(negate(x.xy, p.xy), negate(x.z, p.z))); } }
// BoxBox() helper private static bool PointPlanes(MTransform aFromB, float3 halfExtA, float3 halfExtB, float maxDistance, ref float3 normalOut, ref float distanceOut) { // Calculate the AABB of box B in A-space Aabb aabbBinA; { Aabb aabbBinB = new Aabb { Min = -halfExtB, Max = halfExtB }; aabbBinA = Math.TransformAabb(aFromB, aabbBinB); } // Check for a miss float3 toleranceHalfExt = halfExtA + maxDistance; bool3 miss = (aabbBinA.Min > toleranceHalfExt) | (-toleranceHalfExt > aabbBinA.Max); if (math.any(miss)) { return(false); } // Return the normal with minimum separating distance float3 diff0 = aabbBinA.Min - halfExtA; // positive normal float3 diff1 = -aabbBinA.Max - halfExtA; // negative normal bool3 greater01 = diff0 > diff1; float3 max01 = math.select(diff1, diff0, greater01); distanceOut = math.cmax(max01); int axis = IndexOfMaxComponent(max01); if (axis == 0) { normalOut = new float3(1.0f, 0.0f, 0.0f); } else if (axis == 1) { normalOut = new float3(0.0f, 1.0f, 0.0f); } else { normalOut = new float3(0.0f, 0.0f, 1.0f); } normalOut = math.select(normalOut, -normalOut, greater01); return(true); }
public static sbyte3 negate(sbyte3 x, bool3 p) { Assert.IsSafeBoolean(p.x); Assert.IsSafeBoolean(p.y); Assert.IsSafeBoolean(p.z); if (Sse2.IsSse2Supported) { sbyte3 mask = Sse2.cmpgt_epi8(*(v128 *)&p, default(v128)); return((x ^ mask) - mask); } else { sbyte3 mask = toint8(p); return((x ^ -mask) + mask); } }
void ConvertCharacterJoint(LegacyCharacter joint) { var linearLocks = new bool3(true); var linearLimited = new bool3(false); var angularFree = new bool3(false); var angularLocks = new bool3(false); var angularLimited = new bool3(true); var jointFrameOrientation = GetJointFrameOrientation(joint.axis, joint.swingAxis); var jointData = CreateConfigurableJoint(jointFrameOrientation, joint, linearLocks, linearLimited, new SoftJointLimit { limit = 0f, bounciness = 0f }, new SoftJointLimitSpring { spring = 0f, damper = 0f }, angularFree, angularLocks, angularLimited, joint.lowTwistLimit, joint.highTwistLimit, joint.twistLimitSpring, joint.swing1Limit, joint.swing2Limit, joint.swingLimitSpring); m_EndJointConversionSystem.CreateJointEntity(joint, GetConstrainedBodyPair(joint), jointData); }
void ConvertConfigurableJoint(LegacyConfigurable joint) { var linearLocks = new bool3 ( IsMotionLocked(joint.xMotion), IsMotionLocked(joint.yMotion), IsMotionLocked(joint.zMotion) ); var linearLimited = new bool3 ( IsMotionLimited(joint.xMotion), IsMotionLimited(joint.yMotion), IsMotionLimited(joint.zMotion) ); var angularFree = new bool3 ( IsMotionFree(joint.angularXMotion), IsMotionFree(joint.angularYMotion), IsMotionFree(joint.angularZMotion) ); var angularLocks = new bool3 ( IsMotionLocked(joint.angularXMotion), IsMotionLocked(joint.angularYMotion), IsMotionLocked(joint.angularZMotion) ); var angularLimited = new bool3 ( IsMotionLimited(joint.angularXMotion), IsMotionLimited(joint.angularYMotion), IsMotionLimited(joint.angularZMotion) ); var jointFrameOrientation = GetJointFrameOrientation(joint.axis, joint.secondaryAxis); var jointData = CreateConfigurableJoint(jointFrameOrientation, joint, linearLocks, linearLimited, joint.linearLimit, joint.linearLimitSpring, angularFree, angularLocks, angularLimited, joint.lowAngularXLimit, joint.highAngularXLimit, joint.angularXLimitSpring, joint.angularYLimit, joint.angularZLimit, joint.angularYZLimitSpring); CreateJointEntity(joint.gameObject, jointData, GetPrimaryEntity(joint.gameObject), joint.connectedBody == null ? Entity.Null : GetPrimaryEntity(joint.connectedBody), joint.enableCollision); }
public static void Bool3() { Random32 rng = new Random32(RNG_SEED); bool result = true; for (int i = 0; i < NUM_TESTS; i++) { int r = rng.NextInt(); bool3 x = maxmath.tobool3(r); for (int j = 0; j < 3; j++) { result &= x[j] == System.Convert.ToBoolean((r >> j) & 1); } } Assert.AreEqual(true, result); }
void ConvertCharacterJoint(LegacyCharacter joint) { var linearLocks = new bool3(true); var linearLimited = new bool3(false); var angularFree = new bool3(false); var angularLocks = new bool3(false); var angularLimited = new bool3(true); var jointFrameOrientation = GetJointFrameOrientation(joint.axis, joint.swingAxis); var jointData = CreateConfigurableJoint(jointFrameOrientation, joint, linearLocks, linearLimited, new SoftJointLimit { limit = 0f, bounciness = 0f }, new SoftJointLimitSpring { spring = 0f, damper = 0f }, angularFree, angularLocks, angularLimited, joint.lowTwistLimit, joint.highTwistLimit, joint.twistLimitSpring, joint.swing1Limit, joint.swing2Limit, joint.swingLimitSpring); CreateJointEntity(joint.gameObject, jointData, GetPrimaryEntity(joint.gameObject), joint.connectedBody == null ? Entity.Null : GetPrimaryEntity(joint.connectedBody), joint.enableCollision); }
bool BoxIntersectDecal(float3x4 localToWorld, float4 *planes, float3 decalMin, float3 decalMax) { float3 position = localToWorld.c3; bool3 minLargerThanMax = camMinPos > decalMax; bool3 maxLessThanMin = camMaxPos < decalMin; minLargerThanMax |= maxLessThanMin; if (minLargerThanMax.x || minLargerThanMax.y || minLargerThanMax.z || maxLessThanMin.x || maxLessThanMin.y || maxLessThanMin.z) { return(false); } for (uint i = 0; i < 6; ++i) { float4 plane = planes[i]; float3 absNormal = abs(mul(plane.xyz, float3x3(localToWorld.c0, localToWorld.c1, localToWorld.c2))); if ((dot(position, plane.xyz) - dot(absNormal, 0.5f)) > -plane.w) { return(false); } } return(true); }
public static void fp3_operator_not_equal_wide_scalar() { fp3 a0 = fp3(-155.4411m, -19.4266052m, 174.633057m); fp b0 = (-393.413544m); bool3 r0 = bool3(true, true, true); TestUtils.AreEqual(a0 != b0, r0); fp3 a1 = fp3(507.920715m, 171.151489m, -58.92328m); fp b1 = (59.177063m); bool3 r1 = bool3(true, true, true); TestUtils.AreEqual(a1 != b1, r1); fp3 a2 = fp3(-398.176849m, -165.241516m, 270.341m); fp b2 = (492.20105m); bool3 r2 = bool3(true, true, true); TestUtils.AreEqual(a2 != b2, r2); fp3 a3 = fp3(-380.243256m, -134.345459m, 458.400452m); fp b3 = (501.899048m); bool3 r3 = bool3(true, true, true); TestUtils.AreEqual(a3 != b3, r3); }
// ray direction is assumed to be normalized public static bool Hit(this Box box, Ray r, float tMin, float tMax, out float distance, out float3 normal) { // offset origin by tMin r = new Ray(r.Origin + r.Direction * tMin, r.Direction, r.Time); distance = 0; normal = 0; // from "A Ray-Box Intersection Algorithm and Efficient Dynamic Voxel Rendering" (Majercik et al.) // http://jcgt.org/published/0007/03/04/ float3 rayDirection = r.Direction; float winding = cmax(abs(r.Origin) * box.InverseExtents) < 1 ? -1 : 1; float3 sgn = -sign(rayDirection); float3 distanceToPlane = (box.Extents * winding * sgn - r.Origin) / rayDirection; bool3 test = distanceToPlane >= 0 & bool3( all(abs(r.Origin.yz + rayDirection.yz * distanceToPlane.x) < box.Extents.yz), all(abs(r.Origin.zx + rayDirection.zx * distanceToPlane.y) < box.Extents.zx), all(abs(r.Origin.xy + rayDirection.xy * distanceToPlane.z) < box.Extents.xy)); sgn = test.x ? float3(sgn.x, 0, 0) : test.y ? float3(0, sgn.y, 0) : float3(0, 0, test.z ? sgn.z : 0); bool3 nonZero = sgn != 0; if (!any(nonZero)) { return(false); } distance = nonZero.x ? distanceToPlane.x : nonZero.y ? distanceToPlane.y : distanceToPlane.z; distance += tMin; if (distance > tMax) { return(false); } normal = sgn; return(true); }
public void bool3_operator_logical_not() { bool3 a0 = bool3(true, true, false); bool3 r0 = bool3(false, false, true); TestUtils.AreEqual(!a0, r0); bool3 a1 = bool3(false, false, true); bool3 r1 = bool3(true, true, false); TestUtils.AreEqual(!a1, r1); bool3 a2 = bool3(false, false, false); bool3 r2 = bool3(true, true, true); TestUtils.AreEqual(!a2, r2); bool3 a3 = bool3(false, true, true); bool3 r3 = bool3(true, false, false); TestUtils.AreEqual(!a3, r3); }
public void ConversionSystems_WhenGOHasConfigurableJoint_AngularMotionLockOrLimited_AxesAreConstrained( ConfigurableJointMotion angularXMotion, ConfigurableJointMotion angularYMotion, ConfigurableJointMotion angularZMotion, bool expectedConstrainedX, bool expectedConstrainedY, bool expectedConstrainedZ ) { CreateHierarchy(new[] { typeof(LegacyConfigurable) }, Array.Empty <Type>(), Array.Empty <Type>()); var joint = Root.GetComponent <LegacyConfigurable>(); joint.xMotion = ConfigurableJointMotion.Free; joint.yMotion = ConfigurableJointMotion.Free; joint.zMotion = ConfigurableJointMotion.Free; joint.angularXMotion = angularXMotion; joint.angularYMotion = angularYMotion; joint.angularZMotion = angularZMotion; TestConvertedData <PhysicsJoint>(j => { Assume.That(j.GetConstraints().Length, Is.EqualTo(1), "ConfigurableJoint with limits on only one axis should produce exactly 1 constraint"); var expectedConstrainedAxes = new bool3(expectedConstrainedX, expectedConstrainedY, expectedConstrainedZ); Assert.That(j[0].ConstrainedAxes, Is.EqualTo(expectedConstrainedAxes)); }); }
public static void fp3_operator_equal_scalar_wide() { fp a0 = (36.38391m); fp3 b0 = fp3(-400.4892m, -71.2868347m, 156.978088m); bool3 r0 = bool3(false, false, false); TestUtils.AreEqual(a0 == b0, r0); fp a1 = (-225.238739m); fp3 b1 = fp3(499.141785m, -211.979919m, 428.311951m); bool3 r1 = bool3(false, false, false); TestUtils.AreEqual(a1 == b1, r1); fp a2 = (-489.501343m); fp3 b2 = fp3(-5.691559m, -30.8659363m, -362.9831m); bool3 r2 = bool3(false, false, false); TestUtils.AreEqual(a2 == b2, r2); fp a3 = (184.503174m); fp3 b3 = fp3(-160.470612m, 316.668823m, 390.369263m); bool3 r3 = bool3(false, false, false); TestUtils.AreEqual(a3 == b3, r3); }
public static void fp3_operator_equal_wide_scalar() { fp3 a0 = fp3(65.6712m, 404.415527m, -269.730164m); fp b0 = (-155.815765m); bool3 r0 = bool3(false, false, false); TestUtils.AreEqual(a0 == b0, r0); fp3 a1 = fp3(83.6306152m, -155.868286m, 314.671265m); fp b1 = (152.9945m); bool3 r1 = bool3(false, false, false); TestUtils.AreEqual(a1 == b1, r1); fp3 a2 = fp3(386.365173m, -132.6352m, -65.66748m); fp b2 = (290.04895m); bool3 r2 = bool3(false, false, false); TestUtils.AreEqual(a2 == b2, r2); fp3 a3 = fp3(-69.68326m, 186.845215m, -232.895691m); fp b3 = (-191.190765m); bool3 r3 = bool3(false, false, false); TestUtils.AreEqual(a3 == b3, r3); }
public static void fp3_operator_equal_wide_wide() { fp3 a0 = fp3(-135.18924m, -49.0941162m, 169.129822m); fp3 b0 = fp3(-220.014648m, 66.98004m, 499.2016m); bool3 r0 = bool3(false, false, false); TestUtils.AreEqual(a0 == b0, r0); fp3 a1 = fp3(240.8053m, 314.7392m, 442.393m); fp3 b1 = fp3(-371.1131m, 208.448669m, 390.8037m); bool3 r1 = bool3(false, false, false); TestUtils.AreEqual(a1 == b1, r1); fp3 a2 = fp3(177.924438m, 335.5334m, 168.15448m); fp3 b2 = fp3(-72.44382m, 362.97644m, 194.678345m); bool3 r2 = bool3(false, false, false); TestUtils.AreEqual(a2 == b2, r2); fp3 a3 = fp3(350.729553m, 367.178467m, 46.9414673m); fp3 b3 = fp3(471.644836m, -404.044678m, -144.696747m); bool3 r3 = bool3(false, false, false); TestUtils.AreEqual(a3 == b3, r3); }
public static void fp3_operator_not_equal_scalar_wide() { fp a0 = (478.353149m); fp3 b0 = fp3(459.553223m, 436.453247m, -488.714172m); bool3 r0 = bool3(true, true, true); TestUtils.AreEqual(a0 != b0, r0); fp a1 = (392.767944m); fp3 b1 = fp3(-266.736633m, 338.557861m, -338.100128m); bool3 r1 = bool3(true, true, true); TestUtils.AreEqual(a1 != b1, r1); fp a2 = (-152.314545m); fp3 b2 = fp3(-452.820679m, 209.439331m, 50.10797m); bool3 r2 = bool3(true, true, true); TestUtils.AreEqual(a2 != b2, r2); fp a3 = (372.4344m); fp3 b3 = fp3(-488.0213m, 489.740784m, 270.4001m); bool3 r3 = bool3(true, true, true); TestUtils.AreEqual(a3 != b3, r3); }
public static void bool3_operator_logical_not() { bool3 a0 = bool3(true, true, false); bool3 r0 = bool3(false, false, true); TestUtils.AreEqual(r0, !a0); bool3 a1 = bool3(false, false, true); bool3 r1 = bool3(true, true, false); TestUtils.AreEqual(r1, !a1); bool3 a2 = bool3(false, false, false); bool3 r2 = bool3(true, true, true); TestUtils.AreEqual(r2, !a2); bool3 a3 = bool3(false, true, true); bool3 r3 = bool3(true, false, false); TestUtils.AreEqual(r3, !a3); }
public static void fp3_operator_not_equal_wide_wide() { fp3 a0 = fp3(279.994141m, -43.34201m, -465.724731m); fp3 b0 = fp3(-460.9121m, -476.009033m, 468.1364m); bool3 r0 = bool3(true, true, true); TestUtils.AreEqual(a0 != b0, r0); fp3 a1 = fp3(317.466553m, 85.7149658m, 360.8905m); fp3 b1 = fp3(-341.012543m, -62.65805m, -458.801666m); bool3 r1 = bool3(true, true, true); TestUtils.AreEqual(a1 != b1, r1); fp3 a2 = fp3(366.081543m, 154.542847m, 332.4262m); fp3 b2 = fp3(-457.730225m, -59.5232544m, 3.024231m); bool3 r2 = bool3(true, true, true); TestUtils.AreEqual(a2 != b2, r2); fp3 a3 = fp3(397.11322m, -431.374969m, 489.0108m); fp3 b3 = fp3(155.812744m, -19.8399048m, -6.01693726m); bool3 r3 = bool3(true, true, true); TestUtils.AreEqual(a3 != b3, r3); }
private bool3 OffsetExceedsBounds(float3 offset, float3 minOffset, float3 maxOffset, out bool3 positiveDirection, out float3 newOffset) { bool3 exceeds = false; newOffset = maxOffset - 0.01f; positiveDirection = true; if (offset.x > maxOffset.x) { exceeds.x = true; } else if (offset.x < minOffset.x) { exceeds.x = true; positiveDirection.x = false; newOffset.x = minOffset.x + 0.01f; } if (offset.y > maxOffset.y) { exceeds.y = true; } else if (offset.y < minOffset.y) { exceeds.y = true; positiveDirection.y = false; newOffset.y = minOffset.y + 0.01f; } if (offset.z > maxOffset.z) { exceeds.z = true; } else if (offset.z < minOffset.z) { exceeds.z = true; positiveDirection.z = false; newOffset.z = minOffset.z + 0.01f; } return(exceeds); }
public static PhysicsJoint CreateLimitDOFJoint(RigidTransform offset, bool3 linearLocks, bool3 angularLocks) { var constraints = new FixedList128 <Constraint>(); if (math.any(linearLocks)) { constraints.Add(new Constraint { ConstrainedAxes = linearLocks, Type = ConstraintType.Linear, Min = 0, Max = 0, SpringFrequency = Constraint.DefaultSpringFrequency, SpringDamping = Constraint.DefaultSpringDamping }); } if (math.any(angularLocks)) { constraints.Add(new Constraint { ConstrainedAxes = angularLocks, Type = ConstraintType.Angular, Min = 0, Max = 0, SpringFrequency = Constraint.DefaultSpringFrequency, SpringDamping = Constraint.DefaultSpringDamping }); } var joint = new PhysicsJoint { BodyAFromJoint = BodyFrame.Identity, BodyBFromJoint = offset }; joint.SetConstraints(constraints); return(joint); }
public static BlobAssetReference <JointData> CreateLimitDOFJoint( RigidTransform offset, bool3 linearLocks, bool3 angularLocks) { var constraintCount = (math.any(linearLocks) ? 1 : 0) + (math.any(angularLocks) ? 1 : 0); Constraint[] constraints = new Constraint[constraintCount]; int index = 0; if (math.any(linearLocks)) { constraints[index++] = new Constraint { ConstrainedAxes = linearLocks, Type = ConstraintType.Linear, Min = 0, Max = 0, SpringFrequency = Constraint.DefaultSpringFrequency, SpringDamping = Constraint.DefaultSpringDamping }; } if (math.any(angularLocks)) { constraints[index++] = new Constraint { ConstrainedAxes = angularLocks, Type = ConstraintType.Angular, Min = 0, Max = 0, SpringFrequency = Constraint.DefaultSpringFrequency, SpringDamping = Constraint.DefaultSpringDamping }; } return(JointData.Create( new Math.MTransform(float3x3.identity, float3.zero), new Math.MTransform(offset), constraints )); }
//[WriteOnly] public NativeArray<float3> accRegistry; public void Execute(ref StarEntity currentStar) { //int starRef=0; float3 accForce = float3(0, 0, 0); for (int i = 0; i < stars.Length; i++) { //the attraction direction float3 distVect = stars[i].position.Value - currentStar.position.Value; bool3 samePosition = currentStar.position.Value != stars[i].position.Value; //If distance is (0,0,0), we have currentStar being stars[i], so we don't compute if (samePosition.x || samePosition.y || samePosition.z) { float3 distNorm = normalize(distVect); float attraction = (6.67f * currentStar.mass.Value * stars[i].mass.Value) / (pow(distVect.x, 2) + pow(distVect.y, 2) + pow(distVect.z, 2)) / 10000; accForce += attraction * distNorm; } // else //starRef = i; } //accRegistry[starRef] = accForce; currentStar.acceleration.Value = accForce; }
public static void Bool3() { bool result = true; Random32 rng = new Random32(RNG_SEED); for (int i = 0; i < NUM_TESTS; i++) { bool3 x = rng.NextBool3(); int test = maxmath.first(x); int j = 0; while (j < 3 && !x[j]) { j++; } result &= test == j; } Assert.AreEqual(result && maxmath.first(default(bool3)) == 4, true); }
public static bool IsObjectIsInFrontOf(IsometricData isoObjectLeft, IsometricData isoObjectRight) { var leftMinCal = new float3(-isoObjectLeft.IsoPosition.x, isoObjectLeft.IsoPosition.y, isoObjectRight.IsoPosition.z); var leftMaxCal = leftMinCal + new float3(isoObjectLeft.IsoSize.xy, isoObjectRight.IsoSize.z); var rightMinCal = new float3(-isoObjectRight.IsoPosition.x, isoObjectRight.IsoPosition.y, isoObjectLeft.IsoPosition.z); var rightMaxCal = rightMinCal + new float3(isoObjectRight.IsoSize.xy, isoObjectLeft.IsoSize.z); //from https://shaunlebron.github.io/IsometricBlocks/ bool leftCanBeInFront = math.all(leftMaxCal > rightMinCal); if (leftCanBeInFront) { //from http://bannalia.blogspot.com/2008/02/filmation-math.html bool rightCanBeInFront = math.all(rightMaxCal > leftMinCal); if (rightCanBeInFront) { //left and right can be in front, search deeper var deltaLeftToRight = leftMaxCal - rightMinCal; var deltaRightToLeft = rightMaxCal - leftMinCal; var deltaProjection = isoObjectLeft.IsoSize + isoObjectRight.IsoSize - math.abs(deltaRightToLeft - deltaLeftToRight); var condition = new bool2(deltaProjection.y <= deltaProjection.x && deltaProjection.y <= deltaProjection.z, deltaProjection.x <= deltaProjection.y && deltaProjection.x <= deltaProjection.z); //better than an if else if for vectorization var res = new bool3(condition.x & (deltaLeftToRight.y > deltaRightToLeft.y), (condition.x == false) & condition.y & (deltaLeftToRight.x > deltaRightToLeft.x), (math.any(condition.xy) == false) & (deltaLeftToRight.z > deltaRightToLeft.z)); return(math.any(res)); } } return(leftCanBeInFront); }
public void StringInterop() { var v = new bool3(true, false, false); var s0 = v.ToString(); var s1 = v.ToString("#"); var v0 = bool3.Parse(s0); var v1 = bool3.Parse(s1, "#"); Assert.AreEqual(v, v0); Assert.AreEqual(v, v1); var b0 = bool3.TryParse(s0, out v0); var b1 = bool3.TryParse(s1, "#", out v1); Assert.That(b0); Assert.That(b1); Assert.AreEqual(v, v0); Assert.AreEqual(v, v1); b0 = bool3.TryParse(null, out v0); Assert.False(b0); b0 = bool3.TryParse("", out v0); Assert.False(b0); b0 = bool3.TryParse(s0 + ", 0", out v0); Assert.False(b0); Assert.Throws <NullReferenceException>(() => { bool3.Parse(null); }); Assert.Throws <FormatException>(() => { bool3.Parse(""); }); Assert.Throws <FormatException>(() => { bool3.Parse(s0 + ", 0"); }); var s2 = v.ToString(";", CultureInfo.InvariantCulture); Assert.That(s2.Length > 0); }
public void Indexer() { var v = new bool3(true, false, true); Assert.AreEqual(true, v[0]); Assert.AreEqual(false, v[1]); Assert.AreEqual(true, v[2]); Assert.Throws <ArgumentOutOfRangeException>(() => { var s = v[-2147483648]; }); Assert.Throws <ArgumentOutOfRangeException>(() => { v[-2147483648] = false; }); Assert.Throws <ArgumentOutOfRangeException>(() => { var s = v[-1]; }); Assert.Throws <ArgumentOutOfRangeException>(() => { v[-1] = false; }); Assert.Throws <ArgumentOutOfRangeException>(() => { var s = v[3]; }); Assert.Throws <ArgumentOutOfRangeException>(() => { v[3] = false; }); Assert.Throws <ArgumentOutOfRangeException>(() => { var s = v[2147483647]; }); Assert.Throws <ArgumentOutOfRangeException>(() => { v[2147483647] = false; }); Assert.Throws <ArgumentOutOfRangeException>(() => { var s = v[5]; }); Assert.Throws <ArgumentOutOfRangeException>(() => { v[5] = false; }); v[2] = false; Assert.AreEqual(false, v[2]); v[0] = true; Assert.AreEqual(true, v[0]); }
//All algorithms return a negative distance if inside the collider. /*public static bool DistanceBetween(float3 point, SphereCollider sphere, float maxDistance, out PointDistanceResultInternal result) * { * float3 delta = sphere.center - point; * float pcDistanceSq = math.lengthsq(delta); //point center distance * bool distanceIsZero = pcDistanceSq == 0.0f; * float invPCDistance = math.select(math.rsqrt(pcDistanceSq), 0.0f, distanceIsZero); * float3 inNormal = math.select(delta * invPCDistance, new float3(0, 1, 0), distanceIsZero); // choose an arbitrary normal when the distance is zero * float distance = pcDistanceSq * invPCDistance - sphere.radius; * result = new PointDistanceResultInternal * { * hitpoint = point + inNormal * distance, * distance = distance, * normal = -inNormal, * }; * return distance <= maxDistance; * }*/ /*public static bool DistanceBetween(float3 point, CapsuleCollider capsule, float maxDistance, out PointDistanceResultInternal result) * { * //Strategy: Project p onto the capsule's line clamped to the segment. Then inflate point on line as sphere * float3 edge = capsule.pointB - capsule.pointA; * float3 ap = point - capsule.pointA; * float dot = math.dot(ap, edge); * float edgeLengthSq = math.lengthsq(edge); * dot = math.clamp(dot, 0f, edgeLengthSq); * float3 pointOnSegment = capsule.pointA + edge * dot / edgeLengthSq; * SphereCollider sphere = new SphereCollider(pointOnSegment, capsule.radius); * return DistanceBetween(point, sphere, maxDistance, out result); * }*/ /*public static bool DistanceBetween(float3 point, CylinderCollider cylinder, float maxDistance, out PointDistanceResultInternal result) * { * //Strategy: Project p onto the capsule's line. * //If on the segment, do point vs sphere. * //Otherwise do point vs disk * float3 edge = cylinder.pointB - cylinder.pointA; * float3 ap = point - cylinder.pointA; * float3 unitEdge = math.normalize(edge); * float dot = math.dot(ap, unitEdge); //dot is distance of projected point from pointA * float3 pointOnLine = cylinder.pointA + unitEdge * dot; * if (dot < 0f) * { * //Todo: Optimize math * float3 pointOnLineToPoint = point - pointOnLine; //This gives us our direction from the center of the cap to the edge towards the query point. * if (math.lengthsq(pointOnLineToPoint) > cylinder.radius * cylinder.radius) * { * float3 roundNormal = math.normalize(pointOnLineToPoint); * float3 capNormal = -unitEdge; * result.normal = (roundNormal + capNormal) / math.SQRT2; //Summing orthogonal unit vectors has a length of sqrt2 * result.hitpoint = cylinder.pointA + roundNormal * cylinder.radius; * result.distance = math.distance(point, result.hitpoint); * } * else * { * result.normal = -unitEdge; * result.distance = -dot; * result.hitpoint = point + unitEdge * result.distance; * } * return result.distance <= maxDistance; * } * if (dot * dot > math.lengthsq(edge)) * { * //Todo: Optimize math * float3 pointOnLineToPoint = point - pointOnLine; //This gives us our direction from the center of the cap to the edge towards the query point. * if (math.lengthsq(pointOnLineToPoint) > cylinder.radius * cylinder.radius) * { * float3 roundNormal = math.normalize(pointOnLineToPoint); * float3 capNormal = unitEdge; * result.normal = (roundNormal + capNormal) / math.SQRT2; //Summing orthogonal unit vectors has a length of sqrt2 * result.hitpoint = cylinder.pointB + roundNormal * cylinder.radius; * result.distance = math.distance(point, result.hitpoint); * } * else * { * result.normal = unitEdge; * result.distance = math.distance(pointOnLine, cylinder.pointB); * result.hitpoint = point - unitEdge * result.distance; * } * return result.distance <= maxDistance; * } * else * { * SphereCollider sphere = new SphereCollider(pointOnLine, cylinder.radius); * return DistanceBetween(point, sphere, maxDistance, out result); * } * }*/ public static bool DistanceBetween(float3 point, BoxCollider box, float maxDistance, out PointDistanceResultInternal result) { //Idea: The positive octant of the box contains 7 feature regions: 3 faces, 3 edges, and inside. //The other octants are identical except with flipped signs. So if we unflip signs, //calculate the distance for these 7 regions, and then flip signs again, we get a valid result. //We use feature regions rather than feature types to avoid swizzling since that would require a second branch. float3 osPoint = point - box.center; //os = origin space bool3 isNegative = osPoint < 0f; float3 ospPoint = math.select(osPoint, -osPoint, isNegative); //osp = origin space positive int region = math.csum(math.select(new int3(4, 2, 1), int3.zero, ospPoint < box.halfSize)); switch (region) { case 0: { //Inside the box. Get the closest wall. float3 delta = box.halfSize - ospPoint; float min = math.cmin(delta); bool3 minMask = min == delta; //Prioritize y first, then z, then x if multiple distances perfectly match. //Todo: Should this be configurabe? minMask.xz &= !minMask.y; minMask.x &= !minMask.z; result.hitpoint = math.select(ospPoint, box.halfSize, minMask); result.distance = -min; result.normal = math.select(0f, 1f, minMask); break; } case 1: { //xy in box, z outside //Closest feature is the z-face result.distance = ospPoint.z - box.halfSize.z; result.hitpoint = new float3(ospPoint.xy, box.halfSize.z); result.normal = new float3(0f, 0f, 1f); break; } case 2: { //xz in box, y outside //Closest feature is the y-face result.distance = ospPoint.y - box.halfSize.y; result.hitpoint = new float3(ospPoint.x, box.halfSize.y, ospPoint.z); result.normal = new float3(0f, 1f, 0f); break; } case 3: { //x in box, yz outside //Closest feature is the x-axis edge result.distance = math.distance(ospPoint.yz, box.halfSize.yz); result.hitpoint = new float3(ospPoint.x, box.halfSize.yz); result.normal = new float3(0f, math.SQRT2 / 2f, math.SQRT2 / 2f); break; } case 4: { //yz in box, x outside //Closest feature is the x-face result.distance = ospPoint.x - box.halfSize.x; result.hitpoint = new float3(box.halfSize.x, ospPoint.yz); result.normal = new float3(1f, 0f, 0f); break; } case 5: { //y in box, xz outside //Closest feature is the y-axis edge result.distance = math.distance(ospPoint.xz, box.halfSize.xz); result.hitpoint = new float3(box.halfSize.x, ospPoint.y, box.halfSize.y); result.normal = new float3(math.SQRT2 / 2f, 0f, math.SQRT2 / 2f); break; } case 6: { //z in box, xy outside //Closest feature is the z-axis edge result.distance = math.distance(ospPoint.xy, box.halfSize.xy); result.hitpoint = new float3(box.halfSize.xy, ospPoint.z); result.normal = new float3(math.SQRT2 / 2f, math.SQRT2 / 2f, 0f); break; } default: { //xyz outside box ////Closest feature is the osp corner result.distance = math.distance(ospPoint, box.halfSize); result.hitpoint = box.halfSize; result.normal = math.normalize(math.float3(1f)); break; } } result.hitpoint = math.select(result.hitpoint, -result.hitpoint, isNegative) + box.center; result.normal = math.select(result.normal, -result.normal, isNegative); return(result.distance <= maxDistance); }