diff --git a/docs/docs/00_intro.md b/docs/docs/00_intro.md
deleted file mode 100644
index ecda1793..00000000
--- a/docs/docs/00_intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-sidebar_position: 0
----
-
-# Jitter Physics 2
-
-You will find tutorials and documentation here. Work in progress. You can help
-by editing or adding new content 👋
diff --git a/docs/docs/02_documentation/img/contact.png b/docs/docs/02_documentation/img/contact.png
deleted file mode 100644
index 0d98e164..00000000
Binary files a/docs/docs/02_documentation/img/contact.png and /dev/null differ
diff --git a/docs/docs/02_documentation/img/filter.png b/docs/docs/02_documentation/img/filter.png
deleted file mode 100644
index edb6fffa..00000000
Binary files a/docs/docs/02_documentation/img/filter.png and /dev/null differ
diff --git a/docs/impress/collision.odp b/docs/impress/collision.odp
deleted file mode 100644
index a649afd8..00000000
Binary files a/docs/impress/collision.odp and /dev/null differ
diff --git a/docs/impress/contact.odp b/docs/impress/contact.odp
deleted file mode 100644
index e2d3a343..00000000
Binary files a/docs/impress/contact.odp and /dev/null differ
diff --git a/docs/impress/filter.odp b/docs/impress/filter.odp
deleted file mode 100644
index 7ad39236..00000000
Binary files a/docs/impress/filter.odp and /dev/null differ
diff --git a/src/Jitter2/Collision/DynamicTree.RayCast.cs b/src/Jitter2/Collision/DynamicTree.RayCast.cs
index 509db356..5ceda1ed 100644
--- a/src/Jitter2/Collision/DynamicTree.RayCast.cs
+++ b/src/Jitter2/Collision/DynamicTree.RayCast.cs
@@ -38,7 +38,7 @@ public partial class DynamicTree
public struct RayCastResult
{
public IDynamicTreeProxy Entity;
- public float Fraction;
+ public float Lambda;
public JVector Normal;
public bool Hit;
}
@@ -82,12 +82,12 @@ public Ray(in JVector origin, in JVector direction)
/// Direction of the ray. Does not have to be normalized.
/// Optional pre-filter which allows to skip shapes in the detection.
/// Optional post-filter which allows to skip detections.
- /// The shape which was hit.
+ /// The shape which was hit.
/// The normal of the surface where the ray hits. Zero if ray does not hit.
- /// Distance from the origin to the ray hit point in units of the ray's directin.
+ /// Distance from the origin to the ray hit point in units of the ray's direction.
/// True if the ray hits, false otherwise.
public bool RayCast(JVector origin, JVector direction, RayCastFilterPre? pre, RayCastFilterPost? post,
- out IDynamicTreeProxy? shape, out JVector normal, out float fraction)
+ out IDynamicTreeProxy? proxy, out JVector normal, out float lambda)
{
Ray ray = new(origin, direction)
{
@@ -95,27 +95,27 @@ public bool RayCast(JVector origin, JVector direction, RayCastFilterPre? pre, Ra
FilterPost = post
};
var result = QueryRay(ray);
- shape = result.Entity;
+ proxy = result.Entity;
normal = result.Normal;
- fraction = result.Fraction;
+ lambda = result.Lambda;
return result.Hit;
}
///
- /// Maximum fraction of the ray's length to consider for intersections.
- public bool RayCast(JVector origin, JVector direction, float maxFraction, RayCastFilterPre? pre, RayCastFilterPost? post,
- out IDynamicTreeProxy? shape, out JVector normal, out float fraction)
+ /// Maximum lambda of the ray's length to consider for intersections.
+ public bool RayCast(JVector origin, JVector direction, float maxLambda, RayCastFilterPre? pre, RayCastFilterPost? post,
+ out IDynamicTreeProxy? proxy, out JVector normal, out float lambda)
{
Ray ray = new(origin, direction)
{
FilterPre = pre,
FilterPost = post,
- Lambda = maxFraction
+ Lambda = maxLambda
};
var result = QueryRay(ray);
- shape = result.Entity;
+ proxy = result.Entity;
normal = result.Normal;
- fraction = result.Fraction;
+ lambda = result.Lambda;
return result.Hit;
}
@@ -128,7 +128,7 @@ private RayCastResult QueryRay(in Ray ray)
stack.Push(root);
RayCastResult result = new();
- result.Fraction = ray.Lambda;
+ result.Lambda = ray.Lambda;
while (stack.Count > 0)
{
@@ -143,10 +143,10 @@ private RayCastResult QueryRay(in Ray ray)
if (ray.FilterPre != null && !ray.FilterPre(node.Proxy)) continue;
Unsafe.SkipInit(out RayCastResult res);
- res.Hit = irc.RayCast(ray.Origin, ray.Direction, out res.Normal, out res.Fraction);
+ res.Hit = irc.RayCast(ray.Origin, ray.Direction, out res.Normal, out res.Lambda);
res.Entity = node.Proxy;
- if (res.Hit && res.Fraction < result.Fraction)
+ if (res.Hit && res.Lambda < result.Lambda)
{
if (ray.FilterPost != null && !ray.FilterPost(res)) continue;
result = res;
@@ -161,8 +161,8 @@ private RayCastResult QueryRay(in Ray ray)
bool lres = lnode.ExpandedBox.RayIntersect(ray.Origin, ray.Direction, out float enterl);
bool rres = rnode.ExpandedBox.RayIntersect(ray.Origin, ray.Direction, out float enterr);
- if (enterl > result.Fraction) lres = false;
- if (enterr > result.Fraction) rres = false;
+ if (enterl > result.Lambda) lres = false;
+ if (enterr > result.Lambda) rres = false;
if (lres && rres)
{
diff --git a/src/Jitter2/Collision/NarrowPhase/NarrowPhase.cs b/src/Jitter2/Collision/NarrowPhase/NarrowPhase.cs
index 7dd54c78..142a5f5c 100644
--- a/src/Jitter2/Collision/NarrowPhase/NarrowPhase.cs
+++ b/src/Jitter2/Collision/NarrowPhase/NarrowPhase.cs
@@ -83,15 +83,13 @@ public bool PointTest(in ISupportMappable supportA, in JVector origin)
return true;
}
- public bool RayCast(in ISupportMappable supportA, in JVector origin, in JVector direction, out float fraction, out JVector normal)
+ public bool RayCast(in ISupportMappable supportA, in JVector origin, in JVector direction, out float lambda, out JVector normal)
{
const float CollideEpsilon = 1e-4f;
const int MaxIter = 34;
normal = JVector.Zero;
- fraction = float.PositiveInfinity;
-
- float lambda = 0.0f;
+ lambda = 0.0f;
JVector r = direction;
JVector x = origin;
@@ -120,6 +118,7 @@ public bool RayCast(in ISupportMappable supportA, in JVector origin, in JVector
if (VdotR >= -NumericEpsilon)
{
+ lambda = float.PositiveInfinity;
return false;
}
@@ -141,8 +140,6 @@ public bool RayCast(in ISupportMappable supportA, in JVector origin, in JVector
converged:
- fraction = lambda;
-
float nlen2 = normal.LengthSquared();
if (nlen2 > NumericEpsilon)
@@ -154,7 +151,7 @@ public bool RayCast(in ISupportMappable supportA, in JVector origin, in JVector
}
public bool Sweep(ref MinkowskiDifference mkd, in JVector sweep,
- out JVector p1, out JVector p2, out JVector normal, out float fraction)
+ out JVector p1, out JVector p2, out JVector normal, out float lambda)
{
const float CollideEpsilon = 1e-4f;
const int MaxIter = 34;
@@ -166,7 +163,7 @@ public bool Sweep(ref MinkowskiDifference mkd, in JVector sweep,
JVector posB = mkd.PositionB;
- fraction = 0.0f;
+ lambda = 0.0f;
p1 = p2 = JVector.Zero;
@@ -192,13 +189,13 @@ public bool Sweep(ref MinkowskiDifference mkd, in JVector sweep,
if (VdotR >= -1e-12f)
{
- fraction = float.PositiveInfinity;
+ lambda = float.PositiveInfinity;
return false;
}
- fraction -= VdotW / VdotR;
+ lambda -= VdotW / VdotR;
- mkd.PositionB = posB + fraction * r;
+ mkd.PositionB = posB + lambda * r;
normal = v;
}
@@ -709,7 +706,7 @@ public static bool PointTest(in ISupportMappable support, in JMatrix orientation
/// The position of the shape in world space.
/// The origin of the ray.
/// The direction of the ray; normalization is not necessary.
- /// Specifies the hit point of the ray, calculated as 'origin + fraction * direction'.
+ /// Specifies the hit point of the ray, calculated as 'origin + lambda * direction'.
///
/// The normalized normal vector perpendicular to the surface, pointing outwards. If the ray does not
/// hit, this parameter will be zero.
@@ -717,13 +714,13 @@ public static bool PointTest(in ISupportMappable support, in JMatrix orientation
/// Returns true if the ray intersects with the shape; otherwise, false.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool RayCast(in ISupportMappable support, in JQuaternion orientation,
- in JVector position, in JVector origin, in JVector direction, out float fraction, out JVector normal)
+ in JVector position, in JVector origin, in JVector direction, out float lambda, out JVector normal)
{
// rotate the ray into the reference frame of bodyA..
JVector tdirection = JVector.TransposedTransform(direction, orientation);
JVector torigin = JVector.TransposedTransform(origin - position, orientation);
- bool result = solver.RayCast(support, torigin, tdirection, out fraction, out normal);
+ bool result = solver.RayCast(support, torigin, tdirection, out lambda, out normal);
// ..rotate back.
JVector.Transform(normal, orientation, out normal);
@@ -737,16 +734,16 @@ public static bool RayCast(in ISupportMappable support, in JQuaternion orientati
/// The support function of the shape.
/// The origin of the ray.
/// The direction of the ray; normalization is not necessary.
- /// Specifies the hit point of the ray, calculated as 'origin + fraction * direction'.
+ /// Specifies the hit point of the ray, calculated as 'origin + lambda * direction'.
///
/// The normalized normal vector perpendicular to the surface, pointing outwards. If the ray does not
/// hit, this parameter will be zero.
///
/// Returns true if the ray intersects with the shape; otherwise, false.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool RayCast(in ISupportMappable support, in JVector origin, in JVector direction, out float fraction, out JVector normal)
+ public static bool RayCast(in ISupportMappable support, in JVector origin, in JVector direction, out float lambda, out JVector normal)
{
- return solver.RayCast(support, origin, direction, out fraction, out normal);
+ return solver.RayCast(support, origin, direction, out lambda, out normal);
}
///
@@ -1068,14 +1065,14 @@ public static bool MPREPA(in ISupportMappable supportA, in ISupportMappable supp
/// Zero if no hit is detected.
/// Collision point on shapeB in world space at t = 0, where collision will occur.
/// Zero if no hit is detected.
- /// Time of impact. Infinity if no hit is detected.
+ /// Time of impact. Infinity if no hit is detected.
/// True if the shapes hit, false otherwise.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Sweep(in ISupportMappable supportA, in ISupportMappable supportB,
in JQuaternion orientationA, in JQuaternion orientationB,
in JVector positionA, in JVector positionB,
in JVector sweepA, in JVector sweepB,
- out JVector pointA, out JVector pointB, out JVector normal, out float fraction)
+ out JVector pointA, out JVector pointB, out JVector normal, out float lambda)
{
Unsafe.SkipInit(out MinkowskiDifference mkd);
@@ -1092,7 +1089,7 @@ public static bool Sweep(in ISupportMappable supportA, in ISupportMappable suppo
JVector.ConjugatedTransform(sweep, orientationA, out sweep);
// ..perform toi calculation
- bool res = solver.Sweep(ref mkd, sweep, out pointA, out pointB, out normal, out fraction);
+ bool res = solver.Sweep(ref mkd, sweep, out pointA, out pointB, out normal, out lambda);
if (!res) return false;
@@ -1107,10 +1104,10 @@ public static bool Sweep(in ISupportMappable supportA, in ISupportMappable suppo
// transform back from the relative velocities
// This is where the collision will occur in world space:
- // pointA += fraction * sweepA;
- // pointB += fraction * sweepA; // sweepA is not a typo
+ // pointA += lambda * sweepA;
+ // pointB += lambda * sweepA; // sweepA is not a typo
- pointB += fraction * (sweepA - sweepB);
+ pointB += lambda * (sweepA - sweepB);
return true;
}
@@ -1121,12 +1118,12 @@ public static bool Sweep(in ISupportMappable supportA, in ISupportMappable suppo
///
/// Collision point on shapeA in world space. Zero if no hit is detected.
/// Collision point on shapeB in world space. Zero if no hit is detected.
- /// Time of impact. Infinity if no hit is detected.
+ /// Time of impact. Infinity if no hit is detected.
/// True if the shapes hit, false otherwise.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Sweep(in ISupportMappable supportA, in ISupportMappable supportB,
in JQuaternion orientationB, in JVector positionB, in JVector sweepB,
- out JVector pointA, out JVector pointB, out JVector normal, out float fraction)
+ out JVector pointA, out JVector pointB, out JVector normal, out float lambda)
{
Unsafe.SkipInit(out MinkowskiDifference mkd);
@@ -1136,6 +1133,6 @@ public static bool Sweep(in ISupportMappable supportA, in ISupportMappable suppo
mkd.OrientationB = orientationB;
// ..perform toi calculation
- return solver.Sweep(ref mkd, sweepB, out pointA, out pointB, out normal, out fraction);
+ return solver.Sweep(ref mkd, sweepB, out pointA, out pointB, out normal, out lambda);
}
}
\ No newline at end of file
diff --git a/src/Jitter2/Dynamics/RigidBody.cs b/src/Jitter2/Dynamics/RigidBody.cs
index da13ec5b..0bc7f7a2 100644
--- a/src/Jitter2/Dynamics/RigidBody.cs
+++ b/src/Jitter2/Dynamics/RigidBody.cs
@@ -65,6 +65,9 @@ public sealed class RigidBody : IListIndex, IDebugDrawable
public readonly ulong RigidBodyId;
+ private float restitution = 0.0f;
+ private float friction = 0.2f;
+
///
/// Due to performance considerations, the data used to simulate this body (e.g., velocity or position)
/// is stored within a contiguous block of unmanaged memory. This refers to the raw memory location
@@ -156,8 +159,59 @@ internal void RaiseEndCollide(Arbiter arbiter)
internal JMatrix inverseInertia = JMatrix.Identity;
internal float inverseMass = 1.0f;
- public float Friction { get; set; } = 0.2f;
- public float Restitution { get; set; } = 0.0f;
+ ///
+ /// Gets or sets the friction coefficient for this object.
+ ///
+ ///
+ /// The friction coefficient determines the resistance to sliding motion.
+ /// Higher values create more friction, while lower values allow easier sliding.
+ /// A typical value ranges between 0 (no friction) and 1 (maximum friction).
+ /// Default is 0.2.
+ ///
+ ///
+ /// Thrown if the value is not between 0 and 1.
+ ///
+ public float Friction
+ {
+ get => friction;
+ set
+ {
+ if (value < 0.0f || value > 1.0f)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value),
+ "Friction must be between 0 and 1.");
+ }
+
+ friction = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the restitution (bounciness) of this object.
+ ///
+ ///
+ /// The restitution value determines how much energy is retained after a collision,
+ /// with 0 representing an inelastic collision (no bounce) and 1 representing a perfectly elastic collision (full bounce).
+ /// Values between 0 and 1 create a partially elastic collision effect.
+ /// Default is 0.0.
+ ///
+ ///
+ /// Thrown if the value is not between 0 and 1.
+ ///
+ public float Restitution
+ {
+ get => restitution;
+ set
+ {
+ if (value < 0.0f || value > 1.0f)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value),
+ "Restitution must be between 0 and 1.");
+ }
+
+ restitution = value;
+ }
+ }
private readonly int hashCode;
diff --git a/src/Jitter2/SoftBodies/DynamicTreeCollisionFilter.cs b/src/Jitter2/SoftBodies/DynamicTreeCollisionFilter.cs
index 35626f78..0500bd71 100644
--- a/src/Jitter2/SoftBodies/DynamicTreeCollisionFilter.cs
+++ b/src/Jitter2/SoftBodies/DynamicTreeCollisionFilter.cs
@@ -32,7 +32,7 @@ public static bool Filter(IDynamicTreeProxy proxyA, IDynamicTreeProxy proxyB)
{
if (proxyA is RigidBodyShape rbsA && proxyB is RigidBodyShape rbsB)
{
- if (rbsA.RigidBody == rbsB.RigidBody) return false;
+ return rbsA.RigidBody != rbsB.RigidBody;
}
else if (proxyA is SoftBodyShape softBodyShapeA &&
proxyB is SoftBodyShape softBodyShapeB)
diff --git a/src/Jitter2/World.cs b/src/Jitter2/World.cs
index 4971afab..b93b87ca 100644
--- a/src/Jitter2/World.cs
+++ b/src/Jitter2/World.cs
@@ -287,8 +287,8 @@ public void Clear()
}
///
- /// Removes the specified body from the world. This operation also automatically discards any associated contacts
- /// and constraints.
+ /// Removes the specified body from the world.
+ /// This operation also automatically discards any associated contacts and constraints.
///
public void Remove(RigidBody body)
{
diff --git a/src/JitterDemo/Demos/Player/Player.cs b/src/JitterDemo/Demos/Player/Player.cs
index 65a2fb5e..918151eb 100644
--- a/src/JitterDemo/Demos/Player/Player.cs
+++ b/src/JitterDemo/Demos/Player/Player.cs
@@ -164,11 +164,11 @@ private bool CanJump(out RigidBody? floor, out JVector hitPoint)
// ...or the more traditional way of using a raycast
bool hit = world.RayCast(Body.Position, -JVector.UnitY, preFilter, null,
- out floor, out JVector normal, out float fraction);
+ out floor, out JVector normal, out float lambda);
- float delta = fraction - capsuleHalfHeight;
+ float delta = lambda - capsuleHalfHeight;
- hitPoint = Body.Position - JVector.UnitY * fraction;
+ hitPoint = Body.Position - JVector.UnitY * lambda;
return (hit && delta < 0.04f && floor != null);
*/
}
diff --git a/src/JitterTests/CollisionTests.cs b/src/JitterTests/CollisionTests.cs
index 526b8cfd..f1e2ac57 100644
--- a/src/JitterTests/CollisionTests.cs
+++ b/src/JitterTests/CollisionTests.cs
@@ -133,10 +133,10 @@ public void RayCast()
SphereShape s1 = new(radius);
bool hit = NarrowPhase.RayCast(s1, JQuaternion.CreateRotationX(0.32f), sp,
- op, sp - op, out float fraction, out JVector normal);
+ op, sp - op, out float lambda, out JVector normal);
JVector cn = JVector.Normalize(op - sp); // analytical normal
- JVector hp = op + (sp - op) * fraction; // hit point
+ JVector hp = op + (sp - op) * lambda; // hit point
Assert.That(hit);
Assert.That(MathHelper.CloseToZero(normal - cn, 1e-6f));
@@ -157,20 +157,20 @@ public void SweepTest()
bool hit = NarrowPhase.Sweep(s1, s2, rot, rot,
new JVector(1, 1, 3), new JVector(11, 11, 3),
sweep, -2.0f * sweep,
- out JVector pA, out JVector pB, out JVector normal, out float fraction);
+ out JVector pA, out JVector pB, out JVector normal, out float lambda);
Assert.That(hit);
- float expectedFraction = (MathF.Sqrt(200.0f) - 1.0f) * (1.0f / 3.0f);
+ float expectedlambda = (MathF.Sqrt(200.0f) - 1.0f) * (1.0f / 3.0f);
JVector expectedNormal = JVector.Normalize(new JVector(1, 1, 0));
- JVector expectedPoint = new JVector(1, 1, 3) + expectedNormal * (0.5f + expectedFraction);
- JVector expectedPointA = expectedPoint - sweep * fraction;
- JVector expectedPointB = expectedPoint + 2.0f * sweep * fraction;
+ JVector expectedPoint = new JVector(1, 1, 3) + expectedNormal * (0.5f + expectedlambda);
+ JVector expectedPointA = expectedPoint - sweep * lambda;
+ JVector expectedPointB = expectedPoint + 2.0f * sweep * lambda;
Assert.That((normal - expectedNormal).LengthSquared(), Is.LessThan(1e-4f));
Assert.That((pA - expectedPointA).LengthSquared(), Is.LessThan(1e-4f));
Assert.That((pB - expectedPointB).LengthSquared(), Is.LessThan(1e-4f));
- Assert.That(MathF.Abs(fraction - expectedFraction), Is.LessThan(1e-4f));
+ Assert.That(MathF.Abs(lambda - expectedlambda), Is.LessThan(1e-4f));
}
[TestCase]