Skip to content

Commit c3feade

Browse files
committed
LBJ v23.0.0, alter ContactListener and ContactManager interfaces
1 parent 8284855 commit c3feade

9 files changed

Lines changed: 204 additions & 117 deletions

File tree

MinieExamples/src/main/java/jme3utilities/minie/test/ConveyorDemo.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ public static void main(String[] arguments) {
188188
// *************************************************************************
189189
// ContactListener methods
190190

191+
/**
192+
* Invoked immediately before a contact point is added to a manifold.
193+
*
194+
* @param pointId the native ID of the {@code btManifoldPoint} (not zero)
195+
* @param manifoldId the native ID of the {@code btPersistentManifold} (not
196+
* zero)
197+
* @param pcoA the "A" collision object (not null)
198+
* @param pcoB the "B" collision object (not null)
199+
* @return true to accept the contact, or false to reject it
200+
*/
201+
@Override
202+
public boolean onContactConceived(long pointId, long manifoldId,
203+
PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB) {
204+
return true;
205+
}
206+
191207
/**
192208
* Invoked immediately after a contact manifold is created.
193209
*

MinieExamples/src/main/java/jme3utilities/minie/test/issue/TestIssue40.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,26 @@ public void simpleInitApp() {
161161
// *************************************************************************
162162
// ContactListener methods
163163

164+
/**
165+
* Invoked immediately before a contact point is added to a manifold.
166+
*
167+
* @param pointId the native ID of the {@code btManifoldPoint} (not zero)
168+
* @param manifoldId the native ID of the {@code btPersistentManifold} (not
169+
* zero)
170+
* @param pcoA the "A" collision object (not null)
171+
* @param pcoB the "B" collision object (not null)
172+
* @return true to accept the contact, or false to reject it
173+
*/
174+
@Override
175+
public boolean onContactConceived(long pointId, long manifoldId,
176+
PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB) {
177+
if (tickCount >= startTick) {
178+
System.out.printf(" conceived point %x%n", pointId);
179+
System.out.flush();
180+
}
181+
return true;
182+
}
183+
164184
/**
165185
* Invoked immediately after a contact manifold is removed.
166186
*

MinieLibrary/src/main/java/com/jme3/bullet/ContactManager.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 jMonkeyEngine
2+
* Copyright (c) 2023-2026 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -58,15 +58,10 @@ public interface ContactManager extends ContactListener {
5858
* Register the specified listener for immediate contact notifications.
5959
*
6060
* @param listener the listener to register (not null, alias created)
61-
* @param doEnded true to enable {@code onContactEnded()} callbacks for the
62-
* listener, false to skip them
63-
* @param doProcessed true to enable {@code onContactProcessed()} callbacks
64-
* for the listener, false to skip them
65-
* @param doStarted true to enable {@code onContactStarted()} callbacks for
66-
* the listener, false to skip them
61+
* @param stepFlags the desired flags, ORed together
62+
* @see com.jme3.bullet.StepFlag
6763
*/
68-
void addContactListener(ContactListener listener,
69-
boolean doEnded, boolean doProcessed, boolean doStarted);
64+
void addContactListener(ContactListener listener, int stepFlags);
7065

7166
/**
7267
* Register the specified listener for ongoing contacts.
@@ -112,13 +107,16 @@ void addContactListener(ContactListener listener,
112107
void removeOngoingCollisionListener(PhysicsCollisionListener listener);
113108

114109
/**
115-
* Update the associated PhysicsSpace. This method should be invoked from
116-
* the thread that created the space.
110+
* Update the associated PhysicsSpace, enabling the specified callbacks.
111+
* This method should be invoked from the thread that created the space.
117112
*
118113
* @param timeInterval the time interval to simulate (in seconds, ≥0)
119114
* @param maxSteps the maximum number of simulation steps of size
120115
* {@code accuracy} (≥1) or 0 for a single simulation step of size
121116
* {@code timeInterval}
117+
* @param stepFlags flags indicating the desired callbacks, ORed together
118+
* (default=0x0)
119+
* @see com.jme3.bullet.StepFlag
122120
*/
123-
void update(float timeInterval, int maxSteps);
121+
void update(float timeInterval, int maxSteps, int stepFlags);
124122
}

MinieLibrary/src/main/java/com/jme3/bullet/DefaultContactManager.java

Lines changed: 57 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 jMonkeyEngine
2+
* Copyright (c) 2023-2026 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -53,21 +53,6 @@ public class DefaultContactManager implements ContactManager {
5353
// *************************************************************************
5454
// constants and loggers
5555

56-
/**
57-
* bitmask to indicate that the {@code onContactEnded()} method of a
58-
* particular ContactListener should be invoked
59-
*/
60-
final private static int invokeEnded = 0x2;
61-
/**
62-
* bitmask to indicate that the {@code onContactProcessed()} method of a
63-
* particular ContactListener should be invoked
64-
*/
65-
final private static int invokeProcessed = 0x10;
66-
/**
67-
* bitmask to indicate that the {@code onContactStarted()} method of a
68-
* particular ContactListener should be invoked
69-
*/
70-
final private static int invokeStarted = 0x80;
7156
/**
7257
* message logger for this class
7358
*/
@@ -76,21 +61,6 @@ public class DefaultContactManager implements ContactManager {
7661
// *************************************************************************
7762
// fields
7863

79-
/**
80-
* true to request {@code onContactEnded()} callbacks for the space, false
81-
* to skip them
82-
*/
83-
private boolean doEnded = false;
84-
/**
85-
* true to request {@code onContactProcessed()} callbacks for the space,
86-
* false to skip them
87-
*/
88-
private boolean doProcessed = false;
89-
/**
90-
* true to request {@code onContactStarted()} callbacks for the space, false
91-
* to skip them
92-
*/
93-
private boolean doStarted = false;
9464
/**
9565
* registered listeners for delayed notification of ongoing contacts
9666
*/
@@ -111,14 +81,20 @@ public class DefaultContactManager implements ContactManager {
11181
*/
11282
final private Deque<PhysicsCollisionEvent> startedEvents
11383
= new ArrayDeque<>(99);
84+
/**
85+
* step flags of callbacks needed by the registered listeners, ORed together
86+
*
87+
* @see com.jme3.bullet.StepFlag
88+
*/
89+
private int stepFlags = 0x0;
11490
/**
11591
* list of registered listeners for immediate contact notifications
11692
* (parallel with {@code immediateListenerFlags})
11793
*/
11894
final private List<ContactListener> immediateListeners = new ArrayList<>(4);
11995
/**
120-
* list of invocation flags for immediate contact notifications (parallel
121-
* with {@code immediateListeners})
96+
* list of step flags for immediate contact notifications (parallel with
97+
* {@code immediateListeners})
12298
*/
12399
final private List<Integer> immediateListenerFlags = new ArrayList<>(4);
124100
/**
@@ -158,44 +134,26 @@ public synchronized void addCollisionListener(
158134
assert !startedListeners.contains(listener);
159135

160136
startedListeners.add(listener);
161-
this.doStarted = true;
137+
this.stepFlags |= StepFlag.contactStarted;
162138
}
163139

164140
/**
165141
* Register the specified listener for immediate contact notifications.
166142
*
167143
* @param listener the listener to register (not null, alias created)
168-
* @param doEnded true to enable {@code onContactEnded()} callbacks for the
169-
* listener, false to skip them
170-
* @param doProcessed true to enable {@code onContactProcessed()} callbacks
171-
* for the listener, false to skip them
172-
* @param doStarted true to enable {@code onContactStarted()} callbacks for
173-
* the listener, false to skip them
144+
* @param stepFlags the step flags for this listener, ORed together
174145
*/
175146
@Override
176-
public synchronized void addContactListener(ContactListener listener,
177-
boolean doEnded, boolean doProcessed, boolean doStarted) {
147+
public synchronized void addContactListener(
148+
ContactListener listener, int stepFlags) {
178149
Validate.nonNull(listener, "listener");
179150
assert listener != this;
180151
assert listener != space;
181152
assert !immediateListeners.contains(listener);
182153

183154
immediateListeners.add(listener);
184-
185-
int encodedFlags = (doEnded ? invokeEnded : 0x0)
186-
| (doProcessed ? invokeProcessed : 0x0)
187-
| (doStarted ? invokeStarted : 0x0);
188-
immediateListenerFlags.add(encodedFlags);
189-
190-
if (doEnded) {
191-
this.doEnded = true;
192-
}
193-
if (doProcessed) {
194-
this.doProcessed = true;
195-
}
196-
if (doStarted) {
197-
this.doStarted = true;
198-
}
155+
immediateListenerFlags.add(stepFlags);
156+
this.stepFlags |= stepFlags;
199157
}
200158

201159
/**
@@ -215,7 +173,7 @@ public synchronized void addOngoingCollisionListener(
215173
assert !ongoingListeners.contains(listener);
216174

217175
ongoingListeners.add(listener);
218-
this.doProcessed = true;
176+
this.stepFlags |= StepFlag.contactProcessed;
219177
}
220178

221179
/**
@@ -299,26 +257,46 @@ public synchronized void removeOngoingCollisionListener(
299257
}
300258

301259
/**
302-
* Update the associated PhysicsSpace. This method should be invoked from
303-
* the thread that created the space.
260+
* Update the associated PhysicsSpace, enabling the specified additional
261+
* callbacks. This method should be invoked from the thread that created the
262+
* space.
304263
*
305264
* @param timeInterval the time interval to simulate (in seconds, &ge;0)
306-
* @param maxSteps the maximum number of steps of size {@code accuracy}
307-
* (&ge;1) or 0 for a single step of size {@code timeInterval}
265+
* @param maxSteps the maximum number of simulation steps of size
266+
* {@code accuracy} (&ge;1) or 0 for a single simulation step of size
267+
* {@code timeInterval}
268+
* @param addFlags the desired callbacks, ORed together (default=0x0)
269+
* @see com.jme3.bullet.StepFlag
308270
*/
309271
@Override
310-
public void update(float timeInterval, int maxSteps) {
272+
public void update(float timeInterval, int maxSteps, int addFlags) {
311273
assert Validate.nonNegative(timeInterval, "time interval");
312274
assert Validate.nonNegative(maxSteps, "max steps");
313275

314-
space.update(timeInterval, maxSteps, doEnded, doProcessed, doStarted);
276+
int flags = stepFlags | addFlags;
277+
space.update(timeInterval, maxSteps, flags);
315278
}
316279
// *************************************************************************
317280
// ContactListener methods
318281

319282
/**
320-
* Invoked immediately after a contact manifold is destroyed. Skipped if
321-
* stepSimulation() was invoked with doEnded=false.
283+
* Invoked immediately before a contact point is added to a manifold.
284+
*
285+
* @param pointId the native ID of the {@code btManifoldPoint} (not zero)
286+
* @param manifoldId the native ID of the {@code btPersistentManifold} (not
287+
* zero)
288+
* @param pcoA the "A" collision object (not null)
289+
* @param pcoB the "B" collision object (not null)
290+
* @return true to accept the contact, or false to reject it
291+
*/
292+
@Override
293+
public boolean onContactConceived(long pointId, long manifoldId,
294+
PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB) {
295+
return true;
296+
}
297+
298+
/**
299+
* Invoked immediately after a contact manifold is destroyed.
322300
*
323301
* @param manifoldId the native ID of the {@code btPersistentManifold} (not
324302
* zero)
@@ -328,7 +306,7 @@ public void onContactEnded(long manifoldId) {
328306
int numImmediateListeners = immediateListeners.size();
329307
for (int i = 0; i < numImmediateListeners; ++i) {
330308
int flags = immediateListenerFlags.get(i);
331-
if ((flags & invokeEnded) != 0x0) {
309+
if ((flags & StepFlag.contactEnded) != 0x0) {
332310
ContactListener listener = immediateListeners.get(i);
333311
listener.onContactEnded(manifoldId);
334312
}
@@ -337,8 +315,7 @@ public void onContactEnded(long manifoldId) {
337315

338316
/**
339317
* Invoked immediately after a contact point is refreshed without being
340-
* destroyed. Skipped for Sphere-Sphere contacts. Skipped if
341-
* stepSimulation() was invoked with doProcessed=false.
318+
* destroyed. Skipped for Sphere-Sphere contacts.
342319
*
343320
* @param pcoA the first involved object (not null)
344321
* @param pcoB the 2nd involved object (not null)
@@ -350,7 +327,7 @@ public void onContactProcessed(PhysicsCollisionObject pcoA,
350327
int numImmediateListeners = immediateListeners.size();
351328
for (int i = 0; i < numImmediateListeners; ++i) {
352329
int flags = immediateListenerFlags.get(i);
353-
if ((flags & invokeProcessed) != 0x0) {
330+
if ((flags & StepFlag.contactProcessed) != 0x0) {
354331
ContactListener listener = immediateListeners.get(i);
355332
listener.onContactProcessed(pcoA, pcoB, pointId);
356333
}
@@ -366,8 +343,7 @@ public void onContactProcessed(PhysicsCollisionObject pcoA,
366343
}
367344

368345
/**
369-
* Invoked immediately after a contact manifold is created. Skipped if
370-
* stepSimulation() was invoked with doStarted=false.
346+
* Invoked immediately after a contact manifold is created.
371347
*
372348
* @param manifoldId the native ID of the {@code btPersistentManifold} (not
373349
* zero)
@@ -377,7 +353,7 @@ public void onContactStarted(long manifoldId) {
377353
int numImmediateListeners = immediateListeners.size();
378354
for (int i = 0; i < numImmediateListeners; ++i) {
379355
int flags = immediateListenerFlags.get(i);
380-
if ((flags & invokeStarted) != 0x0) {
356+
if ((flags & StepFlag.contactStarted) != 0x0) {
381357
ContactListener listener = immediateListeners.get(i);
382358
listener.onContactStarted(manifoldId);
383359
}
@@ -411,19 +387,19 @@ public void onContactStarted(long manifoldId) {
411387
// new private methods
412388

413389
/**
414-
* Update the doEnded, doProcessed, and doStarted flags after a listener is
415-
* removed.
390+
* Update the {@code stepFlags} field after a listener is removed.
416391
*/
417392
private void updateFlags() {
418393
int union = 0x0;
419394
for (int flags : immediateListenerFlags) {
420395
union |= flags;
421396
}
422-
423-
this.doEnded = ((union & invokeEnded) != 0x0);
424-
this.doProcessed = ((union & invokeProcessed) != 0x0)
425-
|| !ongoingListeners.isEmpty();
426-
this.doStarted = ((union & invokeStarted) != 0x0)
427-
|| !startedListeners.isEmpty();
397+
if (!ongoingListeners.isEmpty()) {
398+
union |= StepFlag.contactProcessed;
399+
}
400+
if (!startedListeners.isEmpty()) {
401+
union |= StepFlag.contactStarted;
402+
}
403+
this.stepFlags = union;
428404
}
429405
}

0 commit comments

Comments
 (0)