@@ -5,6 +5,22 @@ import org.openrndr.shape.Rectangle
55import kotlin.coroutines.CoroutineContext
66import kotlin.math.abs
77
8+ /* *
9+ * Represents a single physical node with position, velocity, and related properties.
10+ *
11+ * A node serves as an element in simulations, with attributes including its current position,
12+ * previous position, velocity, inverse mass, radius, and a unique identifier. These properties
13+ * define the motion and interaction of the node with forces or other nodes in the simulation.
14+ *
15+ * @property position the current position of the node in the simulation space.
16+ * @property prevPosition the position of the node in the previous simulation step.
17+ * @property velocity the current velocity of the node.
18+ * @property inverseMass the reciprocal of the node's mass. A value of 0 represents an immovable object,
19+ * while higher values represent lower mass.
20+ * @property radius the radius of the node, used for interactions or spatial calculations.
21+ * @property id an optional unique identifier for the node. Default is 0.
22+ * @property bounds a bounding rectangle centered around the node, with dimensions based on its radius.
23+ */
824class Node (
925 var position : Vector2 ,
1026 var prevPosition : Vector2 ,
@@ -18,12 +34,43 @@ class Node(
1834
1935}
2036
37+ /* *
38+ * Represents a connection or relationship between two [Node]s, identified by their indices.
39+ *
40+ * This class is primarily used to model a connection between two nodes or objects in a system,
41+ * such as a physical simulation or graph structure. The `source` and `target` properties represent
42+ * the indices of the connected nodes.
43+ *
44+ * @property source the index of the source node.
45+ * @property target the index of the target node.
46+ */
2147class Link (
2248 var source : Int ,
2349 var target : Int ,
2450)
2551
52+ /* *
53+ * Represents a triangle defined by three node indices in a physical simulation.
54+ *
55+ * A Triangle is primarily used to perform calculations related to its geometry,
56+ * such as computing its signed area based on the positions of nodes in a given list.
57+ *
58+ * @constructor Creates a Triangle with indices pointing to nodes in a list.
59+ * @param a the index of the first node in the triangle.
60+ * @param b the index of the second node in the triangle.
61+ * @param c the index of the third node in the triangle.
62+ */
2663class Triangle (var a : Int , var b : Int , var c : Int ) {
64+
65+ /* *
66+ * Computes the signed area of the triangle defined by the nodes referenced in this triangle.
67+ * The signed area is positive if the nodes are ordered counterclockwise,
68+ * and negative if they are ordered clockwise.
69+ *
70+ * @param nodes a list of [Node] objects where this triangle's node indices correspond to the nodes in the list.
71+ * Each [Node] must have a valid position.
72+ * @return the signed area of the triangle defined by the referenced nodes.
73+ */
2774 fun signedArea (nodes : List <Node >): Double {
2875 val p0 = nodes[a].position
2976 val p1 = nodes[b].position
@@ -34,30 +81,99 @@ class Triangle(var a: Int, var b: Int, var c: Int) {
3481 }
3582}
3683
84+ /* *
85+ * Represents a constraint in a physical system, which influences the behavior of a [Body].
86+ *
87+ * A [Constraint] typically applies rules or restrictions to the motion or interaction of
88+ * the elements within a [Body]. This can include conditions like maintaining distances
89+ * between points, restricting movement to certain boundaries, or other physical interactions.
90+ */
3791interface Constraint {
3892 suspend fun initialize ()
93+
94+ /* *
95+ * Resolves constraints and updates the state of nodes within the given physical body over a time step.
96+ *
97+ * This method applies all constraints associated with the [Body], ensuring that the system adheres
98+ * to the defined physical rules. For example, constraints might enforce distance limitations,
99+ * maintain structural rigidity, or apply boundary conditions. It leverages the constraint-solving
100+ * functionality for the provided time interval, potentially resulting in updated positions or states
101+ * of the body's components.
102+ *
103+ * @param body the [Body] whose constraints are to be resolved, representing the physical system.
104+ * @param dt the duration of the time step during which the constraints are solved, expressed in seconds.
105+ */
39106 suspend fun solve (body : Body , dt : Double )
40107}
41108
109+ /* *
110+ * Represents a physical force that can be applied to a [Body] in a simulation.
111+ *
112+ * Implementing classes define specific behaviors for initializing and
113+ * applying forces on the [Body], altering the state of its nodes over time.
114+ */
42115interface Force {
43116 suspend fun initializeFrame (body : Body )
44117 suspend fun apply (body : Body , dt : Double )
45118}
46119
120+ /* *
121+ * Interface representing a force interaction between two physical bodies in a simulation.
122+ *
123+ * Implementations of this interface define the logic for detecting overlapping pairs of bodies,
124+ * initializing frames for force calculations, and applying interbody forces during simulation steps.
125+ */
47126interface InterbodyForce {
48127 suspend fun initializeFrame ()
49128 suspend fun findOverlappingPairs (bodies : List <Body >): List <Pair <Int , Int >>
50129 suspend fun apply (body : Body , other : Body , dt : Double , substep : Int )
51130}
52131
132+ /* *
133+ * An interface representing a constraint that resolves collisions between two bodies in a simulation.
134+ *
135+ * Implementations of this interface must define the logic for resolving collisions between the specified
136+ * [body] and [other] based on their physical properties, positions, and velocities. This process
137+ * ensures that the bodies interact realistically while respecting the constraints defined for the simulation.
138+ *
139+ * The [solve] method is called with a time step [dt] to calculate and apply necessary adjustments to
140+ * the bodies involved in the collision.
141+ */
53142interface CollisionConstraint {
54143 suspend fun solve (body : Body , other : Body , dt : Double )
55144}
56145
146+ /* *
147+ * Interface for detecting broad-phase collisions in a physics simulation.
148+ *
149+ * The broad-phase collision detector is responsible for identifying potential overlapping
150+ * pairs of bodies in a physics simulation. It typically uses efficient spatial partitioning
151+ * or bounding volume techniques to narrow down the list of potential collisions from
152+ * a large number of bodies.
153+ */
57154interface BroadPhaseCollisionDetector {
58155 suspend fun findOverlappingPairs (bodies : List <Body >): List <Pair <Int , Int >>
59156}
60157
158+ /* *
159+ * Represents a physical body in a simulation composed of nodes, links, and triangles.
160+ *
161+ * A [Body] serves as the central structure in simulations, encapsulating physical properties,
162+ * relationships, and behaviors of its constituent parts. It supports initialization,
163+ * integration of forces, resolution of constraints, and updates to its boundaries.
164+ * The body can either be static or dynamic, depending on the `static` property.
165+ *
166+ * @property nodes the list of [Node]s that make up the physical body.
167+ * @property boundaryNodes the list of indices referring to nodes considered as boundary nodes.
168+ * @property links the list of [Link]s that define relationships or connections between nodes.
169+ * @property boundaryLinks the list of indices referring to links considered as boundary links.
170+ * @property triangles the list of [Triangle]s used for structural and mass-related calculations.
171+ * @property inverseBodyMass the reciprocal of the total mass of the body, used in weight calculations.
172+ * @property static a flag indicating whether the body is static (non-movable) or dynamic.
173+ * @property forces the list of [Force]s acting on the body in the simulation.
174+ * @property constraints the list of [Constraint]s influencing the behavior and interaction of the body.
175+ * @property bounds the bounding rectangle that encapsulates the body's nodes, updated automatically.
176+ */
61177class Body (
62178 val nodes : List <Node >,
63179 val boundaryNodes : List <Int > = emptyList(),
@@ -145,6 +261,26 @@ class Body(
145261 }
146262}
147263
264+ /* *
265+ * Represents a physics simulation of interacting bodies.
266+ *
267+ * The [ForceSimulation] class provides the infrastructure to simulate the dynamics
268+ * of a system of bodies under the influence of forces and constraints. It supports
269+ * customizable interbody forces, collision detection, and resolution, allowing for
270+ * a wide variety of physical interactions.
271+ *
272+ * @property bodies The list of [Body] objects participating in the simulation. Each body
273+ * has its own properties, forces, and constraints that determine its behavior.
274+ * @property broadPhaseCollisionDetector The collision detection algorithm used to identify
275+ * potential overlapping pairs of bodies during the simulation. It operates in the broad-phase
276+ * stage of collision resolution.
277+ * @property collisionConstraint The collision resolution handler responsible for determining
278+ * the outcome of detected collisions between bodies.
279+ * @property interbodyForces A list of interbody forces that affect pairs of bodies in the simulation.
280+ * These forces are computed per pair of bodies and influence their dynamics.
281+ * @property context The coroutine context in which the simulation runs, allowing for asynchronous
282+ * computations. By default, it uses [Dispatchers.Default].
283+ */
148284class ForceSimulation (val bodies : MutableList <Body > = mutableListOf()) {
149285
150286 var broadPhaseCollisionDetector: BroadPhaseCollisionDetector ? = null
0 commit comments